Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: chrome/browser/resources/options/password_manager_list.js

Issue 489103004: Allow editing passwords in settings/passwords (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Exclude 2 tests on Android Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 cr.define('options.passwordManager', function() { 5 cr.define('options.passwordManager', function() {
6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel;
7 /** @const */ var DeletableItemList = options.DeletableItemList; 7 /** @const */ var DeletableItemList = options.DeletableItemList;
8 /** @const */ var DeletableItem = options.DeletableItem; 8 /** @const */ var DeletableItem = options.DeletableItem;
9 /** @const */ var InlineEditableItemList = options.InlineEditableItemList;
10 /** @const */ var InlineEditableItem = options.InlineEditableItem;
9 /** @const */ var List = cr.ui.List; 11 /** @const */ var List = cr.ui.List;
10 12
11 /** 13 /**
12 * Creates a new passwords list item. 14 * Creates a new passwords list item.
13 * @param {ArrayDataModel} dataModel The data model that contains this item. 15 * @param {ArrayDataModel} dataModel The data model that contains this item.
14 * @param {Array} entry An array of the form [url, username, password]. When 16 * @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. 17 * 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 18 * @param {boolean} showPasswords If true, add a button to the element to
17 * allow the user to reveal the saved password. 19 * allow the user to reveal the saved password.
18 * @constructor 20 * @constructor
19 * @extends {cr.ui.ListItem} 21 * @extends {options.InlineEditableItem}
20 */ 22 */
21 function PasswordListItem(dataModel, entry, showPasswords) { 23 function PasswordListItem(dataModel, entry, showPasswords) {
22 var el = cr.doc.createElement('div'); 24 var el = cr.doc.createElement('div');
23 el.dataItem = entry; 25 el.dataItem = entry;
24 el.dataModel = dataModel; 26 el.dataModel = dataModel;
25 el.__proto__ = PasswordListItem.prototype; 27 el.__proto__ = PasswordListItem.prototype;
26 el.decorate(showPasswords); 28 el.decorate(showPasswords);
27 29
28 return el; 30 return el;
29 } 31 }
30 32
31 PasswordListItem.prototype = { 33 PasswordListItem.prototype = {
32 __proto__: DeletableItem.prototype, 34 __proto__: InlineEditableItem.prototype,
33 35
34 /** @override */ 36 /** @override */
35 decorate: function(showPasswords) { 37 decorate: function(showPasswords) {
36 DeletableItem.prototype.decorate.call(this); 38 InlineEditableItem.prototype.decorate.call(this);
37 39
38 // The URL of the site. 40 this.isPlaceholder = !this.url;
39 var urlLabel = this.ownerDocument.createElement('div'); 41
40 urlLabel.classList.add('favicon-cell'); 42 this.contentElement.appendChild(this.createUrlElement());
41 urlLabel.classList.add('weakrtl'); 43 this.contentElement.appendChild(this.createUsernameElement());
42 urlLabel.classList.add('url'); 44
43 urlLabel.setAttribute('title', this.url);
44 urlLabel.textContent = this.url;
45
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);
54
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);
61
62 // The stored password.
63 var passwordInputDiv = this.ownerDocument.createElement('div'); 45 var passwordInputDiv = this.ownerDocument.createElement('div');
64 passwordInputDiv.className = 'password'; 46 passwordInputDiv.className = 'password';
65 47
66 // The password input field. 48 // The password input field.
67 var passwordInput = this.ownerDocument.createElement('input'); 49 var passwordInput = this.ownerDocument.createElement('input');
68 passwordInput.type = 'password'; 50 passwordInput.type = 'password';
69 passwordInput.className = 'inactive-password'; 51 if (!this.isPlaceholder) {
70 passwordInput.readOnly = true; 52 passwordInput.className = 'inactive-password';
71 passwordInput.value = showPasswords ? this.password : '********'; 53 passwordInput.readOnly = true;
54 passwordInput.value = showPasswords ? this.password : '********';
55 }
56 this.passwordField = passwordInput;
57
58 // Makes the password input field editable.
59 this.addEditField(passwordInput, null);
60
61 // Keeps the password validity updated.
62 this.updatePasswordValidity_();
63 passwordInput.addEventListener('input', function(event) {
64 this.updatePasswordValidity_();
65 }.bind(this));
66
72 passwordInputDiv.appendChild(passwordInput); 67 passwordInputDiv.appendChild(passwordInput);
73 this.passwordField = passwordInput; 68
74 69 // The list-inline buttons.
75 // The show/hide button. 70 if (!this.isPlaceholder) {
76 if (showPasswords) { 71 // The container of the list-inline buttons.
77 var button = this.ownerDocument.createElement('button'); 72 var buttonsContainer = this.ownerDocument.createElement('div');
78 button.hidden = true; 73 buttonsContainer.className = 'list-inline-buttons-container';
79 button.className = 'list-inline-button custom-appearance'; 74
80 button.textContent = loadTimeData.getString('passwordShowButton'); 75 var mousedownEventHandler = function(event) {
81 button.addEventListener('click', this.onClick_.bind(this), true);
82 button.addEventListener('mousedown', function(event) {
83 // Don't focus on this button by mousedown. 76 // Don't focus on this button by mousedown.
84 event.preventDefault(); 77 event.preventDefault();
85 // Don't handle list item selection. It causes focus change. 78 // Don't handle list item selection. It causes focus change.
86 event.stopPropagation(); 79 event.stopPropagation();
87 }, false); 80 };
88 passwordInputDiv.appendChild(button); 81
89 this.passwordShowButton = button; 82 // The overwrite button.
83 var overwriteButton = this.ownerDocument.createElement('button');
84 overwriteButton.className =
85 'list-inline-button custom-appearance overwrite-button';
engedy 2014/09/15 14:38:58 nit: Do we use the 'overwrite-button' class anywhe
jaekyeom 2014/09/16 07:58:09 Done.
86 overwriteButton.textContent = loadTimeData.getString(
87 'passwordOverwriteButton');
88 overwriteButton.addEventListener(
89 'click', this.onClickOverwriteButton_.bind(this), true);
90 overwriteButton.addEventListener(
91 'mousedown', mousedownEventHandler, false);
92 buttonsContainer.appendChild(overwriteButton);
93 this.passwordOverwriteButton = overwriteButton;
94
95 // The show/hide button.
96 if (showPasswords) {
97 var button = this.ownerDocument.createElement('button');
98 button.className = 'list-inline-button custom-appearance';
99 button.textContent = loadTimeData.getString('passwordShowButton');
100 button.addEventListener(
101 'click', this.onClickShowButton_.bind(this), true);
102 button.addEventListener('mousedown', mousedownEventHandler, false);
103 buttonsContainer.appendChild(button);
104 this.passwordShowButton = button;
105 }
106
107 passwordInputDiv.appendChild(buttonsContainer);
90 } 108 }
91 109
92 this.contentElement.appendChild(passwordInputDiv); 110 this.contentElement.appendChild(passwordInputDiv);
111
112 // Adds the event listeners for editing.
113 this.addEventListener('canceledit', this.resetInputs);
114 this.addEventListener('commitedit', this.finishEdit);
115 },
116
117 /**
118 * Constructs and returns the URL element for this item.
119 * @return {HTMLElement} The URL element.
120 * @protected
121 */
122 createUrlElement: function() {
123 var urlEl = this.ownerDocument.createElement('div');
124 urlEl.className = 'favicon-cell weakrtl url';
125 urlEl.setAttribute('title', this.url);
126 urlEl.textContent = this.url;
127
128 // The favicon URL is prefixed with "origin/", which essentially removes
129 // the URL path past the top-level domain and ensures that a scheme (e.g.,
130 // http) is being used. This ensures that the favicon returned is the
131 // default favicon for the domain and that the URL has a scheme if none is
132 // present in the password manager.
133 urlEl.style.backgroundImage = getFaviconImageSet(
134 'origin/' + this.url, 16);
135 return urlEl;
136 },
137
138 /**
139 * Constructs and returns the username element for this item.
140 * @return {HTMLElement} The username element.
141 * @protected
142 */
143 createUsernameElement: function() {
144 var usernameEl = this.ownerDocument.createElement('div');
145 usernameEl.className = 'name';
146 usernameEl.textContent = this.username;
147 usernameEl.title = this.username;
148 return usernameEl;
93 }, 149 },
94 150
95 /** @override */ 151 /** @override */
96 selectionChanged: function() { 152 selectionChanged: function() {
97 var input = this.passwordField; 153 InlineEditableItem.prototype.selectionChanged.call(this);
98 var button = this.passwordShowButton; 154
99 // The button doesn't exist when passwords can't be shown. 155 // Don't set 'inactive-password' class for the placeholder so that it
100 if (!button) 156 // shows the background and the borders.
157 if (this.isPlaceholder)
101 return; 158 return;
102 159
103 if (this.selected) { 160 this.passwordField.classList.toggle('inactive-password', !this.selected);
104 input.classList.remove('inactive-password'); 161 },
105 button.hidden = false; 162
106 } else { 163 /** @override */
107 input.classList.add('inactive-password'); 164 get currentInputIsValid() {
108 button.hidden = true; 165 return !!this.passwordField.value;
109 } 166 },
110 }, 167
111 168 /**
112 /** 169 * Returns if the password has been edited.
113 * Reveals the plain text password of this entry. 170 * @return {boolean} Whether the password has been edited.
171 * @protected
172 */
173 passwordHasBeenEdited: function() {
174 return this.passwordField.value != this.password || this.overwriting;
175 },
176
177 /** @override */
178 get hasBeenEdited() {
179 return this.passwordHasBeenEdited();
180 },
181
182 /**
183 * Reveals the plain text password of this entry. Never called for the Add
184 * New Entry row.
185 * @param {string} password The plain text password.
114 */ 186 */
115 showPassword: function(password) { 187 showPassword: function(password) {
116 this.passwordField.value = password; 188 this.overwriting = false;
189 this.password = password;
190 this.setPasswordFieldValue_(password);
117 this.passwordField.type = 'text'; 191 this.passwordField.type = 'text';
118 192 this.passwordField.readOnly = false;
193
194 this.passwordOverwriteButton.hidden = true;
119 var button = this.passwordShowButton; 195 var button = this.passwordShowButton;
120 if (button) 196 if (button)
121 button.textContent = loadTimeData.getString('passwordHideButton'); 197 button.textContent = loadTimeData.getString('passwordHideButton');
122 }, 198 },
123 199
124 /** 200 /**
125 * Hides the plain text password of this entry. 201 * Hides the plain text password of this entry. Never called for the Add
126 */ 202 * New Entry row.
127 hidePassword: function() { 203 * @private
204 */
205 hidePassword_: function() {
128 this.passwordField.type = 'password'; 206 this.passwordField.type = 'password';
129 207 this.passwordField.readOnly = true;
208
209 this.passwordOverwriteButton.hidden = false;
130 var button = this.passwordShowButton; 210 var button = this.passwordShowButton;
131 if (button) 211 if (button)
132 button.textContent = loadTimeData.getString('passwordShowButton'); 212 button.textContent = loadTimeData.getString('passwordShowButton');
133 }, 213 },
134 214
135 /** 215 /**
216 * Resets the input fields to their original values and states.
217 * @protected
218 */
219 resetInputs: function() {
220 this.finishOverwriting_();
221 this.setPasswordFieldValue_(this.password);
222 },
223
224 /**
225 * Commits the new data to the browser.
226 * @protected
227 */
228 finishEdit: function() {
229 this.password = this.passwordField.value;
230 this.finishOverwriting_();
231 PasswordManager.updatePassword(
232 this.getOriginalIndex_(), this.passwordField.value);
233 },
234
235 /**
236 * Called with the response of the browser, which indicates the validity of
237 * the URL.
238 * @param {string} url The URL.
239 * @param {boolean} valid The validity of the URL.
240 */
241 originValidityCheckComplete: function(url, valid) {
242 assertNotReached();
243 },
244
245 /**
246 * Updates the custom validity of the password input field.
247 * @private
248 */
249 updatePasswordValidity_: function() {
250 this.passwordField.setCustomValidity(this.passwordField.value ?
251 '' : loadTimeData.getString('editPasswordInvalidPasswordTooltip'));
252 },
253
254 /**
255 * Finishes password overwriting.
256 * @private
257 */
258 finishOverwriting_: function() {
259 if (!this.overwriting)
260 return;
261 this.overwriting = false;
262 this.passwordOverwriteButton.hidden = false;
263 this.passwordField.readOnly = true;
264 },
265
266 /**
267 * Sets the value of the password input field.
268 * @param {string} password The new value.
269 * @private
270 */
271 setPasswordFieldValue_: function(password) {
272 this.passwordField.value = password;
273 this.updatePasswordValidity_();
274 },
275
276 /**
136 * Get the original index of this item in the data model. 277 * Get the original index of this item in the data model.
137 * @return {number} The index. 278 * @return {number} The index.
138 * @private 279 * @private
139 */ 280 */
140 getOriginalIndex_: function() { 281 getOriginalIndex_: function() {
141 var index = this.dataItem[3]; 282 var index = this.dataItem[3];
142 return index ? index : this.dataModel.indexOf(this.dataItem); 283 return index ? index : this.dataModel.indexOf(this.dataItem);
143 }, 284 },
144 285
145 /** 286 /**
287 * Called when clicking the overwrite button. Allows the user to overwrite
288 * the hidden password.
289 * @param {Event} event The click event.
290 * @private
291 */
292 onClickOverwriteButton_: function(event) {
293 this.overwriting = true;
294 this.passwordOverwriteButton.hidden = true;
295
296 this.setPasswordFieldValue_('');
297 this.passwordField.readOnly = false;
298 this.passwordField.focus();
299 },
300
301 /**
146 * On-click event handler. Swaps the type of the input field from password 302 * On-click event handler. Swaps the type of the input field from password
147 * to text and back. 303 * to text and back.
148 * @private 304 * @private
149 */ 305 */
150 onClick_: function(event) { 306 onClickShowButton_: function(event) {
307 // Prevents committing an edit.
308 this.resetInputs();
309
151 if (this.passwordField.type == 'password') { 310 if (this.passwordField.type == 'password') {
152 // After the user is authenticated, showPassword() will be called. 311 // After the user is authenticated, showPassword() will be called.
153 PasswordManager.requestShowPassword(this.getOriginalIndex_()); 312 PasswordManager.requestShowPassword(this.getOriginalIndex_());
154 } else { 313 } else {
155 this.hidePassword(); 314 this.hidePassword_();
156 } 315 }
157 }, 316 },
158 317
159 /** 318 /**
160 * Get and set the URL for the entry. 319 * Get and set the URL for the entry.
161 * @type {string} 320 * @type {string}
162 */ 321 */
163 get url() { 322 get url() {
164 return this.dataItem[0]; 323 return this.dataItem[0] || '';
165 }, 324 },
166 set url(url) { 325 set url(url) {
167 this.dataItem[0] = url; 326 this.dataItem[0] = url;
168 }, 327 },
169 328
170 /** 329 /**
171 * Get and set the username for the entry. 330 * Get and set the username for the entry.
172 * @type {string} 331 * @type {string}
173 */ 332 */
174 get username() { 333 get username() {
175 return this.dataItem[1]; 334 return this.dataItem[1] || '';
176 }, 335 },
177 set username(username) { 336 set username(username) {
178 this.dataItem[1] = username; 337 this.dataItem[1] = username;
179 }, 338 },
180 339
181 /** 340 /**
182 * Get and set the password for the entry. 341 * Get and set the password for the entry.
183 * @type {string} 342 * @type {string}
184 */ 343 */
185 get password() { 344 get password() {
186 return this.dataItem[2]; 345 return this.dataItem[2] || '';
187 }, 346 },
188 set password(password) { 347 set password(password) {
189 this.dataItem[2] = password; 348 this.dataItem[2] = password;
190 }, 349 },
191 }; 350 };
192 351
193 /** 352 /**
353 * Creates a new passwords list item for the Add New Entry row.
354 * @param {ArrayDataModel} dataModel The data model that contains this item.
355 * @constructor
356 * @extends {options.passwordManager.PasswordListItem}
357 */
358 function PasswordAddRowListItem(dataModel) {
359 var el = cr.doc.createElement('div');
360 el.dataItem = [];
361 el.dataModel = dataModel;
362 el.__proto__ = PasswordAddRowListItem.prototype;
363 el.decorate();
364
365 return el;
366 }
367
368 PasswordAddRowListItem.prototype = {
369 __proto__: PasswordListItem.prototype,
370
371 /** @override */
372 decorate: function() {
373 PasswordListItem.prototype.decorate.call(this, false);
374
375 this.urlField.placeholder = loadTimeData.getString(
376 'newPasswordUrlFieldPlaceholder');
377 this.usernameField.placeholder = loadTimeData.getString(
378 'newPasswordUsernameFieldPlaceholder');
379 this.passwordField.placeholder = loadTimeData.getString(
380 'newPasswordPasswordFieldPlaceholder');
381
382 // Sets the validity of the URL initially.
383 this.setUrlValid_(false);
384 },
385
386 /** @override */
387 createUrlElement: function() {
388 var urlEl = this.createEditableTextCell('');
389 urlEl.className += ' favicon-cell weakrtl url';
390
391 var urlField = urlEl.querySelector('input');
392 urlField.addEventListener('input', this.onUrlInput_.bind(this));
393 this.urlField = urlField;
394
395 return urlEl;
396 },
397
398 /** @override */
399 createUsernameElement: function() {
400 var usernameEl = this.createEditableTextCell('');
401 usernameEl.className = 'name';
402
403 this.usernameField = usernameEl.querySelector('input');
404
405 return usernameEl;
406 },
407
408 /** @override */
409 get currentInputIsValid() {
410 return this.urlValidityKnown && this.urlIsValid &&
411 this.passwordField.value;
412 },
413
414 /** @override */
415 get hasBeenEdited() {
416 return this.urlField.value || this.usernameField.value ||
417 this.passwordHasBeenEdited();
418 },
419
420 /** @override */
421 resetInputs: function() {
422 PasswordListItem.prototype.resetInputs.call(this);
423
424 this.urlField.value = '';
425 this.usernameField.value = '';
426
427 this.setUrlValid_(false);
428 },
429
430 /** @override */
431 finishEdit: function() {
432 var newUrl = this.urlField.value;
433 var newUsername = this.usernameField.value;
434 var newPassword = this.passwordField.value;
435 this.resetInputs();
436
437 PasswordManager.addPassword(newUrl, newUsername, newPassword);
438 },
439
440 /** @override */
441 originValidityCheckComplete: function(url, valid) {
442 if (url == this.urlField.value)
443 this.setUrlValid_(valid);
444 },
445
446 /**
447 * Updates whether the URL in the input is valid.
448 * @param {boolean} valid The validity of the URL.
449 * @private
450 */
451 setUrlValid_: function(valid) {
452 this.urlIsValid = valid;
453 this.urlValidityKnown = true;
454 if (this.urlField) {
455 this.urlField.setCustomValidity(valid ?
456 '' : loadTimeData.getString('editPasswordInvalidUrlTooltip'));
457 }
458 },
459
460 /**
461 * Called when inputting to a URL input.
462 * @param {Event} event The input event.
463 * @private
464 */
465 onUrlInput_: function(event) {
466 this.urlValidityKnown = false;
467 PasswordManager.checkOriginValidityForAdding(this.urlField.value);
468 },
469 };
470
471 /**
194 * Creates a new PasswordExceptions list item. 472 * Creates a new PasswordExceptions list item.
195 * @param {Array} entry A pair of the form [url, username]. 473 * @param {Array} entry A pair of the form [url, username].
196 * @constructor 474 * @constructor
197 * @extends {Deletable.ListItem} 475 * @extends {Deletable.ListItem}
198 */ 476 */
199 function PasswordExceptionsListItem(entry) { 477 function PasswordExceptionsListItem(entry) {
200 var el = cr.doc.createElement('div'); 478 var el = cr.doc.createElement('div');
201 el.dataItem = entry; 479 el.dataItem = entry;
202 el.__proto__ = PasswordExceptionsListItem.prototype; 480 el.__proto__ = PasswordExceptionsListItem.prototype;
203 el.decorate(); 481 el.decorate();
204 482
205 return el; 483 return el;
206 } 484 }
207 485
208 PasswordExceptionsListItem.prototype = { 486 PasswordExceptionsListItem.prototype = {
209 __proto__: DeletableItem.prototype, 487 __proto__: DeletableItem.prototype,
210 488
211 /** 489 /**
212 * Call when an element is decorated as a list item. 490 * Call when an element is decorated as a list item.
213 */ 491 */
214 decorate: function() { 492 decorate: function() {
215 DeletableItem.prototype.decorate.call(this); 493 DeletableItem.prototype.decorate.call(this);
216 494
217 // The URL of the site. 495 // The URL of the site.
218 var urlLabel = this.ownerDocument.createElement('div'); 496 var urlLabel = this.ownerDocument.createElement('div');
219 urlLabel.className = 'url'; 497 urlLabel.className = 'url favicon-cell weakrtl';
220 urlLabel.classList.add('favicon-cell');
221 urlLabel.classList.add('weakrtl');
222 urlLabel.textContent = this.url; 498 urlLabel.textContent = this.url;
223 499
224 // The favicon URL is prefixed with "origin/", which essentially removes 500 // 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., 501 // 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 502 // 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 503 // default favicon for the domain and that the URL has a scheme if none
228 // is present in the password manager. 504 // is present in the password manager.
229 urlLabel.style.backgroundImage = getFaviconImageSet( 505 urlLabel.style.backgroundImage = getFaviconImageSet(
230 'origin/' + this.url, 16); 506 'origin/' + this.url, 16);
231 this.contentElement.appendChild(urlLabel); 507 this.contentElement.appendChild(urlLabel);
232 }, 508 },
233 509
234 /** 510 /**
235 * Get the url for the entry. 511 * Get the url for the entry.
236 * @type {string} 512 * @type {string}
237 */ 513 */
238 get url() { 514 get url() {
239 return this.dataItem; 515 return this.dataItem;
240 }, 516 },
241 set url(url) { 517 set url(url) {
242 this.dataItem = url; 518 this.dataItem = url;
243 }, 519 },
244 }; 520 };
245 521
246 /** 522 /**
247 * Create a new passwords list. 523 * Create a new passwords list.
248 * @constructor 524 * @constructor
249 * @extends {cr.ui.List} 525 * @extends {options.InlineEditableItemList}
250 */ 526 */
251 var PasswordsList = cr.ui.define('list'); 527 var PasswordsList = cr.ui.define('list');
252 528
253 PasswordsList.prototype = { 529 PasswordsList.prototype = {
254 __proto__: DeletableItemList.prototype, 530 __proto__: InlineEditableItemList.prototype,
255 531
256 /** 532 /**
257 * Whether passwords can be revealed or not. 533 * Whether passwords can be revealed or not.
258 * @type {boolean} 534 * @type {boolean}
259 * @private 535 * @private
260 */ 536 */
261 showPasswords_: true, 537 showPasswords_: true,
262 538
263 /** @override */ 539 /** @override */
264 decorate: function() { 540 decorate: function() {
265 DeletableItemList.prototype.decorate.call(this); 541 InlineEditableItemList.prototype.decorate.call(this);
266 Preferences.getInstance().addEventListener( 542 Preferences.getInstance().addEventListener(
267 'profile.password_manager_allow_show_passwords', 543 'profile.password_manager_allow_show_passwords',
268 this.onPreferenceChanged_.bind(this)); 544 this.onPreferenceChanged_.bind(this));
269 }, 545 },
270 546
271 /** 547 /**
272 * Listener for changes on the preference. 548 * Listener for changes on the preference.
273 * @param {Event} event The preference update event. 549 * @param {Event} event The preference update event.
274 * @private 550 * @private
275 */ 551 */
276 onPreferenceChanged_: function(event) { 552 onPreferenceChanged_: function(event) {
277 this.showPasswords_ = event.value.value; 553 this.showPasswords_ = event.value.value;
278 this.redraw(); 554 this.redraw();
279 }, 555 },
280 556
281 /** @override */ 557 /** @override */
282 createItem: function(entry) { 558 createItem: function(entry) {
559 if (!entry)
560 return new PasswordAddRowListItem(this.dataModel);
561
283 var showPasswords = this.showPasswords_; 562 var showPasswords = this.showPasswords_;
284 563
285 if (loadTimeData.getBoolean('disableShowPasswords')) 564 if (loadTimeData.getBoolean('disableShowPasswords'))
286 showPasswords = false; 565 showPasswords = false;
287 566
288 return new PasswordListItem(this.dataModel, entry, showPasswords); 567 return new PasswordListItem(this.dataModel, entry, showPasswords);
289 }, 568 },
290 569
291 /** @override */ 570 /** @override */
292 deleteItemAtIndex: function(index) { 571 deleteItemAtIndex: function(index) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 /** 608 /**
330 * The length of the list. 609 * The length of the list.
331 */ 610 */
332 get length() { 611 get length() {
333 return this.dataModel.length; 612 return this.dataModel.length;
334 }, 613 },
335 }; 614 };
336 615
337 return { 616 return {
338 PasswordListItem: PasswordListItem, 617 PasswordListItem: PasswordListItem,
618 PasswordAddRowListItem: PasswordAddRowListItem,
339 PasswordExceptionsListItem: PasswordExceptionsListItem, 619 PasswordExceptionsListItem: PasswordExceptionsListItem,
340 PasswordsList: PasswordsList, 620 PasswordsList: PasswordsList,
341 PasswordExceptionsList: PasswordExceptionsList, 621 PasswordExceptionsList: PasswordExceptionsList,
342 }; 622 };
343 }); 623 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698