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 {ArrayDataModel} dataModel The data model that contains this item.
14 * @param {Array} entry An array of the form [url, username, password]. When
15 * the list has been filtered, a fourth element [index] may be present.
16 * @param {boolean} showPasswords If true, add a button to the element to
17 * allow the user to reveal the saved password.
19 * @extends {cr.ui.ListItem}
21 function PasswordListItem(dataModel, entry, showPasswords) {
22 var el = cr.doc.createElement('div');
24 el.dataModel = dataModel;
25 el.__proto__ = PasswordListItem.prototype;
26 el.decorate(showPasswords);
31 PasswordListItem.prototype = {
32 __proto__: DeletableItem.prototype,
35 decorate: function(showPasswords) {
36 DeletableItem.prototype.decorate.call(this);
38 // The URL of the site.
39 var urlLabel = this.ownerDocument.createElement('div');
40 urlLabel.classList.add('favicon-cell');
41 urlLabel.classList.add('weakrtl');
42 urlLabel.classList.add('url');
43 urlLabel.setAttribute('title', this.url);
44 urlLabel.textContent = this.url;
46 // The favicon URL is prefixed with "origin/", which essentially removes
47 // the URL path past the top-level domain and ensures that a scheme (e.g.,
48 // http) is being used. This ensures that the favicon returned is the
49 // default favicon for the domain and that the URL has a scheme if none
50 // is present in the password manager.
51 urlLabel.style.backgroundImage = getFaviconImageSet(
52 'origin/' + this.url, 16);
53 this.contentElement.appendChild(urlLabel);
55 // The stored username.
56 var usernameLabel = this.ownerDocument.createElement('div');
57 usernameLabel.className = 'name';
58 usernameLabel.textContent = this.username;
59 usernameLabel.title = this.username;
60 this.contentElement.appendChild(usernameLabel);
62 // The stored password.
63 var passwordInputDiv = this.ownerDocument.createElement('div');
64 passwordInputDiv.className = 'password';
66 // The password input field.
67 var passwordInput = this.ownerDocument.createElement('input');
68 passwordInput.type = 'password';
69 passwordInput.className = 'inactive-password';
70 passwordInput.readOnly = true;
71 passwordInput.value = showPasswords ? this.password : '********';
72 passwordInputDiv.appendChild(passwordInput);
73 this.passwordField = passwordInput;
75 // The show/hide button.
77 var button = this.ownerDocument.createElement('button');
79 button.className = 'list-inline-button custom-appearance';
80 button.textContent = loadTimeData.getString('passwordShowButton');
81 button.addEventListener('click', this.onClick_.bind(this), true);
82 button.addEventListener('mousedown', function(event) {
83 // Don't focus on this button by mousedown.
84 event.preventDefault();
85 // Don't handle list item selection. It causes focus change.
86 event.stopPropagation();
88 passwordInputDiv.appendChild(button);
89 this.passwordShowButton = button;
92 this.contentElement.appendChild(passwordInputDiv);
96 selectionChanged: function() {
97 var input = this.passwordField;
98 var button = this.passwordShowButton;
99 // The button doesn't exist when passwords can't be shown.
104 input.classList.remove('inactive-password');
105 button.hidden = false;
107 input.classList.add('inactive-password');
108 button.hidden = true;
113 * Reveals the plain text password of this entry.
115 showPassword: function(password) {
116 this.passwordField.value = password;
117 this.passwordField.type = 'text';
119 var button = this.passwordShowButton;
121 button.textContent = loadTimeData.getString('passwordHideButton');
125 * Hides the plain text password of this entry.
127 hidePassword: function() {
128 this.passwordField.type = 'password';
130 var button = this.passwordShowButton;
132 button.textContent = loadTimeData.getString('passwordShowButton');
136 * Get the original index of this item in the data model.
137 * @return {number} The index.
140 getOriginalIndex_: function() {
141 var index = this.dataItem[3];
142 return index ? index : this.dataModel.indexOf(this.dataItem);
146 * On-click event handler. Swaps the type of the input field from password
150 onClick_: function(event) {
151 if (this.passwordField.type == 'password') {
152 // After the user is authenticated, showPassword() will be called.
153 PasswordManager.requestShowPassword(this.getOriginalIndex_());
160 * Get and set the URL for the entry.
164 return this.dataItem[0];
167 this.dataItem[0] = url;
171 * Get and set the username for the entry.
175 return this.dataItem[1];
177 set username(username) {
178 this.dataItem[1] = username;
182 * Get and set the password for the entry.
186 return this.dataItem[2];
188 set password(password) {
189 this.dataItem[2] = password;
194 * Creates a new PasswordExceptions list item.
195 * @param {Array} entry A pair of the form [url, username].
197 * @extends {Deletable.ListItem}
199 function PasswordExceptionsListItem(entry) {
200 var el = cr.doc.createElement('div');
202 el.__proto__ = PasswordExceptionsListItem.prototype;
208 PasswordExceptionsListItem.prototype = {
209 __proto__: DeletableItem.prototype,
212 * Call when an element is decorated as a list item.
214 decorate: function() {
215 DeletableItem.prototype.decorate.call(this);
217 // The URL of the site.
218 var urlLabel = this.ownerDocument.createElement('div');
219 urlLabel.className = 'url';
220 urlLabel.classList.add('favicon-cell');
221 urlLabel.classList.add('weakrtl');
222 urlLabel.textContent = this.url;
224 // The favicon URL is prefixed with "origin/", which essentially removes
225 // the URL path past the top-level domain and ensures that a scheme (e.g.,
226 // http) is being used. This ensures that the favicon returned is the
227 // default favicon for the domain and that the URL has a scheme if none
228 // is present in the password manager.
229 urlLabel.style.backgroundImage = getFaviconImageSet(
230 'origin/' + this.url, 16);
231 this.contentElement.appendChild(urlLabel);
235 * Get the url for the entry.
239 return this.dataItem;
247 * Create a new passwords list.
249 * @extends {cr.ui.List}
251 var PasswordsList = cr.ui.define('list');
253 PasswordsList.prototype = {
254 __proto__: DeletableItemList.prototype,
257 * Whether passwords can be revealed or not.
261 showPasswords_: true,
264 decorate: function() {
265 DeletableItemList.prototype.decorate.call(this);
266 Preferences.getInstance().addEventListener(
267 'profile.password_manager_allow_show_passwords',
268 this.onPreferenceChanged_.bind(this));
272 * Listener for changes on the preference.
273 * @param {Event} event The preference update event.
276 onPreferenceChanged_: function(event) {
277 this.showPasswords_ = event.value.value;
282 createItem: function(entry) {
283 var showPasswords = this.showPasswords_;
285 if (loadTimeData.getBoolean('disableShowPasswords'))
286 showPasswords = false;
288 return new PasswordListItem(this.dataModel, entry, showPasswords);
292 deleteItemAtIndex: function(index) {
293 var item = this.dataModel.item(index);
294 if (item && item.length > 3) {
295 // The fourth element, if present, is the original index to delete.
298 PasswordManager.removeSavedPassword(index);
302 * The length of the list.
305 return this.dataModel.length;
310 * Create a new passwords list.
312 * @extends {cr.ui.List}
314 var PasswordExceptionsList = cr.ui.define('list');
316 PasswordExceptionsList.prototype = {
317 __proto__: DeletableItemList.prototype,
320 createItem: function(entry) {
321 return new PasswordExceptionsListItem(entry);
325 deleteItemAtIndex: function(index) {
326 PasswordManager.removePasswordException(index);
330 * The length of the list.
333 return this.dataModel.length;
338 PasswordListItem: PasswordListItem,
339 PasswordExceptionsListItem: PasswordExceptionsListItem,
340 PasswordsList: PasswordsList,
341 PasswordExceptionsList: PasswordExceptionsList,