commit 17f1b13b340513313b090ad6c0e2db308ea281fe
parent da0861d6f7f7280518d2a4511d07401aecf50afa
Author: Thomas Wisniewski <twisniewski@mozilla.com>
Date: Mon, 27 Oct 2025 17:52:23 +0000
Bug 1996037 - Add the ability to disable webcompat interventions by default in the JSON config, while still being togglable in about:compat; r=denschub,webcompat-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D269776
Diffstat:
5 files changed, 116 insertions(+), 15 deletions(-)
diff --git a/browser/extensions/webcompat/lib/about_compat_broker.js b/browser/extensions/webcompat/lib/about_compat_broker.js
@@ -84,7 +84,7 @@ class AboutCompatBroker {
if (active) {
await this._interventions?.disableIntervention(what);
} else {
- await this._interventions?.enableIntervention(what);
+ await this._interventions?.enableIntervention(what, true);
}
break;
}
diff --git a/browser/extensions/webcompat/lib/interventions.js b/browser/extensions/webcompat/lib/interventions.js
@@ -219,9 +219,6 @@ class Interventions {
) {
continue;
}
- if (!(await InterventionHelpers.checkPlatformMatches(intervention))) {
- continue;
- }
if (
InterventionHelpers.isMissingCustomFunctions(
intervention,
@@ -230,6 +227,17 @@ class Interventions {
) {
continue;
}
+ if (!(await InterventionHelpers.checkPlatformMatches(intervention))) {
+ // special case: allow platforms=[] to indicate "disabled by default"
+ if (
+ intervention.platforms &&
+ !intervention.platforms.length &&
+ !intervention.not_platforms
+ ) {
+ config.availableOnPlatform = true;
+ }
+ continue;
+ }
intervention.enabled = true;
config.availableOnPlatform = true;
}
@@ -264,9 +272,9 @@ class Interventions {
resolveReady();
}
- async enableIntervention(config) {
+ async enableIntervention(config, force = false) {
return navigator.locks.request("intervention_lock", async () => {
- await this._enableInterventionNow(config);
+ await this._enableInterventionNow(config, force);
});
}
@@ -276,7 +284,7 @@ class Interventions {
});
}
- async _enableInterventionNow(config) {
+ async _enableInterventionNow(config, force = false) {
if (config.active) {
return;
}
@@ -291,8 +299,9 @@ class Interventions {
.flat()
.filter(v => v !== undefined);
+ let somethingWasEnabled = false;
for (const intervention of config.interventions) {
- if (!intervention.enabled) {
+ if (!intervention.enabled && !force) {
continue;
}
@@ -307,6 +316,8 @@ class Interventions {
}
await this._enableUAOverrides(label, intervention, matches);
await this._enableRequestBlocks(label, intervention, blocks);
+ somethingWasEnabled = true;
+ intervention.enabled = true;
}
if (!this._getActiveInterventionById(config.id)) {
@@ -325,7 +336,7 @@ class Interventions {
}
}
- config.active = true;
+ config.active = somethingWasEnabled;
}
async _disableInterventionNow(_config) {
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": "146.4.0",
+ "version": "146.5.0",
"browser_specific_settings": {
"gecko": {
"id": "webcompat@mozilla.org",
diff --git a/browser/extensions/webcompat/tests/browser/browser_intervention_gating.js b/browser/extensions/webcompat/tests/browser/browser_intervention_gating.js
@@ -157,3 +157,96 @@ add_task(async function test_min_max_versions() {
await WebCompatExtension.disableInterventions(["test2"]);
await WebCompatExtension.overrideFirefoxVersion();
});
+
+add_task(async function test_disabling_by_default() {
+ // platforms=[] means disabled by default
+ const config3 = getConfig("test3", [
+ {
+ platforms: [],
+ js: ["lib/run.js"],
+ },
+ ]);
+ // also check that other criteria not matching still disables completely
+ const config4 = getConfig("test4", [
+ {
+ platforms: [],
+ not_platforms: ["android", "desktop"],
+ js: ["lib/shims.js"],
+ },
+ ]);
+ const configs = await WebCompatExtension.updateInterventions([
+ config3,
+ config4,
+ ]);
+ Assert.deepEqual(
+ configs.map(c => c.active),
+ [false, false],
+ "The correct interventions were activated on startup"
+ );
+ Assert.deepEqual(
+ configs.map(c => c.interventions.map(i => i.enabled)),
+ [[false], [false]],
+ "The interventions were not enabled by default"
+ );
+ const reg = await WebCompatExtension.getRegisteredContentScriptsFor(["test"]);
+ Assert.deepEqual(
+ reg.map(r => r.js).flat(),
+ [],
+ "Content scripts were not registered"
+ );
+
+ const tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: "about:compat",
+ waitForLoad: true,
+ });
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ is(
+ content.origin,
+ "moz-extension://9a310967-e580-48bf-b3e8-4eafebbc122d",
+ "Expected origin of about:compat"
+ );
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ content.document.querySelector(
+ "#interventions tr[data-id=test3] [data-l10n-id=label-enable]"
+ ),
+ "test3 is correctly shown"
+ );
+ ok(
+ !content.document.querySelector("#interventions tr[data-id=test4]"),
+ "test4 is correctly hidden"
+ );
+
+ // click enable, confirm it is enabled
+ content.document
+ .querySelector(
+ "#interventions tr[data-id=test3] [data-l10n-id=label-enable]"
+ )
+ .click();
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ content.document.querySelector(
+ "#interventions tr[data-id=test3] [data-l10n-id=label-disable]"
+ ),
+ "test3 is correctly enabled on click"
+ );
+
+ // now click disable, confirm it is disabled
+ content.document
+ .querySelector(
+ "#interventions tr[data-id=test3] [data-l10n-id=label-disable]"
+ )
+ .click();
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ content.document.querySelector(
+ "#interventions tr[data-id=test3] [data-l10n-id=label-enable]"
+ ),
+ "test3 is correctly disabled again on second click"
+ );
+ });
+ await BrowserTestUtils.removeTab(tab);
+
+ await WebCompatExtension.disableInterventions(["test3", "test4"]);
+});
diff --git a/browser/extensions/webcompat/tests/browser/browser_interventions.js b/browser/extensions/webcompat/tests/browser/browser_interventions.js
@@ -54,11 +54,8 @@ function check_valid_array(a, key, id) {
if (a === undefined) {
return false;
}
- const valid = Array.isArray(a) && a.length;
- ok(
- valid,
- `if defined, ${key} is an array with at least one element for id ${id}`
- );
+ const valid = Array.isArray(a);
+ ok(valid, `if defined, ${key} is an array for id ${id}`);
return valid;
}