tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 90f5a23102ca25f54364c7c4832b6cd3d3d90137
parent edb367016c2c7128c3c9166fe19e28849a130b9b
Author: Thomas Wisniewski <twisniewski@mozilla.com>
Date:   Wed, 19 Nov 2025 15:20:04 +0000

Bug 1999763 - use the child process in the webcompat addon to read prefs (which also lets us read then synchronously to simplify the code); r=denschub,webcompat-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D272318

Diffstat:
Mbrowser/extensions/webcompat/experiment-apis/aboutConfigPrefs.js | 65++++++-----------------------------------------------------------
Mbrowser/extensions/webcompat/experiment-apis/aboutConfigPrefs.json | 45++++++++++++++++++---------------------------
Mbrowser/extensions/webcompat/experiment-apis/aboutConfigPrefsChild.js | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mbrowser/extensions/webcompat/lib/intervention_helpers.js | 2+-
Mbrowser/extensions/webcompat/lib/interventions.js | 32++++++++++++--------------------
Mbrowser/extensions/webcompat/lib/shims.js | 99++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mbrowser/extensions/webcompat/manifest.json | 2+-
Mbrowser/extensions/webcompat/tests/browser/browser_interventions.js | 3++-
Mbrowser/extensions/webcompat/tests/browser/browser_pref_check.js | 3++-
Mbrowser/extensions/webcompat/tests/browser/head.js | 8++++++--
Mtesting/webcompat/fixtures.py | 6++----
11 files changed, 156 insertions(+), 177 deletions(-)

diff --git a/browser/extensions/webcompat/experiment-apis/aboutConfigPrefs.js b/browser/extensions/webcompat/experiment-apis/aboutConfigPrefs.js @@ -6,77 +6,24 @@ /* global ExtensionAPI, ExtensionCommon, Services */ -this.aboutConfigPrefs = class AboutConfigPrefsAPI extends ExtensionAPI { - static ALLOWED_GLOBAL_PREFS = Object.freeze( - [ - "layout.css.prefixes.transforms", - "layout.css.webkit-fill-available.enabled", - "timer.auto_increase_timer_resolution", - ].concat( - Cu.isInAutomation ? ["webcompat.test.pref1", "webcompat.test.pref2"] : [] - ) - ); - +this.aboutConfigPrefs = class extends ExtensionAPI { getAPI(context) { - const EventManager = ExtensionCommon.EventManager; const extensionIDBase = context.extension.id.split("@")[0]; const extensionPrefNameBase = `extensions.${extensionIDBase}.`; - function getSafePref(name) { - if (AboutConfigPrefsAPI.ALLOWED_GLOBAL_PREFS.includes(name)) { - return name; - } - return `${extensionPrefNameBase}${name}`; - } - return { aboutConfigPrefs: { - onPrefChange: new EventManager({ - context, - name: "aboutConfigPrefs.onUAOverridesPrefChange", - register: (fire, name) => { - const prefName = getSafePref(name); - const callback = () => { - fire.async(name).catch(() => {}); // ignore Message Manager disconnects - }; - Services.prefs.addObserver(prefName, callback); - return () => { - Services.prefs.removeObserver(prefName, callback); - }; - }, - }).api(), - async getBranch(branchName) { - const branch = `${extensionPrefNameBase}${branchName}.`; - return Services.prefs.getChildList(branch).map(pref => { - const name = pref.replace(branch, ""); - return { name, value: Services.prefs.getBoolPref(pref) }; - }); - }, - async getPref(_name) { - const name = getSafePref(_name); - try { - switch (Services.prefs.getPrefType(name)) { - case Ci.nsIPrefBranch.PREF_BOOL: - return Services.prefs.getBoolPref(name); - case Ci.nsIPrefBranch.PREF_INT: - return Services.prefs.getIntPref(name); - case Ci.nsIPrefBranch.PREF_STRING: - return Services.prefs.getStringPref(name); - } - } catch (_) {} - return undefined; - }, - async setPref(_name, value) { - const name = getSafePref(_name); + async setPref(name, value) { + const fullName = `${extensionPrefNameBase}${name}`; switch (typeof value) { case "boolean": - Services.prefs.setBoolPref(name, value); + Services.prefs.setBoolPref(fullName, value); break; case "number": - Services.prefs.setIntPref(name, value); + Services.prefs.setIntPref(fullName, value); break; case "string": - Services.prefs.setStringPref(name, value); + Services.prefs.setStringPref(fullName, value); break; } }, diff --git a/browser/extensions/webcompat/experiment-apis/aboutConfigPrefs.json b/browser/extensions/webcompat/experiment-apis/aboutConfigPrefs.json @@ -24,17 +24,17 @@ ], "functions": [ { - "name": "getBranch", + "name": "getCheckableGlobalPrefs", "type": "function", - "description": "Get all child prefs for a branch", - "parameters": [ - { - "name": "branchName", - "type": "string", - "description": "The branch name" + "description": "Lists the global prefs the addon may read", + "parameters": [], + "returns": { + "type": "array", + "description": "The list of pref names.", + "items": { + "type": "string" } - ], - "async": true + } }, { "name": "getPref", @@ -45,30 +45,22 @@ "name": "name", "type": "string", "description": "The preference name" - } - ], - "async": true - }, - { - "name": "getBoolPrefSync", - "type": "function", - "description": "Get a webcompat preference's boolean value synchronously", - "parameters": [ - { - "name": "name", - "type": "string", - "description": "The preference name" }, { "name": "defaultValue", "type": "boolean", "optional": true, - "description": "Default value to return if the pref is not set (defaults to false if omitted)" + "description": "Default value to return if the pref is not set" } ], "returns": { - "type": "boolean", - "description": "returns the value of a boolean pref." + "choices": [ + { "type": "boolean" }, + { "type": "integer" }, + { "type": "string" } + ], + "optional": true, + "description": "returns the value of a pref." } }, { @@ -86,8 +78,7 @@ "type": "any", "description": "The new value" } - ], - "async": true + ] } ] } diff --git a/browser/extensions/webcompat/experiment-apis/aboutConfigPrefsChild.js b/browser/extensions/webcompat/experiment-apis/aboutConfigPrefsChild.js @@ -4,24 +4,72 @@ "use strict"; -/* global ExtensionAPI, Services, XPCOMUtils */ +/* global ExtensionAPI, ExtensionCommon, Services */ + +this.aboutConfigPrefs = class AboutConfigPrefsChildAPI extends ExtensionAPI { + static ALLOWED_GLOBAL_PREFS = Object.freeze( + [ + "layout.css.prefixes.transforms", + "layout.css.webkit-fill-available.enabled", + "timer.auto_increase_timer_resolution", + ].concat( + Cu.isInAutomation ? ["webcompat.test.pref1", "webcompat.test.pref2"] : [] + ) + ); -this.aboutConfigPrefs = class extends ExtensionAPI { getAPI(context) { + const EventManager = ExtensionCommon.EventManager; const extensionIDBase = context.extension.id.split("@")[0]; const extensionPrefNameBase = `extensions.${extensionIDBase}.`; + function getSafePref(name) { + if (AboutConfigPrefsChildAPI.ALLOWED_GLOBAL_PREFS.includes(name)) { + return name; + } + return `${extensionPrefNameBase}${name}`; + } + return { aboutConfigPrefs: { - getBoolPrefSync(prefName, defaultValue = false) { + onPrefChange: new EventManager({ + context, + name: "aboutConfigPrefs.onUAOverridesPrefChange", + register: (fire, name) => { + const prefName = getSafePref(name); + const callback = () => { + fire.async(name).catch(() => {}); // ignore Message Manager disconnects + }; + Services.prefs.addObserver(prefName, callback); + return () => { + Services.prefs.removeObserver(prefName, callback); + }; + }, + }).api(), + getCheckableGlobalPrefs() { + return AboutConfigPrefsChildAPI.ALLOWED_GLOBAL_PREFS; + }, + getPref(_name, defaultValue) { + const name = getSafePref(_name); try { - return Services.prefs.getBoolPref( - `${extensionPrefNameBase}${prefName}`, - defaultValue - ); - } catch (_) { - return defaultValue; - } + switch (Services.prefs.getPrefType(name)) { + case Ci.nsIPrefBranch.PREF_BOOL: + return Services.prefs.getBoolPref( + name, + defaultValue ?? undefined + ); + case Ci.nsIPrefBranch.PREF_INT: + return Services.prefs.getIntPref( + name, + defaultValue ?? undefined + ); + case Ci.nsIPrefBranch.PREF_STRING: + return Services.prefs.getStringPref( + name, + defaultValue ?? undefined + ); + } + } catch (_) {} + return defaultValue ?? undefined; }, }, }; diff --git a/browser/extensions/webcompat/lib/intervention_helpers.js b/browser/extensions/webcompat/lib/intervention_helpers.js @@ -390,7 +390,7 @@ var InterventionHelpers = { async getOS() { const os = - (await browser.aboutConfigPrefs.getPref("platform_override")) ?? + browser.aboutConfigPrefs.getPref("platform_override") ?? (await browser.runtime.getPlatformInfo()).os; if (os === "win") { return "windows"; diff --git a/browser/extensions/webcompat/lib/interventions.js b/browser/extensions/webcompat/lib/interventions.js @@ -6,11 +6,11 @@ /* globals browser, InterventionHelpers */ -const debugLoggingPrefPromise = browser.aboutConfigPrefs.getPref( +const debugLoggingPrefValue = browser.aboutConfigPrefs.getPref( "disable_debug_logging" ); -let debugLog = async function () { - if ((await debugLoggingPrefPromise) !== true) { +let debugLog = function () { + if (debugLoggingPrefValue !== true) { console.debug.apply(this, arguments); } }; @@ -19,7 +19,7 @@ class Interventions { constructor(availableInterventions, customFunctions) { this._originalInterventions = availableInterventions; - this.INTERVENTION_PREF = "perform_injections"; + this.INTERVENTION_PREF = "enable_interventions"; this._interventionsEnabled = true; @@ -94,9 +94,7 @@ class Interventions { checkInterventionPref() { navigator.locks.request("pref_check_lock", async () => { - const value = await browser.aboutConfigPrefs.getPref( - this.INTERVENTION_PREF - ); + const value = browser.aboutConfigPrefs.getPref(this.INTERVENTION_PREF); if (value === undefined) { await browser.aboutConfigPrefs.setPref(this.INTERVENTION_PREF, true); } else if (value === false) { @@ -161,7 +159,7 @@ class Interventions { }); } - async _check_for_needed_prefs(intervention) { + _check_for_needed_prefs(intervention) { if (!intervention.pref_check) { return true; } @@ -169,14 +167,14 @@ class Interventions { if (!this.#checkedPrefListeners.has(pref)) { const listener = () => this.onCheckedPrefChanged(pref); this.#checkedPrefListeners.set(pref, listener); - await browser.aboutConfigPrefs.onPrefChange.addListener(listener, pref); + browser.aboutConfigPrefs.onPrefChange.addListener(listener, pref); } } for (const [pref, value] of Object.entries(intervention.pref_check ?? {})) { if (!this.#checkedPrefCache.has(pref)) { this.#checkedPrefCache.set( pref, - await browser.aboutConfigPrefs.getPref(pref) + browser.aboutConfigPrefs.getPref(pref) ); } if (value !== this.#checkedPrefCache.get(pref)) { @@ -214,9 +212,7 @@ class Interventions { config.DISABLING_PREF = `disabled_interventions.${config.id}`; const disabledPrefListener = () => { navigator.locks.request("pref_check_lock", async () => { - const value = await browser.aboutConfigPrefs.getPref( - config.DISABLING_PREF - ); + const value = browser.aboutConfigPrefs.getPref(config.DISABLING_PREF); if (value === true) { await this.disableIntervention(config); debugLog( @@ -240,21 +236,17 @@ class Interventions { config.DISABLING_PREF ); - const disablingPrefValue = browser.aboutConfigPrefs.getBoolPrefSync( + const disablingPrefValue = browser.aboutConfigPrefs.getPref( config.DISABLING_PREF ); for (const intervention of config.interventions) { intervention.enabled = false; - if (!(await this._check_for_needed_prefs(intervention))) { + if (!this._check_for_needed_prefs(intervention)) { continue; } if ( - await InterventionHelpers.shouldSkip( - intervention, - cleanVersion, - channel - ) + InterventionHelpers.shouldSkip(intervention, cleanVersion, channel) ) { continue; } diff --git a/browser/extensions/webcompat/lib/shims.js b/browser/extensions/webcompat/lib/shims.js @@ -12,7 +12,7 @@ // on tabs where a shim using a given logo happens to be active). const LogosBaseURL = "https://smartblock.firefox.etp/"; -const loggingPrefPromise = browser.aboutConfigPrefs.getPref( +const loggingPrefValue = browser.aboutConfigPrefs.getPref( "disable_debug_logging" ); @@ -24,7 +24,7 @@ const platformPromise = browser.runtime.getPlatformInfo().then(info => { let debug = async function () { if ( - (await loggingPrefPromise) !== true && + loggingPrefValue !== true && (await releaseBranchPromise) !== "release_or_beta" ) { console.debug.apply(this, arguments); @@ -69,8 +69,10 @@ class Shim { this.runFirst = opts.runFirst; this.unblocksOnOptIn = unblocksOnOptIn; this.requestStorageAccessForRedirect = opts.requestStorageAccessForRedirect; - this.shouldUseScriptingAPI = - browser.aboutConfigPrefs.getBoolPrefSync("useScriptingAPI"); + this.shouldUseScriptingAPI = browser.aboutConfigPrefs.getPref( + "useScriptingAPI", + false + ); this.isSmartblockEmbedShim = opts.isSmartblockEmbedShim || false; debug( `WebCompat Shim ${this.id} will be injected using ${ @@ -130,36 +132,33 @@ class Shim { } browser.aboutConfigPrefs.onPrefChange.addListener(async () => { - const value = await browser.aboutConfigPrefs.getPref(pref); + const value = browser.aboutConfigPrefs.getPref(pref); this._disabledPrefValue = value; this._onEnabledStateChanged({ alsoClearResourceCache: true }); }, pref); - this.ready = Promise.all([ - browser.aboutConfigPrefs.getPref(pref), - platformPromise, - releaseBranchPromise, - ]).then(([disabledPrefValue, platform, branch]) => { - this._disabledPrefValue = disabledPrefValue; - - this._disabledByPlatform = - this.platform !== "all" && this.platform !== platform; - - this._disabledByReleaseBranch = false; - for (const supportedBranchAndPlatform of this.branches || []) { - const [supportedBranch, supportedPlatform] = - supportedBranchAndPlatform.split(":"); - if ( - (!supportedPlatform || supportedPlatform == platform) && - supportedBranch != branch - ) { - this._disabledByReleaseBranch = true; + this._disabledPrefValue = browser.aboutConfigPrefs.getPref(pref); + this.ready = Promise.all([platformPromise, releaseBranchPromise]).then( + ([platform, branch]) => { + this._disabledByPlatform = + this.platform !== "all" && this.platform !== platform; + + this._disabledByReleaseBranch = false; + for (const supportedBranchAndPlatform of this.branches || []) { + const [supportedBranch, supportedPlatform] = + supportedBranchAndPlatform.split(":"); + if ( + (!supportedPlatform || supportedPlatform == platform) && + supportedBranch != branch + ) { + this._disabledByReleaseBranch = true; + } } - } - this._preprocessOptions(platform, branch); - this._onEnabledStateChanged(); - }); + this._preprocessOptions(platform, branch); + this._onEnabledStateChanged(); + } + ); } _preprocessOptions(platform, branch) { @@ -874,15 +873,14 @@ class Shims { } async _checkEnabledPref() { - await browser.aboutConfigPrefs.getPref(this.ENABLED_PREF).then(value => { - if (value === undefined) { - browser.aboutConfigPrefs.setPref(this.ENABLED_PREF, true); - } else if (value === false) { - this.enabled = false; - } else { - this.enabled = true; - } - }); + const value = browser.aboutConfigPrefs.getPref(this.ENABLED_PREF); + if (value === undefined) { + await browser.aboutConfigPrefs.setPref(this.ENABLED_PREF, true); + } else if (value === false) { + this.enabled = false; + } else { + this.enabled = true; + } } get enabled() { @@ -909,20 +907,19 @@ class Shims { } async _checkSmartblockEmbedsEnabledPref() { - await browser.aboutConfigPrefs - .getPref(this.SMARTBLOCK_EMBEDS_ENABLED_PREF) - .then(value => { - if (value === undefined) { - browser.aboutConfigPrefs.setPref( - this.SMARTBLOCK_EMBEDS_ENABLED_PREF, - true - ); - } else if (value === false) { - this.smartblockEmbedsEnabled = false; - } else { - this.smartblockEmbedsEnabled = true; - } - }); + const value = browser.aboutConfigPrefs.getPref( + this.SMARTBLOCK_EMBEDS_ENABLED_PREF + ); + if (value === undefined) { + await browser.aboutConfigPrefs.setPref( + this.SMARTBLOCK_EMBEDS_ENABLED_PREF, + true + ); + } else if (value === false) { + this.smartblockEmbedsEnabled = false; + } else { + this.smartblockEmbedsEnabled = true; + } } get smartblockEmbedsEnabled() { diff --git a/browser/extensions/webcompat/manifest.json b/browser/extensions/webcompat/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Web Compatibility Interventions", "description": "Urgent post-release fixes for web compatibility.", - "version": "147.3.0", + "version": "147.4.0", "browser_specific_settings": { "gecko": { "id": "webcompat@mozilla.org", diff --git a/browser/extensions/webcompat/tests/browser/browser_interventions.js b/browser/extensions/webcompat/tests/browser/browser_interventions.js @@ -63,7 +63,8 @@ function check_valid_array(a, key, id) { add_task(async function test_json_data() { const addon = await AddonManager.getAddonByID("webcompat@mozilla.org"); const addonURI = addon.getResourceURI(); - const checkableGlobalPrefs = WebCompatExtension.getCheckableGlobalPrefs(); + const checkableGlobalPrefs = + await WebCompatExtension.getCheckableGlobalPrefs(); const exports = {}; Services.scriptloader.loadSubScript( diff --git a/browser/extensions/webcompat/tests/browser/browser_pref_check.js b/browser/extensions/webcompat/tests/browser/browser_pref_check.js @@ -29,7 +29,8 @@ async function setupTestIntervention(interventions) { add_task(async function test_pref_check() { await WebCompatExtension.started(); - const checkableGlobalPrefs = WebCompatExtension.getCheckableGlobalPrefs(); + const checkableGlobalPrefs = + await WebCompatExtension.getCheckableGlobalPrefs(); ok( checkableGlobalPrefs.includes("webcompat.test.pref1"), "allowed to access pref webcompat.test.pref1" diff --git a/browser/extensions/webcompat/tests/browser/head.js b/browser/extensions/webcompat/tests/browser/head.js @@ -128,8 +128,9 @@ const WebCompatExtension = new (class WebCompatExtension { } getCheckableGlobalPrefs() { - return this.extension.experimentAPIManager.global.aboutConfigPrefs - .ALLOWED_GLOBAL_PREFS; + return this.#run(async function () { + return content.wrappedJSObject.browser.aboutConfigPrefs.getCheckableGlobalPrefs(); + }); } async updateShims(_shims) { @@ -492,4 +493,7 @@ async function generateTestShims() { unblocksOnOptIn: ["*://itisatracker.org/*"], }, ]); + registerCleanupFunction(async () => { + await WebCompatExtension.resetInterventionsAndShimsToDefaults(); + }); } diff --git a/testing/webcompat/fixtures.py b/testing/webcompat/fixtures.py @@ -23,13 +23,12 @@ except ImportError: CB_PBM_PREF = "network.cookie.cookieBehavior.pbmode" CB_PREF = "network.cookie.cookieBehavior" -INJECTIONS_PREF = "extensions.webcompat.perform_injections" +INTERVENTIONS_PREF = "extensions.webcompat.enable_interventions" NOTIFICATIONS_PERMISSIONS_PREF = "permissions.default.desktop-notification" PBM_PREF = "browser.privatebrowsing.autostart" PIP_OVERRIDES_PREF = "extensions.webcompat.enable_picture_in_picture_overrides" SHIMS_PREF = "extensions.webcompat.enable_shims" STRICT_ETP_PREF = "privacy.trackingprotection.enabled" -UA_OVERRIDES_PREF = "extensions.webcompat.perform_ua_overrides" SYSTEM_ADDON_UPDATES_PREF = "extensions.systemAddon.update.enabled" DOWNLOAD_TO_TEMP_PREF = "browser.download.start_downloads_in_tmp_dir" DELETE_DOWNLOADS_PREF = "browser.helperApps.deleteTempFileOnExit" @@ -89,8 +88,7 @@ class FirefoxWebDriver(WebDriver): if "use_interventions" in test_config: value = test_config["use_interventions"] - prefs[INJECTIONS_PREF] = value - prefs[UA_OVERRIDES_PREF] = value + prefs[INTERVENTIONS_PREF] = value prefs[PIP_OVERRIDES_PREF] = value if "use_pbm" in test_config: