Bug 1418266 - add devtools onboarding preferences and probes (beta-only);r=ochameau a=gchang
authorJulian Descottes <jdescottes@mozilla.com>
Thu, 16 Nov 2017 19:56:15 +0100
changeset 442616 5405d1ebc3155fa2574d4a66452cd283358136ed
parent 442615 b9d29c50dff5b02df9aa33af951baf0981eb485a
child 442617 c88f2766d765ad9af1a48ad84c7a4e7166515cdd
push id8273
push usershindli@mozilla.com
push dateThu, 30 Nov 2017 14:16:30 +0000
treeherdermozilla-beta@5405d1ebc315 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau, gchang
bugs1418266
milestone58.0
Bug 1418266 - add devtools onboarding preferences and probes (beta-only);r=ochameau a=gchang The devtools.onboarding.experiment pref now supports 3 states: - off (default) - on - force When set to "on" or "force" the preference will flip devtools enabled to false. When set to "force" the devtools.enabled pref can no longer be flipped to true by looking at devtools.selfxss.count, users have to go through the onboarding flow. To make sure the devtools.enabled pref is only flipped once, we use a supporting pref devtools.onboarding.experiment.flipped MozReview-Commit-ID: B5fPKuGxPW2
devtools/shim/devtools-startup-prefs.js
devtools/shim/devtools-startup.js
toolkit/components/telemetry/Scalars.yaml
--- a/devtools/shim/devtools-startup-prefs.js
+++ b/devtools/shim/devtools-startup-prefs.js
@@ -15,8 +15,23 @@ pref("devtools.jsonview.enabled", true);
 #ifdef MOZ_DEV_EDITION
 sticky_pref("devtools.theme", "dark");
 #else
 sticky_pref("devtools.theme", "light");
 #endif
 
 // Should the devtools toolbar be opened on startup
 pref("devtools.toolbar.visible", false);
+
+// Pref to drive the devtools onboarding flow experiment. States:
+// - off: forces devtools.enabled to true
+// - on: devtools.enabled is not forced to true.
+// - force: devtools.enabled is not forced to true and cannot be set to true by checking
+//   devtools.selfxss.count. User will have to go through onboarding to use DevTools.
+pref("devtools.onboarding.experiment", "off");
+
+// If devtools.onboarding.experiment is set to "on" or "force", we will flip the
+// devtools.enabled preference to false once. The flag is used to make sure it is only
+// flipped once.
+pref("devtools.onboarding.experiment.flipped", false);
+
+// Flag to check if we already logged the devtools onboarding related probe.
+pref("devtools.onboarding.telemetry.logged", false);
--- a/devtools/shim/devtools-startup.js
+++ b/devtools/shim/devtools-startup.js
@@ -243,26 +243,52 @@ DevToolsStartup.prototype = {
     this.hookWindow(window);
 
     if (Services.prefs.getBoolPref(TOOLBAR_VISIBLE_PREF, false)) {
       // Loading devtools-browser will open the developer toolbar by also checking this
       // pref.
       this.initDevTools();
     }
 
-    if (this.devtoolsFlag) {
-      this.handleDevToolsFlag(window);
-      // This listener is called for all Firefox windows, but we want to execute
-      // that command only once.
-      this.devtoolsFlag = false;
+    // This listener is called for all Firefox windows, but we want to execute some code
+    // only once.
+    if (!this._firstWindowReadyReceived) {
+      this.onFirstWindowReady(window);
+      this._firstWindowReadyReceived = true;
     }
 
     JsonView.initialize();
   },
 
+  onFirstWindowReady(window) {
+    if (this.devtoolsFlag) {
+      this.handleDevToolsFlag(window);
+    }
+
+    // Wait until we get a window before sending a ping to telemetry to avoid slowing down
+    // the startup phase.
+    this.pingOnboardingTelemetry();
+  },
+
+  /**
+   * Check if the user is being flagged as DevTools users or not. This probe should only
+   * be logged once per profile.
+   */
+  pingOnboardingTelemetry() {
+    // Only ping telemetry once per profile.
+    let alreadyLoggedPref = "devtools.onboarding.telemetry.logged";
+    if (Services.prefs.getBoolPref(alreadyLoggedPref)) {
+      return;
+    }
+
+    let scalarId = "devtools.onboarding.is_devtools_user";
+    Services.telemetry.scalarSet(scalarId, this.isDevToolsUser());
+    Services.prefs.setBoolPref(alreadyLoggedPref, true);
+  },
+
   /**
    * Register listeners to all possible entry points for Developer Tools.
    * But instead of implementing the actual actions, defer to DevTools codebase.
    * In most cases, it only needs to call this.initDevTools which handles the rest.
    * We do that to prevent loading any DevTools module until the user intent to use them.
    */
   hookWindow(window) {
     // Key Shortcuts need to be added on all the created windows.
@@ -442,24 +468,45 @@ DevToolsStartup.prototype = {
   /**
    * Depending on some runtime parameters (command line arguments as well as existing
    * preferences), the DEVTOOLS_ENABLED_PREF might be forced to true.
    *
    * @param {Boolean} hasDevToolsFlag
    *        true if any DevTools command line argument was passed when starting Firefox.
    */
   setupEnabledPref(hasDevToolsFlag) {
+    // Read the current experiment state.
+    let experimentState = Services.prefs.getCharPref("devtools.onboarding.experiment");
+    let isRegularExperiment = experimentState == "on";
+    let isForcedExperiment = experimentState == "force";
+    let isInExperiment = isRegularExperiment || isForcedExperiment;
+
+    // Force devtools.enabled to true for users that are not part of the experiment.
+    if (!isInExperiment) {
+      Services.prefs.setBoolPref(DEVTOOLS_ENABLED_PREF, true);
+      return;
+    }
+
+    // Force devtools.enabled to false once for each experiment user.
+    if (!Services.prefs.getBoolPref("devtools.onboarding.experiment.flipped")) {
+      Services.prefs.setBoolPref(DEVTOOLS_ENABLED_PREF, false);
+      Services.prefs.setBoolPref("devtools.onboarding.experiment.flipped", true);
+    }
+
     if (Services.prefs.getBoolPref(DEVTOOLS_ENABLED_PREF)) {
       // Nothing to do if DevTools are already enabled.
       return;
     }
 
-    let hasToolbarPref = Services.prefs.getBoolPref(TOOLBAR_VISIBLE_PREF, false);
+    // We only consider checking the actual isDevToolsUser() if the user is in the
+    // "regular" experiment group.
+    let isDevToolsUser = isRegularExperiment && this.isDevToolsUser();
 
-    if (hasDevToolsFlag || hasToolbarPref || this.isDevToolsUser()) {
+    let hasToolbarPref = Services.prefs.getBoolPref(TOOLBAR_VISIBLE_PREF, false);
+    if (hasDevToolsFlag || hasToolbarPref || isDevToolsUser) {
       Services.prefs.setBoolPref(DEVTOOLS_ENABLED_PREF, true);
     }
   },
 
   hookKeyShortcuts(window) {
     let doc = window.document;
     let keyset = doc.createElement("keyset");
     keyset.setAttribute("id", "devtoolsKeyset");
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -951,16 +951,29 @@ devtools.aboutdevtools:
       Number of times the user left about:devtools without enabling devtools.
     expires: "60"
     kind: uint
     notification_emails:
       - dev-developer-tools@lists.mozilla.org, jdescottes@mozilla.com
     record_in_processes:
       - 'main'
 
+devtools.onboarding:
+  is_devtools_user:
+    bug_numbers:
+      - 1408339
+    description: >
+      How many users are flagged as existing devtools users.
+    expires: "60"
+    kind: boolean
+    notification_emails:
+      - dev-developer-tools@lists.mozilla.org, jdescottes@mozilla.com
+    record_in_processes:
+      - 'main'
+
 navigator.storage:
   estimate_count:
     bug_numbers:
       - 1359708
     description: >
       Number of times navigator.storage.estimate has been used.
     expires: "60"
     kind: uint