cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / chrome / browser / resources / options / password_manager_list.js
blobf8ed9e8a5fdc5423ac10318d6bacaf1bb2450d75
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;
11 /** @const */ var URL_DATA_INDEX = 0;
12 /** @const */ var USERNAME_DATA_INDEX = 1;
13 /** @const */ var PASSWORD_DATA_INDEX = 2;
14 /** @const */ var FEDERATION_DATA_INDEX = 3;
15 /** @const */ var ORIGINAL_DATA_INDEX = 4;
17 /**
18 * Creates a new passwords list item.
19 * @param {cr.ui.ArrayDataModel} dataModel The data model that contains this
20 * item.
21 * @param {Array} entry An array of the form [url, username, password,
22 * federation]. When the list has been filtered, a fifth element [index]
23 * may be present.
24 * @param {boolean} showPasswords If true, add a button to the element to
25 * allow the user to reveal the saved password.
26 * @constructor
27 * @extends {options.DeletableItem}
29 function PasswordListItem(dataModel, entry, showPasswords) {
30 var el = cr.doc.createElement('div');
31 el.dataItem = entry;
32 el.dataModel = dataModel;
33 el.__proto__ = PasswordListItem.prototype;
34 el.showPasswords_ = showPasswords;
35 el.decorate();
37 return el;
40 PasswordListItem.prototype = {
41 __proto__: DeletableItem.prototype,
43 /** @override */
44 decorate: function() {
45 DeletableItem.prototype.decorate.call(this);
47 // The URL of the site.
48 var urlLabel = this.ownerDocument.createElement('div');
49 urlLabel.classList.add('favicon-cell');
50 urlLabel.classList.add('weakrtl');
51 urlLabel.classList.add('url');
52 urlLabel.setAttribute('title', this.url);
53 urlLabel.textContent = this.url;
55 // The favicon URL is prefixed with "origin/", which essentially removes
56 // the URL path past the top-level domain and ensures that a scheme (e.g.,
57 // http) is being used. This ensures that the favicon returned is the
58 // default favicon for the domain and that the URL has a scheme if none
59 // is present in the password manager.
60 urlLabel.style.backgroundImage = getFaviconImageSet(
61 'origin/' + this.url, 16);
62 this.contentElement.appendChild(urlLabel);
64 // The stored username.
65 var usernameLabel = this.ownerDocument.createElement('div');
66 usernameLabel.className = 'name';
67 usernameLabel.textContent = this.username;
68 usernameLabel.title = this.username;
69 this.contentElement.appendChild(usernameLabel);
71 if (this.federation) {
72 // The federation.
73 var federationDiv = this.ownerDocument.createElement('div');
74 federationDiv.className = 'federation';
75 federationDiv.textContent = this.federation;
76 this.contentElement.appendChild(federationDiv);
77 } else {
78 // The stored password.
79 var passwordInputDiv = this.ownerDocument.createElement('div');
80 passwordInputDiv.className = 'password';
82 // The password input field.
83 var passwordInput = this.ownerDocument.createElement('input');
84 passwordInput.type = 'password';
85 passwordInput.className = 'inactive-password';
86 passwordInput.readOnly = true;
87 passwordInput.value = this.showPasswords_ ? this.password : '********';
88 passwordInputDiv.appendChild(passwordInput);
89 var deletableItem = this;
90 passwordInput.addEventListener('focus', function() {
91 deletableItem.handleFocus();
92 });
93 this.passwordField = passwordInput;
94 this.setFocusable_(false);
96 // The show/hide button.
97 if (this.showPasswords_) {
98 var button = this.ownerDocument.createElement('button');
99 button.hidden = true;
100 button.className = 'list-inline-button custom-appearance';
101 button.textContent = loadTimeData.getString('passwordShowButton');
102 button.addEventListener('click', this.onClick_.bind(this), true);
103 button.addEventListener('mousedown', function(event) {
104 // Don't focus on this button by mousedown.
105 event.preventDefault();
106 // Don't handle list item selection. It causes focus change.
107 event.stopPropagation();
108 }, false);
109 button.addEventListener('focus', function() {
110 deletableItem.handleFocus();
112 passwordInputDiv.appendChild(button);
113 this.passwordShowButton = button;
115 this.contentElement.appendChild(passwordInputDiv);
120 /** @override */
121 selectionChanged: function() {
122 var input = this.passwordField;
123 var button = this.passwordShowButton;
124 // The button doesn't exist when passwords can't be shown.
125 if (!button)
126 return;
128 if (this.selected) {
129 input.classList.remove('inactive-password');
130 this.setFocusable_(true);
131 button.hidden = false;
132 input.focus();
133 } else {
134 input.classList.add('inactive-password');
135 this.setFocusable_(false);
136 button.hidden = true;
141 * Set the focusability of this row.
142 * @param {boolean} focusable
143 * @private
145 setFocusable_: function(focusable) {
146 var tabIndex = focusable ? 0 : -1;
147 this.passwordField.tabIndex = this.closeButtonElement.tabIndex = tabIndex;
151 * Reveals the plain text password of this entry.
153 showPassword: function(password) {
154 this.passwordField.value = password;
155 this.passwordField.type = 'text';
157 var button = this.passwordShowButton;
158 if (button)
159 button.textContent = loadTimeData.getString('passwordHideButton');
163 * Hides the plain text password of this entry.
165 hidePassword: function() {
166 this.passwordField.type = 'password';
168 var button = this.passwordShowButton;
169 if (button)
170 button.textContent = loadTimeData.getString('passwordShowButton');
174 * Get the original index of this item in the data model.
175 * @return {number} The index.
176 * @private
178 getOriginalIndex_: function() {
179 var index = this.dataItem[ORIGINAL_DATA_INDEX];
180 return index ? index : this.dataModel.indexOf(this.dataItem);
184 * On-click event handler. Swaps the type of the input field from password
185 * to text and back.
186 * @private
188 onClick_: function(event) {
189 if (this.passwordField.type == 'password') {
190 // After the user is authenticated, showPassword() will be called.
191 PasswordManager.requestShowPassword(this.getOriginalIndex_());
192 } else {
193 this.hidePassword();
198 * Get and set the URL for the entry.
199 * @type {string}
201 get url() {
202 return this.dataItem[URL_DATA_INDEX];
204 set url(url) {
205 this.dataItem[URL_DATA_INDEX] = url;
209 * Get and set the username for the entry.
210 * @type {string}
212 get username() {
213 return this.dataItem[USERNAME_DATA_INDEX];
215 set username(username) {
216 this.dataItem[USERNAME_DATA_INDEX] = username;
220 * Get and set the password for the entry.
221 * @type {string}
223 get password() {
224 return this.dataItem[PASSWORD_DATA_INDEX];
226 set password(password) {
227 this.dataItem[PASSWORD_DATA_INDEX] = password;
231 * Get and set the federation for the entry.
232 * @type {string}
234 get federation() {
235 return this.dataItem[FEDERATION_DATA_INDEX];
237 set federation(federation) {
238 this.dataItem[FEDERATION_DATA_INDEX] = federation;
243 * Creates a new PasswordExceptions list item.
244 * @param {Array} entry A pair of the form [url, username].
245 * @constructor
246 * @extends {options.DeletableItem}
248 function PasswordExceptionsListItem(entry) {
249 var el = cr.doc.createElement('div');
250 el.dataItem = entry;
251 el.__proto__ = PasswordExceptionsListItem.prototype;
252 el.decorate();
254 return el;
257 PasswordExceptionsListItem.prototype = {
258 __proto__: DeletableItem.prototype,
261 * Call when an element is decorated as a list item.
263 decorate: function() {
264 DeletableItem.prototype.decorate.call(this);
266 // The URL of the site.
267 var urlLabel = this.ownerDocument.createElement('div');
268 urlLabel.className = 'url';
269 urlLabel.classList.add('favicon-cell');
270 urlLabel.classList.add('weakrtl');
271 urlLabel.textContent = this.url;
273 // The favicon URL is prefixed with "origin/", which essentially removes
274 // the URL path past the top-level domain and ensures that a scheme (e.g.,
275 // http) is being used. This ensures that the favicon returned is the
276 // default favicon for the domain and that the URL has a scheme if none
277 // is present in the password manager.
278 urlLabel.style.backgroundImage = getFaviconImageSet(
279 'origin/' + this.url, 16);
280 this.contentElement.appendChild(urlLabel);
284 * Get the url for the entry.
285 * @type {string}
287 get url() {
288 return this.dataItem;
290 set url(url) {
291 this.dataItem = url;
296 * Create a new passwords list.
297 * @constructor
298 * @extends {options.DeletableItemList}
300 var PasswordsList = cr.ui.define('list');
302 PasswordsList.prototype = {
303 __proto__: DeletableItemList.prototype,
306 * Whether passwords can be revealed or not.
307 * @type {boolean}
308 * @private
310 showPasswords_: true,
312 /** @override */
313 decorate: function() {
314 DeletableItemList.prototype.decorate.call(this);
315 Preferences.getInstance().addEventListener(
316 'profile.password_manager_allow_show_passwords',
317 this.onPreferenceChanged_.bind(this));
318 this.addEventListener('focus', this.onFocus_.bind(this));
322 * Listener for changes on the preference.
323 * @param {Event} event The preference update event.
324 * @private
326 onPreferenceChanged_: function(event) {
327 this.showPasswords_ = event.value.value;
328 this.redraw();
332 * @override
333 * @param {Array} entry
335 createItem: function(entry) {
336 var showPasswords = this.showPasswords_;
338 if (loadTimeData.getBoolean('disableShowPasswords'))
339 showPasswords = false;
341 return new PasswordListItem(this.dataModel, entry, showPasswords);
344 /** @override */
345 deleteItemAtIndex: function(index) {
346 var item = this.dataModel.item(index);
347 if (item && item[ORIGINAL_DATA_INDEX] != undefined) {
348 // The fifth element, if present, is the original index to delete.
349 index = item[ORIGINAL_DATA_INDEX];
351 PasswordManager.removeSavedPassword(index);
355 * The length of the list.
357 get length() {
358 return this.dataModel.length;
362 * Will make to first row focusable if none are selected. This makes it
363 * possible to tab into the rows without pressing up/down first.
364 * @param {Event} e The focus event.
365 * @private
367 onFocus_: function(e) {
368 if (!this.selectedItem && this.items)
369 this.items[0].setFocusable_(true);
374 * Create a new passwords list.
375 * @constructor
376 * @extends {options.DeletableItemList}
378 var PasswordExceptionsList = cr.ui.define('list');
380 PasswordExceptionsList.prototype = {
381 __proto__: DeletableItemList.prototype,
384 * @override
385 * @param {Array} entry
387 createItem: function(entry) {
388 return new PasswordExceptionsListItem(entry);
391 /** @override */
392 deleteItemAtIndex: function(index) {
393 PasswordManager.removePasswordException(index);
397 * The length of the list.
399 get length() {
400 return this.dataModel.length;
404 return {
405 PasswordListItem: PasswordListItem,
406 PasswordExceptionsListItem: PasswordExceptionsListItem,
407 PasswordsList: PasswordsList,
408 PasswordExceptionsList: PasswordExceptionsList,