commit 83efe0f93a603c95bf8cfa50e1736a8ed9ed71f5
parent 48a3edbf20b487fb49c6236d0e5f969390d95840
Author: Chris DuPuis <cdupuis@mozilla.com>
Date: Fri, 21 Nov 2025 22:23:55 +0000
Bug 1997657 - part 2: changes in handling nimbus killswitches r=hsohaney,nrishel
Previously, our implementation of the handling for Nimbus flags
"archiveKillswitch" and "restoreKillswitch" would only have an
effect if the values were set to "true".
Now, in order to support both phased rollout and turning off the
feature, there are three possible states for these flags:
true: feature is turned off (killed)
undefined: feature is turned off (not rolled out)
false: feature is turned on
Differential Revision: https://phabricator.services.mozilla.com/D273526
Diffstat:
3 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs
@@ -637,7 +637,17 @@ export class BackupService extends EventTarget {
// Check if disabled by Nimbus killswitch.
const archiveKillswitchTriggered =
lazy.NimbusFeatures.backupService.getVariable("archiveKillswitch");
- if (archiveKillswitchTriggered) {
+ const archiveOverrideEnabled = Services.prefs.getBoolPref(
+ BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
+ // This is explicitly checking for archiveKillswitchTriggered !== false because
+ // we now also (potentially) want to use this nimbus setting for doing staged rollout
+ // of the feature. What this means is that if the value is:
+ // - true: feature is turned off ("killed")
+ // - undefined: feature is turned off (not launched yet)
+ // - false: feature is turned on
+ if (archiveKillswitchTriggered !== false && !archiveOverrideEnabled) {
return {
enabled: false,
reason: "Archiving a profile disabled remotely.",
@@ -705,7 +715,17 @@ export class BackupService extends EventTarget {
// Check if disabled by Nimbus killswitch.
const restoreKillswitchTriggered =
lazy.NimbusFeatures.backupService.getVariable("restoreKillswitch");
- if (restoreKillswitchTriggered) {
+ const restoreOverrideEnabled = Services.prefs.getBoolPref(
+ BACKUP_RESTORE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
+ // This is explicitly checking for restoreKillswitchTriggered !== false because
+ // we now also (potentially) want to use this nimbus setting for doing staged rollout
+ // of the feature. What this means is that if the value is:
+ // - true: feature is turned off ("killed")
+ // - undefined: feature is turned off (not launched yet)
+ // - false: feature is turned on
+ if (restoreKillswitchTriggered !== false && !restoreOverrideEnabled) {
return {
enabled: false,
reason: "Restore from backup disabled remotely.",
diff --git a/browser/components/backup/tests/xpcshell/test_BackupService_enabled.js b/browser/components/backup/tests/xpcshell/test_BackupService_enabled.js
@@ -15,6 +15,8 @@ const BACKUP_ARCHIVE_ENABLED_PREF_NAME = "browser.backup.archive.enabled";
const BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME =
"browser.backup.archive.overridePlatformCheck";
const BACKUP_RESTORE_ENABLED_PREF_NAME = "browser.backup.restore.enabled";
+const BACKUP_RESTORE_ENABLED_OVERRIDE_PREF_NAME =
+ "browser.backup.restore.overridePlatformCheck";
const SANITIZE_ON_SHUTDOWN_PREF_NAME = "privacy.sanitize.sanitizeOnShutdown";
const SELECTABLE_PROFILES_CREATED_PREF_NAME = "browser.profiles.created";
@@ -49,15 +51,27 @@ add_setup(async () => {
add_task(async function test_archive_killswitch_enrollment() {
let cleanupExperiment;
+ const savedPref = Services.prefs.getBoolPref(
+ BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
await archiveTemplate({
internalReason: "nimbus",
async disable() {
+ Services.prefs.setBoolPref(
+ BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
cleanupExperiment = await NimbusTestUtils.enrollWithFeatureConfig({
featureId: "backupService",
value: { archiveKillswitch: true },
});
},
async enable() {
+ Services.prefs.setBoolPref(
+ BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
+ savedPref
+ );
await cleanupExperiment();
},
// Nimbus calls onUpdate if any experiments are running, meaning that the
@@ -135,6 +149,11 @@ add_task(async function test_archive_disabled_unsupported_os() {
);
Services.prefs.setBoolPref(BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME, false);
sandbox.stub(BackupService, "checkOsSupportsBackup").returns(false);
+ const cleanupExperiment = await NimbusTestUtils.enrollWithFeatureConfig({
+ featureId: "backupService",
+ value: { archiveKillswitch: false },
+ });
+
try {
const bs = new BackupService();
const status = bs.archiveEnabledStatus;
@@ -146,6 +165,7 @@ add_task(async function test_archive_disabled_unsupported_os() {
BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
archiveWasEnabled
);
+ await cleanupExperiment();
}
});
@@ -157,6 +177,10 @@ add_task(async function test_archive_enabled_supported_os() {
);
Services.prefs.setBoolPref(BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME, false);
sandbox.stub(BackupService, "checkOsSupportsBackup").returns(true);
+ const cleanupExperiment = await NimbusTestUtils.enrollWithFeatureConfig({
+ featureId: "backupService",
+ value: { archiveKillswitch: false },
+ });
try {
const bs = new BackupService();
const status = bs.archiveEnabledStatus;
@@ -167,20 +191,33 @@ add_task(async function test_archive_enabled_supported_os() {
BACKUP_ARCHIVE_ENABLED_OVERRIDE_PREF_NAME,
archiveWasEnabled
);
+ await cleanupExperiment();
}
});
add_task(async function test_restore_killswitch_enrollment() {
let cleanupExperiment;
+ const savedPref = Services.prefs.getBoolPref(
+ BACKUP_RESTORE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
await restoreTemplate({
internalReason: "nimbus",
async disable() {
+ Services.prefs.setBoolPref(
+ BACKUP_RESTORE_ENABLED_OVERRIDE_PREF_NAME,
+ false
+ );
cleanupExperiment = await NimbusTestUtils.enrollWithFeatureConfig({
featureId: "backupService",
value: { restoreKillswitch: true },
});
},
async enable() {
+ Services.prefs.setBoolPref(
+ BACKUP_RESTORE_ENABLED_OVERRIDE_PREF_NAME,
+ savedPref
+ );
await cleanupExperiment();
},
// Nimbus calls onUpdate if any experiments are running, meaning that the
diff --git a/toolkit/components/nimbus/FeatureManifest.yaml b/toolkit/components/nimbus/FeatureManifest.yaml
@@ -4787,12 +4787,10 @@ backupService:
pref: browser.backup.scheduled.minimum-time-between-backups-seconds
archiveKillswitch:
type: boolean
- default: false
description: >-
Disables backup archiving, overrides all other configs when true.
restoreKillswitch:
type: boolean
- default: false
description: >-
Disables backup restoration, overrides all other configs when true.