tor-browser

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

commit aa9c92eedbe334df8d86938519849ff4063538bd
parent 7bbf79f1dd69a559d47fe0a64e423b2e4d61e4bd
Author: Beth Rennie <beth@brennie.ca>
Date:   Fri,  9 Jan 2026 21:10:30 +0000

Bug 2003365 - Add EnterprisePolicy to disable rollouts r=mkaply,nimbus-reviewers,fluent-reviewers,relud,flod

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

Diffstat:
Mbrowser/components/enterprisepolicies/Policies.sys.mjs | 8++++++++
Mbrowser/components/enterprisepolicies/schemas/policies-schema.json | 4++++
Mbrowser/locales/en-US/browser/policies/policies-descriptions.ftl | 2++
Mtoolkit/components/nimbus/ExperimentAPI.sys.mjs | 5++++-
Mtoolkit/components/nimbus/test/unit/test_policy.js | 41++++++++++++++++++++++++++++++++---------
5 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/browser/components/enterprisepolicies/Policies.sys.mjs b/browser/components/enterprisepolicies/Policies.sys.mjs @@ -996,6 +996,14 @@ export var Policies = { }, }, + DisableRemoteImprovements: { + onBeforeAddons(manager, param) { + if (param) { + manager.disallowFeature("NimbusRollouts"); + } + }, + }, + DisableForgetButton: { onProfileAfterChange(manager, param) { if (param) { diff --git a/browser/components/enterprisepolicies/schemas/policies-schema.json b/browser/components/enterprisepolicies/schemas/policies-schema.json @@ -559,6 +559,10 @@ "type": "boolean" }, + "DisableRemoteImprovements": { + "type": "boolean" + }, + "DisableSafeMode": { "type": "boolean" }, diff --git a/browser/locales/en-US/browser/policies/policies-descriptions.ftl b/browser/locales/en-US/browser/policies/policies-descriptions.ftl @@ -94,6 +94,8 @@ policy-DisableProfileImport = Disable the menu command to Import data from anoth policy-DisableProfileRefresh = Disable the Refresh { -brand-short-name } button in the about:support page. +policy-DisableRemoteImprovements = Prevent { -brand-short-name } from applying performance, stability, and feature changes between updates. + policy-DisableSafeMode = Disable the feature to restart in Safe Mode. Note: the Shift key to enter Safe Mode can only be disabled on Windows using Group Policy. policy-DisableSecurityBypass = Prevent the user from bypassing certain security warnings. diff --git a/toolkit/components/nimbus/ExperimentAPI.sys.mjs b/toolkit/components/nimbus/ExperimentAPI.sys.mjs @@ -424,7 +424,10 @@ export const ExperimentAPI = new (class { } get rolloutsEnabled() { - return this.#prefValues.rolloutsEnabled; + return ( + this.#prefValues.rolloutsEnabled && + Services.policies.isAllowed("NimbusRollouts") + ); } get studiesEnabled() { diff --git a/toolkit/components/nimbus/test/unit/test_policy.js b/toolkit/components/nimbus/test/unit/test_policy.js @@ -39,6 +39,7 @@ add_setup(function setup() { async function doTest({ policies, labsEnabled, + rolloutsEnabled, studiesEnabled, existingEnrollments = [], expectedEnrollments, @@ -75,31 +76,36 @@ async function doTest({ await initExperimentAPI(); Assert.equal( - ExperimentAPI.studiesEnabled, - studiesEnabled, - "Studies are enabled" - ); - Assert.equal( ExperimentAPI.labsEnabled, labsEnabled, "FirefoxLabs is enabled" ); + Assert.equal( + ExperimentAPI.rolloutsEnabled, + rolloutsEnabled, + "Rollouts are enabled" + ); + Assert.equal( + ExperimentAPI.studiesEnabled, + studiesEnabled, + "Studies are enabled" + ); Assert.equal( loader._enabled, - studiesEnabled || labsEnabled, + labsEnabled || rolloutsEnabled || studiesEnabled, "RemoteSettingsExperimentLoader initialized" ); Assert.equal( loader.setTimer.called, - studiesEnabled || labsEnabled, + labsEnabled || rolloutsEnabled || studiesEnabled, "RemoteSettingsExperimentLoader polling for recipes" ); Assert.equal( loader.updateRecipes.called, - studiesEnabled || labsEnabled, + labsEnabled || rolloutsEnabled || studiesEnabled, "RemoteSettingsExperimentLoader polling for recipes" ); @@ -127,8 +133,9 @@ add_task(async function testDisableStudiesPolicy() { await doTest({ policies: { DisableFirefoxStudies: true }, labsEnabled: true, + rolloutsEnabled: true, studiesEnabled: false, - expectedEnrollments: [], + expectedEnrollments: ["rollout"], expectedOptIns: ["optin"], }); }); @@ -137,6 +144,7 @@ add_task(async function testDisableLabsPolicy() { await doTest({ policies: { UserMessaging: { FirefoxLabs: false } }, labsEnabled: false, + rolloutsEnabled: true, studiesEnabled: true, expectedEnrollments: ["experiment", "rollout"], expectedOptIns: [], @@ -146,10 +154,12 @@ add_task(async function testDisableLabsPolicy() { add_task(async function testNimbusDisabled() { await doTest({ policies: { + DisableRemoteImprovements: true, DisableFirefoxStudies: true, UserMessaging: { FirefoxLabs: false }, }, labsEnabled: false, + rolloutsEnabled: false, studiesEnabled: false, expectedEnrollments: [], expectedOptIns: [], @@ -160,9 +170,22 @@ add_task(async function testDisableLabsPolicyCausesUnenrollments() { await doTest({ policies: { UserMessaging: { FirefoxLabs: false } }, labsEnabled: false, + rolloutsEnabled: true, studiesEnabled: true, expectedEnrollments: ["experiment", "rollout"], existingEnrollments: ["optin"], expectedOptIns: [], }); }); + +add_task(async function testDisableRolloutPolicyCausesUnenrollments() { + await doTest({ + policies: { DisableRemoteImprovements: true }, + labsEnabled: true, + rolloutsEnabled: false, + studiesEnabled: true, + expectedEnrollments: ["experiment"], + existingEnrollments: ["rollout"], + expectedOptIns: ["optin"], + }); +});