Bug 598010 - Update Sync UI in Fennec [r=vingtetun]
authorMark Finkle <mfinkle@mozilla.com>
Thu, 23 Sep 2010 17:18:27 -0400
changeset 66703 16cb55545f6601dc897c0880d3f3294c0752f606
parent 66702 a75f332d845312821e4fa5bebefe3a49bf924dbe
child 66704 3922870bd52511eb71db460f3bd0c992fe7e63a2
push id19389
push userffxbld
push dateWed, 06 Apr 2011 21:33:21 +0000
treeherdermozilla-central@8e9f90073a20 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvingtetun
bugs598010
Bug 598010 - Update Sync UI in Fennec [r=vingtetun]
mobile/chrome/content/browser.xul
mobile/chrome/content/sync.js
mobile/locales/en-US/chrome/preferences.dtd
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -447,28 +447,28 @@
                 <setting pref="network.cookie.cookieBehavior" title="&allowCookies.title;" type="boolint" on="0" off="2"/>
                 <setting pref="signon.rememberSignons" title="&rememberPasswords.title;" type="bool"/>
                 <setting title="&clearPrivateData2.title;" type="control">
                   <button id="prefs-clear-data" label="&clearPrivateData.button;" command="cmd_sanitize"/>
                 </setting>
               </settings>
 #ifdef MOZ_SERVICES_SYNC
               <settings id="prefs-sync" label="&sync.title;">
-                <setting id="sync-user" type="string" title="&sync.username;" />
-                <setting id="sync-pass" type="string" inputtype="password" title="&sync.password;" />
-                <setting id="sync-secret" type="string" inputtype="password" title="&sync.secretPhrase;" />
-                <setting id="sync-device" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this)" collapsed="true"/>
+                <setting id="sync-account" type="string" title="&sync.account;"/>
+                <setting id="sync-pass" type="string" inputtype="password" title="&sync.password;"/>
+                <setting id="sync-secret" type="string" inputtype="string" title="&sync.syncKey;"/>
+                <setting id="sync-device" type="string" title="&sync.deviceName;" onchange="WeaveGlue.changeName(this);" collapsed="true"/>
                 <setting id="sync-connect" type="control">
                   <button label="&sync.connect;" oncommand="WeaveGlue.connect();" />
                 </setting>
                 <setting id="sync-disconnect" type="control" collapsed="true">
                   <button label="&sync.disconnect;" oncommand="WeaveGlue.disconnect();" />
                 </setting>
                 <setting id="sync-sync" type="control" collapsed="true">
-                  <button id="sync-syncButton" label="&sync.syncNow;" oncommand="WeaveGlue.sync();" />
+                  <button id="sync-syncButton" label="&sync.syncNow;" oncommand="WeaveGlue.sync();"/>
                 </setting>
               </settings>
 #endif
             </richlistbox>
           </notificationbox>
         </vbox>
 
         <vbox id="console-container" flex="1">
--- a/mobile/chrome/content/sync.js
+++ b/mobile/chrome/content/sync.js
@@ -35,29 +35,34 @@
  * ***** END LICENSE BLOCK ***** */
 
 let WeaveGlue = {
   init: function init() {
     Components.utils.import("resource://services-sync/service.js");
 
     this._addListeners();
 
-    // Initialize the UI now
-    this._updateOptions();
-
     // Generating keypairs is expensive on mobile, so disable it
     Weave.Service.keyGenEnabled = false;
+
+    // Load the values for the string inputs
+    this.loadInputs();
   },
 
   connect: function connect() {
-    if (this._settings.user.value != Weave.Service.username)
+    // Cause the Sync system to reset internals if we seem to be switching accounts
+    if (this._settings.account.value != Weave.Service.account)
       Weave.Service.startOver();
 
-    Weave.Service.login(this._settings.user.value, this._settings.pass.value,
-      this._settings.secret.value);
+    // Remove any leftover connection string
+    this._settings.connect.removeAttribute("desc");
+
+    // Sync will use the account value and munge it into a username, as needed
+    Weave.Service.account = this._settings.account.value;
+    Weave.Service.login(Weave.Service.username, this._settings.pass.value, this.normalizePassphrase(this._settings.secret.value));
     Weave.Service.persistLogin();
   },
 
   disconnect: function disconnect() {
     Weave.Service.logout();
   },
 
   sync: function sync() {
@@ -65,119 +70,148 @@ let WeaveGlue = {
   },
 
   _addListeners: function _addListeners() {
     let topics = ["weave:service:sync:start", "weave:service:sync:finish",
       "weave:service:sync:error", "weave:service:login:start",
       "weave:service:login:finish", "weave:service:login:error",
       "weave:service:logout:finish"];
 
-    // For each topic, add or remove _updateOptions as the observer
-    let addRem = function(add) topics.forEach(function(topic) Weave.Svc.
-      Obs[add ? "add" : "remove"](topic, WeaveGlue._updateOptions, WeaveGlue));
+    // For each topic, add WeaveGlue the observer
+    topics.forEach(function(topic) {
+      Services.obs.addObserver(WeaveGlue, topic, false);
+    });
 
-    // Add the listeners now, and remove them on unload
-    addRem(true);
-    addEventListener("unload", function() addRem(false), false);
+    // Remove them on unload
+    addEventListener("unload", function() {
+      topics.forEach(function(topic) {
+        Services.obs.removeObserver(WeaveGlue, topic, false);
+      });
+    }, false);
   },
 
   get _settings() {
     // Do a quick test to see if the options exist yet
     let syncButton = document.getElementById("sync-syncButton");
     if (syncButton == null)
       return;
 
     // Get all the setting nodes from the add-ons display
     let settings = {};
-    let ids = ["user", "pass", "secret", "device", "connect", "disconnect", "sync"];
+    let ids = ["account", "pass", "secret", "device", "connect", "disconnect", "sync"];
     ids.forEach(function(id) {
       settings[id] = document.getElementById("sync-" + id);
     });
 
     // Replace the getter with the collection of settings
     delete this._settings;
     return this._settings = settings;
   },
 
-  _updateOptions: function _updateOptions() {
+  observe: function observe(aSubject, aTopic, aData) {
     let loggedIn = Weave.Service.isLoggedIn;
     document.getElementById("cmd_remoteTabs").setAttribute("disabled", !loggedIn);
 
     // Make sure we're online when connecting/syncing
     Util.forceOnline();
 
     // Can't do anything before settings are loaded
     if (this._settings == null)
       return;
 
     // Make some aliases
-    let user = this._settings.user;
+    let account = this._settings.account;
     let pass = this._settings.pass;
     let secret = this._settings.secret;
     let connect = this._settings.connect;
     let device = this._settings.device;
     let disconnect = this._settings.disconnect;
     let sync = this._settings.sync;
     let syncStr = Weave.Str.sync;
 
     // Make sure the options are in the right state
-    user.collapsed = loggedIn;
+    account.collapsed = loggedIn;
     pass.collapsed = loggedIn;
     secret.collapsed = loggedIn;
     connect.collapsed = loggedIn;
     device.collapsed = !loggedIn;
     disconnect.collapsed = !loggedIn;
     sync.collapsed = !loggedIn;
 
     // Check the lock on a timeout because it's set just after notifying
     setTimeout(function() {
       // Prevent certain actions when the service is locked
       if (Weave.Service.locked) {
         connect.firstChild.disabled = true;
         sync.firstChild.disabled = true;
-        connect.setAttribute("title", syncStr.get("connecting.label"));
-        sync.setAttribute("title", syncStr.get("lastSyncInProgress.label"));
+
+        if (aTopic == "weave:service:login:start")
+          connect.setAttribute("title", syncStr.get("connecting.label"));
+
+        if (aTopic == "weave:service:sync:start")
+          sync.setAttribute("title", syncStr.get("lastSyncInProgress.label"));
       } else {
         connect.firstChild.disabled = false;
         sync.firstChild.disabled = false;
         connect.setAttribute("title", syncStr.get("disconnected.label"));
       }
     }, 0);
 
     // Move the disconnect and sync settings out to make connect the last item
     let parent = connect.parentNode;
     if (!loggedIn)
       parent = parent.parentNode;
     parent.appendChild(disconnect);
     parent.appendChild(sync);
 
     // Dynamically generate some strings
-    let connectedStr = syncStr.get("connected.label", [Weave.Service.username]);
+    let connectedStr = syncStr.get("connected.label", [Weave.Service.account]);
     disconnect.setAttribute("title", connectedStr);
 
     // Show the day-of-week and time (HH:MM) of last sync
     let lastSync = Weave.Svc.Prefs.get("lastSync");
     if (lastSync != null) {
       let syncDate = new Date(lastSync).toLocaleFormat("%a %R");
       let dateStr = syncStr.get("lastSync.label", [syncDate]);
       sync.setAttribute("title", dateStr);
     }
 
     // Show what went wrong with login if necessary
-    let login = Weave.Status.login;
-    if (login == Weave.LOGIN_SUCCEEDED)
+    if (aTopic == "weave:service:login:error")
+      connect.setAttribute("desc", Weave.Utils.getErrorString(Weave.Status.login));
+    else
       connect.removeAttribute("desc");
-    else if (login != null)
-      connect.setAttribute("desc", Weave.Utils.getErrorString(login));
 
     // Load the values for the string inputs
-    user.value = Weave.Service.username || "";
-    pass.value = Weave.Service.password || "";
-    secret.value = Weave.Service.passphrase || "";
-    device.value = Weave.Clients.localName || "";
+    this.loadInputs();
+  },
+
+  loadInputs: function loadInputs() {
+    this._settings.account.value = Weave.Service.account || "";
+    this._settings.pass.value = Weave.Service.password || "";
+    let pp = Weave.Service.passphrase || "";
+    if (pp.length == 20)
+      pp = this.hyphenatePassphrase(pp);
+    this._settings.secret.value = pp;
+    this._settings.device.value = Weave.Clients.localName || "";
   },
 
-  changeName: function changeName(input) {
+  changeName: function changeName(aInput) {
     // Make sure to update to a modified name, e.g., empty-string -> default
-    Weave.Clients.localName = input.value;
-    input.value = Weave.Clients.localName;
+    Weave.Clients.localName = aInput.value;
+    aInput.value = Weave.Clients.localName;
+  },
+
+  hyphenatePassphrase: function(passphrase) {
+    // Hyphenate a 20 character passphrase in 4 groups of 5
+    return passphrase.slice(0, 5) + '-'
+         + passphrase.slice(5, 10) + '-'
+         + passphrase.slice(10, 15) + '-'
+         + passphrase.slice(15, 20);
+  },
+
+  normalizePassphrase: function(pp) {
+    // Remove hyphens as inserted by hyphenatePassphrase()
+    if (pp.length == 23 && pp[5] == '-' && pp[11] == '-' && pp[17] == '-')
+      return pp.slice(0, 5) + pp.slice(6, 11) + pp.slice(12, 17) + pp.slice(18, 23);
+    return pp;
   }
 };
--- a/mobile/locales/en-US/chrome/preferences.dtd
+++ b/mobile/locales/en-US/chrome/preferences.dtd
@@ -14,15 +14,15 @@
 <!ENTITY language.auto                             "Auto-detect">
 <!ENTITY defaultBrowser.title                      "Default Browser">
 <!ENTITY defaultBrowser.description                "Make &brandShortName; your default browser">
 <!ENTITY homepage.title                            "Start page">
 <!ENTITY homepage.none                             "Blank Page">
 <!ENTITY homepage.default                          "&brandShortName; Start">
 <!ENTITY homepage.currentpage                      "Use Current Page">
 <!ENTITY sync.title                                "Sync">
-<!ENTITY sync.username                             "Username">
+<!ENTITY sync.account                              "Username/Email">
 <!ENTITY sync.password                             "Password">
-<!ENTITY sync.secretPhrase                         "Secret Phrase">
+<!ENTITY sync.syncKey                              "Sync Key">
 <!ENTITY sync.deviceName                           "Device Name">
 <!ENTITY sync.connect                              "Connect">
 <!ENTITY sync.disconnect                           "Disconnect">
 <!ENTITY sync.syncNow                              "Sync Now">