Bug 239131 Thunderbird should use the new password manager (UI changes). r=philor,ui-review=clarkbw
authorMark Banner <bugzilla@standard8.plus.com>
Thu, 15 Jan 2009 17:55:32 +0000
changeset 1646 12e714b4861c
parent 1645 30c7a484a3ae
child 1647 502d7d8bea0d
push id1318
push userbugzilla@standard8.plus.com
push dateThu, 15 Jan 2009 18:00:33 +0000
treeherdercomm-central@238fe79f54ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilor
bugs239131
Bug 239131 Thunderbird should use the new password manager (UI changes). r=philor,ui-review=clarkbw
mail/components/preferences/jar.mn
mail/components/preferences/privacy.js
mail/components/preferences/privacy.xul
mail/locales/en-US/chrome/messenger/preferences/preferences.properties
mail/locales/en-US/chrome/messenger/preferences/privacy.dtd
--- a/mail/components/preferences/jar.mn
+++ b/mail/components/preferences/jar.mn
@@ -5,18 +5,16 @@ messenger.jar:
 *   content/messenger/preferences/display.xul
 *   content/messenger/preferences/display.js
 *   content/messenger/preferences/compose.xul
 *   content/messenger/preferences/compose.js
 *   content/messenger/preferences/sendoptions.xul
 *   content/messenger/preferences/sendoptions.js
 *   content/messenger/preferences/privacy.xul
 *   content/messenger/preferences/privacy.js
-*   content/messenger/preferences/viewpasswords.js
-*   content/messenger/preferences/viewpasswords.xul
 *   content/messenger/preferences/junkLog.xul
 *   content/messenger/preferences/junkLog.js
 *   content/messenger/preferences/advanced.js
 *   content/messenger/preferences/advanced.xul
 *   content/messenger/preferences/receipts.xul
 *   content/messenger/preferences/connection.js
 *   content/messenger/preferences/connection.xul
 *   content/messenger/preferences/downloads.js
--- a/mail/components/preferences/privacy.js
+++ b/mail/components/preferences/privacy.js
@@ -42,18 +42,17 @@ var gPrivacyPane = {
 
   init: function ()
   {
     this.mPane = document.getElementById("panePrivacy");
 
     this.updateManualMarkMode(document.getElementById('manualMark').checked);
     this.updateJunkLogButton(document.getElementById('enableJunkLogging').checked);
 
-    // Update the MP buttons
-    this.updateMasterPasswordButton();
+    this._initMasterPasswordUI();
 
     // update the checkbox for downloading phishing url tables
     // this.updateDownloadedPhishingListState();
 
     var preference = document.getElementById("mail.preferences.privacy.selectedTabIndex");
     if (preference.value)
       document.getElementById("privacyPrefs").selectedIndex = preference.value;
     this.mInitialized = true;
@@ -98,73 +97,121 @@ var gPrivacyPane = {
     // otherwise go ahead and remove the training data
     var junkmailPlugin = Components.classes["@mozilla.org/messenger/filter-plugin;1?name=bayesianfilter"]
                         .getService(Components.interfaces.nsIJunkMailPlugin);
 
     if (junkmailPlugin)
       junkmailPlugin.resetTrainingData();
   },
 
-  initReencryptCallback: function()
+
+  /**
+   * Initializes master password UI: the "use master password" checkbox, selects
+   * the master password button to show, and enables/disables it as necessary.
+   * The master password is controlled by various bits of NSS functionality,
+   * so the UI for it can't be controlled by the normal preference bindings.
+   */
+  _initMasterPasswordUI: function ()
   {
-    var wallet = Components.classes['@mozilla.org/wallet/wallet-service;1'];
-    wallet = wallet.getService().QueryInterface(Components.interfaces.nsIWalletService);
-    wallet.WALLET_InitReencryptCallback(window);
-  },
+    var noMP = !this._masterPasswordSet();
 
-  viewPasswords: function()
-  {
-    document.documentElement.openWindow("Toolkit:PasswordManager", "chrome://messenger/content/preferences/viewpasswords.xul",
-                                        "", null);
+    document.getElementById("changeMasterPassword").disabled = noMP;
+
+    document.getElementById("useMasterPassword").checked = !noMP;
   },
 
-  changeMasterPassword: function ()
+
+  /**
+   * Returns true if the user has a master password set and false otherwise.
+   */
+  _masterPasswordSet: function ()
   {
-    document.documentElement.openSubDialog("chrome://mozapps/content/preferences/changemp.xul",
-                                           "", null);
-    this.updateMasterPasswordButton();
-  },
-
-  updateMasterPasswordButton: function ()
-  {
-    // See if there's a master password and set the button label accordingly
-    var secmodDB = Components.classes["@mozilla.org/security/pkcs11moduledb;1"]
-                             .getService(Components.interfaces.nsIPKCS11ModuleDB);
+    const Cc = Components.classes, Ci = Components.interfaces;
+    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
+                   getService(Ci.nsIPKCS11ModuleDB);
     var slot = secmodDB.findSlotByName("");
     if (slot) {
-      const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
       var status = slot.status;
-      var noMP = status == nsIPKCS11Slot.SLOT_UNINITIALIZED ||
-                 status == nsIPKCS11Slot.SLOT_READY;
-
-      var bundle = document.getElementById("bundlePreferences");
-      document.getElementById("setMasterPassword").label =
-        bundle.getString(noMP ? "setMasterPassword" : "changeMasterPassword");
-
-      document.getElementById("removeMasterPassword").disabled = noMP;
+      var hasMP = status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
+                  status != Ci.nsIPKCS11Slot.SLOT_READY;
+      return hasMP;
+    } else {
+      // XXX I have no bloody idea what this means
+      return false;
     }
   },
 
-  removeMasterPassword: function ()
+
+  /**
+   * Enables/disables the master password button depending on the state of the
+   * "use master password" checkbox, and prompts for master password removal
+   * if one is set.
+   */
+  updateMasterPasswordButton: function ()
   {
-    var secmodDB = Components.classes["@mozilla.org/security/pkcs11moduledb;1"]
-                              .getService(Components.interfaces.nsIPKCS11ModuleDB);
-    if (secmodDB.isFIPSEnabled)
-    {
+    var checkbox = document.getElementById("useMasterPassword");
+    var button = document.getElementById("changeMasterPassword");
+    button.disabled = !checkbox.checked;
+
+    // unchecking the checkbox should try to immediately remove the master
+    // password, because it's impossible to non-destructively remove the master
+    // password used to encrypt all the passwords without providing it (by
+    // design), and it would be extremely odd to pop up that dialog when the
+    // user closes the prefwindow and saves his settings
+    if (!checkbox.checked)
+      this._removeMasterPassword();
+    else
+      this.changeMasterPassword();
+
+    this._initMasterPasswordUI();
+  },
+
+  /**
+   * Displays the "remove master password" dialog to allow the user to remove
+   * the current master password.  When the dialog is dismissed, master password
+   * UI is automatically updated.
+   */
+  _removeMasterPassword: function ()
+  {
+    const Cc = Components.classes, Ci = Components.interfaces;
+    var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
+                   getService(Ci.nsIPKCS11ModuleDB);
+    if (secmodDB.isFIPSEnabled) {
+      var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
+                          getService(Ci.nsIPromptService);
       var bundle = document.getElementById("bundlePreferences");
       promptService.alert(window,
                           bundle.getString("pw_change_failed_title"),
                           bundle.getString("pw_change2empty_in_fips_mode"));
     }
-    else
-    {
+    else {
       document.documentElement.openSubDialog("chrome://mozapps/content/preferences/removemp.xul",
                                              "", null);
-      this.updateMasterPasswordButton();
-      document.getElementById("setMasterPassword").focus();
     }
+    this._initMasterPasswordUI();
+  },
+
+  /**
+   * Displays a dialog in which the master password may be changed.
+   */
+  changeMasterPassword: function ()
+  {
+    document.documentElement.openSubDialog("chrome://mozapps/content/preferences/changemp.xul",
+                                           "", null);
+    this._initMasterPasswordUI();
+  },
+
+  /**
+   * Shows the sites where the user has saved passwords and the associated
+   * login information.
+   */
+  showPasswords: function ()
+  {
+    document.documentElement.openWindow("Toolkit:PasswordManager",
+                                        "chrome://passwordmgr/content/passwordManager.xul",
+                                        "", null);
   },
 
   updateDownloadedPhishingListState: function()
   {
     document.getElementById('useDownloadedList').disabled = !document.getElementById('enablePhishingDetector').checked;
   }
 };
--- a/mail/components/preferences/privacy.xul
+++ b/mail/components/preferences/privacy.xul
@@ -71,19 +71,16 @@
                   name="mail.phishing.detection.enabled"
                   type="bool"/>
       <preference id="browser.safebrowsing.enabled"
                   name="browser.safebrowsing.enabled"
                   type="bool"/>
       <preference id="mailnews.downloadToTempFile"
                   name="mailnews.downloadToTempFile"
                   type="bool"/>                   
-      <preference id="wallet.crypto"
-                  name="wallet.crypto"
-                  type="bool"/>
       <preference id="pref.privacy.disable_button.view_passwords"
                   name="pref.privacy.disable_button.view_passwords"
                   type="bool"/>
     </preferences>
 
     <tabbox id="privacyPrefs" flex="1" onselect="gPrivacyPane.tabSelectionChanged();">
       <tabs>
         <tab label="&itemJunk.label;"/>
@@ -152,37 +149,37 @@
                     preference="mailnews.downloadToTempFile"/>
 
         </tabpanel>
         
         <!-- Password --> 
 
         <tabpanel orient="vertical"> 
           <description>&savedPasswords.intro;</description>
+          <hbox>
+            <spacer flex="1"/>
+            <button label="&savedPasswords.label;" accesskey="&savedPasswords.accesskey;"
+                    oncommand="gPrivacyPane.showPasswords();"
+                    preference="pref.privacy.disable_button.view_passwords"/>
+          </hbox>
+          <!-- XXX button to do a showExceptions()? -->
+
           <separator class="thin"/>
-          <checkbox id="encryptEnabled" label="&encryptEnabled.label;" accesskey="&encryptEnabled.accesskey;"
-                    preference="wallet.crypto" oncommand="gPrivacyPane.initReencryptCallback();"/>
-          <separator/>
-          <hbox align="start">
-            <description flex="1">&masterPassword.intro;</description>
-            <vbox>
-              <button id="setMasterPassword" 
-                      label="&setMasterPassword.label;" accesskey="&setMasterPassword.accesskey;"
-                      oncommand="gPrivacyPane.changeMasterPassword();"/>
-              <button id="removeMasterPassword"
-                      label="&removeMasterPassword.label;" accesskey="&removeMasterPassword.accesskey;"
-                      oncommand="gPrivacyPane.removeMasterPassword();"/>
-            </vbox>
+
+          <description flex="1">&masterPassword.intro;</description>
+          <hbox>
+            <checkbox id="useMasterPassword" flex="1"
+                      label="&useMasterPassword.label;" accesskey="&useMasterPassword.accesskey;"
+                      oncommand="gPrivacyPane.updateMasterPasswordButton();"/>
+
+            <button id="changeMasterPassword"
+                    label="&changeMasterPassword.label;" accesskey="&changeMasterPassword.accesskey;"
+                    oncommand="gPrivacyPane.changeMasterPassword();"/>
           </hbox>
           <separator flex="1"/>
-          <hbox>
-            <button label="&editPasswords.label;" accesskey="&editPasswords.accesskey;"
-                    oncommand="gPrivacyPane.viewPasswords();"
-                    preference="pref.privacy.disable_button.view_passwords"/>
-          </hbox>
         </tabpanel>
       </tabpanels>
     </tabbox>
 
     <separator/>
 
   </prefpane>
 </overlay>
--- a/mail/locales/en-US/chrome/messenger/preferences/preferences.properties
+++ b/mail/locales/en-US/chrome/messenger/preferences/preferences.properties
@@ -7,20 +7,16 @@ plaintext_domainsAddDomain=Plain Text Do
 domainNameErrorTitle=Domain Name Error
 #### LOCALIZATION NOTE: do not translate %S
 domainDuplicationError=The domain name %S already exists in the HTML or Plain Text lists.
 
 #### Junk
 confirmResetJunkTrainingTitle=Confirm
 confirmResetJunkTrainingText=Are you sure you want to reset the adaptive filter training data?
 
-#### Master Password
-setMasterPassword=Set Master Password…
-changeMasterPassword=Change Master Password…
-
 #### Downloads
 desktopFolderName=Desktop
 myDownloadsFolderName=My Downloads
 chooseDownloadFolderTitle=Choose Download Folder:
 
 #### Download Actions
 extensionNone=(NONE)
 removeButtonSingle=Remove Action
--- a/mail/locales/en-US/chrome/messenger/preferences/privacy.dtd
+++ b/mail/locales/en-US/chrome/messenger/preferences/privacy.dtd
@@ -23,23 +23,21 @@
 <!-- Phishing Detector -->
 <!ENTITY phishingDetector1.intro  "&brandShortName; can analyze messages for suspected email scams by looking for common techniques used to deceive you.">
 <!ENTITY enablePhishingDetector1.label    "Tell me if the message I'm reading is a suspected email scam">
 <!ENTITY enablePhishingDetector1.accesskey  "e">
 <!ENTITY useDownloadedList.label "Use a downloaded list of suspected email scams">
 <!ENTITY useDownloadedList.accesskey "U">
 
 <!-- Passwords -->
-<!ENTITY savedPasswords.intro         "&brandShortName; can remember password information for all of your accounts so you do not need to re-enter your login details.">
-<!ENTITY  encryptEnabled.label        "Use a master password to encrypt stored passwords">
-<!ENTITY  encryptEnabled.accesskey    "s">
-<!ENTITY  masterPassword.intro        "When set, the Master Password protects all your passwords - but you must enter it once per session.">
-<!ENTITY  setMasterPassword.label     "Master Password">
-<!ENTITY  setMasterPassword.accesskey "M">
-<!ENTITY  removeMasterPassword.label  "Remove Master Password…">
-<!ENTITY  removeMasterPassword.accesskey "R">
-<!ENTITY  editPasswords.label         "Edit Saved Passwords">
-<!ENTITY  editPasswords.accesskey     "i">
+<!ENTITY savedPasswords.intro           "&brandShortName; can remember passwords for all of your accounts.">
+<!ENTITY useMasterPassword.label        "Use a master password">
+<!ENTITY useMasterPassword.accesskey    "m">
+<!ENTITY masterPassword.intro           "A Master Password protects all your passwords, but you must enter it once per session.">
+<!ENTITY changeMasterPassword.label     "Change Master Password…">
+<!ENTITY changeMasterPassword.accesskey "C">
+<!ENTITY savedPasswords.label           "Saved Passwords…">
+<!ENTITY savedPasswords.accesskey       "S">
 
 <!-- Anti Virus -->
 <!ENTITY antiVirus.intro      "&brandShortName; can make it easy for anti-virus software to analyze incoming mail messages for viruses before they are stored locally.">
 <!ENTITY antiVirus.label      "Allow anti-virus clients to quarantine individual incoming messages">
 <!ENTITY antiVirus.accesskey  "l">