commit 444d4fbc9d66c4ca3a42132958750224bbafa588
parent 8f2ec3f7c78314af60f32c9de59c83efda1df3e7
Author: Beth Rennie <beth@brennie.ca>
Date: Fri, 31 Oct 2025 03:39:49 +0000
Bug 1972647 - Don't hide Firefox Labs when studies or telemetry are disabled r=mkaply,akulyk
The UserMessaging:FirefoxLabs policy no longer has to set the
"browser.preferences.experimental" pref because whether or not the
Firefox Labs pane is registered is determined by the "FirefoxLabs"
policy feature.
Differential Revision: https://phabricator.services.mozilla.com/D269922
Diffstat:
8 files changed, 31 insertions(+), 212 deletions(-)
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
@@ -1354,8 +1354,6 @@ pref("accessibility.typeaheadfind.timeout", 5000);
pref("accessibility.typeaheadfind.linksonly", false);
pref("accessibility.typeaheadfind.flashBar", 1);
-// Whether we can show the "Firefox Labs" section.
-pref("browser.preferences.experimental", true);
// Whether we had to hide the "Firefox Labs" section because it would be empty.
pref("browser.preferences.experimental.hidden", false);
// Whether we show the "More from Mozilla" section.
diff --git a/browser/components/enterprisepolicies/Policies.sys.mjs b/browser/components/enterprisepolicies/Policies.sys.mjs
@@ -2923,16 +2923,8 @@ export var Policies = {
param.Locked
);
}
- if ("FirefoxLabs" in param) {
- if (!param.FirefoxLabs) {
- manager.disallowFeature("FirefoxLabs");
- }
-
- PoliciesUtils.setDefaultPref(
- "browser.preferences.experimental",
- param.FirefoxLabs,
- param.Locked
- );
+ if ("FirefoxLabs" in param && !param.FirefoxLabs) {
+ manager.disallowFeature("FirefoxLabs");
}
},
},
diff --git a/browser/components/preferences/experimental.js b/browser/components/preferences/experimental.js
@@ -26,7 +26,6 @@ const gExperimentalPane = {
this._onCheckboxChanged = this._onCheckboxChanged.bind(this);
this._onNimbusUpdate = this._onNimbusUpdate.bind(this);
- this._onStudiesEnabledChanged = this._onStudiesEnabledChanged.bind(this);
this._resetAllFeatures = this._resetAllFeatures.bind(this);
setEventListener(
@@ -35,10 +34,6 @@ const gExperimentalPane = {
this._resetAllFeatures
);
- Services.obs.addObserver(
- this._onStudiesEnabledChanged,
- ExperimentAPI.STUDIES_ENABLED_CHANGED
- );
window.addEventListener("unload", () => this._removeObservers());
await this._maybeRenderLabsRecipes();
@@ -169,24 +164,8 @@ const gExperimentalPane = {
}
},
- async _onStudiesEnabledChanged() {
- const studiesEnabled = ExperimentAPI.studiesEnabled;
-
- if (studiesEnabled) {
- await this._maybeRenderLabsRecipes();
- } else {
- this._setCategoryVisibility(true);
- this._removeLabsRecipes();
- this._firefoxLabs = null;
- }
- },
-
_removeObservers() {
ExperimentAPI.manager.store.off("update", this._onNimbusUpdate);
- Services.obs.removeObserver(
- this._onStudiesEnabledChanged,
- ExperimentAPI.STUDIES_ENABLED_CHANGED
- );
},
// Reset the features to their default values
diff --git a/browser/components/preferences/preferences.js b/browser/components/preferences/preferences.js
@@ -81,6 +81,7 @@ ChromeUtils.defineESModuleGetters(this, {
ContextualIdentityService:
"resource://gre/modules/ContextualIdentityService.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
+ ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
ExtensionPreferencesManager:
"resource://gre/modules/ExtensionPreferencesManager.sys.mjs",
ExtensionSettingsStore:
@@ -242,16 +243,17 @@ function init_all() {
if (Services.prefs.getBoolPref("browser.translations.newSettingsUI.enable")) {
register_module("paneTranslations", gTranslationsPane);
}
- if (Services.prefs.getBoolPref("browser.preferences.experimental")) {
+ if (ExperimentAPI.labsEnabled) {
// Set hidden based on previous load's hidden value or if Nimbus is
// disabled.
document.getElementById("category-experimental").hidden =
- !ExperimentAPI.studiesEnabled ||
Services.prefs.getBoolPref(
"browser.preferences.experimental.hidden",
false
);
register_module("paneExperimental", gExperimentalPane);
+ } else {
+ document.getElementById("category-experimental").hidden = true;
}
NimbusFeatures.moreFromMozilla.recordExposureEvent({ once: true });
diff --git a/browser/components/preferences/tests/browser_experimental_features.js b/browser/components/preferences/tests/browser_experimental_features.js
@@ -8,23 +8,6 @@ add_setup(async function setup() {
registerCleanupFunction(cleanup);
});
-add_task(async function testPrefRequired() {
- await SpecialPowers.pushPrefEnv({
- set: [["browser.preferences.experimental", false]],
- });
-
- await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true });
- let doc = gBrowser.contentDocument;
-
- let experimentalCategory = doc.getElementById("category-experimental");
- ok(experimentalCategory, "The category exists");
- ok(experimentalCategory.hidden, "The category is hidden");
-
- BrowserTestUtils.removeTab(gBrowser.selectedTab);
-
- await SpecialPowers.popPrefEnv();
-});
-
add_task(async function testCanOpenWithPref() {
await SpecialPowers.pushPrefEnv({
set: [["browser.preferences.experimental", true]],
@@ -58,10 +41,6 @@ add_task(async function testCanOpenWithPref() {
});
add_task(async function testSearchFindsExperiments() {
- await SpecialPowers.pushPrefEnv({
- set: [["browser.preferences.experimental", true]],
- });
-
await openPreferencesViaOpenPreferencesAPI("paneHome", { leaveOpen: true });
let doc = gBrowser.contentDocument;
@@ -80,6 +59,4 @@ add_task(async function testSearchFindsExperiments() {
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
-
- await SpecialPowers.popPrefEnv();
});
diff --git a/browser/components/preferences/tests/browser_experimental_features_filter.js b/browser/components/preferences/tests/browser_experimental_features_filter.js
@@ -36,10 +36,6 @@ add_task(async function testFilterFeatures() {
];
const cleanup = await setupLabsTest(recipes);
- await SpecialPowers.pushPrefEnv({
- set: [["browser.preferences.experimental", true]],
- });
-
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:preferences#paneExperimental"
diff --git a/browser/components/preferences/tests/browser_experimental_features_hidden_when_not_public.js b/browser/components/preferences/tests/browser_experimental_features_hidden_when_not_public.js
@@ -6,10 +6,6 @@
add_task(async function testNonPublicFeaturesShouldntGetDisplayed() {
const cleanup = await setupLabsTest();
- await SpecialPowers.pushPrefEnv({
- set: [["browser.preferences.experimental", true]],
- });
-
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:preferences#paneExperimental"
@@ -42,7 +38,6 @@ add_task(async function testNonPublicFeaturesShouldntGetDisplayed() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
await cleanup();
- await SpecialPowers.popPrefEnv();
});
add_task(async function testNonPublicFeaturesShouldntGetDisplayed() {
@@ -50,10 +45,7 @@ add_task(async function testNonPublicFeaturesShouldntGetDisplayed() {
const cleanup = await setupLabsTest(DEFAULT_LABS_RECIPES.slice(2));
await SpecialPowers.pushPrefEnv({
- set: [
- ["browser.preferences.experimental", true],
- ["browser.preferences.experimental.hidden", false],
- ],
+ set: [["browser.preferences.experimental.hidden", false]],
});
await BrowserTestUtils.openNewForegroundTab(
diff --git a/browser/components/preferences/tests/browser_experimental_features_studies_disabled.js b/browser/components/preferences/tests/browser_experimental_features_studies_disabled.js
@@ -3,13 +3,20 @@
"use strict";
-add_task(async function testHiddenWhenStudiesDisabled() {
+const { EnterprisePolicyTesting } = ChromeUtils.importESModule(
+ "resource://testing-common/EnterprisePolicyTesting.sys.mjs"
+);
+
+add_task(async function testHiddenWhenLabsDisabled() {
const cleanup = await setupLabsTest();
await SpecialPowers.pushPrefEnv({
- set: [
- ["browser.preferences.experimental", true],
- ["browser.preferences.experimental.hidden", false],
- ],
+ set: [["browser.preferences.experimental.hidden", false]],
+ });
+
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson({
+ policies: {
+ UserMessaging: { FirefoxLabs: false },
+ },
});
await BrowserTestUtils.openNewForegroundTab(
@@ -19,151 +26,27 @@ add_task(async function testHiddenWhenStudiesDisabled() {
const doc = gBrowser.contentDocument;
- await waitForExperimentalFeaturesShown(doc);
-
- const enrollPromises = [
- promiseNimbusStoreUpdate("nimbus-qa-1", true),
- promiseNimbusStoreUpdate("nimbus-qa-2", true),
- ];
-
- await enrollByClick(doc.getElementById("nimbus-qa-1"), true);
- await enrollByClick(doc.getElementById("nimbus-qa-2"), true);
-
- await enrollPromises;
-
- const unenrollPromises = [
- promiseNimbusStoreUpdate("nimbus-qa-1", false),
- promiseNimbusStoreUpdate("nimbus-qa-2", false),
- ];
-
- // Disabling studies should remove the experimental pane.
- await SpecialPowers.pushPrefEnv({
- set: [["app.shield.optoutstudies.enabled", false]],
- });
-
- await waitForExperimentalFeaturesHidden(doc);
- await unenrollPromises;
-
- ok(
- !ExperimentAPI._manager.store.get("nimbus-qa-1")?.active,
- "Should unenroll from nimbus-qa-1"
- );
- ok(
- !ExperimentAPI._manager.store.get("nimbus-qa-2")?.active,
- "Should unenroll from nimbus-qa-2"
+ await TestUtils.waitForCondition(
+ () => doc.getElementById("category-experimental").hidden,
+ "Wait for Experimental Features section label to become hidden"
);
- // Re-enabling studies should re-add it.
- await SpecialPowers.popPrefEnv();
- await waitForExperimentalFeaturesShown(doc);
-
- // Navigate back to the experimental tab.
- EventUtils.synthesizeMouseAtCenter(
- doc.getElementById("category-experimental"),
- {},
- gBrowser.contentWindow
+ is(
+ doc.getElementById("pane-experimental-featureGates"),
+ null,
+ "Experimental Features section not added to the DOM"
);
- await waitForPageFlush();
-
is(
doc.querySelector(".category[selected]").id,
- "category-experimental",
- "Experimental category selected"
- );
-
- ok(
- !doc.getElementById("nimbus-qa-1").checked,
- "nimbus-qa-1 checkbox unchecked"
- );
- ok(
- !doc.getElementById("nimbus-qa-2").checked,
- "nimbus-qa-2 checkbox unchecked"
- );
-
- await enrollByClick(doc.getElementById("nimbus-qa-1"), true);
- await enrollByClick(doc.getElementById("nimbus-qa-2"), true);
-
- // Likewise, disabling telemetry should remove the experimental pane.
- await SpecialPowers.pushPrefEnv({
- set: [["datareporting.healthreport.uploadEnabled", false]],
- });
-
- await waitForExperimentalFeaturesHidden(doc);
-
- ok(
- !ExperimentAPI._manager.store.get("nimbus-qa-1")?.active,
- "Should unenroll from nimbus-qa-1"
- );
- ok(
- !ExperimentAPI._manager.store.get("nimbus-qa-2")?.active,
- "Should unenroll from nimbus-qa-2"
- );
-
- await SpecialPowers.popPrefEnv();
-
- // Re-enabling studies should re-add it.
- await waitForExperimentalFeaturesShown(doc);
-
- ok(
- !doc.getElementById("nimbus-qa-1").checked,
- "nimbus-qa-1 checkbox unchecked"
- );
- ok(
- !doc.getElementById("nimbus-qa-2").checked,
- "nimbus-qa-2 checkbox unchecked"
+ "category-general",
+ "When the experimental features section is hidden, navigating to #experimental should redirect to #general"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
- await cleanup();
await SpecialPowers.popPrefEnv();
-});
-
-async function waitForExperimentalFeaturesShown(doc) {
- await TestUtils.waitForCondition(
- () => doc.querySelector(".featureGate"),
- "Wait for features to be added to the DOM"
- );
-
- ok(
- !doc.getElementById("category-experimental").hidden,
- "Experimental Features section should not be hidden"
- );
-
- ok(
- !Services.prefs.getBoolPref("browser.preferences.experimental.hidden"),
- "Hidden pref should be false"
- );
-}
-
-async function waitForExperimentalFeaturesHidden(doc) {
- await TestUtils.waitForCondition(
- () => doc.getElementById("category-experimental").hidden,
- "Wait for Experimental Features section to get hidden"
- );
-
- ok(
- doc.getElementById("category-experimental").hidden,
- "Experimental Features section should be hidden when all features are hidden"
- );
- ok(
- doc.getElementById("firefoxExperimentalCategory").hidden,
- "Experimental Features header should be hidden when all features are hidden"
- );
- is(
- doc.querySelector(".category[selected]").id,
- "category-general",
- "When the experimental features section is hidden, navigating to #experimental should redirect to #general"
- );
- ok(
- Services.prefs.getBoolPref("browser.preferences.experimental.hidden"),
- "Hidden pref should be true"
- );
-}
+ await cleanup();
-function waitForPageFlush() {
- return new Promise(resolve =>
- requestAnimationFrame(() => requestAnimationFrame(resolve))
- );
-}
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson({});
+});