diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index a87335ce230d..6a1cb4104be6 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -23,12 +23,15 @@ const PAYLOAD_VERSION = 1; // submitted ping data with its histogram definition (bug 832007) #expand const HISTOGRAMS_FILE_VERSION = "__HISTOGRAMS_FILE_VERSION__"; -const PREF_SERVER = "toolkit.telemetry.server"; +const PREF_BRANCH = "toolkit.telemetry."; +const PREF_SERVER = PREF_BRANCH + "server"; #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT -const PREF_ENABLED = "toolkit.telemetry.enabledPreRelease"; +const PREF_ENABLED = PREF_BRANCH + "enabledPreRelease"; #else -const PREF_ENABLED = "toolkit.telemetry.enabled"; +const PREF_ENABLED = PREF_BRANCH + "enabled"; #endif +const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID"; + // Do not gather data more than once a minute const TELEMETRY_INTERVAL = 60000; // Delay before intializing telemetry (ms) @@ -238,6 +241,9 @@ TelemetryPing.prototype = { _pingsLoaded: 0, // The number of those requests that have actually completed. _pingLoadsCompleted: 0, + // The previous build ID, if this is the first run with a new build. + // Undefined if this is not the first run, or the previous build ID is unknown. + _previousBuildID: undefined, /** * When reflecting a histogram into JS, Telemetry hands us an object @@ -366,6 +372,9 @@ TelemetryPing.prototype = { revision: HISTOGRAMS_FILE_VERSION, locale: getLocale() }; + if (this._previousBuildID) { + ret.previousBuildID = this._previousBuildID; + } // sysinfo fields are not always available, get what we can. let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2); @@ -744,9 +753,11 @@ TelemetryPing.prototype = { } #endif let enabled = false; + let previousBuildID = undefined; try { enabled = Services.prefs.getBoolPref(PREF_ENABLED); this._server = Services.prefs.getCharPref(PREF_SERVER); + previousBuildID = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID); } catch (e) { // Prerequesite prefs aren't set } @@ -756,6 +767,15 @@ TelemetryPing.prototype = { Telemetry.canRecord = false; return; } + // Record old value and update build ID preference if this is the first run with a new ID. + // If there is no previousBuildID preference, this.previousBuildID remains undefined + // so no value is sent in the telemetry metadata. + let thisBuildID = Services.appinfo.appBuildID; + if (previousBuildID != thisBuildID) { + this._previousBuildID = previousBuildID; + Services.prefs.setCharPref(PREF_PREVIOUS_BUILDID, thisBuildID); + } + Services.obs.addObserver(this, "profile-before-change", false); Services.obs.addObserver(this, "sessionstore-windows-restored", false); Services.obs.addObserver(this, "quit-application-granted", false); diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js b/toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js new file mode 100644 index 000000000000..67b7a8eec033 --- /dev/null +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +*/ +/* Test inclusion of previous build ID in telemetry pings when build ID changes. + * bug 841028 + * + * Cases to cover: + * 1) Run with no "previousBuildID" stored in prefs: + * -> no previousBuildID in telemetry system info, new value set in prefs. + * 2) previousBuildID in prefs, equal to current build ID: + * -> no previousBuildID in telemetry, prefs not updated. + * 3) previousBuildID in prefs, not equal to current build ID: + * -> previousBuildID in telemetry, new value set in prefs. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Get the TelemetryPing definitions directly so we can test it without going through xpcom. +Services.scriptloader.loadSubScript("resource://gre/components/TelemetryPing.js"); + +// Force the Telemetry enabled preference so that TelemetryPing.setup() doesn't exit early. +Services.prefs.setBoolPref(PREF_ENABLED, true); + +// Set up our dummy AppInfo object so we can control the appBuildID. +Cu.import("resource://testing-common/AppInfo.jsm"); +updateAppInfo(); + +// Check that when run with no previous build ID stored, we update the pref but do not +// put anything into the metadata. +function testFirstRun() { + let ping = new TelemetryPing(); + ping.setup(); + let metadata = ping.getMetadata(); + do_check_false("previousBuildID" in metadata); + let appBuildID = getAppInfo().appBuildID; + let buildIDPref = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID); + do_check_eq(appBuildID, buildIDPref); +} + +// Check that a subsequent run with the same build ID does not put prev build ID in +// metadata. Assumes testFirstRun() has already been called to set the previousBuildID pref. +function testSecondRun() { + let ping = new TelemetryPing(); + ping.setup(); + let metadata = ping.getMetadata(); + do_check_false("previousBuildID" in metadata); +} + + +// Set up telemetry with a different app build ID and check that the old build ID +// is returned in the metadata and the pref is updated to the new build ID. +// Assumes testFirstRun() has been called to set the previousBuildID pref. +const NEW_BUILD_ID = "20130314"; +function testNewBuild() { + let info = getAppInfo(); + let oldBuildID = info.appBuildID; + info.appBuildID = NEW_BUILD_ID; + let ping = new TelemetryPing(); + ping.setup(); + let metadata = ping.getMetadata(); + do_check_eq(metadata.previousBuildID, oldBuildID); + let buildIDPref = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID); + do_check_eq(NEW_BUILD_ID, buildIDPref); +} + + +function run_test() { + // Make sure we have a profile directory. + do_get_profile(); + testFirstRun(); + testSecondRun(); + testNewBuild(); +} diff --git a/toolkit/components/telemetry/tests/unit/xpcshell.ini b/toolkit/components/telemetry/tests/unit/xpcshell.ini index 2238a967519e..20de10addda6 100644 --- a/toolkit/components/telemetry/tests/unit/xpcshell.ini +++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini @@ -8,3 +8,4 @@ tail = # fail-if = os == "android" [test_TelemetryPing_idle.js] [test_TelemetryStopwatch.js] +[test_TelemetryPingBuildID.js]