diff --git a/browser/base/content/browser-fxaccounts.js b/browser/base/content/browser-fxaccounts.js
index e197dee23c6..1af53224851 100644
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -10,11 +10,6 @@ var gFxAccounts = {
_initialized: false,
_inCustomizationMode: false,
- // _expectingNotifyClose is a hack that helps us determine if the
- // migration notification was closed due to being "dismissed" vs closed
- // due to one of the migration buttons being clicked. It's ugly and somewhat
- // fragile, so bug 1119020 exists to help us do this better.
- _expectingNotifyClose: false,
get weave() {
delete this.weave;
@@ -36,7 +31,6 @@ var gFxAccounts = {
this.FxAccountsCommon.ONLOGIN_NOTIFICATION,
this.FxAccountsCommon.ONVERIFIED_NOTIFICATION,
this.FxAccountsCommon.ONLOGOUT_NOTIFICATION,
- "weave:notification:removed",
this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
];
},
@@ -107,10 +101,6 @@ var gFxAccounts = {
gNavToolbox.addEventListener("customizationstarting", this);
gNavToolbox.addEventListener("customizationending", this);
- // Request the current Legacy-Sync-to-FxA migration status. We'll be
- // notified of fxa-migration:state-changed in response if necessary.
- Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
-
EnsureFxAccountsWebChannel();
this._initialized = true;
@@ -140,16 +130,6 @@ var gFxAccounts = {
case "fxa-migration:state-changed":
this.onMigrationStateChanged(data, subject);
break;
- case "weave:notification:removed":
- // this exists just so we can tell the difference between "box was
- // closed due to button press" vs "was closed due to click on [x]"
- let notif = subject.wrappedJSObject.object;
- if (notif.title == this.SYNC_MIGRATION_NOTIFICATION_TITLE &&
- !this._expectingNotifyClose) {
- // it's an [x] on our notification, so record telemetry.
- this.fxaMigrator.recordTelemetry(this.fxaMigrator.TELEMETRY_DECLINED);
- }
- break;
case this.FxAccountsCommon.ONPROFILE_IMAGE_CHANGE_NOTIFICATION:
this.updateUI();
break;
@@ -176,12 +156,25 @@ var gFxAccounts = {
}
},
- onMigrationStateChanged: function (newState, email) {
- this._migrationInfo = !newState ? null : {
- state: newState,
- email: email ? email.QueryInterface(Ci.nsISupportsString).data : null,
- };
- this.updateUI();
+ onMigrationStateChanged: function () {
+ // Since we nuked most of the migration code, this notification will fire
+ // once after legacy Sync has been disconnected (and should never fire
+ // again)
+ let msg = this.strings.GetStringFromName("autoDisconnectDescription")
+ let signInLabel = this.strings.GetStringFromName("autoDisconnectSignIn.label");
+ let signInAccessKey = this.strings.GetStringFromName("autoDisconnectSignIn.accessKey");
+ let learnMoreLink = this.fxaMigrator.learnMoreLink;
+ let note = new Weave.Notification(
+ undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [
+ new Weave.NotificationButton(signInLabel, signInAccessKey, () => {
+ this.openPreferences();
+ }),
+ ], learnMoreLink
+ );
+ note.title = this.SYNC_MIGRATION_NOTIFICATION_TITLE;
+ Weave.Notifications.replaceTitle(note);
+ // ensure the hamburger menu reflects the newly disconnected state.
+ this.updateAppMenuItem();
},
handleEvent: function (event) {
@@ -215,17 +208,15 @@ var gFxAccounts = {
},
updateUI: function () {
+ // It's possible someone signed in to FxA after seeing our notification
+ // about "Legacy Sync migration" (which now is actually "Legacy Sync
+ // auto-disconnect") so kill that notification if it still exists.
+ Weave.Notifications.removeAll(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
this.updateAppMenuItem();
- this.updateMigrationNotification();
},
// Note that updateAppMenuItem() returns a Promise that's only used by tests.
updateAppMenuItem: function () {
- if (this._migrationInfo) {
- this.updateAppMenuItemForMigration();
- return Promise.resolve();
- }
-
let profileInfoEnabled = false;
try {
profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
@@ -233,12 +224,6 @@ var gFxAccounts = {
// Bail out if FxA is disabled.
if (!this.weave.fxAccountsEnabled) {
- // When migration transitions from needs-verification to the null state,
- // fxAccountsEnabled is false because migration has not yet finished. In
- // that case, hide the button. We'll get another notification with a null
- // state once migration is complete.
- this.panelUIFooter.hidden = true;
- this.panelUIFooter.removeAttribute("fxastatus");
return Promise.resolve();
}
@@ -358,90 +343,6 @@ var gFxAccounts = {
});
},
- updateAppMenuItemForMigration: Task.async(function* () {
- let status = null;
- let label = null;
- switch (this._migrationInfo.state) {
- case this.fxaMigrator.STATE_USER_FXA:
- status = "migrate-signup";
- label = this.strings.formatStringFromName("needUserShort",
- [this.panelUILabel.getAttribute("fxabrandname")], 1);
- break;
- case this.fxaMigrator.STATE_USER_FXA_VERIFIED:
- status = "migrate-verify";
- label = this.strings.formatStringFromName("needVerifiedUserShort",
- [this._migrationInfo.email],
- 1);
- break;
- }
- this.panelUILabel.label = label;
- this.panelUIFooter.setAttribute("fxastatus", status);
- }),
-
- updateMigrationNotification: Task.async(function* () {
- if (!this._migrationInfo) {
- this._expectingNotifyClose = true;
- Weave.Notifications.removeAll(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
- // because this is called even when there is no such notification, we
- // set _expectingNotifyClose back to false as we may yet create a new
- // notification (but in general, once we've created a migration
- // notification once in a session, we don't create one again)
- this._expectingNotifyClose = false;
- return;
- }
- let note = null;
- switch (this._migrationInfo.state) {
- case this.fxaMigrator.STATE_USER_FXA: {
- // There are 2 cases here - no email address means it is an offer on
- // the first device (so the user is prompted to create an account).
- // If there is an email address it is the "join the party" flow, so the
- // user is prompted to sign in with the address they previously used.
- let msg, upgradeLabel, upgradeAccessKey, learnMoreLink;
- if (this._migrationInfo.email) {
- msg = this.strings.formatStringFromName("signInAfterUpgradeOnOtherDevice.description",
- [this._migrationInfo.email],
- 1);
- upgradeLabel = this.strings.GetStringFromName("signInAfterUpgradeOnOtherDevice.label");
- upgradeAccessKey = this.strings.GetStringFromName("signInAfterUpgradeOnOtherDevice.accessKey");
- } else {
- msg = this.strings.GetStringFromName("needUserLong");
- upgradeLabel = this.strings.GetStringFromName("upgradeToFxA.label");
- upgradeAccessKey = this.strings.GetStringFromName("upgradeToFxA.accessKey");
- learnMoreLink = this.fxaMigrator.learnMoreLink;
- }
- note = new Weave.Notification(
- undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [
- new Weave.NotificationButton(upgradeLabel, upgradeAccessKey, () => {
- this._expectingNotifyClose = true;
- this.fxaMigrator.createFxAccount(window);
- }),
- ], learnMoreLink
- );
- break;
- }
- case this.fxaMigrator.STATE_USER_FXA_VERIFIED: {
- let msg =
- this.strings.formatStringFromName("needVerifiedUserLong",
- [this._migrationInfo.email], 1);
- let resendLabel =
- this.strings.GetStringFromName("resendVerificationEmail.label");
- let resendAccessKey =
- this.strings.GetStringFromName("resendVerificationEmail.accessKey");
- note = new Weave.Notification(
- undefined, msg, undefined, Weave.Notifications.PRIORITY_INFO, [
- new Weave.NotificationButton(resendLabel, resendAccessKey, () => {
- this._expectingNotifyClose = true;
- this.fxaMigrator.resendVerificationMail();
- }),
- ]
- );
- break;
- }
- }
- note.title = this.SYNC_MIGRATION_NOTIFICATION_TITLE;
- Weave.Notifications.replaceTitle(note);
- }),
-
onMenuPanelCommand: function () {
switch (this.panelUIFooter.getAttribute("fxastatus")) {
@@ -455,12 +356,6 @@ var gFxAccounts = {
this.openSignInAgainPage("menupanel");
}
break;
- case "migrate-signup":
- case "migrate-verify":
- // The migration flow calls for the menu item to open sync prefs rather
- // than requesting migration start immediately.
- this.openPreferences();
- break;
default:
this.openPreferences();
break;
diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js
index d1b1e465b45..71d487a9e62 100644
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -12,9 +12,6 @@ XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "fxaMigrator",
- "resource://services-sync/FxaMigrator.jsm");
-
const PAGE_NO_ACCOUNT = 0;
const PAGE_HAS_ACCOUNT = 1;
const PAGE_NEEDS_UPDATE = 2;
@@ -122,22 +119,17 @@ var gSyncPane = {
FxAccountsCommon.ONLOGIN_NOTIFICATION,
FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
];
- let migrateTopic = "fxa-migration:state-changed";
-
// Add the observers now and remove them on unload
//XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
// of `this`. Fix in a followup. (bug 583347)
topics.forEach(function (topic) {
Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
}, this);
- // The FxA migration observer is a special case.
- Weave.Svc.Obs.add(migrateTopic, this.updateMigrationState, this);
window.addEventListener("unload", function() {
topics.forEach(function (topic) {
Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
}, gSyncPane);
- Weave.Svc.Obs.remove(migrateTopic, gSyncPane.updateMigrationState, gSyncPane);
}, false);
XPCOMUtils.defineLazyGetter(this, '_stringBundle', () => {
@@ -194,7 +186,6 @@ var gSyncPane = {
if (learnMoreLink) {
learnMoreLink.parentNode.removeChild(learnMoreLink);
}
- document.getElementById("sync-migration-buttons-deck").hidden = true;
},
_setupEventListeners: function() {
@@ -292,20 +283,6 @@ var gSyncPane = {
});
setEventListener("tosPP-small-ToS", "click", gSyncPane.openToS);
setEventListener("tosPP-small-PP", "click", gSyncPane.openPrivacyPolicy);
- setEventListener("sync-migrate-upgrade", "click", function () {
- let win = Services.wm.getMostRecentWindow("navigator:browser");
- fxaMigrator.createFxAccount(win);
- });
- setEventListener("sync-migrate-unlink", "click", function () {
- gSyncPane.startOverMigration();
- });
- setEventListener("sync-migrate-forget", "click", function () {
- fxaMigrator.forgetFxAccount();
- });
- setEventListener("sync-migrate-resend", "click", function () {
- let win = Services.wm.getMostRecentWindow("navigator:browser");
- fxaMigrator.resendVerificationMail(win);
- });
setEventListener("fxaSyncComputerName", "keypress", function (e) {
if (e.keyCode == KeyEvent.DOM_VK_RETURN) {
document.getElementById("fxaSaveChangeDeviceName").click();
@@ -324,12 +301,6 @@ var gSyncPane = {
},
updateWeavePrefs: function () {
- // ask the migration module to broadcast its current state (and nothing will
- // happen if it's not loaded - which is good, as that means no migration
- // is pending/necessary) - we don't want to suck that module in just to
- // find there's nothing to do.
- Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
-
let service = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
@@ -448,83 +419,6 @@ var gSyncPane = {
}
},
- updateMigrationState: function(subject, state) {
- this._closeSyncStatusMessageBox();
- let selIndex;
- let sb = this._accountsStringBundle;
- switch (state) {
- case fxaMigrator.STATE_USER_FXA: {
- // There are 2 cases here - no email address means it is an offer on
- // the first device (so the user is prompted to create an account).
- // If there is an email address it is the "join the party" flow, so the
- // user is prompted to sign in with the address they previously used.
- let email = subject ? subject.QueryInterface(Components.interfaces.nsISupportsString).data : null;
- let elt = document.getElementById("syncStatusMessageDescription");
- elt.textContent = email ?
- sb.formatStringFromName("signInAfterUpgradeOnOtherDevice.description",
- [email], 1) :
- sb.GetStringFromName("needUserLong");
-
- // The "Learn more" link.
- if (!email) {
- let learnMoreLink = document.createElement("label");
- learnMoreLink.id = "learnMoreLink";
- learnMoreLink.className = "text-link";
- let { text, href } = fxaMigrator.learnMoreLink;
- learnMoreLink.setAttribute("value", text);
- learnMoreLink.href = href;
- elt.parentNode.insertBefore(learnMoreLink, elt.nextSibling);
- }
-
- // The "upgrade" button.
- let button = document.getElementById("sync-migrate-upgrade");
- button.setAttribute("label",
- sb.GetStringFromName(email
- ? "signInAfterUpgradeOnOtherDevice.label"
- : "upgradeToFxA.label"));
- button.setAttribute("accesskey",
- sb.GetStringFromName(email
- ? "signInAfterUpgradeOnOtherDevice.accessKey"
- : "upgradeToFxA.accessKey"));
- // The "unlink" button - this is only shown for first migration
- button = document.getElementById("sync-migrate-unlink");
- if (email) {
- button.hidden = true;
- } else {
- button.setAttribute("label", sb.GetStringFromName("unlinkMigration.label"));
- button.setAttribute("accesskey", sb.GetStringFromName("unlinkMigration.accessKey"));
- }
- selIndex = 0;
- break;
- }
- case fxaMigrator.STATE_USER_FXA_VERIFIED: {
- let sb = this._accountsStringBundle;
- let email = subject.QueryInterface(Components.interfaces.nsISupportsString).data;
- let label = sb.formatStringFromName("needVerifiedUserLong", [email], 1);
- let elt = document.getElementById("syncStatusMessageDescription");
- elt.setAttribute("value", label);
- // The "resend" button.
- let button = document.getElementById("sync-migrate-resend");
- button.setAttribute("label", sb.GetStringFromName("resendVerificationEmail.label"));
- button.setAttribute("accesskey", sb.GetStringFromName("resendVerificationEmail.accessKey"));
- // The "forget" button.
- button = document.getElementById("sync-migrate-forget");
- button.setAttribute("label", sb.GetStringFromName("forgetMigration.label"));
- button.setAttribute("accesskey", sb.GetStringFromName("forgetMigration.accessKey"));
- selIndex = 1;
- break;
- }
- default:
- if (state) { // |null| is expected, but everything else is not.
- Cu.reportError("updateMigrationState has unknown state: " + state);
- }
- document.getElementById("sync-migration").hidden = true;
- return;
- }
- document.getElementById("sync-migration-buttons-deck").selectedIndex = selIndex;
- document.getElementById("syncStatusMessage").setAttribute("message-type", "migration");
- },
-
// Called whenever one of the sync engine preferences is changed.
onPreferenceChanged: function() {
let prefElts = document.querySelectorAll("#syncEnginePrefs > preference");
@@ -560,30 +454,6 @@ var gSyncPane = {
this.updateWeavePrefs();
},
- // When the "Unlink" button in the migration header is selected we display
- // a slightly different message.
- startOverMigration: function () {
- let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
- Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
- Services.prompt.BUTTON_POS_1_DEFAULT;
- let sb = this._accountsStringBundle;
- let buttonChoice =
- Services.prompt.confirmEx(window,
- sb.GetStringFromName("unlinkVerificationTitle"),
- sb.GetStringFromName("unlinkVerificationDescription"),
- flags,
- sb.GetStringFromName("unlinkVerificationConfirm"),
- null, null, null, {});
-
- // If the user selects cancel, just bail
- if (buttonChoice == 1)
- return;
-
- fxaMigrator.recordTelemetry(fxaMigrator.TELEMETRY_UNLINKED);
- Weave.Service.startOver();
- this.updateWeavePrefs();
- },
-
updatePass: function () {
if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
gSyncUtils.changePassword();
diff --git a/browser/components/preferences/in-content/sync.xul b/browser/components/preferences/in-content/sync.xul
index 8dbfbbe1c84..f269b32d415 100644
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -43,18 +43,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/browser/locales/en-US/chrome/browser/accounts.properties b/browser/locales/en-US/chrome/browser/accounts.properties
index 85d5e28dc15..b14f2c0ca5e 100644
--- a/browser/locales/en-US/chrome/browser/accounts.properties
+++ b/browser/locales/en-US/chrome/browser/accounts.properties
@@ -2,54 +2,16 @@
# 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/.
-# LOCALIZATION NOTE (needUserShort)
-# %S = Firefox Accounts brand name from syncBrand.dtd
-needUserShort = %S required for sync
-needUserLong = We've rebuilt Sync to make it easier for everyone. Please upgrade to a Firefox Account to continue syncing.
+# autoDisconnectDescription is shown in an info bar when we detect an old
+# Sync is being used.
+autoDisconnectDescription = We've rebuilt Sync to make it easier for everyone.
-upgradeToFxA.label = Upgrade
-upgradeToFxA.accessKey = U
-
-# LOCALIZATION NOTE (signInAfterUpgradeOnOtherDevice.description)
-# %S = Email address of user's Firefox Account
-signInAfterUpgradeOnOtherDevice.description = Sync was upgraded on another device by %S. Resume syncing?
-signInAfterUpgradeOnOtherDevice.label = Sign In
-signInAfterUpgradeOnOtherDevice.accessKey = S
-
-# LOCALIZATION NOTE (needVerifiedUserShort, needVerifiedUserLong)
-# %S = Email address of user's Firefox Account
-needVerifiedUserShort = %S not verified
-needVerifiedUserLong = Please click the verification link in the email sent to %S
-
-resendVerificationEmail.label = Resend
-resendVerificationEmail.accessKey = R
+# autoDisconnectSignIn.label and .accessKey are for buttons when we auto-disconnect
+autoDisconnectSignIn.label = Sign in to Sync
+autoDisconnectSignIn.accessKey = S
# LOCALIZATION NOTE (reconnectDescription) - %S = Email address of user's Firefox Account
reconnectDescription = Reconnect %S
# LOCALIZATION NOTE (verifyDescription) - %S = Email address of user's Firefox Account
verifyDescription = Verify %S
-
-forgetMigration.label = Forget
-forgetMigration.accessKey = F
-
-unlinkMigration.label = Unlink Sync
-unlinkMigration.accessKey = L
-
-unlinkVerificationTitle = Unlink old version of Sync?
-unlinkVerificationDescription = If you no longer want to be reminded about upgrading Sync, you can unlink your old Sync account to remove it.
-unlinkVerificationConfirm = Unlink
-
-# These strings are used in a dialog we display after the user requests we resend
-# a verification email.
-verificationSentTitle = Verification Sent
-# LOCALIZATION NOTE (verificationSentHeading) - %S = Email address of user's Firefox Account
-verificationSentHeading = A verification link has been sent to %S
-verificationSentDescription = Please check your email and click the link to begin syncing.
-# LOCALIZATION NOTE (verificationSentFull) - %S = Email address of user's Firefox Account
-verificationSentFull = A verification link has been sent to %S. Please check your email and click the link to begin syncing.
-
-verificationNotSentTitle = Unable to Send Verification
-verificationNotSentHeading = We are unable to send a verification mail at this time
-verificationNotSentDescription = Please try again later.
-verificationNotSentFull = We are unable to send a verification mail at this time, please try again later.
diff --git a/services/sync/modules/FxaMigrator.jsm b/services/sync/modules/FxaMigrator.jsm
index bbc5f0d838d..735b601444e 100644
--- a/services/sync/modules/FxaMigrator.jsm
+++ b/services/sync/modules/FxaMigrator.jsm
@@ -4,15 +4,15 @@
"use strict;"
+// Note that this module used to supervise the step-by-step migration from
+// a legacy Sync account to a FxA-based Sync account. In bug 1205928, this
+// changed to automatically disconnect the legacy Sync account.
+
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
- "resource://gre/modules/FxAccounts.jsm");
XPCOMUtils.defineLazyGetter(this, "WeaveService", function() {
return Cc["@mozilla.org/weave/service;1"]
@@ -23,47 +23,13 @@ XPCOMUtils.defineLazyGetter(this, "WeaveService", function() {
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
"resource://services-sync/main.js");
-// FxAccountsCommon.js doesn't use a "namespace", so create one here.
-var fxAccountsCommon = {};
-Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
-
-// We send this notification whenever the "user" migration state changes.
+// We send this notification when we perform the disconnection. The browser
+// window will show a one-off notification bar.
const OBSERVER_STATE_CHANGE_TOPIC = "fxa-migration:state-changed";
-// We also send the state notification when we *receive* this. This allows
-// consumers to avoid loading this module until it receives a notification
-// from us (which may never happen if there's no migration to do)
-const OBSERVER_STATE_REQUEST_TOPIC = "fxa-migration:state-request";
-
-// We send this notification whenever the migration is paused waiting for
-// something internal to complete.
-const OBSERVER_INTERNAL_STATE_CHANGE_TOPIC = "fxa-migration:internal-state-changed";
-
-// We use this notification so Sync's healthreport module can record telemetry
-// (actually via "health report") for us.
-const OBSERVER_INTERNAL_TELEMETRY_TOPIC = "fxa-migration:internal-telemetry";
const OBSERVER_TOPICS = [
"xpcom-shutdown",
- "weave:service:sync:start",
- "weave:service:sync:finish",
- "weave:service:sync:error",
"weave:eol",
- OBSERVER_STATE_REQUEST_TOPIC,
- fxAccountsCommon.ONLOGIN_NOTIFICATION,
- fxAccountsCommon.ONLOGOUT_NOTIFICATION,
- fxAccountsCommon.ONVERIFIED_NOTIFICATION,
-];
-
-// A list of preference names we write to the migration sentinel. We only
-// write ones that have a user-set value.
-const FXA_SENTINEL_PREFS = [
- "identity.fxaccounts.auth.uri",
- "identity.fxaccounts.remote.force_auth.uri",
- "identity.fxaccounts.remote.signup.uri",
- "identity.fxaccounts.remote.signin.uri",
- "identity.fxaccounts.settings.uri",
- // Note that "identity.sync.tokenserver.uri" and "services.sync.tokenServerURI"
- // have special handing when writing/reading prefs.
];
function Migrator() {
@@ -72,42 +38,14 @@ function Migrator() {
// prefs are set.
this.log.level = Log.Level.Debug;
- this._nextUserStatePromise = Promise.resolve();
-
for (let topic of OBSERVER_TOPICS) {
Services.obs.addObserver(this, topic, false);
}
- // ._state is an optimization so we avoid sending redundant observer
- // notifications when the state hasn't actually changed.
- this._state = null;
}
Migrator.prototype = {
log: Log.repository.getLogger("Sync.SyncMigration"),
- // What user action is necessary to push the migration forward?
- // A |null| state means there is nothing to do. Note that a null state implies
- // either. (a) no migration is necessary or (b) that the migrator module is
- // waiting for something outside of the user's control - eg, sync to complete,
- // the migration sentinel to be uploaded, etc. In most cases the wait will be
- // short, but edge cases (eg, no network, sync bugs that prevent it stopping
- // until shutdown) may require a significantly longer wait.
- STATE_USER_FXA: "waiting for user to be signed in to FxA",
- STATE_USER_FXA_VERIFIED: "waiting for a verified FxA user",
-
- // What internal state are we at? This is primarily used for FHR reporting so
- // we can determine why exactly we might be stalled.
- STATE_INTERNAL_WAITING_SYNC_COMPLETE: "waiting for sync to complete",
- STATE_INTERNAL_WAITING_WRITE_SENTINEL: "waiting for sentinel to be written",
- STATE_INTERNAL_WAITING_START_OVER: "waiting for sync to reset itself",
- STATE_INTERNAL_COMPLETE: "migration complete",
-
- // Flags for the telemetry we record. The UI will call a helper to record
- // the fact some UI was interacted with.
- TELEMETRY_ACCEPTED: "accepted",
- TELEMETRY_DECLINED: "declined",
- TELEMETRY_UNLINKED: "unlinked",
-
finalize() {
for (let topic of OBSERVER_TOPICS) {
Services.obs.removeObserver(this, topic);
@@ -121,428 +59,23 @@ Migrator.prototype = {
this.finalize();
break;
- case OBSERVER_STATE_REQUEST_TOPIC:
- // someone has requested the state - send it.
- this._queueCurrentUserState(true);
- break;
-
default:
- // some other observer that may affect our state has fired, so update.
- this._queueCurrentUserState().then(
- () => this.log.debug("update state from observer " + topic + " complete")
- ).catch(err => {
- let msg = "Failed to handle topic " + topic + ": " + err;
- Cu.reportError(msg);
- this.log.error(msg);
- });
- }
- },
+ // this notification when configured with legacy Sync means we want to
+ // disconnect
+ if (!WeaveService.fxAccountsEnabled) {
+ this.log.info("Disconnecting from legacy Sync");
+ // Set up an observer for when the disconnection is complete.
+ let observe;
+ Services.obs.addObserver(observe = () => {
+ this.log.info("observed that startOver is complete");
+ Services.obs.removeObserver(observe, "weave:service:start-over:finish");
+ // Send the notification for the UI.
+ Services.obs.notifyObservers(null, OBSERVER_STATE_CHANGE_TOPIC, null);
+ }, "weave:service:start-over:finish", false);
- // Try and move to a state where we are blocked on a user action.
- // This needs to be restartable, and the states may, in edge-cases, end
- // up going backwards (eg, user logs out while we are waiting to be told
- // about verification)
- // This is called by our observer notifications - so if there is already
- // a promise in-flight, it's possible we will miss something important - so
- // we wait for the in-flight one to complete then fire another (ie, this
- // is effectively a queue of promises)
- _queueCurrentUserState(forceObserver = false) {
- return this._nextUserStatePromise = this._nextUserStatePromise.then(
- () => this._promiseCurrentUserState(forceObserver),
- err => {
- let msg = "Failed to determine the current user state: " + err;
- Cu.reportError(msg);
- this.log.error(msg);
- return this._promiseCurrentUserState(forceObserver)
- }
- );
- },
-
- _promiseCurrentUserState: Task.async(function* (forceObserver) {
- this.log.trace("starting _promiseCurrentUserState");
- let update = (newState, email=null) => {
- this.log.info("Migration state: '${state}' => '${newState}'",
- {state: this._state, newState: newState});
- if (forceObserver || newState !== this._state) {
- this._state = newState;
- let subject = Cc["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- subject.data = email || "";
- Services.obs.notifyObservers(subject, OBSERVER_STATE_CHANGE_TOPIC, newState);
- }
- return newState;
- }
-
- // If we have no sync user, or are already using an FxA account we must
- // be done.
- if (WeaveService.fxAccountsEnabled) {
- // should not be necessary, but if we somehow ended up with FxA enabled
- // and sync blocked it would be bad - so better safe than sorry.
- this.log.debug("FxA enabled - there's nothing to do!")
- this._unblockSync();
- return update(null);
- }
-
- // so we need to migrate - let's see how far along we are.
- // If sync isn't in EOL mode, then we are still waiting for the server
- // to offer the migration process - so no user action necessary.
- let isEOL = false;
- try {
- isEOL = !!Services.prefs.getCharPref("services.sync.errorhandler.alert.mode");
- } catch (e) {}
-
- if (!isEOL) {
- return update(null);
- }
-
- // So we are in EOL mode - have we a user?
- let fxauser = yield fxAccounts.getSignedInUser();
- if (!fxauser) {
- // See if there is a migration sentinel so we can send the email
- // address that was used on a different device for this account (ie, if
- // this is a "join the party" migration rather than the first)
- let sentinel = yield this._getSyncMigrationSentinel();
- return update(this.STATE_USER_FXA, sentinel && sentinel.email);
- }
- if (!fxauser.verified) {
- return update(this.STATE_USER_FXA_VERIFIED, fxauser.email);
- }
-
- // So we just have housekeeping to do - we aren't blocked on a user, so
- // reflect that.
- this.log.info("No next user state - doing some housekeeping");
- update(null);
-
- // We need to disable sync from automatically starting,
- // and if we are currently syncing wait for it to complete.
- this._blockSync();
-
- // Are we currently syncing?
- if (Weave.Service._locked) {
- // our observers will kick us further along when complete.
- this.log.info("waiting for sync to complete")
- Services.obs.notifyObservers(null, OBSERVER_INTERNAL_STATE_CHANGE_TOPIC,
- this.STATE_INTERNAL_WAITING_SYNC_COMPLETE);
- return null;
- }
-
- // Write the migration sentinel if necessary.
- Services.obs.notifyObservers(null, OBSERVER_INTERNAL_STATE_CHANGE_TOPIC,
- this.STATE_INTERNAL_WAITING_WRITE_SENTINEL);
- yield this._setMigrationSentinelIfNecessary();
-
- // Get the list of enabled engines to we can restore that state.
- let enginePrefs = this._getEngineEnabledPrefs();
-
- // Must be ready to perform the actual migration.
- this.log.info("Performing final sync migration steps");
- // Do the actual migration. We setup one observer for when the new identity
- // is about to be initialized so we can reset some key preferences - but
- // there's no promise associated with this.
- let observeStartOverIdentity;
- Services.obs.addObserver(observeStartOverIdentity = () => {
- this.log.info("observed that startOver is about to re-initialize the identity");
- Services.obs.removeObserver(observeStartOverIdentity, "weave:service:start-over:init-identity");
- // We've now reset all sync prefs - set the engine related prefs back to
- // what they were.
- for (let [prefName, prefType, prefVal] of enginePrefs) {
- this.log.debug("Restoring pref ${prefName} (type=${prefType}) to ${prefVal}",
- {prefName, prefType, prefVal});
- switch (prefType) {
- case Services.prefs.PREF_BOOL:
- Services.prefs.setBoolPref(prefName, prefVal);
- break;
- case Services.prefs.PREF_STRING:
- Services.prefs.setCharPref(prefName, prefVal);
- break;
- default:
- // _getEngineEnabledPrefs doesn't return any other type...
- Cu.reportError("unknown engine pref type for " + prefName + ": " + prefType);
+ // Do the disconnection.
+ Weave.Service.startOver();
}
- }
- }, "weave:service:start-over:init-identity", false);
-
- // And another observer for the startOver being fully complete - the only
- // reason for this is so we can wait until everything is fully reset.
- let startOverComplete = new Promise((resolve, reject) => {
- let observe;
- Services.obs.addObserver(observe = () => {
- this.log.info("observed that startOver is complete");
- Services.obs.removeObserver(observe, "weave:service:start-over:finish");
- resolve();
- }, "weave:service:start-over:finish", false);
- });
-
- Weave.Service.startOver();
- // need to wait for an observer.
- Services.obs.notifyObservers(null, OBSERVER_INTERNAL_STATE_CHANGE_TOPIC,
- this.STATE_INTERNAL_WAITING_START_OVER);
- yield startOverComplete;
- // observer fired, now kick things off with the FxA user.
- this.log.info("scheduling initial FxA sync.");
- // Note we technically don't need to unblockSync as by now all sync prefs
- // have been reset - but it doesn't hurt.
- this._unblockSync();
- Weave.Service.scheduler.scheduleNextSync(0);
-
- // Tell the front end that migration is now complete -- Sync is now
- // configured with an FxA user.
- forceObserver = true;
- this.log.info("Migration complete");
- update(null);
-
- Services.obs.notifyObservers(null, OBSERVER_INTERNAL_STATE_CHANGE_TOPIC,
- this.STATE_INTERNAL_COMPLETE);
- return null;
- }),
-
- /* Return an object with the preferences we care about */
- _getSentinelPrefs() {
- let result = {};
- for (let pref of FXA_SENTINEL_PREFS) {
- if (Services.prefs.prefHasUserValue(pref)) {
- result[pref] = Services.prefs.getCharPref(pref);
- }
- }
- // We used to use services.sync.tokenServerURI as the tokenServer pref but
- // have since changed to identity.sync.tokenserver.uri. However, clients
- // using this pref may not have updated - so always write whatever value
- // is actually being used to the "old" name.
- let tokenServerValue;
- for (let pref of ["services.sync.tokenServerURI", "identity.sync.tokenserver.uri"]) {
- if (Services.prefs.prefHasUserValue(pref)) {
- tokenServerValue = Services.prefs.getCharPref(pref);
- break;
- }
- }
- if (tokenServerValue) {
- result["services.sync.tokenServerURI"] = tokenServerValue;
- }
- return result;
- },
-
- /* Apply any preferences we've obtained from the sentinel */
- _applySentinelPrefs(savedPrefs) {
- for (let pref of FXA_SENTINEL_PREFS) {
- if (savedPrefs[pref]) {
- Services.prefs.setCharPref(pref, savedPrefs[pref]);
- }
- }
- // And special handling for the tokenserver prefs.
- let tokenServerValue = savedPrefs["services.sync.tokenServerURI"];
- if (tokenServerValue) {
- Services.prefs.setCharPref("identity.sync.tokenserver.uri", tokenServerValue);
- }
- },
-
- /* Ask sync to upload the migration sentinel */
- _setSyncMigrationSentinel: Task.async(function* () {
- yield WeaveService.whenLoaded();
- let signedInUser = yield fxAccounts.getSignedInUser();
- let sentinel = {
- email: signedInUser.email,
- uid: signedInUser.uid,
- verified: signedInUser.verified,
- prefs: this._getSentinelPrefs(),
- };
- yield Weave.Service.setFxAMigrationSentinel(sentinel);
- }),
-
- /* Ask sync to upload the migration sentinal if we (or any other linked device)
- haven't previously written one.
- */
- _setMigrationSentinelIfNecessary: Task.async(function* () {
- if (!(yield this._getSyncMigrationSentinel())) {
- this.log.info("writing the migration sentinel");
- yield this._setSyncMigrationSentinel();
- }
- }),
-
- /* Ask sync to return a migration sentinel if one exists, otherwise return null */
- _getSyncMigrationSentinel: Task.async(function* () {
- yield WeaveService.whenLoaded();
- let sentinel = yield Weave.Service.getFxAMigrationSentinel();
- this.log.debug("got migration sentinel ${}", sentinel);
- return sentinel;
- }),
-
- _getDefaultAccountName: Task.async(function* (sentinel) {
- // Requires looking to see if other devices have written a migration
- // sentinel (eg, see _haveSynchedMigrationSentinel), and if not, see if
- // the legacy account name appears to be a valid email address (via the
- // services.sync.account pref), otherwise return null.
- // NOTE: Sync does all this synchronously via nested event loops, but we
- // expose a promise to make future migration to an async-sync easier.
- if (sentinel && sentinel.email) {
- this.log.info("defaultAccountName found via sentinel: ${}", sentinel.email);
- return sentinel.email;
- }
- // No previous migrations, so check the existing account name.
- let account = Weave.Service.identity.account;
- if (account && account.contains("@")) {
- this.log.info("defaultAccountName found via legacy account name: {}", account);
- return account;
- }
- this.log.info("defaultAccountName could not find an account");
- return null;
- }),
-
- // Prevent sync from automatically starting
- _blockSync() {
- Weave.Service.scheduler.blockSync();
- },
-
- _unblockSync() {
- Weave.Service.scheduler.unblockSync();
- },
-
- /* Return a list of [prefName, prefType, prefVal] for all engine related
- preferences.
- */
- _getEngineEnabledPrefs() {
- let result = [];
- for (let engine of Weave.Service.engineManager.getAll()) {
- let prefName = "services.sync.engine." + engine.prefName;
- let prefVal;
- try {
- prefVal = Services.prefs.getBoolPref(prefName);
- result.push([prefName, Services.prefs.PREF_BOOL, prefVal]);
- } catch (ex) {} /* just skip this pref */
- }
- // and the declined list.
- try {
- let prefName = "services.sync.declinedEngines";
- let prefVal = Services.prefs.getCharPref(prefName);
- result.push([prefName, Services.prefs.PREF_STRING, prefVal]);
- } catch (ex) {}
- return result;
- },
-
- /* return true if all engines are enabled, false otherwise. */
- _allEnginesEnabled() {
- return Weave.Service.engineManager.getAll().every(e => e.enabled);
- },
-
- /*
- * Some helpers for the UI to try and move to the next state.
- */
-
- // Open a UI for the user to create a Firefox Account. This should only be
- // called while we are in the STATE_USER_FXA state. When the user completes
- // the creation we'll see an ONLOGIN_NOTIFICATION notification from FxA and
- // we'll move to either the STATE_USER_FXA_VERIFIED state or we'll just
- // complete the migration if they login as an already verified user.
- createFxAccount: Task.async(function* (win) {
- let {url, options} = yield this.getFxAccountCreationOptions();
- win.switchToTabHavingURI(url, true, options);
- // An FxA observer will fire when the user completes this, which will
- // cause us to move to the next "user blocked" state and notify via our
- // observer notification.
- }),
-
- // Returns an object with properties "url" and "options", suitable for
- // opening FxAccounts to create/signin to FxA suitable for the migration
- // state. The caller of this is responsible for the actual opening of the
- // page.
- // This should only be called while we are in the STATE_USER_FXA state. When
- // the user completes the creation we'll see an ONLOGIN_NOTIFICATION
- // notification from FxA and we'll move to either the STATE_USER_FXA_VERIFIED
- // state or we'll just complete the migration if they login as an already
- // verified user.
- getFxAccountCreationOptions: Task.async(function* (win) {
- // warn if we aren't in the expected state - but go ahead anyway!
- if (this._state != this.STATE_USER_FXA) {
- this.log.warn("getFxAccountCreationOptions called in an unexpected state: ${}", this._state);
- }
- // We need to obtain the sentinel and apply any prefs that might be
- // specified *before* attempting to setup FxA as the prefs might
- // specify custom servers etc.
- let sentinel = yield this._getSyncMigrationSentinel();
- if (sentinel && sentinel.prefs) {
- this._applySentinelPrefs(sentinel.prefs);
- }
- // If we already have a sentinel then we assume the user has previously
- // created the specified account, so just ask to sign-in.
- let action = sentinel ? "signin" : "signup";
- // See if we can find a default account name to use.
- let email = yield this._getDefaultAccountName(sentinel);
- let tail = email ? "&email=" + encodeURIComponent(email) : "";
- // A special flag so server-side metrics can tell this is part of migration.
- tail += "&migration=sync11";
- // We want to ask FxA to offer a "Customize Sync" checkbox iff any engines
- // are disabled.
- let customize = !this._allEnginesEnabled();
- tail += "&customizeSync=" + customize;
-
- // We assume the caller of this is going to actually use it, so record
- // telemetry now.
- this.recordTelemetry(this.TELEMETRY_ACCEPTED);
- return {
- url: "about:accounts?action=" + action + tail,
- options: {ignoreFragment: true, replaceQueryString: true}
- };
- }),
-
- // Ask the FxA servers to re-send a verification mail for the currently
- // logged in user. This should only be called while we are in the
- // STATE_USER_FXA_VERIFIED state. When the user clicks on the link in
- // the mail we should see an ONVERIFIED_NOTIFICATION which will cause us
- // to complete the migration.
- resendVerificationMail: Task.async(function * (win) {
- // warn if we aren't in the expected state - but go ahead anyway!
- if (this._state != this.STATE_USER_FXA_VERIFIED) {
- this.log.warn("resendVerificationMail called in an unexpected state: ${}", this._state);
- }
- let ok = true;
- try {
- yield fxAccounts.resendVerificationEmail();
- } catch (ex) {
- this.log.error("Failed to resend verification mail: ${}", ex);
- ok = false;
- }
- this.recordTelemetry(this.TELEMETRY_ACCEPTED);
- let fxauser = yield fxAccounts.getSignedInUser();
- let sb = Services.strings.createBundle("chrome://browser/locale/accounts.properties");
-
- let heading = ok ?
- sb.formatStringFromName("verificationSentHeading", [fxauser.email], 1) :
- sb.GetStringFromName("verificationNotSentHeading");
- let title = sb.GetStringFromName(ok ? "verificationSentTitle" : "verificationNotSentTitle");
- let description = sb.GetStringFromName(ok ? "verificationSentDescription"
- : "verificationNotSentDescription");
-
- let factory = Cc["@mozilla.org/prompter;1"]
- .getService(Ci.nsIPromptFactory);
- let prompt = factory.getPrompt(win, Ci.nsIPrompt);
- let bag = prompt.QueryInterface(Ci.nsIWritablePropertyBag2);
- bag.setPropertyAsBool("allowTabModal", true);
-
- prompt.alert(title, heading + "\n\n" + description);
- }),
-
- // "forget" about the current Firefox account. This should only be called
- // while we are in the STATE_USER_FXA_VERIFIED state. After this we will
- // see an ONLOGOUT_NOTIFICATION, which will cause the migrator to return back
- // to the STATE_USER_FXA state, from where they can choose a different account.
- forgetFxAccount: Task.async(function * () {
- // warn if we aren't in the expected state - but go ahead anyway!
- if (this._state != this.STATE_USER_FXA_VERIFIED) {
- this.log.warn("forgetFxAccount called in an unexpected state: ${}", this._state);
- }
- return fxAccounts.signOut();
- }),
-
- recordTelemetry(flag) {
- // Note the value is the telemetry field name - but this is an
- // implementation detail which could be changed later.
- switch (flag) {
- case this.TELEMETRY_ACCEPTED:
- case this.TELEMETRY_UNLINKED:
- case this.TELEMETRY_DECLINED:
- Services.obs.notifyObservers(null, OBSERVER_INTERNAL_TELEMETRY_TOPIC, flag);
- break;
- default:
- throw new Error("Unexpected telemetry flag: " + flag);
}
},
diff --git a/services/sync/modules/healthreport.jsm b/services/sync/modules/healthreport.jsm
index 47161c09564..dcad4490cdc 100644
--- a/services/sync/modules/healthreport.jsm
+++ b/services/sync/modules/healthreport.jsm
@@ -63,24 +63,6 @@ SyncDevicesMeasurement1.prototype = Object.freeze({
},
});
-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);
};
@@ -92,16 +74,12 @@ SyncProvider.prototype = Object.freeze({
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 () {
@@ -126,11 +104,6 @@ SyncProvider.prototype = Object.freeze({
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);
},
@@ -162,47 +135,6 @@ SyncProvider.prototype = Object.freeze({
});
},
- _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));
},
diff --git a/services/sync/modules/policies.js b/services/sync/modules/policies.js
index d391a443e59..b4de2ee98f5 100644
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -517,45 +517,6 @@ SyncScheduler.prototype = {
this.syncTimer.clear();
},
- /**
- * Prevent new syncs from starting. This is used by the FxA migration code
- * where we can't afford to have a sync start partway through the migration.
- * To handle the edge-case of a sync starting and not stopping, we store
- * this state in a pref, so on the next startup we remain blocked (and thus
- * sync will never start) so the migration can complete.
- *
- * As a safety measure, we only block for some period of time, and after
- * that it will automatically unblock. This ensures that if things go
- * really pear-shaped and we never end up calling unblockSync() we haven't
- * completely broken the world.
- */
- blockSync: function(until = null) {
- if (!until) {
- until = Date.now() + DEFAULT_BLOCK_PERIOD;
- }
- // until is specified in ms, but Prefs can't hold that much
- Svc.Prefs.set("scheduler.blocked-until", Math.floor(until / 1000));
- },
-
- unblockSync: function() {
- Svc.Prefs.reset("scheduler.blocked-until");
- // the migration code should be ready to roll, so resume normal operations.
- this.checkSyncStatus();
- },
-
- get isBlocked() {
- let until = Svc.Prefs.get("scheduler.blocked-until");
- if (until === undefined) {
- return false;
- }
- if (until <= Math.floor(Date.now() / 1000)) {
- // we were previously blocked but the time has expired.
- Svc.Prefs.reset("scheduler.blocked-until");
- return false;
- }
- // we remain blocked.
- return true;
- },
};
this.ErrorHandler = function ErrorHandler(service) {
diff --git a/services/sync/tests/unit/test_block_sync.js b/services/sync/tests/unit/test_block_sync.js
deleted file mode 100644
index f83b7b7408c..00000000000
--- a/services/sync/tests/unit/test_block_sync.js
+++ /dev/null
@@ -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();
-}
diff --git a/services/sync/tests/unit/test_fxa_migration.js b/services/sync/tests/unit/test_fxa_migration.js
index ccb78d43c8a..0ca770e284c 100644
--- a/services/sync/tests/unit/test_fxa_migration.js
+++ b/services/sync/tests/unit/test_fxa_migration.js
@@ -4,9 +4,6 @@ Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost");
// 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");
@@ -83,227 +80,31 @@ function configureLegacySync() {
return [engine, server];
}
-add_task(function *testMigration() {
+add_task(function *testMigrationUnlinks() {
// 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
+ // Arrange for a legacy sync user.
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");
+ let promiseMigration = promiseOneObserver("fxa-migration:state-changed");
+ let promiseStartOver = promiseOneObserver("weave:service:start-over:finish");
_("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);
-});
-
-// Test our tokenServer URL is set correctly given we've changed the prefname
-// it uses.
-add_task(function* testTokenServerOldPrefName() {
- let value = "http://custom-token-server/";
- // Set the pref we used in the past...
- Services.prefs.setCharPref("services.sync.tokenServerURI", value);
- // And make sure the new pref the value will be written to has a different
- // value.
- Assert.notEqual(Services.prefs.getCharPref("identity.sync.tokenserver.uri"), value);
-
- let prefs = fxaMigrator._getSentinelPrefs();
- Assert.equal(prefs["services.sync.tokenServerURI"], value);
- // check it applies correctly.
- Services.prefs.clearUserPref("services.sync.tokenServerURI");
- Assert.ok(!Services.prefs.prefHasUserValue("services.sync.tokenServerURI"));
- fxaMigrator._applySentinelPrefs(prefs);
- // We should have written the pref value to the *new* pref name.
- Assert.equal(Services.prefs.getCharPref("identity.sync.tokenserver.uri"), value);
- // And the old pref name should remain untouched.
- Assert.ok(!Services.prefs.prefHasUserValue("services.sync.tokenServerURI"));
-});
-
-add_task(function* testTokenServerNewPrefName() {
- let value = "http://token-server/";
- // Set the new pref name we now use.
- Services.prefs.setCharPref("identity.sync.tokenserver.uri", value);
-
- let prefs = fxaMigrator._getSentinelPrefs();
- // It should be written to the sentinel with the *old* pref name.
- Assert.equal(prefs["services.sync.tokenServerURI"], value);
- // check it applies correctly.
- Services.prefs.clearUserPref("services.sync.tokenServerURI");
- Assert.ok(!Services.prefs.prefHasUserValue("services.sync.tokenServerURI"));
- fxaMigrator._applySentinelPrefs(prefs);
- // We should have written the pref value to the new pref name.
- Assert.equal(Services.prefs.getCharPref("identity.sync.tokenserver.uri"), value);
- // And the old pref name should remain untouched.
- Assert.ok(!Services.prefs.prefHasUserValue("services.sync.tokenServerURI"));
+ yield promiseStartOver;
+ yield promiseMigration;
+ // We should have seen the observer and Sync should no longer be configured.
+ Assert.ok(!Services.prefs.prefHasUserValue("services.sync.username"));
});
function run_test() {
diff --git a/services/sync/tests/unit/test_fxa_migration_sentinel.js b/services/sync/tests/unit/test_fxa_migration_sentinel.js
deleted file mode 100644
index 809d00e8661..00000000000
--- a/services/sync/tests/unit/test_fxa_migration_sentinel.js
+++ /dev/null
@@ -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);
- });
-}
-
-var 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();
-}
diff --git a/services/sync/tests/unit/test_healthreport_migration.js b/services/sync/tests/unit/test_healthreport_migration.js
deleted file mode 100644
index 23f75674870..00000000000
--- a/services/sync/tests/unit/test_healthreport_migration.js
+++ /dev/null
@@ -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();
- }
-});
diff --git a/services/sync/tests/unit/xpcshell.ini b/services/sync/tests/unit/xpcshell.ini
index b994e2d8605..f6c2280f3e4 100644
--- a/services/sync/tests/unit/xpcshell.ini
+++ b/services/sync/tests/unit/xpcshell.ini
@@ -177,12 +177,7 @@ skip-if = debug
[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]