OLD | NEW |
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 {cr.ui.ArrayDataModel} dataModel The data model that contains this | 15 * @param {cr.ui.ArrayDataModel} dataModel The data model that contains this |
14 * item. | 16 * item. |
15 * @param {Array} entry An array of the form [url, username, password]. When | 17 * @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. | 18 * 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 | 19 * @param {boolean} showPasswords If true, add a button to the element to |
18 * allow the user to reveal the saved password. | 20 * allow the user to reveal the saved password. |
19 * @constructor | 21 * @constructor |
20 * @extends {options.DeletableItem} | 22 * @extends {options.InlineEditableItem} |
21 */ | 23 */ |
22 function PasswordListItem(dataModel, entry, showPasswords) { | 24 function PasswordListItem(dataModel, entry, showPasswords) { |
23 var el = cr.doc.createElement('div'); | 25 var el = cr.doc.createElement('div'); |
24 el.dataItem = entry; | 26 el.dataItem = entry; |
25 el.dataModel = dataModel; | 27 el.dataModel = dataModel; |
26 el.__proto__ = PasswordListItem.prototype; | 28 el.__proto__ = PasswordListItem.prototype; |
27 el.decorate(showPasswords); | 29 el.decorate(showPasswords); |
28 | 30 |
29 return el; | 31 return el; |
30 } | 32 } |
31 | 33 |
32 PasswordListItem.prototype = { | 34 PasswordListItem.prototype = { |
33 __proto__: DeletableItem.prototype, | 35 __proto__: InlineEditableItem.prototype, |
34 | 36 |
35 /** @override */ | 37 /** @override */ |
36 decorate: function(showPasswords) { | 38 decorate: function(showPasswords) { |
37 DeletableItem.prototype.decorate.call(this); | 39 InlineEditableItem.prototype.decorate.call(this); |
38 | 40 |
39 // The URL of the site. | 41 this.isPlaceholder = !this.url; |
40 var urlLabel = this.ownerDocument.createElement('div'); | 42 |
41 urlLabel.classList.add('favicon-cell'); | 43 this.contentElement.appendChild(this.createUrlElement()); |
42 urlLabel.classList.add('weakrtl'); | 44 this.contentElement.appendChild(this.createUsernameElement()); |
43 urlLabel.classList.add('url'); | 45 |
44 urlLabel.setAttribute('title', this.url); | |
45 urlLabel.textContent = this.url; | |
46 | |
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); | |
55 | |
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); | |
62 | |
63 // The stored password. | |
64 var passwordInputDiv = this.ownerDocument.createElement('div'); | 46 var passwordInputDiv = this.ownerDocument.createElement('div'); |
65 passwordInputDiv.className = 'password'; | 47 passwordInputDiv.className = 'password'; |
66 | 48 |
67 // The password input field. | 49 // The password input field. |
68 var passwordInput = this.ownerDocument.createElement('input'); | 50 var passwordInput = this.ownerDocument.createElement('input'); |
69 passwordInput.type = 'password'; | 51 passwordInput.type = 'password'; |
70 passwordInput.className = 'inactive-password'; | 52 if (!this.isPlaceholder) { |
71 passwordInput.readOnly = true; | 53 passwordInput.className = 'inactive-password'; |
72 passwordInput.value = showPasswords ? this.password : '********'; | 54 passwordInput.readOnly = true; |
| 55 passwordInput.value = showPasswords ? this.password : '********'; |
| 56 } |
| 57 this.passwordField = passwordInput; |
| 58 |
| 59 // Makes the password input field editable. |
| 60 this.addEditField(passwordInput, null); |
| 61 |
| 62 // Keeps the password validity updated. |
| 63 this.updatePasswordValidity_(); |
| 64 passwordInput.addEventListener('input', function(event) { |
| 65 this.updatePasswordValidity_(); |
| 66 }.bind(this)); |
| 67 |
73 passwordInputDiv.appendChild(passwordInput); | 68 passwordInputDiv.appendChild(passwordInput); |
74 this.passwordField = passwordInput; | 69 |
75 | 70 // The list-inline buttons. |
76 // The show/hide button. | 71 if (!this.isPlaceholder) { |
77 if (showPasswords) { | 72 // The container of the list-inline buttons. |
78 var button = this.ownerDocument.createElement('button'); | 73 var buttonsContainer = this.ownerDocument.createElement('div'); |
79 button.hidden = true; | 74 buttonsContainer.className = 'list-inline-buttons-container'; |
80 button.className = 'list-inline-button custom-appearance'; | 75 |
81 button.textContent = loadTimeData.getString('passwordShowButton'); | 76 var mousedownEventHandler = function(event) { |
82 button.addEventListener('click', this.onClick_.bind(this), true); | |
83 button.addEventListener('mousedown', function(event) { | |
84 // Don't focus on this button by mousedown. | 77 // Don't focus on this button by mousedown. |
85 event.preventDefault(); | 78 event.preventDefault(); |
86 // Don't handle list item selection. It causes focus change. | 79 // Don't handle list item selection. It causes focus change. |
87 event.stopPropagation(); | 80 event.stopPropagation(); |
88 }, false); | 81 }; |
89 passwordInputDiv.appendChild(button); | 82 |
90 this.passwordShowButton = button; | 83 // The overwrite button. |
| 84 var overwriteButton = this.ownerDocument.createElement('button'); |
| 85 overwriteButton.className = 'list-inline-button custom-appearance'; |
| 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); |
91 } | 108 } |
92 | 109 |
93 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; |
94 }, | 149 }, |
95 | 150 |
96 /** @override */ | 151 /** @override */ |
97 selectionChanged: function() { | 152 selectionChanged: function() { |
98 var input = this.passwordField; | 153 InlineEditableItem.prototype.selectionChanged.call(this); |
99 var button = this.passwordShowButton; | 154 |
100 // The button doesn't exist when passwords can't be shown. | 155 // Don't set 'inactive-password' class for the placeholder so that it |
101 if (!button) | 156 // shows the background and the borders. |
| 157 if (this.isPlaceholder) |
102 return; | 158 return; |
103 | 159 |
104 if (this.selected) { | 160 this.passwordField.classList.toggle('inactive-password', !this.selected); |
105 input.classList.remove('inactive-password'); | 161 }, |
106 button.hidden = false; | 162 |
107 } else { | 163 /** @override */ |
108 input.classList.add('inactive-password'); | 164 get currentInputIsValid() { |
109 button.hidden = true; | 165 return !!this.passwordField.value; |
110 } | 166 }, |
111 }, | 167 |
112 | 168 /** |
113 /** | 169 * Returns if the password has been edited. |
114 * 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. |
115 */ | 186 */ |
116 showPassword: function(password) { | 187 showPassword: function(password) { |
117 this.passwordField.value = password; | 188 this.overwriting = false; |
| 189 this.password = password; |
| 190 this.setPasswordFieldValue_(password); |
118 this.passwordField.type = 'text'; | 191 this.passwordField.type = 'text'; |
119 | 192 this.passwordField.readOnly = false; |
| 193 |
| 194 this.passwordOverwriteButton.hidden = true; |
120 var button = this.passwordShowButton; | 195 var button = this.passwordShowButton; |
121 if (button) | 196 if (button) |
122 button.textContent = loadTimeData.getString('passwordHideButton'); | 197 button.textContent = loadTimeData.getString('passwordHideButton'); |
123 }, | 198 }, |
124 | 199 |
125 /** | 200 /** |
126 * Hides the plain text password of this entry. | 201 * Hides the plain text password of this entry. Never called for the Add |
127 */ | 202 * New Entry row. |
128 hidePassword: function() { | 203 * @private |
| 204 */ |
| 205 hidePassword_: function() { |
129 this.passwordField.type = 'password'; | 206 this.passwordField.type = 'password'; |
130 | 207 this.passwordField.readOnly = true; |
| 208 |
| 209 this.passwordOverwriteButton.hidden = false; |
131 var button = this.passwordShowButton; | 210 var button = this.passwordShowButton; |
132 if (button) | 211 if (button) |
133 button.textContent = loadTimeData.getString('passwordShowButton'); | 212 button.textContent = loadTimeData.getString('passwordShowButton'); |
134 }, | 213 }, |
135 | 214 |
136 /** | 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 /** |
137 * Get the original index of this item in the data model. | 277 * Get the original index of this item in the data model. |
138 * @return {number} The index. | 278 * @return {number} The index. |
139 * @private | 279 * @private |
140 */ | 280 */ |
141 getOriginalIndex_: function() { | 281 getOriginalIndex_: function() { |
142 var index = this.dataItem[3]; | 282 var index = this.dataItem[3]; |
143 return index ? index : this.dataModel.indexOf(this.dataItem); | 283 return index ? index : this.dataModel.indexOf(this.dataItem); |
144 }, | 284 }, |
145 | 285 |
146 /** | 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 /** |
147 * 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 |
148 * to text and back. | 303 * to text and back. |
149 * @private | 304 * @private |
150 */ | 305 */ |
151 onClick_: function(event) { | 306 onClickShowButton_: function(event) { |
| 307 // Prevents committing an edit. |
| 308 this.resetInputs(); |
| 309 |
152 if (this.passwordField.type == 'password') { | 310 if (this.passwordField.type == 'password') { |
153 // After the user is authenticated, showPassword() will be called. | 311 // After the user is authenticated, showPassword() will be called. |
154 PasswordManager.requestShowPassword(this.getOriginalIndex_()); | 312 PasswordManager.requestShowPassword(this.getOriginalIndex_()); |
155 } else { | 313 } else { |
156 this.hidePassword(); | 314 this.hidePassword_(); |
157 } | 315 } |
158 }, | 316 }, |
159 | 317 |
160 /** | 318 /** |
161 * Get and set the URL for the entry. | 319 * Get and set the URL for the entry. |
162 * @type {string} | 320 * @type {string} |
163 */ | 321 */ |
164 get url() { | 322 get url() { |
165 return this.dataItem[0]; | 323 return this.dataItem[0] || ''; |
166 }, | 324 }, |
167 set url(url) { | 325 set url(url) { |
168 this.dataItem[0] = url; | 326 this.dataItem[0] = url; |
169 }, | 327 }, |
170 | 328 |
171 /** | 329 /** |
172 * Get and set the username for the entry. | 330 * Get and set the username for the entry. |
173 * @type {string} | 331 * @type {string} |
174 */ | 332 */ |
175 get username() { | 333 get username() { |
176 return this.dataItem[1]; | 334 return this.dataItem[1] || ''; |
177 }, | 335 }, |
178 set username(username) { | 336 set username(username) { |
179 this.dataItem[1] = username; | 337 this.dataItem[1] = username; |
180 }, | 338 }, |
181 | 339 |
182 /** | 340 /** |
183 * Get and set the password for the entry. | 341 * Get and set the password for the entry. |
184 * @type {string} | 342 * @type {string} |
185 */ | 343 */ |
186 get password() { | 344 get password() { |
187 return this.dataItem[2]; | 345 return this.dataItem[2] || ''; |
188 }, | 346 }, |
189 set password(password) { | 347 set password(password) { |
190 this.dataItem[2] = password; | 348 this.dataItem[2] = password; |
191 }, | 349 }, |
192 }; | 350 }; |
193 | 351 |
194 /** | 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 /** |
195 * Creates a new PasswordExceptions list item. | 472 * Creates a new PasswordExceptions list item. |
196 * @param {Array} entry A pair of the form [url, username]. | 473 * @param {Array} entry A pair of the form [url, username]. |
197 * @constructor | 474 * @constructor |
198 * @extends {options.DeletableItem} | 475 * @extends {options.DeletableItem} |
199 */ | 476 */ |
200 function PasswordExceptionsListItem(entry) { | 477 function PasswordExceptionsListItem(entry) { |
201 var el = cr.doc.createElement('div'); | 478 var el = cr.doc.createElement('div'); |
202 el.dataItem = entry; | 479 el.dataItem = entry; |
203 el.__proto__ = PasswordExceptionsListItem.prototype; | 480 el.__proto__ = PasswordExceptionsListItem.prototype; |
204 el.decorate(); | 481 el.decorate(); |
205 | 482 |
206 return el; | 483 return el; |
207 } | 484 } |
208 | 485 |
209 PasswordExceptionsListItem.prototype = { | 486 PasswordExceptionsListItem.prototype = { |
210 __proto__: DeletableItem.prototype, | 487 __proto__: DeletableItem.prototype, |
211 | 488 |
212 /** | 489 /** |
213 * Call when an element is decorated as a list item. | 490 * Call when an element is decorated as a list item. |
214 */ | 491 */ |
215 decorate: function() { | 492 decorate: function() { |
216 DeletableItem.prototype.decorate.call(this); | 493 DeletableItem.prototype.decorate.call(this); |
217 | 494 |
218 // The URL of the site. | 495 // The URL of the site. |
219 var urlLabel = this.ownerDocument.createElement('div'); | 496 var urlLabel = this.ownerDocument.createElement('div'); |
220 urlLabel.className = 'url'; | 497 urlLabel.className = 'url favicon-cell weakrtl'; |
221 urlLabel.classList.add('favicon-cell'); | |
222 urlLabel.classList.add('weakrtl'); | |
223 urlLabel.textContent = this.url; | 498 urlLabel.textContent = this.url; |
224 | 499 |
225 // The favicon URL is prefixed with "origin/", which essentially removes | 500 // 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., | 501 // 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 | 502 // 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 | 503 // default favicon for the domain and that the URL has a scheme if none |
229 // is present in the password manager. | 504 // is present in the password manager. |
230 urlLabel.style.backgroundImage = getFaviconImageSet( | 505 urlLabel.style.backgroundImage = getFaviconImageSet( |
231 'origin/' + this.url, 16); | 506 'origin/' + this.url, 16); |
232 this.contentElement.appendChild(urlLabel); | 507 this.contentElement.appendChild(urlLabel); |
233 }, | 508 }, |
234 | 509 |
235 /** | 510 /** |
236 * Get the url for the entry. | 511 * Get the url for the entry. |
237 * @type {string} | 512 * @type {string} |
238 */ | 513 */ |
239 get url() { | 514 get url() { |
240 return this.dataItem; | 515 return this.dataItem; |
241 }, | 516 }, |
242 set url(url) { | 517 set url(url) { |
243 this.dataItem = url; | 518 this.dataItem = url; |
244 }, | 519 }, |
245 }; | 520 }; |
246 | 521 |
247 /** | 522 /** |
248 * Create a new passwords list. | 523 * Create a new passwords list. |
249 * @constructor | 524 * @constructor |
250 * @extends {options.DeletableItemList} | 525 * @extends {options.InlineEditableItemList} |
251 */ | 526 */ |
252 var PasswordsList = cr.ui.define('list'); | 527 var PasswordsList = cr.ui.define('list'); |
253 | 528 |
254 PasswordsList.prototype = { | 529 PasswordsList.prototype = { |
255 __proto__: DeletableItemList.prototype, | 530 __proto__: InlineEditableItemList.prototype, |
256 | 531 |
257 /** | 532 /** |
258 * Whether passwords can be revealed or not. | 533 * Whether passwords can be revealed or not. |
259 * @type {boolean} | 534 * @type {boolean} |
260 * @private | 535 * @private |
261 */ | 536 */ |
262 showPasswords_: true, | 537 showPasswords_: true, |
263 | 538 |
264 /** @override */ | 539 /** @override */ |
265 decorate: function() { | 540 decorate: function() { |
266 DeletableItemList.prototype.decorate.call(this); | 541 InlineEditableItemList.prototype.decorate.call(this); |
267 Preferences.getInstance().addEventListener( | 542 Preferences.getInstance().addEventListener( |
268 'profile.password_manager_allow_show_passwords', | 543 'profile.password_manager_allow_show_passwords', |
269 this.onPreferenceChanged_.bind(this)); | 544 this.onPreferenceChanged_.bind(this)); |
270 }, | 545 }, |
271 | 546 |
272 /** | 547 /** |
273 * Listener for changes on the preference. | 548 * Listener for changes on the preference. |
274 * @param {Event} event The preference update event. | 549 * @param {Event} event The preference update event. |
275 * @private | 550 * @private |
276 */ | 551 */ |
277 onPreferenceChanged_: function(event) { | 552 onPreferenceChanged_: function(event) { |
278 this.showPasswords_ = event.value.value; | 553 this.showPasswords_ = event.value.value; |
279 this.redraw(); | 554 this.redraw(); |
280 }, | 555 }, |
281 | 556 |
282 /** | 557 /** |
283 * @override | 558 * @override |
284 * @param {Array} entry | 559 * @param {Array} entry |
285 */ | 560 */ |
286 createItem: function(entry) { | 561 createItem: function(entry) { |
| 562 if (!entry) |
| 563 return new PasswordAddRowListItem(this.dataModel); |
| 564 |
287 var showPasswords = this.showPasswords_; | 565 var showPasswords = this.showPasswords_; |
288 | 566 |
289 if (loadTimeData.getBoolean('disableShowPasswords')) | 567 if (loadTimeData.getBoolean('disableShowPasswords')) |
290 showPasswords = false; | 568 showPasswords = false; |
291 | 569 |
292 return new PasswordListItem(this.dataModel, entry, showPasswords); | 570 return new PasswordListItem(this.dataModel, entry, showPasswords); |
293 }, | 571 }, |
294 | 572 |
295 /** @override */ | 573 /** @override */ |
296 deleteItemAtIndex: function(index) { | 574 deleteItemAtIndex: function(index) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 /** | 614 /** |
337 * The length of the list. | 615 * The length of the list. |
338 */ | 616 */ |
339 get length() { | 617 get length() { |
340 return this.dataModel.length; | 618 return this.dataModel.length; |
341 }, | 619 }, |
342 }; | 620 }; |
343 | 621 |
344 return { | 622 return { |
345 PasswordListItem: PasswordListItem, | 623 PasswordListItem: PasswordListItem, |
| 624 PasswordAddRowListItem: PasswordAddRowListItem, |
346 PasswordExceptionsListItem: PasswordExceptionsListItem, | 625 PasswordExceptionsListItem: PasswordExceptionsListItem, |
347 PasswordsList: PasswordsList, | 626 PasswordsList: PasswordsList, |
348 PasswordExceptionsList: PasswordExceptionsList, | 627 PasswordExceptionsList: PasswordExceptionsList, |
349 }; | 628 }; |
350 }); | 629 }); |
OLD | NEW |