From 925c8d5d0c37dbc1f82e57a92e74350de2c5eab1 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 30 Dec 2021 09:24:38 -0500 Subject: [PATCH] Add setting to control suspension on network activity at launch Related discussion: - https://github.com/gorhill/uBlock/commit/a0a9497b4aca86727b314d8fc31ad345dad08ac8#commitcomment-62560291 The new setting, when disabled (enabled by default), allows a user to prevent uBO from waiting for all filter lists to be loaded before allowing network activity at launch. The setting is enabled by default, meaning uBO waits for all filter lists to be loaded in memory before unsuspending network activity. Some users may find this behavior undesirable, hence the new setting. This gives the option to potentially speed up page load at launch, at the cost of potentially not properly filtering network requests as per filter lists/rules. For platforms not supporting the suspension of network activity, the setting will merely prevent whatever mechanism exists on the platform to mitigate improper filtering of network requests at launch. For example, in Chromium-based browsers, unchecking the new setting will prevent the browser from re-loading tabs for which there was network activity while in "suspended" state at launch. --- platform/chromium/vapi-background-ext.js | 8 +++++--- platform/common/vapi-background.js | 10 ++++------ platform/firefox/vapi-background-ext.js | 8 ++++++-- src/3p-filters.html | 13 ++++++++++--- src/js/3p-filters.js | 15 ++++++++++----- src/js/background.js | 4 ++-- src/js/messaging.js | 1 + src/js/start.js | 20 ++++++++++---------- src/js/storage.js | 10 +++------- src/js/traffic.js | 17 +---------------- 10 files changed, 52 insertions(+), 54 deletions(-) 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 }); }; })(),