Bug 1519276 - Use Feature Gates for Remote Settings integration r=leplatrem,mossop
authorMichael Cooper <mcooper@mozilla.com>
Tue, 19 Feb 2019 22:41:23 +0000
changeset 520847 9782e9ca4302f164db52c1f6e21a7cdb7cfa4007
parent 520846 8fa449f5c88e60963342eef6093f55f9e49df331
child 520848 4ce64be6418df15cd64d65edcd331e86e67204d1
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersleplatrem, mossop
bugs1519276
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1519276 - Use Feature Gates for Remote Settings integration r=leplatrem,mossop Differential Revision: https://phabricator.services.mozilla.com/D19723
browser/app/profile/firefox.js
toolkit/components/featuregates/FeatureGate.jsm
toolkit/components/featuregates/Features.toml
toolkit/components/normandy/lib/RecipeRunner.jsm
toolkit/components/normandy/test/browser/browser_RecipeRunner.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1763,17 +1763,17 @@ pref("browser.chrome.errorReporter.infoU
 // Normandy client preferences
 pref("app.normandy.api_url", "https://normandy.cdn.mozilla.net/api/v1");
 pref("app.normandy.dev_mode", false);
 pref("app.normandy.enabled", true);
 pref("app.normandy.first_run", true);
 pref("app.normandy.logging.level", 50); // Warn
 pref("app.normandy.run_interval_seconds", 21600); // 6 hours
 pref("app.normandy.shieldLearnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/shield");
-pref("app.normandy.remotesettings.enabled", false);
+pref("features.normandy-remote-settings.enabled", false);
 #ifdef MOZ_DATA_REPORTING
 pref("app.shield.optoutstudies.enabled", true);
 #else
 pref("app.shield.optoutstudies.enabled", false);
 #endif
 
 // Multi-lingual preferences
 #ifdef RELEASE_OR_BETA
--- a/toolkit/components/featuregates/FeatureGate.jsm
+++ b/toolkit/components/featuregates/FeatureGate.jsm
@@ -95,17 +95,18 @@ class FeatureGate {
     }
 
     if (!featureDefinitions.has(id)) {
       throw new Error(
         `Unknown feature id ${id}. Features must be defined in toolkit/components/featuregates/Features.toml`
       );
     }
 
-    const definition = featureDefinitions.get(id);
+    // Make a copy of the definition, since we are about to modify it
+    const definition = { ...featureDefinitions.get(id) };
     const targetValueKeys = ["defaultValue", "isPublic"];
     for (const key of targetValueKeys) {
       definition[key] = evaluateTargetedValue(definition[key], kTargetFacts);
     }
     return new FeatureGateImplementation(definition);
   }
 
   /**
--- a/toolkit/components/featuregates/Features.toml
+++ b/toolkit/components/featuregates/Features.toml
@@ -2,8 +2,19 @@
 title = "Demo Feature"
 description = "A no-op feature to demo the feature gate system."
 restart-required = false
 preference = "foo.bar.baz"
 type = "boolean"
 bug-numbers = [1479127]
 is-public = true
 default-value = false
+
+[normandy-remote-settings]
+title = "Normandy: Remote Settings transport"
+description = """
+When enabled, the Normandy client will fetch recipes from Remote Settings \
+instead of direclty from the Normandy API."""
+restart-required = false
+type = "boolean"
+bug-numbers = [1519276]
+is-public = true
+default-value = false
\ No newline at end of file
--- a/toolkit/components/normandy/lib/RecipeRunner.jsm
+++ b/toolkit/components/normandy/lib/RecipeRunner.jsm
@@ -9,16 +9,17 @@ const {XPCOMUtils} = ChromeUtils.import(
 const {LogManager} = ChromeUtils.import("resource://normandy/lib/LogManager.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "timerManager",
                                    "@mozilla.org/updates/timer-manager;1",
                                    "nsIUpdateTimerManager");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   RemoteSettings: "resource://services-settings/remote-settings.js",
+  FeatureGate: "resource://featuregates/FeatureGate.jsm",
   Storage: "resource://normandy/lib/Storage.jsm",
   FilterExpressions: "resource://gre/modules/components-utils/FilterExpressions.jsm",
   NormandyApi: "resource://normandy/lib/NormandyApi.jsm",
   ClientEnvironment: "resource://normandy/lib/ClientEnvironment.jsm",
   CleanupManager: "resource://normandy/lib/CleanupManager.jsm",
   Uptake: "resource://normandy/lib/Uptake.jsm",
   ActionsManager: "resource://normandy/lib/ActionsManager.jsm",
 });
@@ -34,17 +35,16 @@ const TELEMETRY_ENABLED_PREF = "datarepo
 
 const PREF_PREFIX = "app.normandy";
 const RUN_INTERVAL_PREF = `${PREF_PREFIX}.run_interval_seconds`;
 const FIRST_RUN_PREF = `${PREF_PREFIX}.first_run`;
 const SHIELD_ENABLED_PREF = `${PREF_PREFIX}.enabled`;
 const DEV_MODE_PREF = `${PREF_PREFIX}.dev_mode`;
 const API_URL_PREF = `${PREF_PREFIX}.api_url`;
 const LAZY_CLASSIFY_PREF = `${PREF_PREFIX}.experiments.lazy_classify`;
-const REMOTE_SETTINGS_ENABLED_PREF = `${PREF_PREFIX}.remotesettings.enabled`;
 
 const PREFS_TO_WATCH = [
   RUN_INTERVAL_PREF,
   TELEMETRY_ENABLED_PREF,
   SHIELD_ENABLED_PREF,
   API_URL_PREF,
 ];
 
@@ -238,17 +238,17 @@ var RecipeRunner = {
   },
 
   /**
    * Return the list of recipes to run, filtered for the current environment.
    */
   async loadRecipes() {
     // If RemoteSettings is enabled, we read the list of recipes from there.
     // The JEXL filtering is done via the provided callback.
-    if (Services.prefs.getBoolPref(REMOTE_SETTINGS_ENABLED_PREF, false)) {
+    if (await FeatureGate.isEnabled("normandy-remote-settings")) {
       return gRemoteSettingsClient.get();
     }
     // Obtain the recipes from the Normandy server (legacy).
     let recipes;
     try {
       recipes = await NormandyApi.fetchRecipes({enabled: true});
       log.debug(
         `Fetched ${recipes.length} recipes from the server: ` +
--- a/toolkit/components/normandy/test/browser/browser_RecipeRunner.js
+++ b/toolkit/components/normandy/test/browser/browser_RecipeRunner.js
@@ -173,17 +173,17 @@ decorate_task(
       "RecipeRunner should report uptake telemetry",
     );
   }
 );
 
 decorate_task(
   withPrefEnv({
     set: [
-      ["app.normandy.remotesettings.enabled", true],
+      ["features.normandy-remote-settings.enabled", true],
     ],
   }),
   withStub(ActionsManager.prototype, "runRecipe"),
   withStub(ActionsManager.prototype, "fetchRemoteActions"),
   withStub(ActionsManager.prototype, "finalize"),
   async function testReadFromRemoteSettings(
     runRecipeStub,
     fetchRemoteActionsStub,