Bug 1471647 - Add a pref to override the Telemetry update channel. r?dexter draft
authorChristian Holler <choller@mozilla.com>
Thu, 28 Jun 2018 15:05:11 +0200
changeset 814113 872486f61f9e61bcb225cf4c492127363b1bebb5
parent 814112 40423bb8aa180813c4eb1cc58dcee9f0ad440841
child 814114 edd862e02e301fc41431e259670bdfd4e3ac5ccb
push id115101
push usercholler@mozilla.com
push dateWed, 04 Jul 2018 14:14:14 +0000
reviewersdexter
bugs1471647
milestone63.0a1
Bug 1471647 - Add a pref to override the Telemetry update channel. r?dexter MozReview-Commit-ID: 4pRYWT8R8bB
toolkit/components/telemetry/TelemetryController.jsm
toolkit/components/telemetry/TelemetryEnvironment.jsm
toolkit/components/telemetry/TelemetryReportingPolicy.jsm
toolkit/components/telemetry/TelemetryUtils.jsm
toolkit/components/telemetry/docs/internals/preferences.rst
toolkit/components/telemetry/tests/unit/test_TelemetryUtils.js
--- a/toolkit/components/telemetry/TelemetryController.jsm
+++ b/toolkit/components/telemetry/TelemetryController.jsm
@@ -50,17 +50,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/base/telemetry;1",
                                    "nsITelemetry");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   ClientID: "resource://gre/modules/ClientID.jsm",
   AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
   TelemetryStorage: "resource://gre/modules/TelemetryStorage.jsm",
   TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
-  UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
   TelemetryArchive: "resource://gre/modules/TelemetryArchive.jsm",
   TelemetrySession: "resource://gre/modules/TelemetrySession.jsm",
   TelemetrySend: "resource://gre/modules/TelemetrySend.jsm",
   TelemetryReportingPolicy: "resource://gre/modules/TelemetryReportingPolicy.jsm",
   TelemetryModules: "resource://gre/modules/TelemetryModules.jsm",
   UpdatePing: "resource://gre/modules/UpdatePing.jsm",
   TelemetryHealthPing: "resource://gre/modules/TelemetryHealthPing.jsm",
   TelemetryEventPing: "resource://gre/modules/TelemetryEventPing.jsm",
@@ -320,17 +319,17 @@ var Impl = {
     try {
       arch = Services.sysinfo.get("arch");
     } catch (e) {
       this._log.trace("_getApplicationSection - Unable to get system architecture.", e);
     }
 
     let updateChannel = null;
     try {
-      updateChannel = UpdateUtils.getUpdateChannel(false);
+      updateChannel = Utils.getUpdateChannel();
     } catch (e) {
       this._log.trace("_getApplicationSection - Unable to get update channel.", e);
     }
 
     return {
       architecture: arch,
       buildId: Services.appinfo.appBuildID,
       name: Services.appinfo.name,
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -25,18 +25,16 @@ const { AddonManager } = ChromeUtils.imp
 ChromeUtils.defineModuleGetter(this, "AttributionCode",
                                "resource:///modules/AttributionCode.jsm");
 ChromeUtils.defineModuleGetter(this, "ctypes",
                                "resource://gre/modules/ctypes.jsm");
 ChromeUtils.defineModuleGetter(this, "LightweightThemeManager",
                                "resource://gre/modules/LightweightThemeManager.jsm");
 ChromeUtils.defineModuleGetter(this, "ProfileAge",
                                "resource://gre/modules/ProfileAge.jsm");
-ChromeUtils.defineModuleGetter(this, "UpdateUtils",
-                               "resource://gre/modules/UpdateUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "WindowsRegistry",
                                "resource://gre/modules/WindowsRegistry.jsm");
 
 // The maximum length of a string (e.g. description) in the addons section.
 const MAX_ADDON_STRING_LENGTH = 100;
 // The maximum length of a string value in the settings.attribution object.
 const MAX_ATTRIBUTION_STRING_LENGTH = 100;
 // The maximum lengths for the experiment id and branch in the experiments section.
@@ -1406,17 +1404,17 @@ EnvironmentCache.prototype = {
   },
 
   /**
    * Update the cached settings data.
    */
   _updateSettings() {
     let updateChannel = null;
     try {
-      updateChannel = UpdateUtils.getUpdateChannel(false);
+      updateChannel = Utils.getUpdateChannel();
     } catch (e) {}
 
     this._currentEnvironment.settings = {
       blocklistEnabled: Services.prefs.getBoolPref(PREF_BLOCKLIST_ENABLED, true),
       e10sEnabled: Services.appinfo.browserTabsRemoteAutostart,
       e10sMultiProcesses: Services.appinfo.maxWebProcessCount,
       telemetryEnabled: Utils.isTelemetryEnabled,
       locale: getBrowserLocale(),
--- a/toolkit/components/telemetry/TelemetryReportingPolicy.jsm
+++ b/toolkit/components/telemetry/TelemetryReportingPolicy.jsm
@@ -12,18 +12,16 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/Services.jsm", this);
 ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
 ChromeUtils.import("resource://services-common/observers.js", this);
 ChromeUtils.import("resource://gre/modules/TelemetryUtils.jsm", this);
 
 ChromeUtils.defineModuleGetter(this, "TelemetrySend",
                                "resource://gre/modules/TelemetrySend.jsm");
-ChromeUtils.defineModuleGetter(this, "UpdateUtils",
-                               "resource://gre/modules/UpdateUtils.jsm");
 
 const LOGGER_NAME = "Toolkit.Telemetry";
 const LOGGER_PREFIX = "TelemetryReportingPolicy::";
 
 // Oldest year to allow in date preferences. The FHR infobar was implemented in
 // 2012 and no dates older than that should be encountered.
 const OLDEST_ALLOWED_ACCEPTANCE_YEAR = 2012;
 
@@ -245,17 +243,17 @@ var TelemetryReportingPolicyImpl = {
    */
   get minimumPolicyVersion() {
     const minPolicyVersion = Services.prefs.getIntPref(TelemetryUtils.Preferences.MinimumPolicyVersion, 1);
 
     // First check if the current channel has a specific minimum policy version. If not,
     // use the general minimum policy version.
     let channel = "";
     try {
-      channel = UpdateUtils.getUpdateChannel(false);
+      channel = TelemetryUtils.getUpdateChannel();
     } catch (e) {
       this._log.error("minimumPolicyVersion - Unable to retrieve the current channel.");
       return minPolicyVersion;
     }
     const channelPref = TelemetryUtils.Preferences.MinimumPolicyVersion + ".channel-" + channel;
     return Services.prefs.getIntPref(channelPref, minPolicyVersion);
   },
 
--- a/toolkit/components/telemetry/TelemetryUtils.jsm
+++ b/toolkit/components/telemetry/TelemetryUtils.jsm
@@ -6,16 +6,18 @@
 
 var EXPORTED_SYMBOLS = [
   "TelemetryUtils"
 ];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm", this);
 ChromeUtils.defineModuleGetter(this, "AppConstants",
                                "resource://gre/modules/AppConstants.jsm");
+ChromeUtils.defineModuleGetter(this, "UpdateUtils",
+                               "resource://gre/modules/UpdateUtils.jsm");
 
 const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
 
 const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
 
 const IS_CONTENT_PROCESS = (function() {
   // We cannot use Services.appinfo here because in telemetry xpcshell tests,
   // appinfo is initially unavailable, and becomes available only later on.
@@ -81,16 +83,17 @@ var TelemetryUtils = {
     ArchiveEnabled: "toolkit.telemetry.archive.enabled",
     CachedClientId: "toolkit.telemetry.cachedClientID",
     FirstRun: "toolkit.telemetry.reportingpolicy.firstRun",
     FirstShutdownPingEnabled: "toolkit.telemetry.firstShutdownPing.enabled",
     HealthPingEnabled: "toolkit.telemetry.healthping.enabled",
     HybridContentEnabled: "toolkit.telemetry.hybridContent.enabled",
     OverrideOfficialCheck: "toolkit.telemetry.send.overrideOfficialCheck",
     OverridePreRelease: "toolkit.telemetry.testing.overridePreRelease",
+    OverrideUpdateChannel: "toolkit.telemetry.overrideUpdateChannel",
     Server: "toolkit.telemetry.server",
     ShutdownPingSender: "toolkit.telemetry.shutdownPingSender.enabled",
     ShutdownPingSenderFirstSession: "toolkit.telemetry.shutdownPingSender.enabledFirstSession",
     TelemetryEnabled: "toolkit.telemetry.enabled",
     Unified: "toolkit.telemetry.unified",
     UpdatePing: "toolkit.telemetry.updatePing.enabled",
     NewProfilePingEnabled: "toolkit.telemetry.newProfilePing.enabled",
     NewProfilePingDelay: "toolkit.telemetry.newProfilePing.delay",
@@ -366,9 +369,26 @@ var TelemetryUtils = {
             ret[process][name][key] = packHistogram(hgram);
           }
         }
       }
     }
 
     return ret;
   },
+
+  /**
+   * @returns {string} The name of the update channel to report
+   * in telemetry.
+   * By default, this is the same as the name of the channel that
+   * the browser uses to download its updates. However in certain
+   * situations, a single update channel provides multiple (distinct)
+   * build types, that need to be distinguishable on Telemetry.
+   */
+  getUpdateChannel() {
+    let overrideChannel = Services.prefs.getCharPref(this.Preferences.OverrideUpdateChannel, undefined);
+    if (overrideChannel) {
+      return overrideChannel;
+    }
+
+    return UpdateUtils.getUpdateChannel(false);
+  },
 };
--- a/toolkit/components/telemetry/docs/internals/preferences.rst
+++ b/toolkit/components/telemetry/docs/internals/preferences.rst
@@ -157,16 +157,21 @@ Preferences
   The minimum frequency at which an :doc:`../data/event-ping` will be sent.
   Default is 60 (minutes).
 
 ``toolkit.telemetry.eventping.maximumFrequency``
 
   The maximum frequency at which an :doc:`../data/event-ping` will be sent.
   Default is 10 (minutes).
 
+``toolkit.telemetry.overrideUpdateChannel``
+
+  Override the ``channel`` value that is reported via Telemetry.
+  This is useful for distinguishing different types of builds that otherwise still report as the same update channel.
+
 Data-choices notification
 -------------------------
 
 ``toolkit.telemetry.reportingpolicy.firstRun``
 
   This preference is not present until the first run. After, its value is set to false. This is used to show the infobar with a more aggressive timeout if it wasn't shown yet.
 
 ``datareporting.policy.firstRunURL``
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryUtils.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryUtils.js
@@ -1,13 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm", this);
+ChromeUtils.import("resource://gre/modules/Preferences.jsm", this);
 ChromeUtils.import("resource://gre/modules/TelemetryUtils.jsm", this);
+ChromeUtils.import("resource://gre/modules/UpdateUtils.jsm", this);
 
 add_task(async function testHistogramPacking() {
   const HISTOGRAM_SNAPSHOT = {
     sample_process: {
       HISTOGRAM_1_DATA: {
         counts: [
           1, 0, 0
         ],
@@ -166,8 +168,26 @@ add_task(async function testKeyedHistogr
       }
     }
   };
   Assert.ok("TELEMETRY_TEST_HISTOGRAM_2_DATA" in packedKeyedHistogramsTest.sample_process,
             "Test histograms must be reported in test mode.");
   Assert.ok(ObjectUtils.deepEqual(EXPECTED_DATA_TEST, packedKeyedHistogramsTest),
             "Packed data must be correct.");
 });
+
+add_task(async function testUpdateChannelOverride() {
+  if (Preferences.has(TelemetryUtils.Preferences.OverrideUpdateChannel)) {
+    // If the pref is already set at this point, the test is running in a build
+    // that makes use of the override pref. For testing purposes, unset the pref.
+    Preferences.set(TelemetryUtils.Preferences.OverrideUpdateChannel, "");
+  }
+
+  // Check that we return the same channel as UpdateUtils, by default
+  Assert.equal(TelemetryUtils.getUpdateChannel(), UpdateUtils.getUpdateChannel(false),
+               "The telemetry reported channel must match the one from UpdateChannel, by default.");
+
+  // Now set the override pref and check that we return the correct channel
+  const OVERRIDE_TEST_CHANNEL = "nightly-test";
+  Preferences.set(TelemetryUtils.Preferences.OverrideUpdateChannel, OVERRIDE_TEST_CHANNEL);
+  Assert.equal(TelemetryUtils.getUpdateChannel(), OVERRIDE_TEST_CHANNEL,
+               "The telemetry reported channel must match the override pref when pref is set.");
+});