commit 76ea50f404a2fd0a0fa09ce1e1bac4fc79f2af18
parent 4a827df2b32cb5c5f28fc93501afa3a0da2206a9
Author: Chris DuPuis <cdupuis@mozilla.com>
Date: Fri, 21 Nov 2025 17:12:53 +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
@@ -4806,12 +4806,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.