Bug 590805 - Sync UI: Revamp setup wizard (part 3), r=mconnor a=blocking2.0
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Wed, 08 Sep 2010 03:37:46 +0200
changeset 52169 134be5ec050ca08cab9b3ab3a94cdf3c9cc2e837
parent 52168 201cc86810962292e4290630cb0fea9b60bbc18c
child 52170 9ec78f93036c047fb35a683c58c74e59f8276d8f
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmconnor, blocking2.0
bugs590805
milestone2.0b6pre
Bug 590805 - Sync UI: Revamp setup wizard (part 3), r=mconnor a=blocking2.0 Generate Sync Key: Fix up the Change/Update Passphrase dialog in the preference pane.
browser/base/content/syncGenericChange.js
browser/base/content/syncGenericChange.xul
browser/components/preferences/sync.xul
browser/locales/en-US/chrome/browser/preferences/sync.dtd
browser/locales/en-US/chrome/browser/syncGenericChange.properties
--- a/browser/base/content/syncGenericChange.js
+++ b/browser/base/content/syncGenericChange.js
@@ -16,54 +16,61 @@
  * The Initial Developer of the Original Code is the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Edward Lee <edilee@mozilla.com>
  *   Mike Connor <mconnor@mozilla.com>
  *   Paul O’Shannessy <paul@oshannessy.com>
+ *   Philipp von Weitershausen <philipp@weitershausen.de>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
 Components.utils.import("resource://services-sync/main.js");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 let Change = {
   _dialog: null,
   _dialogType: null,
   _status: null,
   _statusIcon: null,
   _firstBox: null,
   _secondBox: null,
 
+  get _passphraseBox() {
+    delete this._passphraseBox;
+    return this._passphraseBox = document.getElementById("passphraseBox");
+  },
+
   get _currentPasswordInvalid() {
     return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
   },
 
   get _updatingPassphrase() {
     return this._dialogType == "UpdatePassphrase";
   },
 
   onLoad: function Change_onLoad() {
     /* Load labels */
-    let box1label = document.getElementById("textBox1Label");
-    let box2label = document.getElementById("textBox2Label");
     let introText = document.getElementById("introText");
     let introText2 = document.getElementById("introText2");
     let warningText = document.getElementById("warningText");
 
     // load some other elements & info from the window
     this._dialog = document.getElementById("change-dialog");
     this._dialogType = window.arguments[0];
     this._status = document.getElementById("status");
@@ -72,36 +79,47 @@ let Change = {
     this._secondBox = document.getElementById("textBox2");
 
     this._stringBundle =
       Services.strings.createBundle("chrome://browser/locale/syncGenericChange.properties");
 
     switch (this._dialogType) {
       case "UpdatePassphrase":
       case "ResetPassphrase":
-        box1label.value = this._str("new.passphrase.label");
+        document.getElementById("textBox1Row").hidden = true;
+        document.getElementById("textBox2Row").hidden = true;
+        let passphraseLabel = document.getElementById("passphraseLabel");
+        passphraseLabel.value = this._str("new.synckey.label");
 
         if (this._updatingPassphrase) {
-          document.title = this._str("new.passphrase.title");
-          introText.textContent = this._str("new.passphrase.introText");
+          document.getElementById("passphraseBackupButtons").hidden = true;
+          document.getElementById("generatePassphraseButton").hidden = true;
+          document.title = this._str("new.synckey.title");
+          introText.textContent = this._str("new.synckey.introText");
           this._dialog.getButton("accept")
-              .setAttribute("label", this._str("new.passphrase.acceptButton"));
-          document.getElementById("textBox2Row").hidden = true;
+              .setAttribute("label", this._str("new.synckey.acceptButton"));
         }
         else {
-          document.title = this._str("change.passphrase.title");
-          box2label.value = this._str("new.passphrase.confirm");
-          introText.textContent = this._str("change.passphrase.introText");
-          introText2.textContent = this._str("change.passphrase.introText2");
-          warningText.textContent = this._str("change.passphrase.warningText");
+          let pp = Weave.Service.passphrase;
+          if (pp.length == 20)
+            pp = gSyncUtils.hyphenatePassphrase(pp);
+          document.getElementById("passphraseBox").value = pp;
+          document.title = this._str("change.synckey.title");
+          introText.innerHTML = this._str("change.synckey.introText");
+          introText2.innerHTML = this._str("change.synckey.introText2");
+          warningText.innerHTML = this._str("change.synckey.warningText");
           this._dialog.getButton("accept")
-              .setAttribute("label", this._str("change.passphrase.acceptButton"));
+              .setAttribute("label", this._str("change.synckey.acceptButton"));
         }
         break;
       case "ChangePassword":
+        document.getElementById("passphraseRow").hidden = true;
+        document.getElementById("passphraseBackupButtons").hidden = true;
+        let box1label = document.getElementById("textBox1Label");
+        let box2label = document.getElementById("textBox2Label");
         box1label.value = this._str("new.password.label");
 
         if (this._currentPasswordInvalid) {
           document.title = this._str("new.password.title");
           introText.textContent = this._str("new.password.introText");
           this._dialog.getButton("accept")
               .setAttribute("label", this._str("new.password.acceptButton"));
           document.getElementById("textBox2Row").hidden = true;
@@ -146,34 +164,42 @@ let Change = {
         return this.doChangePassphrase();
         break;
       case "ChangePassword":
         return this.doChangePassword();
         break;
     }
   },
 
+  doGeneratePassphrase: function () {
+    let passphrase = gSyncUtils.generatePassphrase();
+    let el = document.getElementById("passphraseBox");
+    el.value = gSyncUtils.hyphenatePassphrase(passphrase);
+    this._dialog.getButton("accept").disabled = false;
+  },
+
   doChangePassphrase: function Change_doChangePassphrase() {
+    let pp = gSyncUtils.normalizePassphrase(this._passphraseBox.value);
     if (this._updatingPassphrase) {
-      Weave.Service.passphrase = this._firstBox.value;
+      Weave.Service.passphrase = pp;
       if (Weave.Service.login()) {
-        this._updateStatus("change.passphrase.success", "success");
+        this._updateStatus("change.synckey.success", "success");
         Weave.Service.persistLogin();
       }
       else {
         this._updateStatus("new.passphrase.status.incorrect", "error");
       }
     }
     else {
-      this._updateStatus("change.passphrase.label", "active");
+      this._updateStatus("change.synckey.label", "active");
 
-      if (Weave.Service.changePassphrase(this._firstBox.value))
-        this._updateStatus("change.passphrase.success", "success");
+      if (Weave.Service.changePassphrase(pp))
+        this._updateStatus("change.synckey.success", "success");
       else
-        this._updateStatus("change.passphrase.error", "error");
+        this._updateStatus("change.synckey.error", "error");
     }
 
     return false;
   },
 
   doChangePassword: function Change_doChangePassword() {
     if (this._currentPasswordInvalid) {
       Weave.Service.password = this._firstBox.value;
@@ -192,31 +218,31 @@ let Change = {
         this._updateStatus("change.password.status.success", "success");
       else
         this._updateStatus("change.password.status.error", "error");
     }
 
     return false;
   },
 
-  validate: function (event) {
+  validate: function () {
     let valid = false;
     let errorString = "";
 
     if (this._dialogType == "ChangePassword") {
       if (this._currentPasswordInvalid)
         [valid, errorString] = gSyncUtils.validatePassword(this._firstBox);
       else
         [valid, errorString] = gSyncUtils.validatePassword(this._firstBox, this._secondBox);
     }
     else {
       if (this._updatingPassphrase)
-        [valid, errorString] = gSyncUtils.validatePassphrase(this._firstBox);
+        [valid, errorString] = gSyncUtils.validatePassphrase(this._passphraseBox);
       else
-        [valid, errorString] = gSyncUtils.validatePassphrase(this._firstBox, this._secondBox);
+        [valid, errorString] = gSyncUtils.validatePassphrase(this._passphraseBox, true);
     }
 
     if (errorString == "")
       this._clearStatus();
     else
       this._updateStatusWithString(errorString, "error");
 
     this._dialog.getButton("accept").disabled = !valid;
--- a/browser/base/content/syncGenericChange.xul
+++ b/browser/base/content/syncGenericChange.xul
@@ -18,16 +18,17 @@
 # The Initial Developer of the Original Code is the Mozilla Foundation.
 # Portions created by the Initial Developer are Copyright (C) 2009
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Edward Lee <edilee@mozilla.com>
 #   Mike Connor <mconnor@mozilla.com>
 #   Paul O’Shannessy <paul@oshannessy.com>
+#   Philipp von Weitershausen <philipp@weitershausen.de>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -36,57 +37,92 @@
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?>
 
+<!DOCTYPE window [
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
+<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
+%brandDTD;
+%syncBrandDTD;
+%syncSetupDTD;
+]>
 <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml"
         id="change-dialog"
         windowtype="Weave:ChangeSomething"
         buttons="accept,cancel"
         onload="Change.onLoad()"
         buttondisabledaccept="true"
         ondialogaccept="return Change.onDialogAccept();"
         defaultButton="accept">
 
   <script type="application/javascript"
           src="chrome://browser/content/syncGenericChange.js"/>
   <script type="application/javascript"
           src="chrome://browser/content/syncUtils.js"/>
+  <script type="application/javascript"
+          src="chrome://global/content/printUtils.js"/>
 
   <hbox align="top">
     <image id="syncIcon"/>
     <spacer style="width: 1em"/>
     <description flex="1">
       <html:p id="introText"/>
       <html:p id="introText2"/>
     </description>
   </hbox>
   <separator class="thin"/>
   <vbox>
     <grid>
       <columns>
         <column align="right"/>
-        <column/>
+        <column flex="3"/>
+        <column flex="1"/>
       </columns>
       <rows>
-        <row>
+        <row id="textBox1Row" align="center">
           <label id="textBox1Label" control="textBox1"/>
-          <textbox id="textBox1" type="password" oninput="Change.validate(event)"/>
+          <textbox id="textBox1" type="password" oninput="Change.validate()"/>
+          <spacer/>
+        </row>
+        <row id="textBox2Row" align="center">
+          <label id="textBox2Label" control="textBox2"/>
+          <textbox id="textBox2" type="password" oninput="Change.validate()"/>
+          <spacer/>
         </row>
-        <row id="textBox2Row">
-          <label id="textBox2Label" control="textBox2"/>
-          <textbox id="textBox2" type="password" oninput="Change.validate(event)"/>
+        <row id="passphraseRow" align="center">
+          <label id="passphraseLabel" control="passphraseBox"/>
+          <textbox id="passphraseBox"
+                   onfocus="this.select()"
+                   oninput="Change.validate()"/>
+          <label id="generatePassphraseButton"
+                 value="&syncKeyGenerate.label;"
+                 class="text-link inline-link"
+                 onclick="event.stopPropagation();
+                          Change.doGeneratePassphrase();"/>
         </row>
       </rows>
     </grid>
+    <hbox id="passphraseBackupButtons">
+      <button label="&button.syncKeyBackup.email.label;"
+              accesskey="&button.syncKeyBackup.email.accesskey;"
+              oncommand="gSyncUtils.passphraseEmail('passphraseBox');"/>
+      <button label="&button.syncKeyBackup.print.label;"
+              accesskey="&button.syncKeyBackup.print.accesskey;"
+              oncommand="gSyncUtils.passphrasePrint('passphraseBox');"/>
+      <button label="&button.syncKeyBackup.save.label;"
+              accesskey="&button.syncKeyBackup.save.accesskey;"
+              oncommand="gSyncUtils.passphraseSave('passphraseBox');"/>
+    </hbox>
 
     <description>
       <html:p class="data" id="warningText"/>
     </description>
 
     <hbox align="center">
       <image id="statusIcon" class="statusIcon"/>
       <label id="status" class="status" value=" "/>
--- a/browser/components/preferences/sync.xul
+++ b/browser/components/preferences/sync.xul
@@ -116,17 +116,17 @@
                 <row id="manageAccountControls" hidden="true">
                   <spacer/>
                     <vbox class="indent">
                       <label class="text-link"
                              onclick="gSyncUtils.changePassword(); return false;"
                              value="&changePassword.label;"/>
                       <label class="text-link"
                              onclick="gSyncUtils.resetPassphrase(); return false;"
-                             value="&changePassphrase.label;"/>
+                             value="&mySyncKey.label;"/>
                       <label class="text-link"
                              onclick="gSyncPane.resetSync(); return false;"
                              value="&resetSync.label;"/>
                       <label class="text-link"
                              onclick="gSyncPane.startOver(true); return false;"
                              value="&differentAccount.label;"/>
                     </vbox>
                   <spacer/>
--- a/browser/locales/en-US/chrome/browser/preferences/sync.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/sync.dtd
@@ -10,17 +10,17 @@
 <!-- Login error feedback -->
 <!ENTITY updatePass.label             "Update">
 <!ENTITY resetPass.label              "Reset">
 
 <!-- Manage Account -->
 <!ENTITY manageAccount.label          "Manage Account">
 <!ENTITY manageAccount.accesskey      "A">
 <!ENTITY changePassword.label         "Change Password">
-<!ENTITY changePassphrase.label       "Change Secret Phrase">
+<!ENTITY mySyncKey.label              "My Sync Key">
 <!ENTITY resetSync.label              "Reset Sync">
 <!ENTITY differentAccount.label       "Use a Different Account">
 
 <!-- Sync Settings -->
 <!ENTITY syncPrefsCaption.label       "Browser Sync">
 <!ENTITY syncComputerName.label       "Computer Name:">
 <!ENTITY syncComputerName.accesskey   "c">
 <!ENTITY syncModeSwitchDesc.label     "&brandShortName; will: ">
--- a/browser/locales/en-US/chrome/browser/syncGenericChange.properties
+++ b/browser/locales/en-US/chrome/browser/syncGenericChange.properties
@@ -3,35 +3,33 @@ change.password.title = Change your Pass
 change.password.acceptButton = Change Password
 change.password.status.active = Changing your password…
 change.password.status.success = Your password has been changed.
 change.password.status.error = There was an error changing your password.
 
 change.password.introText = Your password must be at least 8 characters long.  It cannot be the same as either your user name or your secret phrase.
 change.password.warningText = Note: All of your other devices will be unable to connect to your account once you change this password.
 
-change.passphrase.title = Change your Secret Phrase
-change.passphrase.acceptButton = Change Secret Phrase
-change.passphrase.label = Changing secret phrase and uploading local data, please wait…
-change.passphrase.error = There was an error while changing your secret phrase!
-change.passphrase.success = Your secret phrase was successfully changed!
+change.synckey.title = Change your Sync Key
+change.synckey.acceptButton = Change Sync Key
+change.synckey.label = Changing Sync Key and uploading local data, please wait…
+change.synckey.error = There was an error while changing your secret phrase!
+change.synckey.success = Your secret phrase was successfully changed!
 
-# LOCALIZATION NOTE (change.passphrase.introText) "Sync" should match &syncBrand.shortName.label; from syncBrand.dtd
-change.passphrase.introText = Your secret phrase must be at least 12 characters long.  Sync uses this phrase as part of encrypting your data.
-# LOCALIZATION NOTE (change.passphrase.introText2) "Firefox Sync" should match syncBrand.fullName.label from syncBrand.dtd
-change.passphrase.introText2 = You may wish to write this down, as this is never sent over the Internet and is not backed up or synced by Firefox Sync for your security.
-# LOCALIZATION NOTE (change.passphrase.warningText) "Sync" should match &syncBrand.shortName.label; from syncBrand.dtd
-change.passphrase.warningText = Note: This will erase all data stored on the Sync server and upload new data secured by this phrase. Your other devices will not sync until the secret phrase is entered for that device.
+change.synckey.introText = Firefox Cares About Your Privacy
+change.synckey.introText2 = To ensure your total privacy, all of your data is encrypted prior to being uploaded. The key to decrypt your data is not uploaded.
+# LOCALIZATION NOTE (change.synckey.warningText) "Sync" should match &syncBrand.shortName.label; from syncBrand.dtd
+change.synckey.warningText = Note: Changing this will erase all data stored on the Sync server and upload new data secured by this phrase. Your other devices will not sync until the new Sync Key is entered for that device.
+
+new.synckey.label = Your Sync Key
 
 # LOCALIZATION NOTE (new.password.title): This (and associated new.password/passphrase) are used on a second computer when it detects that your password or passphrase has been changed on a different device.
 new.password.title            = Update Password
 new.password.introText        = Your password was rejected by the server, please update your password.
 new.password.label            = Enter your new password
 new.password.confirm          = Confirm your new password
 new.password.acceptButton     = Update Password
 new.password.status.incorrect = Password incorrect, please try again.
 
-new.passphrase.title            = Update Secret Phrase
-new.passphrase.introText        = Your secret phrase has changed, please enter your new secret phrase
-new.passphrase.label            = New secret phrase
-new.passphrase.confirm          = Confirm secret phrase
-new.passphrase.acceptButton     = Update Secret Phrase
-new.passphrase.status.incorrect = Secret phrase incorrect, please try again.
+new.synckey.title          = Update Sync Key
+new.synckey.introText        = Your Sync Key has changed, please enter your new Sync Key
+new.synckey.acceptButton     = Update Sync Key
+new.synckey.status.incorrect = Sync Key incorrect, please try again.