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.
5 cr.define('options.passwordManager', function() {
6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel;
7 /** @const */ var DeletableItemList = options.DeletableItemList;
8 /** @const */ var DeletableItem = options.DeletableItem;
9 /** @const */ var List = cr.ui.List;
12 * Creates a new passwords list item.
13 * @param {cr.ui.ArrayDataModel} dataModel The data model that contains this
15 * @param {Array} entry An array of the form [url, username, password]. When
16 * the list has been filtered, a fourth element [index] may be present.
17 * @param {boolean} showPasswords If true, add a button to the element to
18 * allow the user to reveal the saved password.
20 * @extends {options.DeletableItem}
22 function PasswordListItem(dataModel, entry, showPasswords) {
23 var el = cr.doc.createElement('div');
25 el.dataModel = dataModel;
26 el.__proto__ = PasswordListItem.prototype;
27 el.decorate(showPasswords);
32 PasswordListItem.prototype = {
33 __proto__: DeletableItem.prototype,
36 decorate: function(showPasswords) {
37 DeletableItem.prototype.decorate.call(this);
39 // The URL of the site.
40 var urlLabel = this.ownerDocument.createElement('div');
41 urlLabel.classList.add('favicon-cell');
42 urlLabel.classList.add('weakrtl');
43 urlLabel.classList.add('url');
44 urlLabel.setAttribute('title', this.url);
45 urlLabel.textContent = this.url;
47 // The favicon URL is prefixed with "origin/", which essentially removes
48 // the URL path past the top-level domain and ensures that a scheme (e.g.,
49 // http) is being used. This ensures that the favicon returned is the
50 // default favicon for the domain and that the URL has a scheme if none
51 // is present in the password manager.
52 urlLabel.style.backgroundImage = getFaviconImageSet(
53 'origin/' + this.url, 16);
54 this.contentElement.appendChild(urlLabel);
56 // The stored username.
57 var usernameLabel = this.ownerDocument.createElement('div');
58 usernameLabel.className = 'name';
59 usernameLabel.textContent = this.username;
60 usernameLabel.title = this.username;
61 this.contentElement.appendChild(usernameLabel);
63 // The stored password.
64 var passwordInputDiv = this.ownerDocument.createElement('div');
65 passwordInputDiv.className = 'password';
67 // The password input field.
68 var passwordInput = this.ownerDocument.createElement('input');
69 passwordInput.type = 'password';
70 passwordInput.className = 'inactive-password';
71 passwordInput.readOnly = true;
72 passwordInput.value = showPasswords ? this.password : '********';
73 passwordInputDiv.appendChild(passwordInput);
74 this.passwordField = passwordInput;
76 // The show/hide button.
78 var button = this.ownerDocument.createElement('button');
80 button.className = 'list-inline-button custom-appearance';
81 button.textContent = loadTimeData.getString('passwordShowButton');
82 button.addEventListener('click', this.onClick_.bind(this), true);
83 button.addEventListener('mousedown', function(event) {
84 // Don't focus on this button by mousedown.
85 event.preventDefault();
86 // Don't handle list item selection. It causes focus change.
87 event.stopPropagation();
89 passwordInputDiv.appendChild(button);
90 this.passwordShowButton = button;
93 this.contentElement.appendChild(passwordInputDiv);
97 selectionChanged: function() {
98 var input = this.passwordField;
99 var button = this.passwordShowButton;
100 // The button doesn't exist when passwords can't be shown.
105 input.classList.remove('inactive-password');
106 button.hidden = false;
108 input.classList.add('inactive-password');
109 button.hidden = true;
114 * Reveals the plain text password of this entry.
116 showPassword: function(password) {
117 this.passwordField.value = password;
118 this.passwordField.type = 'text';
120 var button = this.passwordShowButton;
122 button.textContent = loadTimeData.getString('passwordHideButton');
126 * Hides the plain text password of this entry.
128 hidePassword: function() {
129 this.passwordField.type = 'password';
131 var button = this.passwordShowButton;
133 button.textContent = loadTimeData.getString('passwordShowButton');
137 * Get the original index of this item in the data model.
138 * @return {number} The index.
141 getOriginalIndex_: function() {
142 var index = this.dataItem[3];
143 return index ? index : this.dataModel.indexOf(this.dataItem);
147 * On-click event handler. Swaps the type of the input field from password
151 onClick_: function(event) {
152 if (this.passwordField.type == 'password') {
153 // After the user is authenticated, showPassword() will be called.
154 PasswordManager.requestShowPassword(this.getOriginalIndex_());
161 * Get and set the URL for the entry.
165 return this.dataItem[0];
168 this.dataItem[0] = url;
172 * Get and set the username for the entry.
176 return this.dataItem[1];
178 set username(username) {
179 this.dataItem[1] = username;
183 * Get and set the password for the entry.
187 return this.dataItem[2];
189 set password(password) {
190 this.dataItem[2] = password;
195 * Creates a new PasswordExceptions list item.
196 * @param {Array} entry A pair of the form [url, username].
198 * @extends {options.DeletableItem}
200 function PasswordExceptionsListItem(entry) {
201 var el = cr.doc.createElement('div');
203 el.__proto__ = PasswordExceptionsListItem.prototype;
209 PasswordExceptionsListItem.prototype = {
210 __proto__: DeletableItem.prototype,
213 * Call when an element is decorated as a list item.
215 decorate: function() {
216 DeletableItem.prototype.decorate.call(this);
218 // The URL of the site.
219 var urlLabel = this.ownerDocument.createElement('div');
220 urlLabel.className = 'url';
221 urlLabel.classList.add('favicon-cell');
222 urlLabel.classList.add('weakrtl');
223 urlLabel.textContent = this.url;
225 // The favicon URL is prefixed with "origin/", which essentially removes
226 // the URL path past the top-level domain and ensures that a scheme (e.g.,
227 // http) is being used. This ensures that the favicon returned is the
228 // default favicon for the domain and that the URL has a scheme if none
229 // is present in the password manager.
230 urlLabel.style.backgroundImage = getFaviconImageSet(
231 'origin/' + this.url, 16);
232 this.contentElement.appendChild(urlLabel);
236 * Get the url for the entry.
240 return this.dataItem;
248 * Create a new passwords list.
250 * @extends {options.DeletableItemList}
252 var PasswordsList = cr.ui.define('list');
254 PasswordsList.prototype = {
255 __proto__: DeletableItemList.prototype,
258 * Whether passwords can be revealed or not.
262 showPasswords_: true,
265 decorate: function() {
266 DeletableItemList.prototype.decorate.call(this);
267 Preferences.getInstance().addEventListener(
268 'profile.password_manager_allow_show_passwords',
269 this.onPreferenceChanged_.bind(this));
273 * Listener for changes on the preference.
274 * @param {Event} event The preference update event.
277 onPreferenceChanged_: function(event) {
278 this.showPasswords_ = event.value.value;
284 * @param {Array} entry
286 createItem: function(entry) {
287 var showPasswords = this.showPasswords_;
289 if (loadTimeData.getBoolean('disableShowPasswords'))
290 showPasswords = false;
292 return new PasswordListItem(this.dataModel, entry, showPasswords);
296 deleteItemAtIndex: function(index) {
297 var item = this.dataModel.item(index);
298 if (item && item.length > 3) {
299 // The fourth element, if present, is the original index to delete.
302 PasswordManager.removeSavedPassword(index);
306 * The length of the list.
309 return this.dataModel.length;
314 * Create a new passwords list.
316 * @extends {cr.ui.List}
318 var PasswordExceptionsList = cr.ui.define('list');
320 PasswordExceptionsList.prototype = {
321 __proto__: DeletableItemList.prototype,
325 * @param {Array} entry
327 createItem: function(entry) {
328 return new PasswordExceptionsListItem(entry);
332 deleteItemAtIndex: function(index) {
333 PasswordManager.removePasswordException(index);
337 * The length of the list.
340 return this.dataModel.length;
345 PasswordListItem: PasswordListItem,
346 PasswordExceptionsListItem: PasswordExceptionsListItem,
347 PasswordsList: PasswordsList,
348 PasswordExceptionsList: PasswordExceptionsList,