commit 36eb24d7e02783511c18ebd19d19c6d094521423
parent 4df8da901efb8a95c23fd95e8cd5430b6ff35605
Author: Thomas Wisniewski <twisniewski@mozilla.com>
Date: Tue, 18 Nov 2025 19:48:20 +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:
11 files changed, 149 insertions(+), 178 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,14 @@
],
"functions": [
{
- "name": "getBranch",
+ "name": "getCheckableGlobalPrefs",
"type": "function",
- "description": "Get all child prefs for a branch",
- "parameters": [
- {
- "name": "branchName",
- "type": "string",
- "description": "The branch name"
- }
- ],
- "async": true
+ "description": "Lists the global prefs the addon may read",
+ "parameters": [],
+ "returns": {
+ "type": "array",
+ "description": "the list of pref names."
+ }
},
{
"name": "getPref",
@@ -45,30 +42,17 @@
"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."
+ "type": "object",
+ "description": "returns the value of a pref."
}
},
{
@@ -86,8 +70,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: