mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
Remove healthreport telemetry module from Sync + tests
This commit is contained in:
parent
56e3c42f4e
commit
b2be364394
8 changed files with 0 additions and 1089 deletions
|
|
@ -1,262 +0,0 @@
|
|||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"SyncProvider",
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm", this);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", this);
|
||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
|
||||
const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC};
|
||||
const DAILY_LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT};
|
||||
const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
|
||||
"resource://services-sync/main.js");
|
||||
|
||||
function SyncMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
SyncMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "sync",
|
||||
version: 1,
|
||||
|
||||
fields: {
|
||||
enabled: DAILY_LAST_NUMERIC_FIELD,
|
||||
preferredProtocol: DAILY_LAST_TEXT_FIELD,
|
||||
activeProtocol: DAILY_LAST_TEXT_FIELD,
|
||||
syncStart: DAILY_COUNTER_FIELD,
|
||||
syncSuccess: DAILY_COUNTER_FIELD,
|
||||
syncError: DAILY_COUNTER_FIELD,
|
||||
},
|
||||
});
|
||||
|
||||
function SyncDevicesMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
SyncDevicesMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "devices",
|
||||
version: 1,
|
||||
|
||||
fields: {},
|
||||
|
||||
shouldIncludeField: function (name) {
|
||||
return true;
|
||||
},
|
||||
|
||||
fieldType: function (name) {
|
||||
return Metrics.Storage.FIELD_DAILY_COUNTER;
|
||||
},
|
||||
});
|
||||
|
||||
function SyncMigrationMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
SyncMigrationMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "migration",
|
||||
version: 1,
|
||||
|
||||
fields: {
|
||||
state: DAILY_LAST_TEXT_FIELD, // last "user" or "internal" state we saw for the day
|
||||
accepted: DAILY_COUNTER_FIELD, // number of times user tried to start migration
|
||||
declined: DAILY_COUNTER_FIELD, // number of times user closed nagging infobar
|
||||
unlinked: DAILY_LAST_NUMERIC_FIELD, // did the user decline and unlink
|
||||
},
|
||||
});
|
||||
|
||||
this.SyncProvider = function () {
|
||||
Metrics.Provider.call(this);
|
||||
};
|
||||
SyncProvider.prototype = Object.freeze({
|
||||
__proto__: Metrics.Provider.prototype,
|
||||
|
||||
name: "org.mozilla.sync",
|
||||
|
||||
measurementTypes: [
|
||||
SyncDevicesMeasurement1,
|
||||
SyncMeasurement1,
|
||||
SyncMigrationMeasurement1,
|
||||
],
|
||||
|
||||
_OBSERVERS: [
|
||||
"weave:service:sync:start",
|
||||
"weave:service:sync:finish",
|
||||
"weave:service:sync:error",
|
||||
"fxa-migration:state-changed",
|
||||
"fxa-migration:internal-state-changed",
|
||||
"fxa-migration:internal-telemetry",
|
||||
],
|
||||
|
||||
postInit: function () {
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.addObserver(this, o, false);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
onShutdown: function () {
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.removeObserver(this, o);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
observe: function (subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "weave:service:sync:start":
|
||||
case "weave:service:sync:finish":
|
||||
case "weave:service:sync:error":
|
||||
return this._observeSync(subject, topic, data);
|
||||
|
||||
case "fxa-migration:state-changed":
|
||||
case "fxa-migration:internal-state-changed":
|
||||
case "fxa-migration:internal-telemetry":
|
||||
return this._observeMigration(subject, topic, data);
|
||||
}
|
||||
Cu.reportError("unexpected topic in sync healthreport provider: " + topic);
|
||||
},
|
||||
|
||||
_observeSync: function (subject, topic, data) {
|
||||
let field;
|
||||
switch (topic) {
|
||||
case "weave:service:sync:start":
|
||||
field = "syncStart";
|
||||
break;
|
||||
|
||||
case "weave:service:sync:finish":
|
||||
field = "syncSuccess";
|
||||
break;
|
||||
|
||||
case "weave:service:sync:error":
|
||||
field = "syncError";
|
||||
break;
|
||||
|
||||
default:
|
||||
Cu.reportError("unexpected sync topic in sync healthreport provider: " + topic);
|
||||
return;
|
||||
}
|
||||
|
||||
let m = this.getMeasurement(SyncMeasurement1.prototype.name,
|
||||
SyncMeasurement1.prototype.version);
|
||||
return this.enqueueStorageOperation(function recordSyncEvent() {
|
||||
return m.incrementDailyCounter(field);
|
||||
});
|
||||
},
|
||||
|
||||
_observeMigration: function(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "fxa-migration:state-changed":
|
||||
case "fxa-migration:internal-state-changed": {
|
||||
// We record both "user" and "internal" states in the same field. This
|
||||
// works for us as user state is always null when there is an internal
|
||||
// state.
|
||||
if (!data) {
|
||||
return; // we don't count the |null| state
|
||||
}
|
||||
let m = this.getMeasurement(SyncMigrationMeasurement1.prototype.name,
|
||||
SyncMigrationMeasurement1.prototype.version);
|
||||
return this.enqueueStorageOperation(function() {
|
||||
return m.setDailyLastText("state", data);
|
||||
});
|
||||
}
|
||||
|
||||
case "fxa-migration:internal-telemetry": {
|
||||
// |data| is our field name.
|
||||
let m = this.getMeasurement(SyncMigrationMeasurement1.prototype.name,
|
||||
SyncMigrationMeasurement1.prototype.version);
|
||||
return this.enqueueStorageOperation(function() {
|
||||
switch (data) {
|
||||
case "accepted":
|
||||
case "declined":
|
||||
return m.incrementDailyCounter(data);
|
||||
case "unlinked":
|
||||
return m.setDailyLastNumeric(data, 1);
|
||||
default:
|
||||
Cu.reportError("Unexpected migration field in sync healthreport provider: " + data);
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
Cu.reportError("unexpected migration topic in sync healthreport provider: " + topic);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
collectDailyData: function () {
|
||||
return this.storage.enqueueTransaction(this._populateDailyData.bind(this));
|
||||
},
|
||||
|
||||
_populateDailyData: function* () {
|
||||
let m = this.getMeasurement(SyncMeasurement1.prototype.name,
|
||||
SyncMeasurement1.prototype.version);
|
||||
|
||||
let svc = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
|
||||
let enabled = svc.enabled;
|
||||
yield m.setDailyLastNumeric("enabled", enabled ? 1 : 0);
|
||||
|
||||
// preferredProtocol is constant and only changes as the client
|
||||
// evolves.
|
||||
yield m.setDailyLastText("preferredProtocol", "1.5");
|
||||
|
||||
let protocol = svc.fxAccountsEnabled ? "1.5" : "1.1";
|
||||
yield m.setDailyLastText("activeProtocol", protocol);
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Before grabbing more information, be sure the Sync service
|
||||
// is fully initialized. This has the potential to initialize
|
||||
// Sync on the spot. This may be undesired if Sync appears to
|
||||
// be enabled but it really isn't. That responsibility should
|
||||
// be up to svc.enabled to not return false positives, however.
|
||||
yield svc.whenLoaded();
|
||||
|
||||
if (Weave.Status.service != Weave.STATUS_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Device types are dynamic. So we need to dynamically create fields if
|
||||
// they don't exist.
|
||||
let dm = this.getMeasurement(SyncDevicesMeasurement1.prototype.name,
|
||||
SyncDevicesMeasurement1.prototype.version);
|
||||
let devices = Weave.Service.clientsEngine.deviceTypes;
|
||||
for (let [field, count] of devices) {
|
||||
let hasField = this.storage.hasFieldFromMeasurement(dm.id, field,
|
||||
this.storage.FIELD_DAILY_LAST_NUMERIC);
|
||||
let fieldID;
|
||||
if (hasField) {
|
||||
fieldID = this.storage.fieldIDFromMeasurement(dm.id, field);
|
||||
} else {
|
||||
fieldID = yield this.storage.registerField(dm.id, field,
|
||||
this.storage.FIELD_DAILY_LAST_NUMERIC);
|
||||
}
|
||||
|
||||
yield this.storage.setDailyLastNumericFromFieldID(fieldID, count);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -21,7 +21,6 @@ EXTRA_JS_MODULES['services-sync'] += [
|
|||
'modules/addonutils.js',
|
||||
'modules/browserid_identity.js',
|
||||
'modules/engines.js',
|
||||
'modules/healthreport.jsm',
|
||||
'modules/identity.js',
|
||||
'modules/jpakeclient.js',
|
||||
'modules/keys.js',
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// Simple test for block/unblock.
|
||||
add_task(function *() {
|
||||
Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.")
|
||||
Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref");
|
||||
Weave.Service.scheduler.blockSync();
|
||||
|
||||
Assert.ok(Weave.Service.scheduler.isBlocked, "sync is blocked.")
|
||||
Assert.ok(Svc.Prefs.has("scheduler.blocked-until"), "have the blocked pref");
|
||||
|
||||
Weave.Service.scheduler.unblockSync();
|
||||
Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.")
|
||||
Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref");
|
||||
|
||||
// now check the "until" functionality.
|
||||
let until = Date.now() + 1000;
|
||||
Weave.Service.scheduler.blockSync(until);
|
||||
Assert.ok(Weave.Service.scheduler.isBlocked, "sync is blocked.")
|
||||
Assert.ok(Svc.Prefs.has("scheduler.blocked-until"), "have the blocked pref");
|
||||
|
||||
// wait for 'until' to pass.
|
||||
yield new Promise((resolve, reject) => {
|
||||
CommonUtils.namedTimer(resolve, 1000, {}, "timer");
|
||||
});
|
||||
|
||||
// should have automagically unblocked and removed the pref.
|
||||
Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.")
|
||||
Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref");
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
// Test the FxAMigration module
|
||||
Cu.import("resource://services-sync/FxaMigrator.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
Cu.import("resource://services-sync/browserid_identity.js");
|
||||
|
||||
// Set our username pref early so sync initializes with the legacy provider.
|
||||
Services.prefs.setCharPref("services.sync.username", "foo");
|
||||
// And ensure all debug messages end up being printed.
|
||||
Services.prefs.setCharPref("services.sync.log.appender.dump", "Debug");
|
||||
|
||||
// Now import sync
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// And reset the username.
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
|
||||
Cu.import("resource://testing-common/services/sync/utils.js");
|
||||
Cu.import("resource://testing-common/services/common/logging.js");
|
||||
Cu.import("resource://testing-common/services/sync/rotaryengine.js");
|
||||
|
||||
const FXA_USERNAME = "someone@somewhere";
|
||||
|
||||
// Utilities
|
||||
function promiseOneObserver(topic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let observer = function(subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
resolve({ subject: subject, data: data });
|
||||
}
|
||||
Services.obs.addObserver(observer, topic, false);
|
||||
});
|
||||
}
|
||||
|
||||
function promiseStopServer(server) {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Helpers
|
||||
function configureLegacySync() {
|
||||
let engine = new RotaryEngine(Service);
|
||||
engine.enabled = true;
|
||||
Svc.Prefs.set("registerEngines", engine.name);
|
||||
Svc.Prefs.set("log.logger.engine.rotary", "Trace");
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {rotary: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
crypto: {},
|
||||
rotary: {}
|
||||
};
|
||||
|
||||
const USER = "foo";
|
||||
const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea";
|
||||
|
||||
setBasicCredentials(USER, "password", PASSPHRASE);
|
||||
|
||||
let onRequest = function(request, response) {
|
||||
// ideally we'd only do this while a legacy user is configured, but WTH.
|
||||
response.setHeader("x-weave-alert", JSON.stringify({code: "soft-eol"}));
|
||||
}
|
||||
let server = new SyncServer({onRequest: onRequest});
|
||||
server.registerUser(USER, "password");
|
||||
server.createContents(USER, contents);
|
||||
server.start();
|
||||
|
||||
Service.serverURL = server.baseURI;
|
||||
Service.clusterURL = server.baseURI;
|
||||
Service.identity.username = USER;
|
||||
Service._updateCachedURLs();
|
||||
|
||||
Service.engineManager._engines[engine.name] = engine;
|
||||
|
||||
return [engine, server];
|
||||
}
|
||||
|
||||
function configureFxa() {
|
||||
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost");
|
||||
}
|
||||
|
||||
add_task(function *testMigration() {
|
||||
configureFxa();
|
||||
|
||||
// when we do a .startOver we want the new provider.
|
||||
let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity");
|
||||
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", false);
|
||||
|
||||
// disable the addons engine - this engine choice is arbitrary, but we
|
||||
// want to check it remains disabled after migration.
|
||||
Services.prefs.setBoolPref("services.sync.engine.addons", false);
|
||||
|
||||
do_register_cleanup(() => {
|
||||
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", oldValue)
|
||||
Services.prefs.setBoolPref("services.sync.engine.addons", true);
|
||||
});
|
||||
|
||||
// No sync user - that should report no user-action necessary.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null,
|
||||
"no user state when complete");
|
||||
|
||||
// Arrange for a legacy sync user and manually bump the migrator
|
||||
let [engine, server] = configureLegacySync();
|
||||
|
||||
// Check our disabling of the "addons" engine worked, and for good measure,
|
||||
// that the "passwords" engine is enabled.
|
||||
Assert.ok(!Service.engineManager.get("addons").enabled, "addons is disabled");
|
||||
Assert.ok(Service.engineManager.get("passwords").enabled, "passwords is enabled");
|
||||
|
||||
// monkey-patch the migration sentinel code so we know it was called.
|
||||
let haveStartedSentinel = false;
|
||||
let origSetFxAMigrationSentinel = Service.setFxAMigrationSentinel;
|
||||
let promiseSentinelWritten = new Promise((resolve, reject) => {
|
||||
Service.setFxAMigrationSentinel = function(arg) {
|
||||
haveStartedSentinel = true;
|
||||
return origSetFxAMigrationSentinel.call(Service, arg).then(result => {
|
||||
Service.setFxAMigrationSentinel = origSetFxAMigrationSentinel;
|
||||
resolve(result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// We are now configured for legacy sync, but we aren't in an EOL state yet,
|
||||
// so should still be not waiting for a user.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null,
|
||||
"no user state before server EOL");
|
||||
|
||||
// Start a sync - this will cause an EOL notification which the migrator's
|
||||
// observer will notice.
|
||||
let promise = promiseOneObserver("fxa-migration:state-changed");
|
||||
_("Starting sync");
|
||||
Service.sync();
|
||||
_("Finished sync");
|
||||
|
||||
// We should have seen the observer, so be waiting for an FxA user.
|
||||
Assert.equal((yield promise).data, fxaMigrator.STATE_USER_FXA, "now waiting for FxA.")
|
||||
|
||||
// Re-calling our user-state promise should also reflect the same state.
|
||||
Assert.equal((yield fxaMigrator._queueCurrentUserState()),
|
||||
fxaMigrator.STATE_USER_FXA,
|
||||
"still waiting for FxA.");
|
||||
|
||||
// arrange for an unverified FxA user.
|
||||
let config = makeIdentityConfig({username: FXA_USERNAME});
|
||||
let fxa = new FxAccounts({});
|
||||
config.fxaccount.user.email = config.username;
|
||||
delete config.fxaccount.user.verified;
|
||||
// *sob* - shouldn't need this boilerplate
|
||||
fxa.internal.currentAccountState.getCertificate = function(data, keyPair, mustBeValidUntil) {
|
||||
this.cert = {
|
||||
validUntil: fxa.internal.now() + CERT_LIFETIME,
|
||||
cert: "certificate",
|
||||
};
|
||||
return Promise.resolve(this.cert.cert);
|
||||
};
|
||||
|
||||
// As soon as we set the FxA user the observers should fire and magically
|
||||
// transition.
|
||||
promise = promiseOneObserver("fxa-migration:state-changed");
|
||||
fxAccounts.setSignedInUser(config.fxaccount.user);
|
||||
|
||||
let observerInfo = yield promise;
|
||||
Assert.equal(observerInfo.data,
|
||||
fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"now waiting for verification");
|
||||
Assert.ok(observerInfo.subject instanceof Ci.nsISupportsString,
|
||||
"email was passed to observer");
|
||||
Assert.equal(observerInfo.subject.data,
|
||||
FXA_USERNAME,
|
||||
"email passed to observer is correct");
|
||||
|
||||
// should have seen the user set, so state should automatically update.
|
||||
Assert.equal((yield fxaMigrator._queueCurrentUserState()),
|
||||
fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"now waiting for verification");
|
||||
|
||||
// Before we verify the user, fire off a sync that calls us back during
|
||||
// the sync and before it completes - this way we can ensure we do the right
|
||||
// thing in terms of blocking sync and waiting for it to complete.
|
||||
|
||||
let wasWaiting = false;
|
||||
// This is a PITA as sync is pseudo-blocking.
|
||||
engine._syncFinish = function () {
|
||||
// We aren't in a generator here, so use a helper to block on promises.
|
||||
function getState() {
|
||||
let cb = Async.makeSpinningCallback();
|
||||
fxaMigrator._queueCurrentUserState().then(state => cb(null, state));
|
||||
return cb.wait();
|
||||
}
|
||||
// should still be waiting for verification.
|
||||
Assert.equal(getState(), fxaMigrator.STATE_USER_FXA_VERIFIED,
|
||||
"still waiting for verification");
|
||||
|
||||
// arrange for the user to be verified. The fxAccount's mock story is
|
||||
// broken, so go behind its back.
|
||||
config.fxaccount.user.verified = true;
|
||||
fxAccounts.setSignedInUser(config.fxaccount.user);
|
||||
Services.obs.notifyObservers(null, ONVERIFIED_NOTIFICATION, null);
|
||||
|
||||
// spinningly wait for the migrator to catch up - sync is running so
|
||||
// we should be in a 'null' user-state as there is no user-action
|
||||
// necessary.
|
||||
let cb = Async.makeSpinningCallback();
|
||||
promiseOneObserver("fxa-migration:state-changed").then(({ data: state }) => cb(null, state));
|
||||
Assert.equal(cb.wait(), null, "no user action necessary while sync completes.");
|
||||
|
||||
// We must not have started writing the sentinel yet.
|
||||
Assert.ok(!haveStartedSentinel, "haven't written a sentinel yet");
|
||||
|
||||
// sync should be blocked from continuing
|
||||
Assert.ok(Service.scheduler.isBlocked, "sync is blocked.")
|
||||
|
||||
wasWaiting = true;
|
||||
throw ex;
|
||||
};
|
||||
|
||||
_("Starting sync");
|
||||
Service.sync();
|
||||
_("Finished sync");
|
||||
|
||||
// mock sync so we can ensure the final sync is scheduled with the FxA user.
|
||||
// (letting a "normal" sync complete is a PITA without mocking huge amounts
|
||||
// of FxA infra)
|
||||
let promiseFinalSync = new Promise((resolve, reject) => {
|
||||
let oldSync = Service.sync;
|
||||
Service.sync = function() {
|
||||
Service.sync = oldSync;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
Assert.ok(wasWaiting, "everything was good while sync was running.")
|
||||
|
||||
// The migration is now going to run to completion.
|
||||
// sync should still be "blocked"
|
||||
Assert.ok(Service.scheduler.isBlocked, "sync is blocked.");
|
||||
|
||||
// We should see the migration sentinel written and it should return true.
|
||||
Assert.ok((yield promiseSentinelWritten), "wrote the sentinel");
|
||||
|
||||
// And we should see a new sync start
|
||||
yield promiseFinalSync;
|
||||
|
||||
// and we should be configured for FxA
|
||||
let WeaveService = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
Assert.ok(WeaveService.fxAccountsEnabled, "FxA is enabled");
|
||||
Assert.ok(Service.identity instanceof BrowserIDManager,
|
||||
"sync is configured with the browserid_identity provider.");
|
||||
Assert.equal(Service.identity.username, config.username, "correct user configured")
|
||||
Assert.ok(!Service.scheduler.isBlocked, "sync is not blocked.")
|
||||
// and the user state should remain null.
|
||||
Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()),
|
||||
null,
|
||||
"still no user action necessary");
|
||||
// and our engines should be in the same enabled/disabled state as before.
|
||||
Assert.ok(!Service.engineManager.get("addons").enabled, "addons is still disabled");
|
||||
Assert.ok(Service.engineManager.get("passwords").enabled, "passwords is still enabled");
|
||||
|
||||
// aaaand, we are done - clean up.
|
||||
yield promiseStopServer(server);
|
||||
});
|
||||
|
||||
|
||||
function run_test() {
|
||||
initTestLogging();
|
||||
do_register_cleanup(() => {
|
||||
fxaMigrator.finalize();
|
||||
Svc.Prefs.resetBranch("");
|
||||
});
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the reading and writing of the sync migration sentinel.
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js");
|
||||
|
||||
Cu.import("resource://testing-common/services/sync/utils.js");
|
||||
Cu.import("resource://testing-common/services/common/logging.js");
|
||||
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
|
||||
// Set our username pref early so sync initializes with the legacy provider.
|
||||
Services.prefs.setCharPref("services.sync.username", "foo");
|
||||
|
||||
// Now import sync
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
|
||||
const USER = "foo";
|
||||
const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea";
|
||||
|
||||
function promiseStopServer(server) {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.stop(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
let numServerRequests = 0;
|
||||
|
||||
// Helpers
|
||||
function configureLegacySync() {
|
||||
let contents = {
|
||||
meta: {global: {}},
|
||||
crypto: {},
|
||||
};
|
||||
|
||||
setBasicCredentials(USER, "password", PASSPHRASE);
|
||||
|
||||
numServerRequests = 0;
|
||||
let server = new SyncServer({
|
||||
onRequest: () => {
|
||||
++numServerRequests
|
||||
}
|
||||
});
|
||||
server.registerUser(USER, "password");
|
||||
server.createContents(USER, contents);
|
||||
server.start();
|
||||
|
||||
Service.serverURL = server.baseURI;
|
||||
Service.clusterURL = server.baseURI;
|
||||
Service.identity.username = USER;
|
||||
Service._updateCachedURLs();
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
// Test a simple round-trip of the get/set functions.
|
||||
add_task(function *() {
|
||||
// Arrange for a legacy sync user.
|
||||
let server = configureLegacySync();
|
||||
|
||||
Assert.equal((yield Service.getFxAMigrationSentinel()), null, "no sentinel to start");
|
||||
|
||||
let sentinel = {foo: "bar"};
|
||||
yield Service.setFxAMigrationSentinel(sentinel);
|
||||
|
||||
Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back");
|
||||
|
||||
yield promiseStopServer(server);
|
||||
});
|
||||
|
||||
// Test the records are cached by the record manager.
|
||||
add_task(function *() {
|
||||
// Arrange for a legacy sync user.
|
||||
let server = configureLegacySync();
|
||||
Service.login();
|
||||
|
||||
// Reset the request count here as the login would have made some.
|
||||
numServerRequests = 0;
|
||||
|
||||
Assert.equal((yield Service.getFxAMigrationSentinel()), null, "no sentinel to start");
|
||||
Assert.equal(numServerRequests, 1, "first fetch should hit the server");
|
||||
|
||||
let sentinel = {foo: "bar"};
|
||||
yield Service.setFxAMigrationSentinel(sentinel);
|
||||
Assert.equal(numServerRequests, 2, "setting sentinel should hit the server");
|
||||
|
||||
Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back");
|
||||
Assert.equal(numServerRequests, 2, "second fetch should not should hit the server");
|
||||
|
||||
// Clobber the caches and ensure we still get the correct value back when we
|
||||
// do hit the server.
|
||||
Service.recordManager.clearCache();
|
||||
Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back");
|
||||
Assert.equal(numServerRequests, 3, "should have re-hit the server with empty caches");
|
||||
|
||||
yield promiseStopServer(server);
|
||||
});
|
||||
|
||||
// Test the records are cached by a sync.
|
||||
add_task(function* () {
|
||||
let server = configureLegacySync();
|
||||
|
||||
// A first sync clobbers meta/global due to it being empty, so we first
|
||||
// do a sync which forces a good set of data on the server.
|
||||
Service.sync();
|
||||
|
||||
// Now create a sentinel exists on the server. It's encrypted, so we need to
|
||||
// put an encrypted version.
|
||||
let cryptoWrapper = new CryptoWrapper("meta", "fxa_credentials");
|
||||
let sentinel = {foo: "bar"};
|
||||
cryptoWrapper.cleartext = {
|
||||
id: "fxa_credentials",
|
||||
sentinel: sentinel,
|
||||
deleted: false,
|
||||
}
|
||||
cryptoWrapper.encrypt(Service.identity.syncKeyBundle);
|
||||
let payload = {
|
||||
ciphertext: cryptoWrapper.ciphertext,
|
||||
IV: cryptoWrapper.IV,
|
||||
hmac: cryptoWrapper.hmac,
|
||||
};
|
||||
|
||||
server.createContents(USER, {
|
||||
meta: {fxa_credentials: payload},
|
||||
crypto: {},
|
||||
});
|
||||
|
||||
// Another sync - this will cause the encrypted record to be fetched.
|
||||
Service.sync();
|
||||
// Reset the request count here as the sync will have made many!
|
||||
numServerRequests = 0;
|
||||
|
||||
// Asking for the sentinel should use the copy cached in the record manager.
|
||||
Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got it");
|
||||
Assert.equal(numServerRequests, 0, "should not have hit the server");
|
||||
|
||||
// And asking for it again should work (we have to work around the fact the
|
||||
// ciphertext is clobbered on first decrypt...)
|
||||
Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got it again");
|
||||
Assert.equal(numServerRequests, 0, "should not have hit the server");
|
||||
|
||||
yield promiseStopServer(server);
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
initTestLogging();
|
||||
run_next_test();
|
||||
}
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm", this);
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", this);
|
||||
Cu.import("resource://services-sync/main.js", this);
|
||||
Cu.import("resource://services-sync/healthreport.jsm", this);
|
||||
Cu.import("resource://testing-common/services/common/logging.js", this);
|
||||
Cu.import("resource://testing-common/services/healthreport/utils.jsm", this);
|
||||
|
||||
function run_test() {
|
||||
initTestLogging();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_constructor() {
|
||||
let provider = new SyncProvider();
|
||||
});
|
||||
|
||||
// Provider can initialize and de-initialize properly.
|
||||
add_task(function* test_init() {
|
||||
let storage = yield Metrics.Storage("init");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function* test_collect() {
|
||||
let storage = yield Metrics.Storage("collect");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
// Initially nothing should be configured.
|
||||
let now = new Date();
|
||||
yield provider.collectDailyData();
|
||||
|
||||
let m = provider.getMeasurement("sync", 1);
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 1);
|
||||
Assert.ok(values.days.hasDay(now));
|
||||
let day = values.days.getDay(now);
|
||||
Assert.ok(day.has("enabled"));
|
||||
Assert.ok(day.has("activeProtocol"));
|
||||
Assert.ok(day.has("preferredProtocol"));
|
||||
Assert.equal(day.get("enabled"), 0);
|
||||
Assert.equal(day.get("preferredProtocol"), "1.5");
|
||||
Assert.equal(day.get("activeProtocol"), "1.5",
|
||||
"Protocol without setup should be FX Accounts version.");
|
||||
|
||||
// Now check for old Sync setup.
|
||||
let branch = new Preferences("services.sync.");
|
||||
branch.set("username", "foo");
|
||||
branch.reset("fxaccounts.enabled");
|
||||
yield provider.collectDailyData();
|
||||
values = yield m.getValues();
|
||||
Assert.equal(values.days.getDay(now).get("activeProtocol"), "1.1",
|
||||
"Protocol with old Sync setup is correct.");
|
||||
|
||||
Assert.equal(Weave.Status.__authManager, undefined, "Detect code changes");
|
||||
|
||||
// Let's enable Sync so we can get more useful data.
|
||||
// We need to do this because the FHR probe only records more info if Sync
|
||||
// is configured properly.
|
||||
Weave.Service.identity.account = "johndoe";
|
||||
Weave.Service.identity.basicPassword = "ilovejane";
|
||||
Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
|
||||
Weave.Service.clusterURL = "http://localhost/";
|
||||
Assert.equal(Weave.Status.checkSetup(), Weave.STATUS_OK);
|
||||
|
||||
yield provider.collectDailyData();
|
||||
values = yield m.getValues();
|
||||
day = values.days.getDay(now);
|
||||
Assert.equal(day.get("enabled"), 1);
|
||||
|
||||
// An empty account should have 1 device: us.
|
||||
let dm = provider.getMeasurement("devices", 1);
|
||||
values = yield dm.getValues();
|
||||
Assert.ok(values.days.hasDay(now));
|
||||
day = values.days.getDay(now);
|
||||
Assert.equal(day.size, 1);
|
||||
let engine = Weave.Service.clientsEngine;
|
||||
Assert.ok(engine);
|
||||
Assert.ok(day.has(engine.localType));
|
||||
Assert.equal(day.get(engine.localType), 1);
|
||||
|
||||
// Add some devices and ensure they show up.
|
||||
engine._store._remoteClients["id1"] = {type: "mobile"};
|
||||
engine._store._remoteClients["id2"] = {type: "tablet"};
|
||||
engine._store._remoteClients["id3"] = {type: "mobile"};
|
||||
|
||||
yield provider.collectDailyData();
|
||||
values = yield dm.getValues();
|
||||
day = values.days.getDay(now);
|
||||
|
||||
let expected = {
|
||||
"foobar": 0,
|
||||
"tablet": 1,
|
||||
"mobile": 2,
|
||||
"desktop": 0,
|
||||
};
|
||||
|
||||
for (let type in expected) {
|
||||
let count = expected[type];
|
||||
|
||||
if (engine.localType == type) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
Assert.ok(!day.has(type));
|
||||
} else {
|
||||
Assert.ok(day.has(type));
|
||||
Assert.equal(day.get(type), count);
|
||||
}
|
||||
}
|
||||
|
||||
engine._store._remoteClients = {};
|
||||
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function* test_sync_events() {
|
||||
let storage = yield Metrics.Storage("sync_events");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
let m = provider.getMeasurement("sync", 1);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
Services.obs.notifyObservers(null, "weave:service:sync:start", null);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
Services.obs.notifyObservers(null, "weave:service:sync:finish", null);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
Services.obs.notifyObservers(null, "weave:service:sync:error", null);
|
||||
}
|
||||
|
||||
// Wait for storage to complete.
|
||||
yield m.storage.enqueueOperation(() => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
let values = yield m.getValues();
|
||||
let now = new Date();
|
||||
Assert.ok(values.days.hasDay(now));
|
||||
let day = values.days.getDay(now);
|
||||
|
||||
Assert.ok(day.has("syncStart"));
|
||||
Assert.ok(day.has("syncSuccess"));
|
||||
Assert.ok(day.has("syncError"));
|
||||
Assert.equal(day.get("syncStart"), 5);
|
||||
Assert.equal(day.get("syncSuccess"), 3);
|
||||
Assert.equal(day.get("syncError"), 2);
|
||||
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function* test_healthreporter_json() {
|
||||
let reporter = yield getHealthReporter("healthreporter_json");
|
||||
yield reporter.init();
|
||||
try {
|
||||
yield reporter._providerManager.registerProvider(new SyncProvider());
|
||||
yield reporter.collectMeasurements();
|
||||
let payload = yield reporter.getJSONPayload(true);
|
||||
let now = new Date();
|
||||
let today = reporter._formatDate(now);
|
||||
|
||||
Assert.ok(today in payload.data.days);
|
||||
let day = payload.data.days[today];
|
||||
|
||||
Assert.ok("org.mozilla.sync.sync" in day);
|
||||
Assert.ok("org.mozilla.sync.devices" in day);
|
||||
|
||||
let devices = day["org.mozilla.sync.devices"];
|
||||
let engine = Weave.Service.clientsEngine;
|
||||
Assert.ok(engine);
|
||||
let type = engine.localType;
|
||||
Assert.ok(type);
|
||||
Assert.ok(type in devices);
|
||||
Assert.equal(devices[type], 1);
|
||||
} finally {
|
||||
reporter._shutdown();
|
||||
}
|
||||
});
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm", this);
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", this);
|
||||
Cu.import("resource://services-sync/healthreport.jsm", this);
|
||||
Cu.import("resource://services-sync/FxaMigrator.jsm", this);
|
||||
Cu.import("resource://testing-common/services/common/logging.js", this);
|
||||
Cu.import("resource://testing-common/services/healthreport/utils.jsm", this);
|
||||
|
||||
|
||||
function run_test() {
|
||||
initTestLogging();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* test_no_data() {
|
||||
let storage = yield Metrics.Storage("collect");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
try {
|
||||
// Initially nothing should be configured.
|
||||
let now = new Date();
|
||||
yield provider.collectDailyData();
|
||||
|
||||
let m = provider.getMeasurement("migration", 1);
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 0);
|
||||
Assert.ok(!values.days.hasDay(now));
|
||||
} finally {
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
}
|
||||
});
|
||||
|
||||
function checkCorrectStateRecorded(provider, state) {
|
||||
// Wait for storage to complete.
|
||||
yield m.storage.enqueueOperation(() => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
let m = provider.getMeasurement("migration", 1);
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 1);
|
||||
Assert.ok(values.days.hasDay(now));
|
||||
let day = values.days.getDay(now);
|
||||
|
||||
Assert.ok(day.has("state"));
|
||||
Assert.equal(day.get("state"), state);
|
||||
}
|
||||
|
||||
add_task(function* test_state() {
|
||||
let storage = yield Metrics.Storage("collect");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
try {
|
||||
// Initially nothing should be configured.
|
||||
let now = new Date();
|
||||
|
||||
// We record both a "user" and "internal" state in the same field.
|
||||
// So simulate a "user" state first.
|
||||
Services.obs.notifyObservers(null, "fxa-migration:state-changed",
|
||||
fxaMigrator.STATE_USER_FXA_VERIFIED);
|
||||
checkCorrectStateRecorded(provider, fxaMigrator.STATE_USER_FXA_VERIFIED);
|
||||
|
||||
// And an internal state.
|
||||
Services.obs.notifyObservers(null, "fxa-migration:internal-state-changed",
|
||||
fxaMigrator.STATE_INTERNAL_WAITING_SYNC_COMPLETE);
|
||||
checkCorrectStateRecorded(provider, fxaMigrator.STATE_INTERNAL_WAITING_SYNC_COMPLETE);
|
||||
} finally {
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* test_flags() {
|
||||
let storage = yield Metrics.Storage("collect");
|
||||
let provider = new SyncProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
try {
|
||||
// Initially nothing should be configured.
|
||||
let now = new Date();
|
||||
|
||||
let m = provider.getMeasurement("migration", 1);
|
||||
|
||||
let record = function*(what) {
|
||||
Services.obs.notifyObservers(null, "fxa-migration:internal-telemetry", what);
|
||||
// Wait for storage to complete.
|
||||
yield m.storage.enqueueOperation(Promise.resolve);
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 1);
|
||||
return values.days.getDay(now);
|
||||
}
|
||||
|
||||
let values = yield m.getValues();
|
||||
Assert.equal(values.days.size, 1);
|
||||
let day = values.days.getDay(now);
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
|
||||
// let's send an unknown value to ensure our error mitigation works.
|
||||
day = yield record("unknown");
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
|
||||
// record an fxaMigrator.TELEMETRY_ACCEPTED state.
|
||||
day = yield record(fxaMigrator.TELEMETRY_ACCEPTED);
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 1);
|
||||
|
||||
// and again - it should get 2.
|
||||
day = yield record(fxaMigrator.TELEMETRY_ACCEPTED);
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2);
|
||||
|
||||
// record fxaMigrator.TELEMETRY_DECLINED - also a counter.
|
||||
day = yield record(fxaMigrator.TELEMETRY_DECLINED);
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2);
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_DECLINED), 1);
|
||||
|
||||
day = yield record(fxaMigrator.TELEMETRY_DECLINED);
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2);
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_DECLINED), 2);
|
||||
|
||||
// and fxaMigrator.TELEMETRY_UNLINKED - this is conceptually a "daily bool".
|
||||
// (ie, it's DAILY_LAST_NUMERIC_FIELD and only ever has |1| written to it)
|
||||
day = yield record(fxaMigrator.TELEMETRY_UNLINKED);
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED));
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED));
|
||||
Assert.ok(day.has(fxaMigrator.TELEMETRY_UNLINKED));
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_UNLINKED), 1);
|
||||
// and doing it again still leaves us with |1|
|
||||
day = yield record(fxaMigrator.TELEMETRY_UNLINKED);
|
||||
Assert.equal(day.get(fxaMigrator.TELEMETRY_UNLINKED), 1);
|
||||
} finally {
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
}
|
||||
});
|
||||
|
|
@ -168,15 +168,4 @@ skip-if = debug
|
|||
[test_tab_store.js]
|
||||
[test_tab_tracker.js]
|
||||
|
||||
[test_healthreport.js]
|
||||
skip-if = ! healthreport
|
||||
|
||||
[test_healthreport_migration.js]
|
||||
skip-if = ! healthreport
|
||||
|
||||
[test_warn_on_truncated_response.js]
|
||||
|
||||
# FxA migration
|
||||
[test_block_sync.js]
|
||||
[test_fxa_migration.js]
|
||||
[test_fxa_migration_sentinel.js]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue