From 3bb73065e32aab639324a8d1dbe9bfdf3f45ea76 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 31 Jan 2021 10:30:12 -0500 Subject: [PATCH] Fix broken forward compatibility re. imported lists Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1480 Forward compatiblity was broken due to `externalLists` being converted into an Array from a string, i.e. downgrading to uBO 1.32.4 was completely breaking uBO. This commit restores `externalLists` as a string which is what older versions of uBO expect. A new property `importedLists` has been created to hold the imported lists as an array, while `externalLists` will be kept around for a while until it is completely removed in some future. --- src/js/background.js | 3 ++- src/js/messaging.js | 6 +++--- src/js/start.js | 15 ++++++++++++--- src/js/storage.js | 41 ++++++++++++++++++++++------------------- src/js/utils.js | 2 ++ 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 54a4bfa5c..e96566c36 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -92,10 +92,11 @@ const µBlock = (( ) => { // jshint ignore:line colorBlindFriendly: false, contextMenuEnabled: true, dynamicFilteringEnabled: false, - externalLists: [], + externalLists: '', firewallPaneMinimized: true, hyperlinkAuditingDisabled: true, ignoreGenericCosmeticFilters: vAPI.webextFlavor.soup.has('mobile'), + importedLists: [], largeMediaSize: 50, parseAllABPHideFilters: true, popupPanelSections: 0b111, diff --git a/src/js/messaging.js b/src/js/messaging.js index a733f2522..1bba6889d 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -949,9 +949,9 @@ const restoreUserData = async function(request) { userData.hostnameSwitchesString += '\nno-csp-reports: * true'; } - // List of external lists is meant to be an array. - if ( typeof userData.externalLists === 'string' ) { - userData.externalLists = userData.externalLists.trim().split(/[\n\r]+/); + // List of external lists is meant to be a string. + if ( Array.isArray(userData.externalLists) ) { + userData.externalLists = userData.externalLists.join('\n'); } // https://github.com/chrisaljoudi/uBlock/issues/1102 diff --git a/src/js/start.js b/src/js/start.js index c1e41f9c8..dfe64106b 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -160,9 +160,18 @@ const onNetWhitelistReady = function(netWhitelistRaw, adminExtra) { // User settings are in memory const onUserSettingsReady = function(fetched) { - // List of external lists is meant to be an array - if ( typeof fetched.externalLists === 'string' ) { - fetched.externalLists = + // `externalLists` will be deprecated in some future, it is kept around + // for forward compatibility purpose, and should reflect the content of + // `importedLists`. + if ( Array.isArray(fetched.externalLists) ) { + fetched.externalLists = fetched.externalLists.join('\n'); + vAPI.storage.set({ externalLists: fetched.externalLists }); + } + if ( + fetched.importedLists.length === 0 && + fetched.externalLists !== '' + ) { + fetched.importedLists = fetched.externalLists.trim().split(/[\n\r]+/); } diff --git a/src/js/storage.js b/src/js/storage.js index c48099fe9..e59c1bbb9 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -116,10 +116,17 @@ this.userSettings, this.userSettingsDefault ); + + // `externalLists` will be deprecated in some future, it is kept around + // for forward compatibility purpose, and should reflect the content of + // `importedLists`. + this.userSettings.externalLists = + this.userSettings.importedLists.join('\n'); + const toRemove = []; for ( const key in this.userSettings ) { if ( this.userSettings.hasOwnProperty(key) === false ) { continue; } - if ( toSave.hasOwnProperty(key) === false ) { continue; } + if ( toSave.hasOwnProperty(key) ) { continue; } toRemove.push(key); } if ( toRemove.length !== 0 ) { @@ -368,7 +375,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { µBlock.applyFilterListSelection = function(details) { let selectedListKeySet = new Set(this.selectedFilterLists); - let externalLists = this.userSettings.externalLists.slice(); + let importedLists = this.userSettings.importedLists.slice(); // Filter lists to select if ( Array.isArray(details.toSelect) ) { @@ -386,9 +393,9 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { for ( let i = 0, n = details.toRemove.length; i < n; i++ ) { const assetKey = details.toRemove[i]; selectedListKeySet.delete(assetKey); - const pos = externalLists.indexOf(assetKey); + const pos = importedLists.indexOf(assetKey); if ( pos !== -1 ) { - externalLists.splice(pos, 1); + importedLists.splice(pos, 1); } this.removeFilterList(assetKey); } @@ -418,7 +425,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { } return url; }; - const importedSet = new Set(this.listKeysFromCustomFilterLists(externalLists)); + const importedSet = new Set(this.listKeysFromCustomFilterLists(importedLists)); const toImportSet = new Set(this.listKeysFromCustomFilterLists(details.toImport)); for ( const urlKey of toImportSet ) { if ( importedSet.has(urlKey) ) { @@ -431,12 +438,12 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { } selectedListKeySet.add(assetKey); } - externalLists = Array.from(importedSet).sort(); + importedLists = Array.from(importedSet).sort(); } const result = Array.from(selectedListKeySet); - if ( externalLists.join() !== this.userSettings.externalLists.join() ) { - this.userSettings.externalLists = externalLists; + if ( importedLists.join() !== this.userSettings.importedLists.join() ) { + this.userSettings.importedLists = importedLists; this.saveUserSettings(); } this.saveSelectedFilterLists(result); @@ -597,7 +604,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // Custom filter lists. const importedListKeys = this.listKeysFromCustomFilterLists( - this.userSettings.externalLists + this.userSettings.importedLists ); for ( const listKey of importedListKeys ) { const entry = { @@ -631,7 +638,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { newAvailableLists[listURL] = newEntry; this.assets.registerAssetSource(listURL, newEntry); importedListKeys.push(listURL); - this.userSettings.externalLists.push(listURL.trim()); + this.userSettings.importedLists.push(listURL.trim()); this.saveUserSettings(); this.saveSelectedFilterLists([ listURL ], true); }; @@ -1351,11 +1358,6 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { if ( typeof data.userSettings === 'object' ) { const µbus = this.userSettings; const adminus = data.userSettings; - // List of external lists is meant to be an array. - if ( typeof adminus.externalLists === 'string' ) { - adminus.externalLists = - adminus.externalLists.trim().split(/[\n\r]+/); - } for ( const name in µbus ) { if ( µbus.hasOwnProperty(name) === false ) { continue; } if ( adminus.hasOwnProperty(name) === false ) { continue; } @@ -1371,13 +1373,14 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { Array.isArray(toOverwrite.filterLists) && toOverwrite.filterLists.length !== 0 ) { - const externalLists = []; + const importedLists = []; for ( const list of toOverwrite.filterLists ) { if ( /^[a-z-]+:\/\//.test(list) === false ) { continue; } - externalLists.push(list); + importedLists.push(list); } - if ( externalLists.length !== 0 ) { - bin.externalLists = externalLists; + if ( importedLists.length !== 0 ) { + bin.importedLists = importedLists; + bin.externalLists = importedLists.join('\n'); } bin.selectedFilterLists = toOverwrite.filterLists; binNotEmpty = true; diff --git a/src/js/utils.js b/src/js/utils.js index b582a9359..6c8ffd960 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -687,6 +687,8 @@ /******************************************************************************/ +// TODO: properly compare arrays + µBlock.getModifiedSettings = function(edit, orig = {}) { const out = {}; for ( const prop in edit ) {