Bug 1501329 - Persist information about canary after resetting client ID r=chutten

We erroneously reset client IDs on Fennec to a canary client ID.
This is now detected and a new valid and random client ID is set.

This adds a new boolean attribute "wasCanary" to the `state.json` file
generated by ClientID.jsm.

Depends on D9544

Differential Revision: https://phabricator.services.mozilla.com/D9903

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan-Erik Rediger 2018-10-26 18:01:13 +00:00
Родитель b604174729
Коммит b463e79733
4 изменённых файлов: 67 добавлений и 3 удалений

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

@ -15,10 +15,10 @@ const PING_FORMAT_VERSION = 4;
const OPTOUT_PING_TYPE = "optout";
const TEST_PING_TYPE = "test-ping-type";
function sendPing() {
function sendPing(addEnvironment = false) {
let options = {
addClientId: true,
addEnvironment: false,
addEnvironment,
};
return TelemetryController.submitExternalPing(TEST_PING_TYPE, {}, options);
}
@ -211,6 +211,7 @@ add_task(async function test_clientid_canary_nonunified_no_pref_trigger() {
// Restart the instance
await TelemetryController.testShutdown();
await TelemetryStorage.testClearPendingPings();
await TelemetryController.testReset();
let newClientId = await ClientID.getClientID();
@ -221,6 +222,7 @@ add_task(async function test_clientid_canary_nonunified_no_pref_trigger() {
// Restart the instance
await TelemetryController.testShutdown();
await TelemetryStorage.testClearPendingPings();
await TelemetryController.testReset();
newClientId = await ClientID.getClientID();

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

@ -9,9 +9,12 @@ var EXPORTED_SYMBOLS = ["ClientID"];
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/Log.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
const LOGGER_NAME = "Toolkit.Telemetry";
const LOGGER_PREFIX = "ClientID::";
// Must match ID in TelemetryUtils
const CANARY_CLIENT_ID = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
ChromeUtils.defineModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
@ -56,6 +59,18 @@ var ClientID = Object.freeze({
return ClientIDImpl.getClientID();
},
/**
* This returns true if the client ID prior to the last client ID reset was a canary client ID.
* Android only. Always returns null on Desktop.
*/
wasCanaryClientID() {
if (AppConstants.platform == "android") {
return ClientIDImpl.wasCanaryClientID();
}
return null;
},
/**
* Get the client id synchronously without hitting the disk.
* This returns:
@ -107,6 +122,7 @@ var ClientIDImpl = {
_saveClientIdTask: null,
_removeClientIdTask: null,
_logger: null,
_wasCanary: null,
_loadClientID() {
if (this._loadClientIdTask) {
@ -130,6 +146,9 @@ var ClientIDImpl = {
// Try to load the client id from the DRS state file.
try {
let state = await CommonUtils.readJSON(gStateFilePath);
if (AppConstants.platform == "android" && state && "wasCanary" in state) {
this._wasCanary = state.wasCanary;
}
if (state && this.updateClientID(state.clientID)) {
return this._clientID;
}
@ -157,6 +176,10 @@ var ClientIDImpl = {
*/
async _saveClientID() {
let obj = { clientID: this._clientID };
// We detected a canary client ID when resetting, storing this as a flag
if (AppConstants.platform == "android" && this._wasCanary) {
obj.wasCanary = true;
}
await OS.File.makeDir(gDatareportingPath);
await CommonUtils.writeJSON(obj, gStateFilePath);
this._saveClientIdTask = null;
@ -176,6 +199,14 @@ var ClientIDImpl = {
return Promise.resolve(this._clientID);
},
/**
* This returns true if the client ID prior to the last client ID reset was a canary client ID.
* Android only. Always returns null on Desktop.
*/
wasCanaryClientID() {
return this._wasCanary;
},
/**
* Get the client id synchronously without hitting the disk.
* This returns:
@ -243,6 +274,8 @@ var ClientIDImpl = {
},
async resetClientID() {
let oldClientId = this._clientID;
// Wait for the removal.
// Asynchronous calls to getClientID will also be blocked on this.
this._removeClientIdTask = this._doRemoveClientID();
@ -251,6 +284,11 @@ var ClientIDImpl = {
await this._removeClientIdTask;
// On Android we detect resets after a canary client ID.
if (AppConstants.platform == "android" ) {
this._wasCanary = oldClientId == CANARY_CLIENT_ID;
}
// Generate a new id.
return this.getClientID();
},

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

@ -7,6 +7,7 @@ ChromeUtils.import("resource://gre/modules/ClientID.jsm");
ChromeUtils.import("resource://services-common/utils.js");
ChromeUtils.import("resource://gre/modules/osfile.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
const PREF_CACHED_CLIENTID = "toolkit.telemetry.cachedClientID";
@ -130,3 +131,27 @@ add_task(async function test_resetParallelGet() {
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.");
});
add_task({
skip_if: () => AppConstants.platform != "android",
}, async function test_FennecCanaryDetect() {
const KNOWN_UUID = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
// We should get a valid UUID after reset
let firstClientID = await ClientID.resetClientID();
Assert.notEqual(KNOWN_UUID, firstClientID, "Client ID should be random.");
// Set the canary client ID.
await ClientID.setClientID(KNOWN_UUID);
Assert.equal(KNOWN_UUID, await ClientID.getClientID(), "Client ID should be known canary.");
let newClientID = await ClientID.resetClientID();
Assert.notEqual(KNOWN_UUID, newClientID, "After reset Client ID should be random.");
Assert.notEqual(firstClientID, newClientID, "After reset Client ID should be new.");
Assert.ok(ClientID.wasCanaryClientID(), "After reset we should have detected a canary client ID");
let clientID = await ClientID.resetClientID();
Assert.notEqual(KNOWN_UUID, clientID, "After reset Client ID should be random.");
Assert.notEqual(newClientID, clientID, "After reset Client ID should be new.");
Assert.ok(!ClientID.wasCanaryClientID(), "After reset we should not have detected a canary client ID");
});

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

@ -12,7 +12,6 @@ support-files =
skip-if = toolkit == 'android'
[test_CanonicalJSON.js]
[test_client_id.js]
skip-if = toolkit == 'android'
[test_Color.js]
[test_CreditCard.js]
[test_DeferredTask.js]