Bug 571997 - Copy Password doesn't ask for master password while Show Passwords does [r=dolske]
authorPaul O’Shannessy <paul@oshannessy.com>
Tue, 21 Jun 2011 10:44:09 -0700
changeset 71478 ae1c0ef60963eb94249862dad83a7daadc5b39cd
parent 71477 bdd4d79f9836523194629e56bb66cf8f44212894
child 71479 5c3cca20059017e04b80e65f3dccddbbf6ae918c
push idunknown
push userunknown
push dateunknown
reviewersdolske
bugs571997
milestone7.0a1
Bug 571997 - Copy Password doesn't ask for master password while Show Passwords does [r=dolske]
toolkit/components/passwordmgr/content/passwordManager.js
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -39,16 +39,17 @@
 # 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 *****
 
 /*** =================== SAVED SIGNONS CODE =================== ***/
 
 var kSignonBundle;
+var showingPasswords = false;
 
 function SignonsStartup() {
   kSignonBundle = document.getElementById("signonBundle");
   document.getElementById("togglePasswords").label = kSignonBundle.getString("showPasswords");
   document.getElementById("togglePasswords").accessKey = kSignonBundle.getString("showPasswordsAccessKey");
   document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll");
   LoadSignons();
 
@@ -166,17 +167,17 @@ function DeleteAllSignons() {
   var syncNeeded = (signonsTreeView._filterSet.length != 0);
   DeleteAllFromTree(signonsTree, signonsTreeView,
                         signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons,
                         deletedSignons, "removeSignon", "removeAllSignons");
   FinalizeSignonDeletions(syncNeeded);
 }
 
 function TogglePasswordVisible() {
-  if (showingPasswords || ConfirmShowPasswords()) {
+  if (showingPasswords || masterPasswordLogin(AskUserShowPasswords)) {
     showingPasswords = !showingPasswords;
     document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords");
     document.getElementById("togglePasswords").accessKey = kSignonBundle.getString(showingPasswords ? "hidePasswordsAccessKey" : "showPasswordsAccessKey");
     document.getElementById("passwordCol").hidden = !showingPasswords;
     _filterPasswords();
   }
 
   // Notify observers that the password visibility toggling is
@@ -192,39 +193,16 @@ function AskUserShowPasswords() {
 
   // Confirm the user wants to display passwords
   return prompter.confirmEx(window,
           null,
           kSignonBundle.getString("noMasterPasswordPrompt"), prompter.STD_YES_NO_BUTTONS,
           null, null, null, null, dummy) == 0;    // 0=="Yes" button
 }
 
-function ConfirmShowPasswords() {
-  // This doesn't harm if passwords are not encrypted
-  var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"]
-                    .createInstance(Components.interfaces.nsIPK11TokenDB);
-  var token = tokendb.getInternalKeyToken();
-
-  // If there is no master password, still give the user a chance to opt-out of displaying passwords
-  if (token.checkPassword(""))
-    return AskUserShowPasswords();
-
-  // So there's a master password. But since checkPassword didn't succeed, we're logged out (per nsIPK11Token.idl).
-  try {
-    // Relogin and ask for the master password.
-    token.login(true);  // 'true' means always prompt for token password. User will be prompted until
-                        // clicking 'Cancel' or entering the correct password.
-  } catch (e) {
-    // An exception will be thrown if the user cancels the login prompt dialog.
-    // User is also logged out of Software Security Device.
-  }
-
-  return token.isLoggedIn();
-}
-
 function FinalizeSignonDeletions(syncNeeded) {
   for (var s=0; s<deletedSignons.length; s++) {
     passwordmanager.removeLogin(deletedSignons[s]);
   }
   // If the deletion has been performed in a filtered view, reflect the deletion in the unfiltered table.
   // See bug 405389.
   if (syncNeeded) {
     try {
@@ -367,24 +345,51 @@ function _filterPasswords()
   // if the view is not empty then select the first item
   if (signonsTreeView.rowCount > 0)
     signonsTreeView.selection.select(0);
 
   document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielFiltered");
 }
 
 function CopyPassword() {
+  // Don't copy passwords if we aren't already showing the passwords & a master
+  // password hasn't been entered.
+  if (!showingPasswords && !masterPasswordLogin())
+    return;
   // Copy selected signon's password to clipboard
   var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
                   getService(Components.interfaces.nsIClipboardHelper);
   var row = document.getElementById("signonsTree").currentIndex;
   var password = signonsTreeView.getCellText(row, {id : "passwordCol" });
   clipboard.copyString(password);
 }
 
 function UpdateCopyPassword() {
   var singleSelection = (signonsTreeView.selection.count == 1);
   var menuitem = document.getElementById("context-copypassword");
   if (singleSelection)
     menuitem.removeAttribute("disabled");
   else
     menuitem.setAttribute("disabled", "true");
 }
+
+function masterPasswordLogin(noPasswordCallback) {
+  // This doesn't harm if passwords are not encrypted
+  var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"]
+                    .createInstance(Components.interfaces.nsIPK11TokenDB);
+  var token = tokendb.getInternalKeyToken();
+
+  // If there is no master password, still give the user a chance to opt-out of displaying passwords
+  if (token.checkPassword(""))
+    return noPasswordCallback ? noPasswordCallback() : true;
+
+  // So there's a master password. But since checkPassword didn't succeed, we're logged out (per nsIPK11Token.idl).
+  try {
+    // Relogin and ask for the master password.
+    token.login(true);  // 'true' means always prompt for token password. User will be prompted until
+                        // clicking 'Cancel' or entering the correct password.
+  } catch (e) {
+    // An exception will be thrown if the user cancels the login prompt dialog.
+    // User is also logged out of Software Security Device.
+  }
+
+  return token.isLoggedIn();
+}