From 059e4e5e28ccf4e2ccee9781053341b60b0c389c Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 29 Feb 2024 11:43:51 -0500 Subject: [PATCH] Imrpove saving request stats for non-persistent background page Related issue: https://github.com/uBlockOrigin/uBlock-issues/issues/2969 Related previous commit: https://github.com/gorhill/uBlock/commit/5a338b7210 The save-to-storage period is back to being around ~4 minutes, but now browser.storage.session API is used to keep track of request stats should the extension be suspended before the period elapse. --- platform/common/vapi-background.js | 32 +++++++++++------ src/js/background.js | 7 ++-- src/js/messaging.js | 4 +-- src/js/pagestore.js | 6 ++-- src/js/start.js | 10 +++--- src/js/storage.js | 56 ++++++++++++++++++++++-------- 6 files changed, 74 insertions(+), 41 deletions(-) diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js index 83d04a9af..7f336066f 100644 --- a/platform/common/vapi-background.js +++ b/platform/common/vapi-background.js @@ -109,9 +109,9 @@ vAPI.generateSecret = (size = 1) => { * * */ -vAPI.sessionStorage = webext.storage.session || { +vAPI.sessionStorage = browser.storage.session || { get() { - return Promise.resolve({}); + return Promise.resolve(); }, set() { return Promise.resolve(); @@ -122,6 +122,7 @@ vAPI.sessionStorage = webext.storage.session || { clear() { return Promise.resolve(); }, + unavailable: true, }; /******************************************************************************* @@ -315,10 +316,10 @@ vAPI.Tabs = class { }); } - async executeScript() { + async executeScript(...args) { let result; try { - result = await webext.tabs.executeScript(...arguments); + result = await webext.tabs.executeScript(...args); } catch(reason) { } @@ -543,7 +544,7 @@ vAPI.Tabs = class { targetURL = vAPI.getURL(targetURL); } - vAPI.tabs.update(tabId, { url: targetURL }); + return vAPI.tabs.update(tabId, { url: targetURL }); } async remove(tabId) { @@ -1778,15 +1779,24 @@ vAPI.cloud = (( ) => { /******************************************************************************/ /******************************************************************************/ -vAPI.alarms = browser.alarms || { - create() { +vAPI.alarms = { + create(...args) { + browser.alarms.create(...args); }, - clear() { + createIfNotPresent(name, ...args) { + browser.alarms.get(name).then(details => { + if ( details !== undefined ) { return; } + browser.alarms.create(name, ...args); + }); + }, + async clear(...args) { + return browser.alarms.clear(...args); }, onAlarm: { - addListener() { - } - } + addListener(...args) { + browser.alarms.onAlarm.addListener(...args); + }, + }, }; /******************************************************************************/ diff --git a/src/js/background.js b/src/js/background.js index 79cae6eb1..601851924 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -174,11 +174,10 @@ const µBlock = { // jshint ignore:line 'moz-extension-scheme', ], - localSettings: { - blockedRequestCount: 0, - allowedRequestCount: 0, + requestStats: { + blockedCount: 0, + allowedCount: 0, }, - localSettingsLastModified: 0, // Read-only systemSettings: { diff --git a/src/js/messaging.js b/src/js/messaging.js index 468579a4f..f34443cf7 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -365,8 +365,8 @@ const popupDataFromTabId = function(tabId, tabTitle) { colorBlindFriendly: µbus.colorBlindFriendly, cosmeticFilteringSwitch: false, firewallPaneMinimized: µbus.firewallPaneMinimized, - globalAllowedRequestCount: µb.localSettings.allowedRequestCount, - globalBlockedRequestCount: µb.localSettings.blockedRequestCount, + globalAllowedRequestCount: µb.requestStats.allowedCount, + globalBlockedRequestCount: µb.requestStats.blockedCount, fontSize: µbhs.popupFontSize, godMode: µbhs.filterAuthorMode, netFilteringSwitch: false, diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 907e74743..838bd3aa6 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -739,10 +739,8 @@ const PageStore = class { aggregateAllowed += 1; } } - if ( aggregateAllowed !== 0 || aggregateBlocked !== 0 ) { - µb.localSettings.blockedRequestCount += aggregateBlocked; - µb.localSettings.allowedRequestCount += aggregateAllowed; - µb.localSettingsLastModified = now; + if ( aggregateAllowed || aggregateBlocked ) { + µb.incrementRequestStats(aggregateBlocked, aggregateAllowed); } journal.length = 0; } diff --git a/src/js/start.js b/src/js/start.js index bd0bd4660..2bda75c1f 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -327,7 +327,6 @@ const onFirstFetchReady = (fetched, adminExtra) => { } // Order is important -- do not change: - fromFetch(µb.localSettings, fetched); fromFetch(µb.restoreBackupSettings, fetched); permanentFirewall.fromString(fetched.dynamicFilteringString); @@ -362,14 +361,9 @@ const createDefaultProps = ( ) => { 'dynamicFilteringString': µb.dynamicFilteringDefault.join('\n'), 'urlFilteringString': '', 'hostnameSwitchesString': µb.hostnameSwitchesDefault.join('\n'), - 'lastRestoreFile': '', - 'lastRestoreTime': 0, - 'lastBackupFile': '', - 'lastBackupTime': 0, 'netWhitelist': µb.netWhitelistDefault, 'version': '0.0.0.0' }; - toFetch(µb.localSettings, fetchableProps); toFetch(µb.restoreBackupSettings, fetchableProps); return fetchableProps; }; @@ -424,6 +418,7 @@ try { ubolog(`Cache magic numbers ready ${Date.now()-vAPI.T0} ms after launch`); onCacheSettingsReady(bin); }), + µb.loadLocalSettings(), ]); // https://github.com/uBlockOrigin/uBlock-issues/issues/1547 @@ -523,6 +518,9 @@ while ( µb.alarmQueue.length !== 0 ) { case 'createSelfie': µb.selfieManager.create(); break; + case 'saveLocalSettings': + µb.saveLocalSettings(); + break; } } diff --git a/src/js/storage.js b/src/js/storage.js index 6ac386632..0c545e938 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -97,23 +97,51 @@ import { /******************************************************************************/ { - let localSettingsLastSaved = Date.now(); - - const shouldSave = ( ) => { - if ( µb.localSettingsLastModified > localSettingsLastSaved ) { - µb.saveLocalSettings(); + µb.loadLocalSettings = ( ) => Promise.all([ + vAPI.sessionStorage.get('requestStats'), + vAPI.storage.get('requestStats'), + vAPI.storage.get([ 'blockedRequestCount', 'allowedRequestCount' ]), + ]).then(([ a, b, c ]) => { + if ( a instanceof Object && a.requestStats ) { return a.requestStats; } + if ( b instanceof Object && b.requestStats ) { return b.requestStats; } + if ( c instanceof Object && Object.keys(c).length === 2 ) { + return { + blockedCount: c.blockedRequestCount, + allowedCount: c.allowedRequestCount, + }; } - saveTimer.on(saveDelay); + return { blockedCount: 0, allowedCount: 0 }; + }).then(({ blockedCount, allowedCount }) => { + µb.requestStats.blockedCount += blockedCount; + µb.requestStats.allowedCount += allowedCount; + }); + + const SAVE_DELAY_IN_MINUTES = 3.6; + const QUICK_SAVE_DELAY_IN_SECONDS = 23; + + const saveTimer = vAPI.defer.create(( ) => { + µb.saveLocalSettings(); + }); + + const quickSaveTimer = vAPI.defer.create(( ) => { + saveTimer.on({ min: SAVE_DELAY_IN_MINUTES }); + if ( vAPI.sessionStorage.unavailable ) { return; } + vAPI.sessionStorage.set({ requestStats: µb.requestStats }); + vAPI.alarms.createIfNotPresent('saveLocalSettings', { + delayInMinutes: SAVE_DELAY_IN_MINUTES + 0.5 + }); + }); + + µb.incrementRequestStats = (blocked, allowed) => { + µb.requestStats.blockedCount += blocked; + µb.requestStats.allowedCount += allowed; + quickSaveTimer.on({ sec: QUICK_SAVE_DELAY_IN_SECONDS }); }; - const saveTimer = vAPI.defer.create(shouldSave); - const saveDelay = { sec: 23 }; - - saveTimer.onidle(saveDelay); - - µb.saveLocalSettings = function() { - localSettingsLastSaved = Date.now(); - return vAPI.storage.set(this.localSettings); + µb.saveLocalSettings = ( ) => { + vAPI.alarms.clear('saveLocalSettings'); + quickSaveTimer.off(); saveTimer.off(); + return vAPI.storage.set({ requestStats: µb.requestStats }); }; }