tor-browser

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

commit 8f71edffd04897bc2a673d04e7c48b7c74f32633
parent a3c91c5ecb3c912b503aa5b968883e276f62e124
Author: Beth Rennie <beth@brennie.ca>
Date:   Fri, 31 Oct 2025 03:39:48 +0000

Bug 1972647 - Hide Firefox Labs opt-ins from about:studies r=nimbus-reviewers,relud

We do not want users to confuse these opt-ins with regular studies,
especially when studies are disabled, as that may lead them to believe
that we are running studies without their consent.

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

Diffstat:
Mtoolkit/components/normandy/content/AboutPages.sys.mjs | 8++++++--
Mtoolkit/components/normandy/test/browser/browser_about_studies.js | 54+++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/toolkit/components/normandy/content/AboutPages.sys.mjs b/toolkit/components/normandy/content/AboutPages.sys.mjs @@ -101,7 +101,11 @@ ChromeUtils.defineLazyGetter(AboutPages, "aboutStudies", () => { }, getMessagingSystemList() { - return lazy.ExperimentAPI.manager.store.getAll(); + // Do not include Firefox Labs. Those are shown on + // about:preferences#experimental. + return lazy.ExperimentAPI.manager.store + .getAll() + .filter(e => !e.isFirefoxLabsOptIn); }, async optInToExperiment(data) { @@ -220,7 +224,7 @@ ChromeUtils.defineLazyGetter(AboutPages, "aboutStudies", () => { ); this._sendToAll( "Shield:UpdateMessagingSystemExperimentList", - lazy.ExperimentAPI.manager.store.getAll() + this.getMessagingSystemList() ); }, diff --git a/toolkit/components/normandy/test/browser/browser_about_studies.js b/toolkit/components/normandy/test/browser/browser_about_studies.js @@ -12,8 +12,8 @@ const { NimbusTestUtils } = ChromeUtils.importESModule( const { ExperimentAPI } = ChromeUtils.importESModule( "resource://nimbus/ExperimentAPI.sys.mjs" ); -const { RemoteSettingsExperimentLoader } = ChromeUtils.importESModule( - "resource://nimbus/lib/RemoteSettingsExperimentLoader.sys.mjs" +const { FirefoxLabs } = ChromeUtils.importESModule( + "resource://nimbus/FirefoxLabs.sys.mjs" ); const { NormandyTestUtils } = ChromeUtils.importESModule( @@ -866,7 +866,7 @@ add_task(async function test_forceEnroll() { } ); - NimbusTestUtils.assert.storeIsEmpty(ExperimentAPI.manager.store); + await NimbusTestUtils.assert.storeIsEmpty(ExperimentAPI.manager.store); sandbox.restore(); }); @@ -956,3 +956,51 @@ add_task(async function test_inactive_rollouts_under_completed_studies() { // Cleanup for multiple test runs await NimbusTestUtils.assert.storeIsEmpty(ExperimentAPI.manager.store); }); + +add_task(async function testFirefoxLabs() { + const study = NimbusTestUtils.factories.recipe("study"); + await ExperimentAPI.manager.enroll(study, "rs-loader"); + + const optin = NimbusTestUtils.factories.recipe("optin", { + isRollout: true, + isFirefoxLabsOptIn: true, + firefoxLabsTitle: "title", + firefoxLabsDescription: "description", + firefoxLabsGroup: "group", + requiresRestart: false, + }); + + ExperimentAPI.manager.optInRecipes.push(optin); + + const labs = await FirefoxLabs.create(); + await labs.enroll("optin", "control"); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: "about:studies" }, + async browser => { + const nimbusItems = await SpecialPowers.spawn(browser, [], async () => { + await ContentTaskUtils.waitForCondition( + () => content.document.querySelector(".nimbus .remove-button"), + "waiting for page to load" + ); + + return Array.from( + content.document.querySelectorAll(".nimbus"), + el => el.dataset.studySlug + ); + }); + + Assert.deepEqual( + nimbusItems, + ["study"], + "Firefox Labs opt-in not present" + ); + } + ); + + await labs.unenroll("optin", "control"); + await ExperimentAPI.manager.unenroll("study"); + ExperimentAPI.manager.optInRecipes.pop(); + + await NimbusTestUtils.assert.storeIsEmpty(ExperimentAPI.manager.store); +});