michael@0: // -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /*** =================== SAVED SIGNONS CODE =================== ***/ michael@0: michael@0: var kSignonBundle; michael@0: var showingPasswords = false; michael@0: michael@0: function SignonsStartup() { michael@0: kSignonBundle = document.getElementById("signonBundle"); michael@0: document.getElementById("togglePasswords").label = kSignonBundle.getString("showPasswords"); michael@0: document.getElementById("togglePasswords").accessKey = kSignonBundle.getString("showPasswordsAccessKey"); michael@0: document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll"); michael@0: LoadSignons(); michael@0: michael@0: // filter the table if requested by caller michael@0: if (window.arguments && michael@0: window.arguments[0] && michael@0: window.arguments[0].filterString) michael@0: setFilter(window.arguments[0].filterString); michael@0: michael@0: FocusFilterBox(); michael@0: } michael@0: michael@0: function setFilter(aFilterString) { michael@0: document.getElementById("filter").value = aFilterString; michael@0: _filterPasswords(); michael@0: } michael@0: michael@0: var signonsTreeView = { michael@0: _filterSet : [], michael@0: _lastSelectedRanges : [], michael@0: selection: null, michael@0: michael@0: rowCount : 0, michael@0: setTree : function(tree) {}, michael@0: getImageSrc : function(row,column) {}, michael@0: getProgressMode : function(row,column) {}, michael@0: getCellValue : function(row,column) {}, michael@0: getCellText : function(row,column) { michael@0: var signon = this._filterSet.length ? this._filterSet[row] : signons[row]; michael@0: switch (column.id) { michael@0: case "siteCol": michael@0: return signon.httpRealm ? michael@0: (signon.hostname + " (" + signon.httpRealm + ")"): michael@0: signon.hostname; michael@0: case "userCol": michael@0: return signon.username || ""; michael@0: case "passwordCol": michael@0: return signon.password || ""; michael@0: default: michael@0: return ""; michael@0: } michael@0: }, michael@0: isSeparator : function(index) { return false; }, michael@0: isSorted : function() { return false; }, michael@0: isContainer : function(index) { return false; }, michael@0: cycleHeader : function(column) {}, michael@0: getRowProperties : function(row) { return ""; }, michael@0: getColumnProperties : function(column) { return ""; }, michael@0: getCellProperties : function(row,column) { michael@0: if (column.element.getAttribute("id") == "siteCol") michael@0: return "ltr"; michael@0: michael@0: return ""; michael@0: } michael@0: }; michael@0: michael@0: michael@0: function LoadSignons() { michael@0: // loads signons into table michael@0: try { michael@0: signons = passwordmanager.getAllLogins(); michael@0: } catch (e) { michael@0: signons = []; michael@0: } michael@0: signonsTreeView.rowCount = signons.length; michael@0: michael@0: // sort and display the table michael@0: signonsTree.treeBoxObject.view = signonsTreeView; michael@0: // The sort column didn't change. SortTree (called by michael@0: // SignonColumnSort) assumes we want to toggle the sort michael@0: // direction but here we don't so we have to trick it michael@0: lastSignonSortAscending = !lastSignonSortAscending; michael@0: SignonColumnSort(lastSignonSortColumn); michael@0: michael@0: // disable "remove all signons" button if there are no signons michael@0: var element = document.getElementById("removeAllSignons"); michael@0: var toggle = document.getElementById("togglePasswords"); michael@0: if (signons.length == 0) { michael@0: element.setAttribute("disabled","true"); michael@0: toggle.setAttribute("disabled","true"); michael@0: } else { michael@0: element.removeAttribute("disabled"); michael@0: toggle.removeAttribute("disabled"); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: function SignonSelected() { michael@0: var selections = GetTreeSelections(signonsTree); michael@0: if (selections.length) { michael@0: document.getElementById("removeSignon").removeAttribute("disabled"); michael@0: } michael@0: } michael@0: michael@0: function DeleteSignon() { michael@0: var syncNeeded = (signonsTreeView._filterSet.length != 0); michael@0: DeleteSelectedItemFromTree(signonsTree, signonsTreeView, michael@0: signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons, michael@0: deletedSignons, "removeSignon", "removeAllSignons"); michael@0: FinalizeSignonDeletions(syncNeeded); michael@0: } michael@0: michael@0: function DeleteAllSignons() { michael@0: var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] michael@0: .getService(Components.interfaces.nsIPromptService); michael@0: michael@0: // Confirm the user wants to remove all passwords michael@0: var dummy = { value: false }; michael@0: if (prompter.confirmEx(window, michael@0: kSignonBundle.getString("removeAllPasswordsTitle"), michael@0: kSignonBundle.getString("removeAllPasswordsPrompt"), michael@0: prompter.STD_YES_NO_BUTTONS + prompter.BUTTON_POS_1_DEFAULT, michael@0: null, null, null, null, dummy) == 1) // 1 == "No" button michael@0: return; michael@0: michael@0: var syncNeeded = (signonsTreeView._filterSet.length != 0); michael@0: DeleteAllFromTree(signonsTree, signonsTreeView, michael@0: signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons, michael@0: deletedSignons, "removeSignon", "removeAllSignons"); michael@0: FinalizeSignonDeletions(syncNeeded); michael@0: } michael@0: michael@0: function TogglePasswordVisible() { michael@0: if (showingPasswords || masterPasswordLogin(AskUserShowPasswords)) { michael@0: showingPasswords = !showingPasswords; michael@0: document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords"); michael@0: document.getElementById("togglePasswords").accessKey = kSignonBundle.getString(showingPasswords ? "hidePasswordsAccessKey" : "showPasswordsAccessKey"); michael@0: document.getElementById("passwordCol").hidden = !showingPasswords; michael@0: _filterPasswords(); michael@0: } michael@0: michael@0: // Notify observers that the password visibility toggling is michael@0: // completed. (Mostly useful for tests) michael@0: Components.classes["@mozilla.org/observer-service;1"] michael@0: .getService(Components.interfaces.nsIObserverService) michael@0: .notifyObservers(null, "passwordmgr-password-toggle-complete", null); michael@0: } michael@0: michael@0: function AskUserShowPasswords() { michael@0: var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); michael@0: var dummy = { value: false }; michael@0: michael@0: // Confirm the user wants to display passwords michael@0: return prompter.confirmEx(window, michael@0: null, michael@0: kSignonBundle.getString("noMasterPasswordPrompt"), prompter.STD_YES_NO_BUTTONS, michael@0: null, null, null, null, dummy) == 0; // 0=="Yes" button michael@0: } michael@0: michael@0: function FinalizeSignonDeletions(syncNeeded) { michael@0: for (var s=0; s 0) michael@0: signonsTreeView.selection.select(0); michael@0: michael@0: document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielFiltered"); michael@0: } michael@0: michael@0: function CopyPassword() { michael@0: // Don't copy passwords if we aren't already showing the passwords & a master michael@0: // password hasn't been entered. michael@0: if (!showingPasswords && !masterPasswordLogin()) michael@0: return; michael@0: // Copy selected signon's password to clipboard michael@0: var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. michael@0: getService(Components.interfaces.nsIClipboardHelper); michael@0: var row = document.getElementById("signonsTree").currentIndex; michael@0: var password = signonsTreeView.getCellText(row, {id : "passwordCol" }); michael@0: clipboard.copyString(password, document); michael@0: } michael@0: michael@0: function CopyUsername() { michael@0: // Copy selected signon's username to clipboard michael@0: var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. michael@0: getService(Components.interfaces.nsIClipboardHelper); michael@0: var row = document.getElementById("signonsTree").currentIndex; michael@0: var username = signonsTreeView.getCellText(row, {id : "userCol" }); michael@0: clipboard.copyString(username); michael@0: } michael@0: michael@0: function UpdateCopyPassword() { michael@0: var singleSelection = (signonsTreeView.selection.count == 1); michael@0: var passwordMenuitem = document.getElementById("context-copypassword"); michael@0: var usernameMenuitem = document.getElementById("context-copyusername"); michael@0: if (singleSelection) { michael@0: usernameMenuitem.removeAttribute("disabled"); michael@0: passwordMenuitem.removeAttribute("disabled"); michael@0: } else { michael@0: usernameMenuitem.setAttribute("disabled", "true"); michael@0: passwordMenuitem.setAttribute("disabled", "true"); michael@0: } michael@0: } michael@0: michael@0: function masterPasswordLogin(noPasswordCallback) { michael@0: // This doesn't harm if passwords are not encrypted michael@0: var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"] michael@0: .createInstance(Components.interfaces.nsIPK11TokenDB); michael@0: var token = tokendb.getInternalKeyToken(); michael@0: michael@0: // If there is no master password, still give the user a chance to opt-out of displaying passwords michael@0: if (token.checkPassword("")) michael@0: return noPasswordCallback ? noPasswordCallback() : true; michael@0: michael@0: // So there's a master password. But since checkPassword didn't succeed, we're logged out (per nsIPK11Token.idl). michael@0: try { michael@0: // Relogin and ask for the master password. michael@0: token.login(true); // 'true' means always prompt for token password. User will be prompted until michael@0: // clicking 'Cancel' or entering the correct password. michael@0: } catch (e) { michael@0: // An exception will be thrown if the user cancels the login prompt dialog. michael@0: // User is also logged out of Software Security Device. michael@0: } michael@0: michael@0: return token.isLoggedIn(); michael@0: }