diff -r 000000000000 -r 6474c204b198 toolkit/components/passwordmgr/content/passwordManager.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolkit/components/passwordmgr/content/passwordManager.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,373 @@ +// -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*** =================== 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(); + + // filter the table if requested by caller + if (window.arguments && + window.arguments[0] && + window.arguments[0].filterString) + setFilter(window.arguments[0].filterString); + + FocusFilterBox(); +} + +function setFilter(aFilterString) { + document.getElementById("filter").value = aFilterString; + _filterPasswords(); +} + +var signonsTreeView = { + _filterSet : [], + _lastSelectedRanges : [], + selection: null, + + rowCount : 0, + setTree : function(tree) {}, + getImageSrc : function(row,column) {}, + getProgressMode : function(row,column) {}, + getCellValue : function(row,column) {}, + getCellText : function(row,column) { + var signon = this._filterSet.length ? this._filterSet[row] : signons[row]; + switch (column.id) { + case "siteCol": + return signon.httpRealm ? + (signon.hostname + " (" + signon.httpRealm + ")"): + signon.hostname; + case "userCol": + return signon.username || ""; + case "passwordCol": + return signon.password || ""; + default: + return ""; + } + }, + isSeparator : function(index) { return false; }, + isSorted : function() { return false; }, + isContainer : function(index) { return false; }, + cycleHeader : function(column) {}, + getRowProperties : function(row) { return ""; }, + getColumnProperties : function(column) { return ""; }, + getCellProperties : function(row,column) { + if (column.element.getAttribute("id") == "siteCol") + return "ltr"; + + return ""; + } +}; + + +function LoadSignons() { + // loads signons into table + try { + signons = passwordmanager.getAllLogins(); + } catch (e) { + signons = []; + } + signonsTreeView.rowCount = signons.length; + + // sort and display the table + signonsTree.treeBoxObject.view = signonsTreeView; + // The sort column didn't change. SortTree (called by + // SignonColumnSort) assumes we want to toggle the sort + // direction but here we don't so we have to trick it + lastSignonSortAscending = !lastSignonSortAscending; + SignonColumnSort(lastSignonSortColumn); + + // disable "remove all signons" button if there are no signons + var element = document.getElementById("removeAllSignons"); + var toggle = document.getElementById("togglePasswords"); + if (signons.length == 0) { + element.setAttribute("disabled","true"); + toggle.setAttribute("disabled","true"); + } else { + element.removeAttribute("disabled"); + toggle.removeAttribute("disabled"); + } + + return true; +} + +function SignonSelected() { + var selections = GetTreeSelections(signonsTree); + if (selections.length) { + document.getElementById("removeSignon").removeAttribute("disabled"); + } +} + +function DeleteSignon() { + var syncNeeded = (signonsTreeView._filterSet.length != 0); + DeleteSelectedItemFromTree(signonsTree, signonsTreeView, + signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons, + deletedSignons, "removeSignon", "removeAllSignons"); + FinalizeSignonDeletions(syncNeeded); +} + +function DeleteAllSignons() { + var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + + // Confirm the user wants to remove all passwords + var dummy = { value: false }; + if (prompter.confirmEx(window, + kSignonBundle.getString("removeAllPasswordsTitle"), + kSignonBundle.getString("removeAllPasswordsPrompt"), + prompter.STD_YES_NO_BUTTONS + prompter.BUTTON_POS_1_DEFAULT, + null, null, null, null, dummy) == 1) // 1 == "No" button + return; + + var syncNeeded = (signonsTreeView._filterSet.length != 0); + DeleteAllFromTree(signonsTree, signonsTreeView, + signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons, + deletedSignons, "removeSignon", "removeAllSignons"); + FinalizeSignonDeletions(syncNeeded); +} + +function TogglePasswordVisible() { + 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 + // completed. (Mostly useful for tests) + Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService) + .notifyObservers(null, "passwordmgr-password-toggle-complete", null); +} + +function AskUserShowPasswords() { + var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); + var dummy = { value: false }; + + // 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 FinalizeSignonDeletions(syncNeeded) { + for (var s=0; s 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, document); +} + +function CopyUsername() { + // Copy selected signon's username to clipboard + var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. + getService(Components.interfaces.nsIClipboardHelper); + var row = document.getElementById("signonsTree").currentIndex; + var username = signonsTreeView.getCellText(row, {id : "userCol" }); + clipboard.copyString(username); +} + +function UpdateCopyPassword() { + var singleSelection = (signonsTreeView.selection.count == 1); + var passwordMenuitem = document.getElementById("context-copypassword"); + var usernameMenuitem = document.getElementById("context-copyusername"); + if (singleSelection) { + usernameMenuitem.removeAttribute("disabled"); + passwordMenuitem.removeAttribute("disabled"); + } else { + usernameMenuitem.setAttribute("disabled", "true"); + passwordMenuitem.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(); +}