toolkit/components/passwordmgr/content/passwordManager.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*** =================== SAVED SIGNONS CODE =================== ***/
     9 var kSignonBundle;
    10 var showingPasswords = false;
    12 function SignonsStartup() {
    13   kSignonBundle = document.getElementById("signonBundle");
    14   document.getElementById("togglePasswords").label = kSignonBundle.getString("showPasswords");
    15   document.getElementById("togglePasswords").accessKey = kSignonBundle.getString("showPasswordsAccessKey");
    16   document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll");
    17   LoadSignons();
    19   // filter the table if requested by caller
    20   if (window.arguments &&
    21       window.arguments[0] &&
    22       window.arguments[0].filterString)
    23     setFilter(window.arguments[0].filterString);
    25   FocusFilterBox();
    26 }
    28 function setFilter(aFilterString) {
    29   document.getElementById("filter").value = aFilterString;
    30   _filterPasswords();
    31 }
    33 var signonsTreeView = {
    34   _filterSet : [],
    35   _lastSelectedRanges : [],
    36   selection: null,
    38   rowCount : 0,
    39   setTree : function(tree) {},
    40   getImageSrc : function(row,column) {},
    41   getProgressMode : function(row,column) {},
    42   getCellValue : function(row,column) {},
    43   getCellText : function(row,column) {
    44     var signon = this._filterSet.length ? this._filterSet[row] : signons[row];
    45     switch (column.id) {
    46       case "siteCol":
    47         return signon.httpRealm ?
    48                (signon.hostname + " (" + signon.httpRealm + ")"):
    49                signon.hostname;
    50       case "userCol":
    51         return signon.username || "";
    52       case "passwordCol":
    53         return signon.password || "";
    54       default:
    55         return "";
    56     }
    57   },
    58   isSeparator : function(index) { return false; },
    59   isSorted : function() { return false; },
    60   isContainer : function(index) { return false; },
    61   cycleHeader : function(column) {},
    62   getRowProperties : function(row) { return ""; },
    63   getColumnProperties : function(column) { return ""; },
    64   getCellProperties : function(row,column) {
    65     if (column.element.getAttribute("id") == "siteCol")
    66       return "ltr";
    68     return "";
    69   }
    70 };
    73 function LoadSignons() {
    74   // loads signons into table
    75   try {
    76     signons = passwordmanager.getAllLogins();
    77   } catch (e) {
    78     signons = [];
    79   }
    80   signonsTreeView.rowCount = signons.length;
    82   // sort and display the table
    83   signonsTree.treeBoxObject.view = signonsTreeView;
    84   // The sort column didn't change. SortTree (called by
    85   // SignonColumnSort) assumes we want to toggle the sort
    86   // direction but here we don't so we have to trick it
    87   lastSignonSortAscending = !lastSignonSortAscending;
    88   SignonColumnSort(lastSignonSortColumn);
    90   // disable "remove all signons" button if there are no signons
    91   var element = document.getElementById("removeAllSignons");
    92   var toggle = document.getElementById("togglePasswords");
    93   if (signons.length == 0) {
    94     element.setAttribute("disabled","true");
    95     toggle.setAttribute("disabled","true");
    96   } else {
    97     element.removeAttribute("disabled");
    98     toggle.removeAttribute("disabled");
    99   }
   101   return true;
   102 }
   104 function SignonSelected() {
   105   var selections = GetTreeSelections(signonsTree);
   106   if (selections.length) {
   107     document.getElementById("removeSignon").removeAttribute("disabled");
   108   }
   109 }
   111 function DeleteSignon() {
   112   var syncNeeded = (signonsTreeView._filterSet.length != 0);
   113   DeleteSelectedItemFromTree(signonsTree, signonsTreeView,
   114                              signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons,
   115                              deletedSignons, "removeSignon", "removeAllSignons");
   116   FinalizeSignonDeletions(syncNeeded);
   117 }
   119 function DeleteAllSignons() {
   120   var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
   121                            .getService(Components.interfaces.nsIPromptService);
   123   // Confirm the user wants to remove all passwords
   124   var dummy = { value: false };
   125   if (prompter.confirmEx(window,
   126                          kSignonBundle.getString("removeAllPasswordsTitle"),
   127                          kSignonBundle.getString("removeAllPasswordsPrompt"),
   128                          prompter.STD_YES_NO_BUTTONS + prompter.BUTTON_POS_1_DEFAULT,
   129                          null, null, null, null, dummy) == 1) // 1 == "No" button
   130     return;
   132   var syncNeeded = (signonsTreeView._filterSet.length != 0);
   133   DeleteAllFromTree(signonsTree, signonsTreeView,
   134                         signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons,
   135                         deletedSignons, "removeSignon", "removeAllSignons");
   136   FinalizeSignonDeletions(syncNeeded);
   137 }
   139 function TogglePasswordVisible() {
   140   if (showingPasswords || masterPasswordLogin(AskUserShowPasswords)) {
   141     showingPasswords = !showingPasswords;
   142     document.getElementById("togglePasswords").label = kSignonBundle.getString(showingPasswords ? "hidePasswords" : "showPasswords");
   143     document.getElementById("togglePasswords").accessKey = kSignonBundle.getString(showingPasswords ? "hidePasswordsAccessKey" : "showPasswordsAccessKey");
   144     document.getElementById("passwordCol").hidden = !showingPasswords;
   145     _filterPasswords();
   146   }
   148   // Notify observers that the password visibility toggling is
   149   // completed.  (Mostly useful for tests)
   150   Components.classes["@mozilla.org/observer-service;1"]
   151             .getService(Components.interfaces.nsIObserverService)
   152             .notifyObservers(null, "passwordmgr-password-toggle-complete", null);
   153 }
   155 function AskUserShowPasswords() {
   156   var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
   157   var dummy = { value: false };
   159   // Confirm the user wants to display passwords
   160   return prompter.confirmEx(window,
   161           null,
   162           kSignonBundle.getString("noMasterPasswordPrompt"), prompter.STD_YES_NO_BUTTONS,
   163           null, null, null, null, dummy) == 0;    // 0=="Yes" button
   164 }
   166 function FinalizeSignonDeletions(syncNeeded) {
   167   for (var s=0; s<deletedSignons.length; s++) {
   168     passwordmanager.removeLogin(deletedSignons[s]);
   169   }
   170   // If the deletion has been performed in a filtered view, reflect the deletion in the unfiltered table.
   171   // See bug 405389.
   172   if (syncNeeded) {
   173     try {
   174       signons = passwordmanager.getAllLogins();
   175     } catch (e) {
   176       signons = [];
   177     }
   178   }
   179   deletedSignons.length = 0;
   180 }
   182 function HandleSignonKeyPress(e) {
   183   if (e.keyCode == 46) {
   184     DeleteSignon();
   185   }
   186 }
   188 function getColumnByName(column) {
   189   switch (column) {
   190     case "hostname":
   191       return document.getElementById("siteCol");
   192     case "username":
   193       return document.getElementById("userCol");
   194     case "password":
   195       return document.getElementById("passwordCol");
   196   }
   197 }
   199 var lastSignonSortColumn = "hostname";
   200 var lastSignonSortAscending = true;
   202 function SignonColumnSort(column) {
   203   // clear out the sortDirection attribute on the old column
   204   var lastSortedCol = getColumnByName(lastSignonSortColumn);
   205   lastSortedCol.removeAttribute("sortDirection");
   207   // sort
   208   lastSignonSortAscending =
   209     SortTree(signonsTree, signonsTreeView,
   210                  signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons,
   211                  column, lastSignonSortColumn, lastSignonSortAscending);
   212   lastSignonSortColumn = column;
   214   // set the sortDirection attribute to get the styling going
   215   // first we need to get the right element
   216   var sortedCol = getColumnByName(column);
   217   sortedCol.setAttribute("sortDirection", lastSignonSortAscending ?
   218                                           "ascending" : "descending");
   219 }
   221 function SignonClearFilter() {
   222   var singleSelection = (signonsTreeView.selection.count == 1);
   224   // Clear the Tree Display
   225   signonsTreeView.rowCount = 0;
   226   signonsTree.treeBoxObject.rowCountChanged(0, -signonsTreeView._filterSet.length);
   227   signonsTreeView._filterSet = [];
   229   // Just reload the list to make sure deletions are respected
   230   LoadSignons();
   232   // Restore selection
   233   if (singleSelection) {
   234     signonsTreeView.selection.clearSelection();
   235     for (let i = 0; i < signonsTreeView._lastSelectedRanges.length; ++i) {
   236       var range = signonsTreeView._lastSelectedRanges[i];
   237       signonsTreeView.selection.rangedSelect(range.min, range.max, true);
   238     }
   239   } else {
   240     signonsTreeView.selection.select(0);
   241   }
   242   signonsTreeView._lastSelectedRanges = [];
   244   document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielAll");
   245 }
   247 function FocusFilterBox() {
   248   var filterBox = document.getElementById("filter");
   249   if (filterBox.getAttribute("focused") != "true")
   250     filterBox.focus();
   251 }
   253 function SignonMatchesFilter(aSignon, aFilterValue) {
   254   if (aSignon.hostname.toLowerCase().indexOf(aFilterValue) != -1)
   255     return true;
   256   if (aSignon.username &&
   257       aSignon.username.toLowerCase().indexOf(aFilterValue) != -1)
   258     return true;
   259   if (aSignon.httpRealm &&
   260       aSignon.httpRealm.toLowerCase().indexOf(aFilterValue) != -1)
   261     return true;
   262   if (showingPasswords && aSignon.password &&
   263       aSignon.password.toLowerCase().indexOf(aFilterValue) != -1)
   264     return true;
   266   return false;
   267 }
   269 function FilterPasswords(aFilterValue, view) {
   270   aFilterValue = aFilterValue.toLowerCase();
   271   return signons.filter(function (s) SignonMatchesFilter(s, aFilterValue));
   272 }
   274 function SignonSaveState() {
   275   // Save selection
   276   var seln = signonsTreeView.selection;
   277   signonsTreeView._lastSelectedRanges = [];
   278   var rangeCount = seln.getRangeCount();
   279   for (var i = 0; i < rangeCount; ++i) {
   280     var min = {}; var max = {};
   281     seln.getRangeAt(i, min, max);
   282     signonsTreeView._lastSelectedRanges.push({ min: min.value, max: max.value });
   283   }
   284 }
   286 function _filterPasswords()
   287 {
   288   var filter = document.getElementById("filter").value;
   289   if (filter == "") {
   290     SignonClearFilter();
   291     return;
   292   }
   294   var newFilterSet = FilterPasswords(filter, signonsTreeView);
   295   if (!signonsTreeView._filterSet.length) {
   296     // Save Display Info for the Non-Filtered mode when we first
   297     // enter Filtered mode.
   298     SignonSaveState();
   299   }
   300   signonsTreeView._filterSet = newFilterSet;
   302   // Clear the display
   303   let oldRowCount = signonsTreeView.rowCount;
   304   signonsTreeView.rowCount = 0;
   305   signonsTree.treeBoxObject.rowCountChanged(0, -oldRowCount);
   306   // Set up the filtered display
   307   signonsTreeView.rowCount = signonsTreeView._filterSet.length;
   308   signonsTree.treeBoxObject.rowCountChanged(0, signonsTreeView.rowCount);
   310   // if the view is not empty then select the first item
   311   if (signonsTreeView.rowCount > 0)
   312     signonsTreeView.selection.select(0);
   314   document.getElementById("signonsIntro").textContent = kSignonBundle.getString("loginsSpielFiltered");
   315 }
   317 function CopyPassword() {
   318   // Don't copy passwords if we aren't already showing the passwords & a master
   319   // password hasn't been entered.
   320   if (!showingPasswords && !masterPasswordLogin())
   321     return;
   322   // Copy selected signon's password to clipboard
   323   var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
   324                   getService(Components.interfaces.nsIClipboardHelper);
   325   var row = document.getElementById("signonsTree").currentIndex;
   326   var password = signonsTreeView.getCellText(row, {id : "passwordCol" });
   327   clipboard.copyString(password, document);
   328 }
   330 function CopyUsername() {
   331   // Copy selected signon's username to clipboard
   332   var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].
   333                   getService(Components.interfaces.nsIClipboardHelper);
   334   var row = document.getElementById("signonsTree").currentIndex;
   335   var username = signonsTreeView.getCellText(row, {id : "userCol" });
   336   clipboard.copyString(username);
   337 }
   339 function UpdateCopyPassword() {
   340   var singleSelection = (signonsTreeView.selection.count == 1);
   341   var passwordMenuitem = document.getElementById("context-copypassword");
   342   var usernameMenuitem = document.getElementById("context-copyusername");
   343   if (singleSelection) {
   344     usernameMenuitem.removeAttribute("disabled");
   345     passwordMenuitem.removeAttribute("disabled");
   346   } else {
   347     usernameMenuitem.setAttribute("disabled", "true");
   348     passwordMenuitem.setAttribute("disabled", "true");
   349   }
   350 }
   352 function masterPasswordLogin(noPasswordCallback) {
   353   // This doesn't harm if passwords are not encrypted
   354   var tokendb = Components.classes["@mozilla.org/security/pk11tokendb;1"]
   355                     .createInstance(Components.interfaces.nsIPK11TokenDB);
   356   var token = tokendb.getInternalKeyToken();
   358   // If there is no master password, still give the user a chance to opt-out of displaying passwords
   359   if (token.checkPassword(""))
   360     return noPasswordCallback ? noPasswordCallback() : true;
   362   // So there's a master password. But since checkPassword didn't succeed, we're logged out (per nsIPK11Token.idl).
   363   try {
   364     // Relogin and ask for the master password.
   365     token.login(true);  // 'true' means always prompt for token password. User will be prompted until
   366                         // clicking 'Cancel' or entering the correct password.
   367   } catch (e) {
   368     // An exception will be thrown if the user cancels the login prompt dialog.
   369     // User is also logged out of Software Security Device.
   370   }
   372   return token.isLoggedIn();
   373 }

mercurial