diff --git a/platform/chromium/vapi-background-ext.js b/platform/chromium/vapi-background-ext.js index b40c2f14bf68b..1369714a744aa 100644 --- a/platform/chromium/vapi-background-ext.js +++ b/platform/chromium/vapi-background-ext.js @@ -186,9 +186,11 @@ vAPI.Tabs = class extends vAPI.Tabs { return { cancel: true }; } - unsuspendAllRequests() { - for ( const tabId of this.suspendedTabIds ) { - vAPI.tabs.reload(tabId); + unsuspendAllRequests(discard = false) { + if ( discard !== true ) { + for ( const tabId of this.suspendedTabIds ) { + vAPI.tabs.reload(tabId); + } } this.suspendedTabIds.clear(); } diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js index daafa7f2445b0..ce7c90ed1cd63 100644 --- a/platform/common/vapi-background.js +++ b/platform/common/vapi-background.js @@ -1220,12 +1220,10 @@ vAPI.Net = class { } unsuspendAllRequests() { } - suspend(force = false) { - if ( this.canSuspend() || force ) { - this.suspendDepth += 1; - } + suspend() { + this.suspendDepth += 1; } - unsuspend(all = false) { + unsuspend({ all = false, discard = false } = {}) { if ( this.suspendDepth === 0 ) { return; } if ( all ) { this.suspendDepth = 0; @@ -1233,7 +1231,7 @@ vAPI.Net = class { this.suspendDepth -= 1; } if ( this.suspendDepth !== 0 ) { return; } - this.unsuspendAllRequests(); + this.unsuspendAllRequests(discard); } canSuspend() { return false; diff --git a/platform/firefox/vapi-background-ext.js b/platform/firefox/vapi-background-ext.js index 69609f216fd60..fc04d32dcc572 100644 --- a/platform/firefox/vapi-background-ext.js +++ b/platform/firefox/vapi-background-ext.js @@ -292,11 +292,15 @@ import { this.pendingRequests.push(pending); return pending.promise; } - unsuspendAllRequests() { + unsuspendAllRequests(discard = false) { const pendingRequests = this.pendingRequests; this.pendingRequests = []; for ( const entry of pendingRequests ) { - entry.resolve(this.onBeforeSuspendableRequest(entry.details)); + entry.resolve( + discard !== true + ? this.onBeforeSuspendableRequest(entry.details) + : undefined + ); } } canSuspend() { diff --git a/src/3p-filters.html b/src/3p-filters.html index 24e73095d06e9..2eca266e8fabb 100644 --- a/src/3p-filters.html +++ b/src/3p-filters.html @@ -24,10 +24,17 @@
-
-
+
+
-
+
+ +
+
+ +
+
+
diff --git a/src/js/3p-filters.js b/src/js/3p-filters.js index 3f1dc1081bee9..924159c07c7fc 100644 --- a/src/js/3p-filters.js +++ b/src/js/3p-filters.js @@ -286,7 +286,8 @@ const renderFilterLists = function(soft) { // Re-insert import widget. uDom('[data-groupkey="custom"] .listEntries').append(importWidget); - uDom.nodeFromId('autoUpdate').checked = listDetails.autoUpdate === true; + uDom.nodeFromId('autoUpdate').checked = + listDetails.autoUpdate === true; uDom.nodeFromId('listsOfBlockedHostsPrompt').textContent = vAPI.i18n('3pListsOfBlockedHostsPrompt') .replace( @@ -301,6 +302,8 @@ const renderFilterLists = function(soft) { listDetails.parseCosmeticFilters === true; uDom.nodeFromId('ignoreGenericCosmeticFilters').checked = listDetails.ignoreGenericCosmeticFilters === true; + uDom.nodeFromId('suspendUntilListsAreLoaded').checked = + listDetails.suspendUntilListsAreLoaded === true; // Compute a hash of the settings so that we can keep track of changes // affecting the loading of filter lists. @@ -529,11 +532,12 @@ const buttonPurgeAllHandler = async function(hard) { /******************************************************************************/ -const autoUpdateCheckboxChanged = function() { +const userSettingCheckboxChanged = function() { + const target = event.target; messaging.send('dashboard', { what: 'userSettings', - name: 'autoUpdate', - value: this.checked, + name: target.id, + value: target.checked, }); }; @@ -683,9 +687,10 @@ self.hasUnsavedData = function() { /******************************************************************************/ -uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged); +uDom('#autoUpdate').on('change', userSettingCheckboxChanged); uDom('#parseCosmeticFilters').on('change', onFilteringSettingsChanged); uDom('#ignoreGenericCosmeticFilters').on('change', onFilteringSettingsChanged); +uDom('#suspendUntilListsAreLoaded').on('change', userSettingCheckboxChanged); uDom('#buttonApply').on('click', ( ) => { buttonApplyHandler(); }); uDom('#buttonUpdate').on('click', ( ) => { buttonUpdateHandler(); }); uDom('#buttonPurgeAll').on('click', ev => { diff --git a/src/js/background.js b/src/js/background.js index 4e94b942c3cdf..5c9d95abe5957 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -80,7 +80,6 @@ const hiddenSettingsDefault = { requestJournalProcessPeriod: 1000, selfieAfter: 2, strictBlockingBypassDuration: 120, - suspendTabsUntilReady: 'unset', uiPopupConfig: 'unset', uiFlavor: 'unset', uiStyles: 'unset', @@ -109,6 +108,7 @@ const userSettingsDefault = { prefetchingDisabled: true, requestLogMaxEntries: 1000, showIconBadge: true, + suspendUntilListsAreLoaded: true, tooltipsDisabled: false, webrtcIPAddressHidden: false, }; @@ -214,7 +214,7 @@ const µBlock = { // jshint ignore:line readyToFilter: false, supportStats: { - launchToReadiness: '', + allReadyAfter: '', }, pageStores: new Map(), diff --git a/src/js/messaging.js b/src/js/messaging.js index 4aa038a4c0d43..b2f7cc3d5e907 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -1091,6 +1091,7 @@ const getLists = async function(callback) { isUpdating: io.isUpdating(), netFilterCount: staticNetFilteringEngine.getFilterCount(), parseCosmeticFilters: µb.userSettings.parseAllABPHideFilters, + suspendUntilListsAreLoaded: µb.userSettings.suspendUntilListsAreLoaded, userFiltersPath: µb.userFiltersPath }; const [ lists, metadata ] = await Promise.all([ diff --git a/src/js/start.js b/src/js/start.js index cb3d43e4f2227..2702973eae7da 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -192,6 +192,13 @@ const onNetWhitelistReady = function(netWhitelistRaw, adminExtra) { // User settings are in memory const onUserSettingsReady = function(fetched) { + // Terminate suspended state? + if ( fetched.suspendUntilListsAreLoaded === false ) { + vAPI.net.unsuspend({ all: true, discard: true }); + ubolog(`Unsuspend network activity listener`); + µb.supportStats.unsuspendAfter = `${Date.now() - vAPI.T0} ms`; + } + // `externalLists` will be deprecated in some future, it is kept around // for forward compatibility purpose, and should reflect the content of // `importedLists`. @@ -282,13 +289,6 @@ const onHiddenSettingsReady = async function() { ubolog(`Override default webext flavor with ${tokens}`); } - // Maybe override current network listener suspend state - if ( µb.hiddenSettings.suspendTabsUntilReady === 'no' ) { - vAPI.net.unsuspend(true); - } else if ( µb.hiddenSettings.suspendTabsUntilReady === 'yes' ) { - vAPI.net.suspend(true); - } - // Maybe disable WebAssembly if ( vAPI.canWASM && µb.hiddenSettings.disableWebAssembly !== true ) { const wasmModuleFetcher = function(path) { @@ -506,11 +506,11 @@ browser.runtime.onUpdateAvailable.addListener(details => { } }); -µb.supportStats.launchToReadiness = `${Date.now() - vAPI.T0} ms`; +µb.supportStats.allReadyAfter = `${Date.now() - vAPI.T0} ms`; if ( selfieIsValid ) { - µb.supportStats.launchToReadiness += ' (selfie)'; + µb.supportStats.allReadyAfter += ' (selfie)'; } -ubolog(`All ready ${µb.supportStats.launchToReadiness} ms after launch`); +ubolog(`All ready ${µb.supportStats.allReadyAfter} ms after launch`); // <<<<< end of private scope })(); diff --git a/src/js/storage.js b/src/js/storage.js index 65d3974198d1d..2532a0eb8b21a 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -239,12 +239,6 @@ import { if ( typeof hs[key] !== typeof hsDefault[key] ) { continue; } this.hiddenSettings[key] = hs[key]; } - if ( typeof this.hiddenSettings.suspendTabsUntilReady === 'boolean' ) { - this.hiddenSettings.suspendTabsUntilReady = - this.hiddenSettings.suspendTabsUntilReady - ? 'yes' - : 'unset'; - } this.fireDOMEvent('hiddenSettingsChanged'); }; @@ -810,7 +804,9 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { const onFilterListsReady = function(lists) { this.availableFilterLists = lists; - vAPI.net.suspend(); + if ( vAPI.net.canSuspend() ) { + vAPI.net.suspend(); + } redirectEngine.reset(); staticExtFilteringEngine.reset(); staticNetFilteringEngine.reset(); diff --git a/src/js/traffic.js b/src/js/traffic.js index d4a01bbf6153b..e44ca913958e6 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -1146,22 +1146,7 @@ const webRequest = { { urls: [ 'http://*/*', 'https://*/*' ] }, [ 'blocking', 'responseHeaders' ] ); - vAPI.net.unsuspend(true); - // Mitigation: force-reload active tabs for environments not - // supporting suspended network request listeners. - if ( - vAPI.net.canSuspend() !== true || - µb.hiddenSettings.suspendTabsUntilReady === 'no' - ) { - const tabs = await vAPI.tabs.query({ - active: true, - url: [ 'https://*/*', 'http://*/*' ], - windowType: 'normal', - }); - for ( const tab of tabs ) { - vAPI.tabs.reload(tab.id); - } - } + vAPI.net.unsuspend({ all: true }); }; })(),