Backed out 4 changesets (bug 1445921) for Linting failure on components/telemetry/tests/unit/test_TelemetryController.js on a CLOSED TREE

Backed out changeset b5bff80b9d18 (bug 1445921)
Backed out changeset b859e76fcc67 (bug 1445921)
Backed out changeset 7c23db3a5f53 (bug 1445921)
Backed out changeset f3ef58bc6b38 (bug 1445921)

--HG--
extra : rebase_source : 00bc0e17ea782a73c5067c1f8d615fc7b80bbabb
This commit is contained in:
Gurzau Raul 2018-07-09 13:06:17 +03:00
Родитель 30f1ace53b
Коммит dd9a507efe
16 изменённых файлов: 170 добавлений и 382 удалений

Просмотреть файл

@ -1359,20 +1359,6 @@ telemetry:
record_in_processes:
- 'main'
data_upload_optin:
bug_numbers:
- 1445921
description: >
User opted into sending Telemetry data again.
expires: "never"
kind: boolean
notification_emails:
- jrediger@mozilla.com
- telemetry-client-dev@mozilla.com
release_channel_collection: opt-out
record_in_processes:
- 'main'
telemetry.discarded:
accumulations:
bug_numbers:

Просмотреть файл

@ -40,7 +40,7 @@ const NEWPROFILE_PING_DEFAULT_DELAY = 30 * 60 * 1000;
// Ping types.
const PING_TYPE_MAIN = "main";
const PING_TYPE_OPTOUT = "optout";
const PING_TYPE_DELETION = "deletion";
// Session ping reasons.
const REASON_GATHER_PAYLOAD = "gather-payload";
@ -848,49 +848,28 @@ var Impl = {
/**
* Called whenever the FHR Upload preference changes (e.g. when user disables FHR from
* the preferences panel), this triggers sending the optout ping.
* the preferences panel), this triggers sending the deletion ping.
*/
_onUploadPrefChange() {
const uploadEnabled = Services.prefs.getBoolPref(TelemetryUtils.Preferences.FhrUploadEnabled, false);
if (uploadEnabled) {
this._log.trace("_onUploadPrefChange - upload was enabled again. Resetting client ID");
// Delete cached client ID immediately, so other usage is forced to refetch it.
this._clientID = null;
// Generate a new client ID and make sure this module uses the new version
let p = ClientID.resetClientID().then(id => {
this._clientID = id;
Telemetry.scalarSet("telemetry.data_upload_optin", true);
});
this._shutdownBarrier.client.addBlocker(
"TelemetryController: resetting client ID after data upload was enabled", p);
// There's nothing we should do if we are enabling upload.
return;
}
let p = (async () => {
try {
// 1. Cancel the current pings.
// 2. Clear unpersisted pings
// Clear the current pings.
await TelemetrySend.clearCurrentPings();
// 3. Remove all pending pings
await TelemetryStorage.removeAppDataPings();
// Remove all the pending pings, but not the deletion ping.
await TelemetryStorage.runRemovePendingPingsTask();
} catch (e) {
this._log.error("_onUploadPrefChange - error clearing pending pings", e);
} finally {
// 4. Reset session and subsession counter
TelemetrySession.resetSubsessionCounter();
// 5. Set ClientID to a known value
this._clientID = await ClientID.setClientID(TelemetryUtils.knownClientID);
// 6. Send the optout ping.
this._log.trace("_onUploadPrefChange - Sending optout ping.");
this.submitExternalPing(PING_TYPE_OPTOUT, {}, { addClientId: false });
// Always send the deletion ping.
this._log.trace("_onUploadPrefChange - Sending deletion ping.");
this.submitExternalPing(PING_TYPE_DELETION, {}, { addClientId: true });
}
})();
@ -902,7 +881,7 @@ var Impl = {
_attachObservers() {
if (IS_UNIFIED_TELEMETRY) {
// Watch the FHR upload setting to trigger optout pings.
// Watch the FHR upload setting to trigger deletion pings.
Services.prefs.addObserver(TelemetryUtils.Preferences.FhrUploadEnabled, this, true);
}
},

Просмотреть файл

@ -59,7 +59,7 @@ const PING_FORMAT_VERSION = 4;
const MS_IN_A_MINUTE = 60 * 1000;
const PING_TYPE_OPTOUT = "optout";
const PING_TYPE_DELETION = "deletion";
// We try to spread "midnight" pings out over this interval.
const MIDNIGHT_FUZZING_INTERVAL_MS = 60 * MS_IN_A_MINUTE;
@ -118,20 +118,24 @@ function isV4PingFormat(aPing) {
}
/**
* Check if the provided ping is an optout ping.
* Check if the provided ping is a deletion ping.
* @param {Object} aPing The ping to check.
* @return {Boolean} True if the ping is an optout ping, false otherwise.
* @return {Boolean} True if the ping is a deletion ping, false otherwise.
*/
function isOptoutPing(aPing) {
return isV4PingFormat(aPing) && (aPing.type == PING_TYPE_OPTOUT);
function isDeletionPing(aPing) {
return isV4PingFormat(aPing) && (aPing.type == PING_TYPE_DELETION);
}
/**
* Save the provided ping as a pending ping.
* Save the provided ping as a pending ping. If it's a deletion ping, save it
* to a special location.
* @param {Object} aPing The ping to save.
* @return {Promise} A promise resolved when the ping is saved.
*/
function savePing(aPing) {
if (isDeletionPing(aPing)) {
return TelemetryStorage.saveDeletionPing(aPing);
}
return TelemetryStorage.savePendingPing(aPing);
}
@ -441,17 +445,16 @@ var SendScheduler = {
}
// Get a list of pending pings, sorted by last modified, descending.
// Filter out all the pings we can't send now. This addresses scenarios like "optout" pings
// which can be sent even when upload is disabled.
// Filter out all the pings we can't send now. This addresses scenarios like "deletion" pings
// which can be send even when upload is disabled.
let pending = TelemetryStorage.getPendingPingList();
let current = TelemetrySendImpl.getUnpersistedPings();
this._log.trace("_doSendTask - pending: " + pending.length + ", current: " + current.length);
// Note that the two lists contain different kind of data. |pending| only holds ping
// info, while |current| holds actual ping data.
if (!TelemetrySendImpl.sendingEnabled()) {
// If sending is disabled, only handle an unpersisted optout ping
pending = [];
current = current.filter(p => isOptoutPing(p));
pending = pending.filter(pingInfo => TelemetryStorage.isDeletionPing(pingInfo.id));
current = current.filter(p => isDeletionPing(p));
}
this._log.trace("_doSendTask - can send - pending: " + pending.length + ", current: " + current.length);
@ -944,13 +947,9 @@ var TelemetrySendImpl = {
try {
await this._doPing(ping, ping.id, false);
} catch (ex) {
if (isOptoutPing(ping)) {
// Optout pings should only be tried once and then discarded.
this._log.info("sendPings - optout ping " + ping.id + " not sent, discarding", ex);
} else {
this._log.info("sendPings - ping " + ping.id + " not sent, saving to disk", ex);
await savePing(ping);
}
this._log.info("sendPings - ping " + ping.id + " not sent, saving to disk", ex);
// Deletion pings must be saved to a special location.
await savePing(ping);
} finally {
this._currentPings.delete(ping.id);
}
@ -1022,6 +1021,9 @@ var TelemetrySendImpl = {
}
if (success && isPersisted) {
if (TelemetryStorage.isDeletionPing(id)) {
return TelemetryStorage.removeDeletionPing();
}
return TelemetryStorage.removePendingPing(id);
}
return Promise.resolve();
@ -1224,7 +1226,7 @@ var TelemetrySendImpl = {
/**
* Check if sending is disabled. If FHR is not allowed to upload,
* pings are not sent to the server (Telemetry is a sub-feature of FHR). If trying
* to send an optout ping, don't block it.
* to send a deletion ping, don't block it.
* If unified telemetry is off, don't send pings if Telemetry is disabled.
*
* @param {Object} [ping=null] A ping to be checked.
@ -1241,8 +1243,8 @@ var TelemetrySendImpl = {
// With unified Telemetry, the FHR upload setting controls whether we can send pings.
// The Telemetry pref enables sending extended data sets instead.
if (IS_UNIFIED_TELEMETRY) {
// Optout pings are sent once even if the upload is disabled.
if (ping && isOptoutPing(ping)) {
// Deletion pings are sent even if the upload is disabled.
if (ping && isDeletionPing(ping)) {
return true;
}
return Services.prefs.getBoolPref(TelemetryUtils.Preferences.FhrUploadEnabled, false);
@ -1279,11 +1281,8 @@ var TelemetrySendImpl = {
async _persistCurrentPings() {
for (let [id, ping] of this._currentPings) {
try {
// Never save an optout ping to disk
if (!isOptoutPing(ping)) {
await savePing(ping);
this._log.trace("_persistCurrentPings - saved ping " + id);
}
await savePing(ping);
this._log.trace("_persistCurrentPings - saved ping " + id);
} catch (ex) {
this._log.error("_persistCurrentPings - failed to save ping " + id, ex);
} finally {

Просмотреть файл

@ -566,17 +566,6 @@ var TelemetrySession = Object.freeze({
getMetadata(reason) {
return Impl.getMetadata(reason);
},
/**
* Reset the subsession and profile subsession counter.
* This should only be called when the profile should be considered completely new,
* e.g. after opting out of sending Telemetry
*/
resetSubsessionCounter() {
Impl._subsessionCounter = 0;
Impl._profileSubsessionCounter = 0;
},
/**
* Used only for testing purposes.
*/

Просмотреть файл

@ -26,6 +26,7 @@ const Utils = TelemetryUtils;
const DATAREPORTING_DIR = "datareporting";
const PINGS_ARCHIVE_DIR = "archived";
const ABORTED_SESSION_FILE_NAME = "aborted-session-ping";
const DELETION_PING_FILE_NAME = "pending-deletion-ping";
const SESSION_STATE_FILE_NAME = "session-state.json";
XPCOMUtils.defineLazyGetter(this, "gDataReportingDir", function() {
@ -37,6 +38,9 @@ XPCOMUtils.defineLazyGetter(this, "gPingsArchivePath", function() {
XPCOMUtils.defineLazyGetter(this, "gAbortedSessionFilePath", function() {
return OS.Path.join(gDataReportingDir, ABORTED_SESSION_FILE_NAME);
});
XPCOMUtils.defineLazyGetter(this, "gDeletionPingFilePath", function() {
return OS.Path.join(gDataReportingDir, DELETION_PING_FILE_NAME);
});
ChromeUtils.defineModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
ChromeUtils.defineModuleGetter(this, "TelemetryHealthPing",
@ -205,7 +209,7 @@ var TelemetryStorage = {
},
/**
* Run the task to remove all the pending pings
* Run the task to remove all the pending pings (except the deletion ping).
*
* @return {Promise} Resolved when the pings are removed.
*/
@ -213,14 +217,6 @@ var TelemetryStorage = {
return TelemetryStorageImpl.runRemovePendingPingsTask();
},
/**
* Remove all pings that are stored in the userApplicationDataDir
* under the "Pending Pings" sub-directory.
*/
removeAppDataPings() {
return TelemetryStorageImpl.removeAppDataPings();
},
/**
* Reset the storage state in tests.
*/
@ -338,6 +334,30 @@ var TelemetryStorage = {
return TelemetryStorageImpl.loadAbortedSessionPing();
},
/**
* Save the deletion ping.
* @param ping The deletion ping.
* @return {Promise} A promise resolved when the ping is saved.
*/
saveDeletionPing(ping) {
return TelemetryStorageImpl.saveDeletionPing(ping);
},
/**
* Remove the deletion ping.
* @return {Promise} Resolved when the ping is deleted from the disk.
*/
removeDeletionPing() {
return TelemetryStorageImpl.removeDeletionPing();
},
/**
* Check if the ping id identifies a deletion ping.
*/
isDeletionPing(aPingId) {
return TelemetryStorageImpl.isDeletionPing(aPingId);
},
/**
* Remove the aborted-session ping if present.
*
@ -540,6 +560,8 @@ var TelemetryStorageImpl = {
_logger: null,
// Used to serialize aborted session ping writes to disk.
_abortedSessionSerializer: new SaveSerializer(),
// Used to serialize deletion ping writes to disk.
_deletionPingSerializer: new SaveSerializer(),
// Used to serialize session state writes to disk.
_stateSaveSerializer: new SaveSerializer(),
@ -593,6 +615,10 @@ var TelemetryStorageImpl = {
this._log.error("shutdown - failed to flush aborted-session writes", ex);
});
await this._deletionPingSerializer.flushTasks().catch(ex => {
this._log.error("shutdown - failed to flush deletion ping writes", ex);
});
if (this._cleanArchiveTask) {
await this._cleanArchiveTask.catch(ex => {
this._log.error("shutdown - the archive cleaning task failed", ex);
@ -1398,7 +1424,7 @@ var TelemetryStorageImpl = {
},
/**
* Run the task to remove all the pending pings
* Run the task to remove all the pending pings (except the deletion ping).
*
* @return {Promise} Resolved when the pings are removed.
*/
@ -1450,17 +1476,17 @@ var TelemetryStorageImpl = {
},
/**
* Iterate through all pings in the userApplicationDataDir under the "Pending Pings" sub-directory
* and yield each file.
* This function migrates pings that are stored in the userApplicationDataDir
* under the "Pending Pings" sub-directory.
*/
async* _iterateAppDataPings() {
this._log.trace("_iterateAppDataPings");
async _migrateAppDataPings() {
this._log.trace("_migrateAppDataPings");
// The test suites might not create and define the "UAppData" directory.
// The tests suites might not create and define the "UAppData" directory.
// We account for that here instead of manually going through each test using
// telemetry to manually create the directory and define the constant.
if (!OS.Constants.Path.userApplicationDataDir) {
this._log.trace("_iterateAppDataPings - userApplicationDataDir is not defined. Is this a test?");
this._log.trace("_migrateAppDataPings - userApplicationDataDir is not defined. Is this a test?");
return;
}
@ -1472,59 +1498,32 @@ var TelemetryStorageImpl = {
try {
// Check if appDataPendingPings exists and bail out if it doesn't.
if (!(await iter.exists())) {
this._log.trace("_iterateAppDataPings - the AppData pending pings directory doesn't exist.");
this._log.trace("_migrateAppDataPings - the AppData pending pings directory doesn't exist.");
return;
}
let files = (await iter.nextBatch()).filter(e => !e.isDir);
for (let file of files) {
yield file;
try {
// Load the ping data from the original file.
const pingData = await this.loadPingFile(file.path);
// Save it among the pending pings in the user profile, overwrite on
// ping id collision.
await TelemetryStorage.savePing(pingData, true);
// Finally remove the file.
await OS.File.remove(file.path);
} catch (ex) {
this._log.error("_migrateAppDataPings - failed to remove file " + file.path, ex);
continue;
}
}
} finally {
await iter.close();
}
},
/**
* Remove all pings that are stored in the userApplicationDataDir
* under the "Pending Pings" sub-directory.
*/
async removeAppDataPings() {
this._log.trace("removeAppDataPings");
for await (const file of this._iterateAppDataPings()) {
try {
await OS.File.remove(file.path);
} catch (ex) {
this._log.error("removeAppDataPings - failed to remove file " + file.path, ex);
}
}
},
/**
* Migrate pings that are stored in the userApplicationDataDir
* under the "Pending Pings" sub-directory.
*/
async _migrateAppDataPings() {
this._log.trace("_migrateAppDataPings");
for await (const file of this._iterateAppDataPings()) {
try {
// Load the ping data from the original file.
const pingData = await this.loadPingFile(file.path);
// Save it among the pending pings in the user profile, overwrite on
// ping id collision.
await TelemetryStorage.savePing(pingData, true);
// Finally remove the file.
await OS.File.remove(file.path);
} catch (ex) {
this._log.error("_migrateAppDataPings - failed to remove file " + file.path, ex);
}
}
},
loadPendingPingList() {
// If we already have a pending scanning task active, return that.
if (this._scanPendingPingsTask) {
@ -1617,6 +1616,17 @@ var TelemetryStorageImpl = {
await iter.close();
}
// Explicitly load the deletion ping from its known path, if it's there.
if (await OS.File.exists(gDeletionPingFilePath)) {
this._log.trace("_scanPendingPings - Adding pending deletion ping.");
// We can't get the ping id or the last modification date without hitting the disk.
// Since deletion has a special handling, we don't really need those.
this._pendingPings.set(Utils.generateUUID(), {
path: gDeletionPingFilePath,
lastModificationDate: Date.now(),
});
}
this._scannedPendingDirectory = true;
return this._buildPingList();
},
@ -1760,6 +1770,53 @@ var TelemetryStorageImpl = {
});
},
/**
* Save the deletion ping.
* @param ping The deletion ping.
* @return {Promise} Resolved when the ping is saved.
*/
async saveDeletionPing(ping) {
this._log.trace("saveDeletionPing - ping path: " + gDeletionPingFilePath);
await OS.File.makeDir(gDataReportingDir, { ignoreExisting: true });
let p = this._deletionPingSerializer.enqueueTask(() =>
this.savePingToFile(ping, gDeletionPingFilePath, true));
this._trackPendingPingSaveTask(p);
return p;
},
/**
* Remove the deletion ping.
* @return {Promise} Resolved when the ping is deleted from the disk.
*/
async removeDeletionPing() {
return this._deletionPingSerializer.enqueueTask(async () => {
try {
await OS.File.remove(gDeletionPingFilePath, { ignoreAbsent: false });
this._log.trace("removeDeletionPing - success");
} catch (ex) {
if (ex.becauseNoSuchFile) {
this._log.trace("removeDeletionPing - no such file");
} else {
this._log.error("removeDeletionPing - error removing ping", ex);
}
}
});
},
isDeletionPing(aPingId) {
let pingInfo = this._pendingPings.get(aPingId);
if (!pingInfo) {
return false;
}
if (pingInfo.path != gDeletionPingFilePath) {
return false;
}
return true;
},
/**
* Remove FHR database files. This is temporary and will be dropped in
* the future.

Просмотреть файл

@ -120,13 +120,6 @@ var TelemetryUtils = {
FirstRunURL: "datareporting.policy.firstRunURL",
}),
/**
* A fixed valid client ID used when Telemetry upload is disabled.
*/
get knownClientID() {
return "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
},
/**
* True if this is a content process.
*/

Просмотреть файл

@ -26,4 +26,4 @@ Important examples are:
* :doc:`crash <../data/crash-ping>` - a ping that is captured and sent after a Firefox process crashes.
* :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:`optout <../data/optout-ping>` - sent when FHR upload is disabled
* :doc:`deletion <../data/deletion-ping>` - sent when FHR upload is disabled, requesting deletion of the data associated with this user.

Просмотреть файл

@ -19,7 +19,7 @@ Structure:
.. code-block:: js
{
type: <string>, // "main", "activation", "optout", "saved-session", ...
type: <string>, // "main", "activation", "deletion", "saved-session", ...
id: <UUID>, // a UUID that identifies this ping
creationDate: <ISO date>, // the date the ping was generated
version: <number>, // the version of the ping format, currently 4

Просмотреть файл

@ -1,6 +1,6 @@
"deletion" ping (obsolete)
==========================
"deletion" ping
===============
This ping is generated when a user turns off FHR upload from the Preferences panel, changing the related ``datareporting.healthreport.uploadEnabled`` preference. This requests that all associated data from that user be deleted.
@ -17,10 +17,3 @@ Structure:
clientId: <UUID>,
payload: { }
}
Version History
---------------
- Firefox 63:
- Replaced by "optout" ping (`bug 1445921 <https://bugzilla.mozilla.org/show_bug.cgi?id=1445921>`_).

Просмотреть файл

@ -10,7 +10,6 @@ Data documentation
common-ping
environment
main-ping
optout-ping
deletion-ping
crash-ping
backgroundhangmonitor-ping

Просмотреть файл

@ -1,33 +0,0 @@
"optout" ping
=============
This ping is generated when a user turns off FHR upload from the Preferences panel, changing the related ``datareporting.healthreport.uploadEnabled`` :doc:`preference <../internals/preferences>`.
This ping contains no client id and no environment data.
Structure:
.. code-block:: js
{
version: 4,
type: "optout",
... common ping data
payload: { }
}
Expected behaviours
-------------------
The following is a list of expected behaviours for the ``optout`` ping:
- Sending the "optout" ping is best-effort. Telemetry tries to send the ping once and discards it immediately if sending fails.
- The ping might be delayed if ping sending is throttled (e.g. around midnight).
- The ping can be lost if the browser is shutdown before the ping is sent out the "optout" ping is discarded.
Version History
---------------
- Firefox 63:
- "optout" ping replaced the "deletion" ping (`bug 1445921 <https://bugzilla.mozilla.org/show_bug.cgi?id=1445921>`_).

Просмотреть файл

@ -165,9 +165,6 @@ function decodeRequestPayload(request) {
payload = JSON.parse((new TextDecoder()).decode(bytes));
}
// Check for canary value
Assert.notEqual(OPTOUT_KNOWN_CLIENTID, payload.clientId, "Known clientId should never appear in a ping on the server");
return payload;
}

Просмотреть файл

@ -18,10 +18,9 @@ ChromeUtils.import("resource://gre/modules/TelemetrySend.jsm", this);
ChromeUtils.import("resource://gre/modules/TelemetryArchive.jsm", this);
ChromeUtils.import("resource://gre/modules/TelemetryUtils.jsm", this);
ChromeUtils.import("resource://gre/modules/Preferences.jsm");
ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm", this);
const PING_FORMAT_VERSION = 4;
const OPTOUT_PING_TYPE = "optout";
const DELETION_PING_TYPE = "deletion";
const TEST_PING_TYPE = "test-ping-type";
const PLATFORM_VERSION = "1.9.2";
@ -138,58 +137,31 @@ add_task(async function test_simplePing() {
});
add_task(async function test_disableDataUpload() {
const OPTIN_PROBE = "telemetry.data_upload_optin";
const isUnified = Preferences.get(TelemetryUtils.Preferences.Unified, false);
if (!isUnified) {
// Skipping the test if unified telemetry is off, as no optout ping will
// Skipping the test if unified telemetry is off, as no deletion ping will
// be generated.
return;
}
// Check that the optin probe is not set, there should be other data in the snapshot though
let snapshot = Telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false).parent;
Assert.ok(!(OPTIN_PROBE in snapshot), "Data optin scalar should not be set at start");
// Send a first ping to get the current used client id
await sendPing(true, false);
let ping = await PingServer.promiseNextPing();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
let firstClientId = ping.clientId;
Assert.ok(firstClientId, "Test ping needs a client ID");
Assert.notEqual(TelemetryUtils.knownClientID, firstClientId, "Client ID should be valid and random");
// Disable FHR upload: this should trigger a optout ping.
// Disable FHR upload: this should trigger a deletion ping.
Preferences.set(TelemetryUtils.Preferences.FhrUploadEnabled, false);
ping = await PingServer.promiseNextPing();
checkPingFormat(ping, OPTOUT_PING_TYPE, false, false);
let ping = await PingServer.promiseNextPing();
checkPingFormat(ping, DELETION_PING_TYPE, true, false);
// Wait on ping activity to settle.
await TelemetrySend.testWaitOnOutgoingPings();
snapshot = Telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false).parent;
Assert.ok(!(OPTIN_PROBE in snapshot), "Data optin scalar should not be set after optout");
// Restore FHR Upload.
Preferences.set(TelemetryUtils.Preferences.FhrUploadEnabled, true);
// We need to wait until the scalar is set
await ContentTaskUtils.waitForCondition(() => {
const snapshot =
Telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
return Object.keys(snapshot).includes("parent") &&
OPTIN_PROBE in snapshot.parent;
});
snapshot = Telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false).parent;
Assert.ok(snapshot[OPTIN_PROBE], "Enabling data upload should set optin probe");
// Simulate a failure in sending the optout ping by disabling the HTTP server.
// Simulate a failure in sending the deletion ping by disabling the HTTP server.
await PingServer.stop();
// Try to send a ping. It will be saved as pending and get deleted when disabling upload.
TelemetryController.submitExternalPing(TEST_PING_TYPE, {});
// Disable FHR upload to send a optout ping again.
// Disable FHR upload to send a deletion ping again.
Preferences.set(TelemetryUtils.Preferences.FhrUploadEnabled, false);
// Wait on sending activity to settle, as |TelemetryController.testReset()| doesn't do that.
@ -202,8 +174,8 @@ add_task(async function test_disableDataUpload() {
// Disabling Telemetry upload must clear out all the pending pings.
let pendingPings = await TelemetryStorage.loadPendingPingList();
Assert.equal(pendingPings.length, 0,
"All the pending pings should have been deleted, including the optout ping");
Assert.equal(pendingPings.length, 1,
"All the pending pings but the deletion ping should have been deleted");
// Enable the ping server again.
PingServer.start();
@ -215,20 +187,8 @@ add_task(async function test_disableDataUpload() {
await TelemetrySend.shutdown();
// Reset the controller to spin the ping sending task.
await TelemetryController.testReset();
// Re-enable Telemetry
Preferences.set(TelemetryUtils.Preferences.FhrUploadEnabled, true);
// Send a test ping
await sendPing(true, false);
// We should have only received the test ping
ping = await PingServer.promiseNextPing();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
// The data in the test ping should be different than before
Assert.notEqual(TelemetryUtils.knownClientID, ping.clientId, "Client ID should be reset to a random value");
Assert.notEqual(firstClientId, ping.clientId, "Client ID should be different from the previous value");
checkPingFormat(ping, DELETION_PING_TYPE, true, false);
// Wait on ping activity to settle before moving on to the next test. If we were
// to shut down telemetry, even though the PingServer caught the expected pings,
@ -236,6 +196,8 @@ add_task(async function test_disableDataUpload() {
// a couple of ticks). Shutting down would cancel the request and save them as
// pending pings.
await TelemetrySend.testWaitOnOutgoingPings();
// Restore FHR Upload.
Preferences.set(TelemetryUtils.Preferences.FhrUploadEnabled, true);
});
add_task(async function test_pingHasClientId() {
@ -331,11 +293,11 @@ add_task(async function test_archivePings() {
const uploadPref = isUnified ? TelemetryUtils.Preferences.FhrUploadEnabled : TelemetryUtils.Preferences.TelemetryEnabled;
Preferences.set(uploadPref, false);
// If we're using unified telemetry, disabling ping upload will generate a "optout"
// If we're using unified telemetry, disabling ping upload will generate a "deletion"
// ping. Catch it.
if (isUnified) {
let ping = await PingServer.promiseNextPing();
checkPingFormat(ping, OPTOUT_PING_TYPE, false, false);
checkPingFormat(ping, DELETION_PING_TYPE, true, false);
}
// Register a new Ping Handler that asserts if a ping is received, then send a ping.

Просмотреть файл

@ -352,7 +352,7 @@ add_task(async function test_pendingPingsQuota() {
await TelemetrySend.testWaitOnOutgoingPings();
await TelemetryStorage.testPendingQuotaTaskPromise();
// Remove the pending optout ping generated when flipping FHR upload off.
// Remove the pending deletion ping generated when flipping FHR upload off.
await TelemetryStorage.testClearPendingPings();
let expectedPrunedPings = [];

Просмотреть файл

@ -56,7 +56,7 @@ var ClientID = Object.freeze({
return ClientIDImpl.getClientID();
},
/**
/**
* Get the client id synchronously without hitting the disk.
* This returns:
* - the current on-disk client id if it was already loaded
@ -67,31 +67,6 @@ var ClientID = Object.freeze({
return ClientIDImpl.getCachedClientID();
},
/**
* Set a specific client id asynchronously, writing it to disk
* and updating the cached version.
*
* Should only ever be used when a known client ID value should be set.
* Use `resetClientID` to generate a new random one if required.
*
* @return {Promise<string>} The stable client ID.
*/
setClientID(id) {
return ClientIDImpl.setClientID(id);
},
/**
* Reset the client id asynchronously, writing it to disk
* and updating the cached version.
*
* Should only be used if a reset is explicitely requested by the user.
*
* @return {Promise<string>} A new stable client ID.
*/
resetClientID() {
return ClientIDImpl.resetClientID();
},
/**
* Only used for testing. Invalidates the client ID so that it gets read
* again from file.
@ -105,7 +80,6 @@ var ClientIDImpl = {
_clientID: null,
_loadClientIdTask: null,
_saveClientIdTask: null,
_removeClientIdTask: null,
_logger: null,
_loadClientID() {
@ -124,9 +98,6 @@ var ClientIDImpl = {
* If no Client ID is found, we generate a new one.
*/
async _doLoadClientID() {
// If there's a removal in progress, let's wait for it
await this._removeClientIdTask;
// Try to load the client id from the DRS state file.
try {
let state = await CommonUtils.readJSON(gStateFilePath);
@ -221,40 +192,6 @@ var ClientIDImpl = {
this._clientID = null;
},
async setClientID(id) {
if (!this.updateClientID(id)) {
throw ("Invalid client ID: " + id);
}
this._saveClientIdTask = this._saveClientID();
await this._saveClientIdTask;
return this._clientID;
},
async _doRemoveClientID() {
// Reset stored id.
this._clientID = null;
// Clear the client id from the preference cache.
Services.prefs.clearUserPref(PREF_CACHED_CLIENTID);
// Remove the client id from disk
await OS.File.remove(gStateFilePath, {ignoreAbsent: true});
},
async resetClientID() {
// Wait for the removal.
// Asynchronous calls to getClientID will also be blocked on this.
this._removeClientIdTask = this._doRemoveClientID();
let clear = () => this._removeClientIdTask = null;
this._removeClientIdTask.then(clear, clear);
await this._removeClientIdTask;
// Generate a new id.
return this.getClientID();
},
/**
* Sets the client id to the given value and updates the value cached in
* preferences only if the given id is a valid.

Просмотреть файл

@ -8,8 +8,6 @@ ChromeUtils.import("resource://services-common/utils.js");
ChromeUtils.import("resource://gre/modules/osfile.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const PREF_CACHED_CLIENTID = "toolkit.telemetry.cachedClientID";
function run_test() {
do_get_profile();
run_next_test();
@ -26,6 +24,7 @@ add_task(async function() {
["", "setStringPref"],
["3d1e1560-682a-4043-8cf2-aaaaaaaaaaaZ", "setStringPref"],
];
const PREF_CACHED_CLIENTID = "toolkit.telemetry.cachedClientID";
// If there is no DRS file, we should get a new client ID.
await ClientID._reset();
@ -61,72 +60,3 @@ add_task(async function() {
"ClientID should reset invalid cached IDs");
}
});
add_task(async function test_setClientID() {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const invalidIDs = [
-1,
0.5,
"INVALID-UUID",
true,
"",
"3d1e1560-682a-4043-8cf2-aaaaaaaaaaaZ",
];
const KNOWN_UUID = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
await ClientID._reset();
// We should be able to set a valid UUID
await ClientID.setClientID(KNOWN_UUID);
let clientID = await ClientID.getClientID();
Assert.equal(KNOWN_UUID, clientID);
// Setting invalid UUIDs should always fail and not modify the client ID
for (let invalidID of invalidIDs) {
await ClientID._reset();
let prevClientID = await ClientID.getClientID();
await ClientID.setClientID(invalidID)
.then(() => Assert.ok(false, `Invalid client ID '${invalidID}' should be rejected`))
.catch(() => Assert.ok(true));
clientID = await ClientID.getClientID();
Assert.equal(typeof(clientID), "string");
Assert.ok(uuidRegex.test(clientID));
Assert.equal(prevClientID, clientID);
}
});
add_task(async function test_resetClientID() {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
// We should get a valid UUID after reset
await ClientID._reset();
let firstClientID = await ClientID.getClientID();
Assert.equal(typeof(firstClientID), "string");
Assert.ok(uuidRegex.test(firstClientID));
// When resetting again we should get a new ID
let nextClientID = await ClientID.resetClientID();
Assert.equal(typeof(nextClientID), "string");
Assert.ok(uuidRegex.test(nextClientID));
Assert.notEqual(firstClientID, nextClientID, "After reset client ID should be different.");
let cachedID = ClientID.getCachedClientID();
Assert.equal(nextClientID, cachedID);
let prefClientID = Services.prefs.getStringPref(PREF_CACHED_CLIENTID, null);
Assert.equal(nextClientID, prefClientID);
});
add_task(async function test_resetParallelGet() {
// We should get a valid UUID after reset
let firstClientID = await ClientID.resetClientID();
// We should get the same ID twice when requesting it in parallel to a reset.
let p = ClientID.resetClientID();
let newClientID = await ClientID.getClientID();
let otherClientID = await p;
Assert.notEqual(firstClientID, newClientID, "After reset client ID should be different.");
Assert.equal(newClientID, otherClientID, "Getting the client ID in parallel to a reset should give the same id.");
});