mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 11:15:34 +00:00
Bug 1120372 - Introduce the "update" ping. r=bsmedberg,gfritzsche,mhowell
This ping will be sent as soon as an update is ready to be applied, after it's downloaded. This is currently enabled but protected behind the 'toolkit.telemetry.updatePing.enabled' preference. MozReview-Commit-ID: 4TuM0e5MzBl --HG-- extra : rebase_source : aa3ebda3cf1e1fc2cdb8c294a643973c5101fa1c
This commit is contained in:
parent
3823e46830
commit
2d82f2c5e6
@ -1516,6 +1516,8 @@ pref("toolkit.telemetry.archive.enabled", true);
|
||||
pref("toolkit.telemetry.shutdownPingSender.enabled", true);
|
||||
// Enables sending the 'new-profile' ping on new profiles.
|
||||
pref("toolkit.telemetry.newProfilePing.enabled", true);
|
||||
// Enables sending 'update' pings on Firefox updates.
|
||||
pref("toolkit.telemetry.updatePing.enabled", true);
|
||||
|
||||
// Telemetry experiments settings.
|
||||
pref("experiments.enabled", true);
|
||||
|
@ -76,6 +76,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "TelemetryReportingPolicy",
|
||||
"resource://gre/modules/TelemetryReportingPolicy.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryModules",
|
||||
"resource://gre/modules/TelemetryModules.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdatePing",
|
||||
"resource://gre/modules/UpdatePing.jsm");
|
||||
|
||||
/**
|
||||
* Setup Telemetry logging. This function also gets called when loggin related
|
||||
@ -695,6 +697,10 @@ var Impl = {
|
||||
// lead to some stale client ids.
|
||||
this._clientID = ClientID.getCachedClientID();
|
||||
|
||||
// Init the update ping telemetry as early as possible. This won't have
|
||||
// an impact on startup.
|
||||
UpdatePing.earlyInit();
|
||||
|
||||
// Delay full telemetry initialization to give the browser time to
|
||||
// run various late initializers. Otherwise our gathered memory
|
||||
// footprint and other numbers would be too optimistic.
|
||||
@ -781,6 +787,8 @@ var Impl = {
|
||||
await this._delayedNewPingTask.finalize();
|
||||
}
|
||||
|
||||
UpdatePing.shutdown();
|
||||
|
||||
// Stop the datachoices infobar display.
|
||||
TelemetryReportingPolicy.shutdown();
|
||||
TelemetryEnvironment.shutdown();
|
||||
|
@ -34,6 +34,7 @@ this.TelemetryUtils = {
|
||||
ShutdownPingSender: "toolkit.telemetry.shutdownPingSender.enabled",
|
||||
TelemetryEnabled: "toolkit.telemetry.enabled",
|
||||
Unified: "toolkit.telemetry.unified",
|
||||
UpdatePing: "toolkit.telemetry.updatePing.enabled",
|
||||
NewProfilePingEnabled: "toolkit.telemetry.newProfilePing.enabled",
|
||||
NewProfilePingDelay: "toolkit.telemetry.newProfilePing.delay",
|
||||
PreviousBuildID: "toolkit.telemetry.previousBuildID",
|
||||
|
104
toolkit/components/telemetry/UpdatePing.jsm
Normal file
104
toolkit/components/telemetry/UpdatePing.jsm
Normal file
@ -0,0 +1,104 @@
|
||||
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Log.jsm", this);
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
||||
Cu.import("resource://gre/modules/TelemetryUtils.jsm", this);
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryController",
|
||||
"resource://gre/modules/TelemetryController.jsm");
|
||||
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
const PING_TYPE = "update";
|
||||
const UPDATE_DOWNLOADED_TOPIC = "update-downloaded";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["UpdatePing"];
|
||||
|
||||
/**
|
||||
* This module is responsible for listening to all the relevant update
|
||||
* signals, gathering the needed information and assembling the "update"
|
||||
* ping.
|
||||
*/
|
||||
this.UpdatePing = {
|
||||
earlyInit() {
|
||||
this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, "UpdatePing::");
|
||||
this._enabled = Preferences.get(TelemetryUtils.Preferences.UpdatePing, false);
|
||||
|
||||
this._log.trace("init - enabled: " + this._enabled);
|
||||
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, UPDATE_DOWNLOADED_TOPIC);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate an "update" ping with reason "ready" and dispatch it
|
||||
* to the Telemetry system.
|
||||
*
|
||||
* @param {String} aUpdateState The state of the downloaded patch. See
|
||||
* nsIUpdateService.idl for a list of possible values.
|
||||
*/
|
||||
_handleUpdateReady(aUpdateState) {
|
||||
const ALLOWED_STATES = [
|
||||
"applied", "applied-service", "pending", "pending-service", "pending-elevate"
|
||||
];
|
||||
if (!ALLOWED_STATES.includes(aUpdateState)) {
|
||||
this._log.trace("Unexpected update state: " + aUpdateState);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the information about the update we're going to apply from the
|
||||
// update manager.
|
||||
let updateManager =
|
||||
Cc["@mozilla.org/updates/update-manager;1"].getService(Ci.nsIUpdateManager);
|
||||
if (!updateManager || !updateManager.activeUpdate) {
|
||||
this._log.trace("Cannot get the update manager or no update is currently active.");
|
||||
return;
|
||||
}
|
||||
|
||||
let update = updateManager.activeUpdate;
|
||||
|
||||
const payload = {
|
||||
reason: "ready",
|
||||
targetChannel: update.channel,
|
||||
targetVersion: update.appVersion,
|
||||
targetBuildId: update.buildID,
|
||||
};
|
||||
|
||||
const options = {
|
||||
addClientId: true,
|
||||
addEnvironment: true,
|
||||
usePingSender: true,
|
||||
};
|
||||
|
||||
TelemetryController.submitExternalPing(PING_TYPE, payload, options)
|
||||
.catch(e => this._log.error("_handleUpdateReady - failed to submit update ping", e));
|
||||
},
|
||||
|
||||
/**
|
||||
* The notifications handler.
|
||||
*/
|
||||
observe(aSubject, aTopic, aData) {
|
||||
this._log.trace("observe - aTopic: " + aTopic);
|
||||
if (aTopic == UPDATE_DOWNLOADED_TOPIC) {
|
||||
this._handleUpdateReady(aData);
|
||||
}
|
||||
},
|
||||
|
||||
shutdown() {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(this, UPDATE_DOWNLOADED_TOPIC);
|
||||
},
|
||||
};
|
@ -27,6 +27,6 @@ Important examples are:
|
||||
* :doc:`main <../data/main-ping>` - contains the information collected by Telemetry (Histograms, hang stacks, ...)
|
||||
* :doc:`saved-session <../data/main-ping>` - has the same format as a main ping, but it contains the *"classic"* Telemetry payload with measurements covering the whole browser session. This is only a separate type to make storage of saved-session easier server-side. This is temporary and will be removed soon.
|
||||
* :doc:`crash <../data/crash-ping>` - a ping that is captured and sent after Firefox crashes.
|
||||
* :doc:`new-profile <../data/new-profile-ping>` - sent on the first run of a new profile
|
||||
* ``upgrade`` - *planned* - sent right after an upgrade
|
||||
* :doc:`deletion <../data/deletion-ping>` - sent when FHR upload is disabled, requesting deletion of the data associated with this user
|
||||
* :doc:`new-profile <../data/new-profile-ping>` - sent on the first run of a new profile.
|
||||
* :doc:`update <../data/update-ping>` - sent right after an update is downloaded.
|
||||
* :doc:`deletion <../data/deletion-ping>` - sent when FHR upload is disabled, requesting deletion of the data associated with this user.
|
||||
|
52
toolkit/components/telemetry/docs/data/update-ping.rst
Normal file
52
toolkit/components/telemetry/docs/data/update-ping.rst
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
"update" ping
|
||||
==================
|
||||
|
||||
This opt-out ping is sent from Firefox Desktop when a browser update is ready to be applied. There is a
|
||||
plan to send this ping after an update is successfully applied and the work will happen in `bug 1380256 <https://bugzilla.mozilla.org/show_bug.cgi?id=1380256>`_.
|
||||
|
||||
Structure:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
{
|
||||
type: "update",
|
||||
... common ping data
|
||||
clientId: <UUID>,
|
||||
environment: { ... },
|
||||
payload: {
|
||||
reason: <string>, // "ready"
|
||||
targetChannel: <string>, // "nightly"
|
||||
targetVersion: <string>, // "56.01a"
|
||||
targetBuildId: <string>, // "20080811053724"
|
||||
}
|
||||
}
|
||||
|
||||
payload.reason
|
||||
--------------
|
||||
This field only supports the value ``ready``, meaning that the ping was generated after an update was downloaded
|
||||
and marked as ready to be processed. For *non-staged* updates this happens as soon as the download
|
||||
finishes and is verified while for *staged* updates this happens before the staging step is started.
|
||||
|
||||
payload.targetChannel
|
||||
-----------------------
|
||||
The Firefox channel the update was fetched from (only valid for pings with reason "ready").
|
||||
|
||||
payload.targetVersion
|
||||
-----------------------
|
||||
The Firefox version the browser is updating to. Follows the same format a application.version (only valid for pings with reason "ready").
|
||||
|
||||
payload.targetBuildId
|
||||
-----------------------
|
||||
The Firefox build id the browser is updating to. Follows the same format a application.buildId (only valid for pings with reason "ready").
|
||||
|
||||
Expected behaviours
|
||||
-------------------
|
||||
The following is a list of conditions and expected behaviours for the ``update`` ping:
|
||||
|
||||
- **The ping is generated once every time an update is downloaded, after it was verified:**
|
||||
|
||||
- *for users who saw the privacy policy*, the ``update`` ping is sent immediately;
|
||||
- *for users who did not see the privacy policy*, the ``update`` ping is saved to disk and after the policy is displayed.
|
||||
- **If the download of the update retries or other fallback occur**: the ``update`` ping will not be generated
|
||||
multiple times, but only one time once the download is complete and verified.
|
@ -62,6 +62,10 @@ Preferences
|
||||
|
||||
Controls the delay after which the :doc:`../data/new-profile` is sent on new profiles.
|
||||
|
||||
``toolkit.telemetry.updatePing.enabled``
|
||||
|
||||
Enable the :doc:`../data/update-ping` on browser updates.
|
||||
|
||||
Data-choices notification
|
||||
-------------------------
|
||||
|
||||
|
@ -95,6 +95,7 @@ EXTRA_JS_MODULES += [
|
||||
'TelemetryUtils.jsm',
|
||||
'ThirdPartyCookieProbe.jsm',
|
||||
'UITelemetry.jsm',
|
||||
'UpdatePing.jsm',
|
||||
]
|
||||
|
||||
TESTING_JS_MODULES += [
|
||||
|
@ -5,6 +5,7 @@ support-files =
|
||||
downloadPage.html
|
||||
testConstants.js
|
||||
|
||||
[browser_TelemetryUpdatePing.js]
|
||||
[browser_updatesBackgroundWindow.js]
|
||||
[browser_updatesBackgroundWindowFailures.js]
|
||||
[browser_updatesBasicPrompt.js]
|
||||
|
@ -0,0 +1,72 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
Cu.import("resource://testing-common/TelemetryArchiveTesting.jsm", this);
|
||||
|
||||
/**
|
||||
* Please note that this is really a Telemetry test, not an
|
||||
* "update UI" test like the rest of the tests in this directory.
|
||||
* This test does not live in toolkit/components/telemetry/tests to prevent
|
||||
* duplicating the code for all the test dependencies. Unfortunately, due
|
||||
* to a limitation in the build system, we were not able to simply reference
|
||||
* the dependencies as "support-files" in the test manifest.
|
||||
*/
|
||||
add_task(async function testUpdatePingReady() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[PREF_APP_UPDATE_STAGING_ENABLED, false],
|
||||
[PREF_APP_UPDATE_AUTO, false]
|
||||
]});
|
||||
|
||||
let updateParams = "promptWaitTime=0";
|
||||
|
||||
let archiveChecker = new TelemetryArchiveTesting.Checker();
|
||||
await archiveChecker.promiseInit();
|
||||
|
||||
// Trigger an "update" ping by downloading and applying an update.
|
||||
await runUpdateTest(updateParams, 1, [
|
||||
{
|
||||
notificationId: "update-available",
|
||||
button: "button",
|
||||
beforeClick() {
|
||||
checkWhatsNewLink("update-available-whats-new");
|
||||
}
|
||||
},
|
||||
{
|
||||
notificationId: "update-restart",
|
||||
button: "secondarybutton",
|
||||
cleanup() {
|
||||
AppMenuNotifications.removeNotification(/.*/);
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
// We cannot control when the ping will be generated/archived after we trigger
|
||||
// an update, so let's make sure to have one before moving on with validation.
|
||||
let updatePing;
|
||||
await BrowserTestUtils.waitForCondition(async function() {
|
||||
// Check that the ping made it into the Telemetry archive.
|
||||
// The test data is defined in ../data/sharedUpdateXML.js
|
||||
updatePing = await archiveChecker.promiseFindPing("update", [
|
||||
[["payload", "reason"], "ready"],
|
||||
[["payload", "targetBuildId"], "20080811053724"]
|
||||
]);
|
||||
return !!updatePing;
|
||||
}, "Make sure the ping is generated before trying to validate it.", 500, 100);
|
||||
|
||||
ok(updatePing, "The 'update' ping must be correctly sent.");
|
||||
|
||||
// We don't know the exact value for the other fields, so just check
|
||||
// that they're available.
|
||||
for (let f of ["targetVersion", "targetChannel"]) {
|
||||
ok(f in updatePing.payload,
|
||||
`${f} must be available in the update ping payload.`);
|
||||
ok(typeof(updatePing.payload[f]) == "string",
|
||||
`${f} must have the correct format.`);
|
||||
}
|
||||
|
||||
// Also make sure that the ping contains both a client id and an
|
||||
// environment section.
|
||||
ok("clientId" in updatePing, "The update ping must report a client id.");
|
||||
ok("environment" in updatePing, "The update ping must report the environment.");
|
||||
});
|
@ -112,3 +112,6 @@ FINAL_TARGET_FILES += [
|
||||
'TestAUSReadStrings2.ini',
|
||||
'TestAUSReadStrings3.ini',
|
||||
]
|
||||
|
||||
with Files("browser/browser_TelemetryUpdatePing.js"):
|
||||
BUG_COMPONENT = ("Toolkit", "Telemetry")
|
||||
|
Loading…
Reference in New Issue
Block a user