summaryrefslogtreecommitdiffstats
path: root/toolkit/components/normandy/NormandyMigrations.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/normandy/NormandyMigrations.sys.mjs')
-rw-r--r--toolkit/components/normandy/NormandyMigrations.sys.mjs139
1 files changed, 139 insertions, 0 deletions
diff --git a/toolkit/components/normandy/NormandyMigrations.sys.mjs b/toolkit/components/normandy/NormandyMigrations.sys.mjs
new file mode 100644
index 0000000000..389102e144
--- /dev/null
+++ b/toolkit/components/normandy/NormandyMigrations.sys.mjs
@@ -0,0 +1,139 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { Log } from "resource://gre/modules/Log.sys.mjs";
+import { AddonStudies } from "resource://normandy/lib/AddonStudies.sys.mjs";
+import { PreferenceExperiments } from "resource://normandy/lib/PreferenceExperiments.sys.mjs";
+import { RecipeRunner } from "resource://normandy/lib/RecipeRunner.sys.mjs";
+
+const BOOTSTRAP_LOGGER_NAME = "app.normandy.bootstrap";
+
+const PREF_PREFIX = "app.normandy";
+const LEGACY_PREF_PREFIX = "extensions.shield-recipe-client";
+const PREF_LOGGING_LEVEL = "app.normandy.logging.level";
+const PREF_MIGRATIONS_APPLIED = "app.normandy.migrationsApplied";
+const PREF_OPTOUTSTUDIES_ENABLED = "app.shield.optoutstudies.enabled";
+
+// Logging
+const log = Log.repository.getLogger(BOOTSTRAP_LOGGER_NAME);
+log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
+log.level = Services.prefs.getIntPref(PREF_LOGGING_LEVEL, Log.Level.Warn);
+
+export const NormandyMigrations = {
+ async applyAll() {
+ let migrationsApplied = Services.prefs.getIntPref(
+ PREF_MIGRATIONS_APPLIED,
+ 0
+ );
+
+ for (let i = migrationsApplied; i < this.migrations.length; i++) {
+ await this.applyOne(i);
+ migrationsApplied++;
+ Services.prefs.setIntPref(PREF_MIGRATIONS_APPLIED, migrationsApplied);
+ }
+ },
+
+ async applyOne(id) {
+ const migration = this.migrations[id];
+ log.debug(`Running Normandy migration ${migration.name}`);
+ await migration();
+ },
+
+ migrations: [
+ migrateShieldPrefs,
+ migrateStudiesEnabledWithoutHealthReporting,
+ AddonStudies.migrations
+ .migration01AddonStudyFieldsToSlugAndUserFacingFields,
+ PreferenceExperiments.migrations.migration01MoveExperiments,
+ PreferenceExperiments.migrations.migration02MultiPreference,
+ PreferenceExperiments.migrations.migration03AddActionName,
+ PreferenceExperiments.migrations.migration04RenameNameToSlug,
+ RecipeRunner.migrations.migration01RemoveOldRecipesCollection,
+ AddonStudies.migrations.migration02RemoveOldAddonStudyAction,
+ migrateRemoveLastBuildIdPref,
+ PreferenceExperiments.migrations.migration05RemoveOldAction,
+ PreferenceExperiments.migrations.migration06TrackOverriddenPrefs,
+ ],
+};
+
+function migrateShieldPrefs() {
+ const legacyBranch = Services.prefs.getBranch(LEGACY_PREF_PREFIX + ".");
+ const newBranch = Services.prefs.getBranch(PREF_PREFIX + ".");
+
+ for (const prefName of legacyBranch.getChildList("")) {
+ const legacyPrefType = legacyBranch.getPrefType(prefName);
+ const newPrefType = newBranch.getPrefType(prefName);
+
+ // If new preference exists and is not the same as the legacy pref, skip it
+ if (
+ newPrefType !== Services.prefs.PREF_INVALID &&
+ newPrefType !== legacyPrefType
+ ) {
+ log.error(
+ `Error migrating normandy pref ${prefName}; pref type does not match.`
+ );
+ continue;
+ }
+
+ // Now move the value over. If it matches the default, this will be a no-op
+ switch (legacyPrefType) {
+ case Services.prefs.PREF_STRING:
+ newBranch.setCharPref(prefName, legacyBranch.getCharPref(prefName));
+ break;
+
+ case Services.prefs.PREF_INT:
+ newBranch.setIntPref(prefName, legacyBranch.getIntPref(prefName));
+ break;
+
+ case Services.prefs.PREF_BOOL:
+ newBranch.setBoolPref(prefName, legacyBranch.getBoolPref(prefName));
+ break;
+
+ case Services.prefs.PREF_INVALID:
+ // This should never happen.
+ log.error(
+ `Error migrating pref ${prefName}; pref type is invalid (${legacyPrefType}).`
+ );
+ break;
+
+ default:
+ // This should never happen either.
+ log.error(
+ `Error getting startup pref ${prefName}; unknown value type ${legacyPrefType}.`
+ );
+ }
+
+ legacyBranch.clearUserPref(prefName);
+ }
+}
+
+/**
+ * Migration to handle moving the studies opt-out pref from under the health
+ * report upload pref to an independent pref.
+ *
+ * If the pref was set to true and the health report upload pref was set
+ * to true then the pref should stay true. Otherwise set it to false.
+ */
+function migrateStudiesEnabledWithoutHealthReporting() {
+ const optOutStudiesEnabled = Services.prefs.getBoolPref(
+ PREF_OPTOUTSTUDIES_ENABLED,
+ false
+ );
+ const healthReportUploadEnabled = Services.prefs.getBoolPref(
+ "datareporting.healthreport.uploadEnabled",
+ false
+ );
+ Services.prefs.setBoolPref(
+ PREF_OPTOUTSTUDIES_ENABLED,
+ optOutStudiesEnabled && healthReportUploadEnabled
+ );
+}
+
+/**
+ * Tracking last build ID is now done by comparing Services.appinfo.appBuildID
+ * and Services.appinfo.lastAppBuildID. Remove the manual tracking.
+ */
+function migrateRemoveLastBuildIdPref() {
+ Services.prefs.clearUserPref("app.normandy.last_seen_buildid");
+}