From bec6cad2c029ef59de40043dcc998bb3c861cc69 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 7 Apr 2023 20:24:20 -0400 Subject: [PATCH] Start using browser.alarms instead of setTimeout() where applicable Related documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Background_scripts#convert_to_non-persistent --- platform/chromium/manifest.json | 1 + platform/common/vapi-background.js | 55 ++++++++++++++++++++++++++++++ platform/firefox/manifest.json | 1 + platform/opera/manifest.json | 1 + src/js/storage.js | 32 ++++------------- 5 files changed, 65 insertions(+), 25 deletions(-) diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index c48776edc..e99393f27 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -82,6 +82,7 @@ "open_in_tab": true }, "permissions": [ + "alarms", "contextMenus", "privacy", "storage", diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js index 376ebecd6..cf2f00509 100644 --- a/platform/common/vapi-background.js +++ b/platform/common/vapi-background.js @@ -95,6 +95,61 @@ vAPI.storage = webext.storage.local; /******************************************************************************/ /******************************************************************************/ +vAPI.alarms = { + create(callback) { + this.uniqueIdGenerator += 1; + const name = this.uniqueIdGenerator.toString(36); + const client = new this.Client(name, callback); + this.clientMap.set(name, client); + return client; + }, + Client: class { + constructor(name, callback) { + this.name = name; + this.callback = callback; + } + on(delay) { + const delayInMinutes = this.normalizeDelay(delay); + browser.alarms.get(this.name, alarm => { + if ( alarm ) { return; } + return browser.alarms.create(this.name, { delayInMinutes }); + }); + } + offon(delay) { + const delayInMinutes = this.normalizeDelay(delay); + return browser.alarms.create(this.name, { delayInMinutes }); + } + off() { + return browser.alarms.clear(this.name); + } + normalizeDelay(delay) { + let delayInMinutes = 0; + if ( typeof delay === 'number' ) { + delayInMinutes = delay; + } else if ( typeof delay === 'object' ) { + if ( delay.sec !== undefined ) { + delayInMinutes = delay.sec / 60; + } else if ( delay.ms !== undefined ) { + delayInMinutes = delay.ms / 60000; + } + } + return Math.max(delayInMinutes, 1); + } + }, + onAlarm(alarm) { + const client = this.clientMap.get(alarm.name); + if ( client === undefined ) { return; } + client.callback(alarm); + }, + clientMap: new Map(), + uniqueIdGenerator: 1000000, +}; + +browser.alarms.onAlarm.addListener(alarm => vAPI.alarms.onAlarm(alarm)); + +/******************************************************************************/ +/******************************************************************************/ + // https://github.com/gorhill/uMatrix/issues/234 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy/network diff --git a/platform/firefox/manifest.json b/platform/firefox/manifest.json index b7ea2e375..816df87b3 100644 --- a/platform/firefox/manifest.json +++ b/platform/firefox/manifest.json @@ -90,6 +90,7 @@ "open_in_tab": true }, "permissions": [ + "alarms", "dns", "menus", "privacy", diff --git a/platform/opera/manifest.json b/platform/opera/manifest.json index d5b02fb3e..e0d437099 100644 --- a/platform/opera/manifest.json +++ b/platform/opera/manifest.json @@ -78,6 +78,7 @@ "name": "uBlock Origin", "options_page": "dashboard.html", "permissions": [ + "alarms", "contextMenus", "privacy", "storage", diff --git a/src/js/storage.js b/src/js/storage.js index 2b1924b3a..23f1b3e87 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -1276,35 +1276,17 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { return false; }; - let createTimer; - let destroyTimer; - const destroy = function() { - io.remove(/^selfie\//); - µb.selfieIsInvalid = true; - createTimer = vAPI.setTimeout(( ) => { - createTimer = undefined; - create(); - }, µb.hiddenSettings.selfieAfter * 60000); - }; - - const destroyAsync = function() { - if ( destroyTimer !== undefined ) { return; } - if ( createTimer !== undefined ) { - clearTimeout(createTimer); - createTimer = undefined; + if ( µb.selfieIsInvalid === false ) { + io.remove(/^selfie\//); + µb.selfieIsInvalid = true; } - destroyTimer = vAPI.setTimeout( - ( ) => { - destroyTimer = undefined; - destroy(); - }, - 1019 - ); - µb.selfieIsInvalid = true; + createAlarm.offon(µb.hiddenSettings.selfieAfter); }; - µb.selfieManager = { load, destroy: destroyAsync }; + const createAlarm = vAPI.alarms.create(create); + + µb.selfieManager = { load, destroy }; } /******************************************************************************/