Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 cr.define('options', function() {
      6   /** @const */ var OptionsPage = options.OptionsPage;
      7   /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel;
      8 
      9   /////////////////////////////////////////////////////////////////////////////
     10   // PasswordManager class:
     11 
     12   /**
     13    * Encapsulated handling of password and exceptions page.
     14    * @constructor
     15    */
     16   function PasswordManager() {
     17     this.activeNavTab = null;
     18     OptionsPage.call(this,
     19                      'passwords',
     20                      loadTimeData.getString('passwordsPageTabTitle'),
     21                      'password-manager');
     22   }
     23 
     24   cr.addSingletonGetter(PasswordManager);
     25 
     26   PasswordManager.prototype = {
     27     __proto__: OptionsPage.prototype,
     28 
     29     /**
     30      * The saved passwords list.
     31      * @type {DeletableItemList}
     32      * @private
     33      */
     34     savedPasswordsList_: null,
     35 
     36     /**
     37      * The password exceptions list.
     38      * @type {DeletableItemList}
     39      * @private
     40      */
     41     passwordExceptionsList_: null,
     42 
     43     /**
     44      * The timer id of the timer set on search query change events.
     45      * @type {number}
     46      * @private
     47      */
     48     queryDelayTimerId_: 0,
     49 
     50     /**
     51      * The most recent search query, or null if the query is empty.
     52      * @type {?string}
     53      * @private
     54      */
     55     lastQuery_: null,
     56 
     57     /** @override */
     58     initializePage: function() {
     59       OptionsPage.prototype.initializePage.call(this);
     60 
     61       $('password-manager-confirm').onclick = function() {
     62         OptionsPage.closeOverlay();
     63       };
     64 
     65       $('password-search-box').addEventListener('search',
     66           this.handleSearchQueryChange_.bind(this));
     67 
     68       this.createSavedPasswordsList_();
     69       this.createPasswordExceptionsList_();
     70     },
     71 
     72     /** @override */
     73     canShowPage: function() {
     74       return !(cr.isChromeOS && UIAccountTweaks.loggedInAsGuest());
     75     },
     76 
     77     /** @override */
     78     didShowPage: function() {
     79       // Updating the password lists may cause a blocking platform dialog pop up
     80       // (Mac, Linux), so we delay this operation until the page is shown.
     81       chrome.send('updatePasswordLists');
     82       $('password-search-box').focus();
     83     },
     84 
     85     /**
     86      * Creates, decorates and initializes the saved passwords list.
     87      * @private
     88      */
     89     createSavedPasswordsList_: function() {
     90       this.savedPasswordsList_ = $('saved-passwords-list');
     91       options.passwordManager.PasswordsList.decorate(this.savedPasswordsList_);
     92       this.savedPasswordsList_.autoExpands = true;
     93     },
     94 
     95     /**
     96      * Creates, decorates and initializes the password exceptions list.
     97      * @private
     98      */
     99     createPasswordExceptionsList_: function() {
    100       this.passwordExceptionsList_ = $('password-exceptions-list');
    101       options.passwordManager.PasswordExceptionsList.decorate(
    102           this.passwordExceptionsList_);
    103       this.passwordExceptionsList_.autoExpands = true;
    104     },
    105 
    106     /**
    107      * Handles search query changes.
    108      * @param {!Event} e The event object.
    109      * @private
    110      */
    111     handleSearchQueryChange_: function(e) {
    112       if (this.queryDelayTimerId_)
    113         window.clearTimeout(this.queryDelayTimerId_);
    114 
    115       // Searching cookies uses a timeout of 500ms. We use a shorter timeout
    116       // because there are probably fewer passwords and we want the UI to be
    117       // snappier since users will expect that it's "less work."
    118       this.queryDelayTimerId_ = window.setTimeout(
    119           this.searchPasswords_.bind(this), 250);
    120     },
    121 
    122     /**
    123      * Search passwords using text in |password-search-box|.
    124      * @private
    125      */
    126     searchPasswords_: function() {
    127       this.queryDelayTimerId_ = 0;
    128       var filter = $('password-search-box').value;
    129       filter = (filter == '') ? null : filter;
    130       if (this.lastQuery_ != filter) {
    131         this.lastQuery_ = filter;
    132         // Searching for passwords has the side effect of requerying the
    133         // underlying password store. This is done intentionally, as on OS X and
    134         // Linux they can change from outside and we won't be notified of it.
    135         chrome.send('updatePasswordLists');
    136       }
    137     },
    138 
    139     /**
    140      * Updates the visibility of the list and empty list placeholder.
    141      * @param {!List} list The list to toggle visilibility for.
    142      */
    143     updateListVisibility_: function(list) {
    144       var empty = list.dataModel.length == 0;
    145       var listPlaceHolderID = list.id + '-empty-placeholder';
    146       list.hidden = empty;
    147       $(listPlaceHolderID).hidden = !empty;
    148     },
    149 
    150     /**
    151      * Updates the data model for the saved passwords list with the values from
    152      * |entries|.
    153      * @param {Array} entries The list of saved password data.
    154      */
    155     setSavedPasswordsList_: function(entries) {
    156       if (this.lastQuery_) {
    157         // Implement password searching here in javascript, rather than in C++.
    158         // The number of saved passwords shouldn't be too big for us to handle.
    159         var query = this.lastQuery_;
    160         var filter = function(entry, index, list) {
    161           // Search both URL and username.
    162           if (entry[0].indexOf(query) >= 0 || entry[1].indexOf(query) >= 0) {
    163             // Keep the original index so we can delete correctly. See also
    164             // deleteItemAtIndex() in password_manager_list.js that uses this.
    165             entry[3] = index;
    166             return true;
    167           }
    168           return false;
    169         };
    170         entries = entries.filter(filter);
    171       }
    172       this.savedPasswordsList_.dataModel = new ArrayDataModel(entries);
    173       this.updateListVisibility_(this.savedPasswordsList_);
    174     },
    175 
    176     /**
    177      * Updates the data model for the password exceptions list with the values
    178      * from |entries|.
    179      * @param {Array} entries The list of password exception data.
    180      */
    181     setPasswordExceptionsList_: function(entries) {
    182       this.passwordExceptionsList_.dataModel = new ArrayDataModel(entries);
    183       this.updateListVisibility_(this.passwordExceptionsList_);
    184     },
    185   };
    186 
    187   /**
    188    * Removes a saved password.
    189    * @param {number} rowIndex indicating the row to remove.
    190    */
    191   PasswordManager.removeSavedPassword = function(rowIndex) {
    192       chrome.send('removeSavedPassword', [String(rowIndex)]);
    193   };
    194 
    195   /**
    196    * Removes a password exception.
    197    * @param {number} rowIndex indicating the row to remove.
    198    */
    199   PasswordManager.removePasswordException = function(rowIndex) {
    200       chrome.send('removePasswordException', [String(rowIndex)]);
    201   };
    202 
    203   /**
    204    * Removes all saved passwords.
    205    */
    206   PasswordManager.removeAllPasswords = function() {
    207     chrome.send('removeAllSavedPasswords');
    208   };
    209 
    210   /**
    211    * Removes all password exceptions.
    212    */
    213   PasswordManager.removeAllPasswordExceptions = function() {
    214     chrome.send('removeAllPasswordExceptions');
    215   };
    216 
    217   PasswordManager.setSavedPasswordsList = function(entries) {
    218     PasswordManager.getInstance().setSavedPasswordsList_(entries);
    219   };
    220 
    221   PasswordManager.setPasswordExceptionsList = function(entries) {
    222     PasswordManager.getInstance().setPasswordExceptionsList_(entries);
    223   };
    224 
    225   // Export
    226   return {
    227     PasswordManager: PasswordManager
    228   };
    229 
    230 });
    231