Bug 958927 - XUL dialogs for sync unlink and relink confirmation dialogs. r=gavin
authorMark Hammond <mhammond@skippinet.com.au>
Tue, 28 Jan 2014 20:43:01 -0800
changeset 181803 288310faa1ffc58829378c26c33c66411812a888
parent 181802 8d5d72c011711ba8b7837679267502acbbf681b8
child 181804 9b3dc7c6dae9863ce59b2be44903f86ab1ca7313
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs958927
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 958927 - XUL dialogs for sync unlink and relink confirmation dialogs. r=gavin Conflicts: browser/base/content/aboutaccounts/aboutaccounts.js
browser/base/content/aboutaccounts/aboutaccounts.js
browser/components/preferences/sync.js
browser/locales/en-US/chrome/browser/syncSetup.properties
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -4,24 +4,64 @@
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FxAccounts.jsm");
 
+const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUser";
+
 function log(msg) {
   //dump("FXA: " + msg + "\n");
 };
 
 function error(msg) {
   console.log("Firefox Account Error: " + msg + "\n");
 };
 
+function getPreviousAccountName() {
+  try {
+    return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
+  } catch (_) {
+    return "";
+  }
+}
+
+function setPreviousAccountName(acctName) {
+  let string = Cc["@mozilla.org/supports-string;1"]
+               .createInstance(Ci.nsISupportsString);
+  string.data = acctName;
+  Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
+}
+
+function needRelinkWarning(accountData) {
+  let prevAcct = getPreviousAccountName();
+  return prevAcct && prevAcct != accountData.email;
+}
+
+function promptForRelink() {
+  let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
+  let continueLabel = sb.GetStringFromName("continue.label");
+  let title = sb.GetStringFromName("relink.verify.title");
+  let description = sb.formatStringFromName("relink.verify.description",
+                                            [Services.prefs.getCharPref(PREF_LAST_FXA_USER)], 1);
+  let body = sb.GetStringFromName("relink.verify.heading") +
+             "\n\n" + description;
+  let ps = Services.prompt;
+  let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
+                    (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
+                    ps.BUTTON_POS_1_DEFAULT;
+  let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
+                                     continueLabel, null, null, null,
+                                     {});
+  return pressed == 0; // 0 is the "continue" button
+}
+
 let wrapper = {
   iframe: null,
 
   init: function () {
     let weave = Cc["@mozilla.org/weave/service;1"]
                   .getService(Ci.nsISupports)
                   .wrappedJSObject;
 
@@ -63,16 +103,33 @@ let wrapper = {
   onLogin: function (accountData) {
     log("Received: 'login'. Data:" + JSON.stringify(accountData));
 
     if (accountData.customizeSync) {
       Services.prefs.setBoolPref("services.sync.needsCustomization", true);
       delete accountData.customizeSync;
     }
 
+    // If the last fxa account used for sync isn't this account, we display
+    // a modal dialog checking they really really want to do this...
+    // (This is sync-specific, so ideally would be in sync's identity module,
+    // but it's a little more seamless to do here, and sync is currently the
+    // only fxa consumer, so...
+    if (needRelinkWarning(accountData) && !promptForRelink()) {
+      // we need to tell the page we successfully received the message, but
+      // then bail without telling fxAccounts
+      this.injectData("message", { status: "login" });
+      // and reload the page or else it remains in a "signed in" state.
+      window.location.reload();
+      return;
+    }
+
+    // Remember who it was so we can log out next time.
+    setPreviousAccountName(accountData.email);
+
     fxAccounts.setSignedInUser(accountData).then(
       () => {
         this.injectData("message", { status: "login" });
         // until we sort out a better UX, just leave the jelly page in place.
         // If the account email is not yet verified, it will tell the user to
         // go check their email, but then it will *not* change state after
         // the verification completes (the browser will begin syncing, but
         // won't notify the user). If the email has already been verified,
--- a/browser/components/preferences/sync.js
+++ b/browser/components/preferences/sync.js
@@ -273,16 +273,35 @@ let gSyncPane = {
   },
 
   openOldSyncSupportPage: function() {
     let url = Services.urlFormatter.formatURLPref('app.support.baseURL') + "old-sync"
     this.openContentInBrowser(url);
   },
 
   unlinkFirefoxAccount: function(confirm) {
+    if (confirm) {
+      // We use a string bundle shared with aboutAccounts.
+      let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
+      let continueLabel = sb.GetStringFromName("continue.label");
+      let title = sb.GetStringFromName("unlink.verify.title");
+      let body = sb.GetStringFromName("unlink.verify.heading") +
+                 "\n\n" +
+                 sb.GetStringFromName("unlink.verify.description");
+      let ps = Services.prompt;
+      let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
+                        (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
+                        ps.BUTTON_POS_1_DEFAULT;
+      let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
+                                         continueLabel, null, null, null,
+                                         {});
+      if (pressed != 0) { // 0 is the "continue" button
+        return;
+      }
+    }
     Components.utils.import('resource://gre/modules/FxAccounts.jsm');
     fxAccounts.signOut().then(() => {
       this.updateWeavePrefs();
     });
   },
 
   openQuotaDialog: function () {
     let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
--- a/browser/locales/en-US/chrome/browser/syncSetup.properties
+++ b/browser/locales/en-US/chrome/browser/syncSetup.properties
@@ -44,8 +44,19 @@ newAccount.action.label = Firefox Sync i
 newAccount.change.label = You can choose exactly what to sync by selecting Sync Options below.
 resetClient.change2.label = Firefox Sync will now merge all this device's browser data into your Sync account.
 wipeClient.change2.label = Firefox Sync will now replace all of the browser data on this device with the data in your Sync account.
 wipeRemote.change2.label = Firefox Sync will now replace all of the browser data in your Sync account with the data on this device.
 existingAccount.change.label = You can change this preference by selecting Sync Options below.
 
 # Several other strings are used (via Weave.Status.login), but they come from
 #  /services/sync
+
+# Firefox Accounts based setup.
+continue.label = Continue
+unlink.verify.title = Unlink Browser
+unlink.verify.heading = Are you sure?
+unlink.verify.description = This browser will stop syncing with your other computers, but won't delete any of your local browsing data.
+
+relink.verify.title = Merge Warning
+relink.verify.heading = Are you sure you want to sign in to Sync?
+# LOCALIZATION NOTE (relink.verify.description): Email address of a user previously signed into sync.
+relink.verify.description = A different user was previously signed in to Sync on this device. Signing in will merge this browser's bookmarks, passwords and other settings with %S