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 {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); |
| 39 |
| 40 // The user can edit the saved passwords if and only if he can reveal |
| 41 // them. |
| 42 this.editable = showPasswords; |
37 | 43 |
38 // The URL of the site. | 44 // The URL of the site. |
39 var urlLabel = this.ownerDocument.createElement('div'); | 45 var urlLabel = this.ownerDocument.createElement('div'); |
40 urlLabel.classList.add('favicon-cell'); | 46 urlLabel.classList.add('favicon-cell'); |
41 urlLabel.classList.add('weakrtl'); | 47 urlLabel.classList.add('weakrtl'); |
42 urlLabel.classList.add('url'); | 48 urlLabel.classList.add('url'); |
43 urlLabel.setAttribute('title', this.url); | 49 urlLabel.setAttribute('title', this.url); |
44 urlLabel.textContent = this.url; | 50 urlLabel.textContent = this.url; |
45 | 51 |
46 // The favicon URL is prefixed with "origin/", which essentially removes | 52 // The favicon URL is prefixed with "origin/", which essentially removes |
(...skipping 18 matching lines...) Expand all Loading... |
65 | 71 |
66 // The password input field. | 72 // The password input field. |
67 var passwordInput = this.ownerDocument.createElement('input'); | 73 var passwordInput = this.ownerDocument.createElement('input'); |
68 passwordInput.type = 'password'; | 74 passwordInput.type = 'password'; |
69 passwordInput.className = 'inactive-password'; | 75 passwordInput.className = 'inactive-password'; |
70 passwordInput.readOnly = true; | 76 passwordInput.readOnly = true; |
71 passwordInput.value = showPasswords ? this.password : '********'; | 77 passwordInput.value = showPasswords ? this.password : '********'; |
72 passwordInputDiv.appendChild(passwordInput); | 78 passwordInputDiv.appendChild(passwordInput); |
73 this.passwordField = passwordInput; | 79 this.passwordField = passwordInput; |
74 | 80 |
75 // The show/hide button. | |
76 if (showPasswords) { | 81 if (showPasswords) { |
| 82 // The show/hide button. |
77 var button = this.ownerDocument.createElement('button'); | 83 var button = this.ownerDocument.createElement('button'); |
78 button.hidden = true; | 84 button.hidden = true; |
79 button.className = 'list-inline-button custom-appearance'; | 85 button.className = 'list-inline-button custom-appearance'; |
80 button.textContent = loadTimeData.getString('passwordShowButton'); | 86 button.textContent = loadTimeData.getString('passwordShowButton'); |
81 button.addEventListener('click', this.onClick_.bind(this), true); | 87 button.addEventListener('click', this.onClick_.bind(this), true); |
82 button.addEventListener('mousedown', function(event) { | 88 button.addEventListener('mousedown', function(event) { |
83 // Don't focus on this button by mousedown. | 89 // Don't focus on this button by mousedown. |
84 event.preventDefault(); | 90 event.preventDefault(); |
85 // Don't handle list item selection. It causes focus change. | 91 // Don't handle list item selection. It causes focus change. |
86 event.stopPropagation(); | 92 event.stopPropagation(); |
87 }, false); | 93 }, false); |
88 passwordInputDiv.appendChild(button); | 94 passwordInputDiv.appendChild(button); |
89 this.passwordShowButton = button; | 95 this.passwordShowButton = button; |
| 96 |
| 97 // Makes the password input field editable. |
| 98 this.addEditField(passwordInput, null); |
| 99 this.addEventListener('canceledit', this.onEditCancelled_); |
| 100 this.addEventListener('commitedit', this.onEditCommitted_); |
90 } | 101 } |
91 | 102 |
92 this.contentElement.appendChild(passwordInputDiv); | 103 this.contentElement.appendChild(passwordInputDiv); |
93 }, | 104 }, |
94 | 105 |
95 /** @override */ | 106 /** @override */ |
96 selectionChanged: function() { | 107 selectionChanged: function() { |
| 108 InlineEditableItem.prototype.selectionChanged.call(this); |
| 109 |
97 var input = this.passwordField; | 110 var input = this.passwordField; |
98 var button = this.passwordShowButton; | 111 var button = this.passwordShowButton; |
99 // The button doesn't exist when passwords can't be shown. | 112 // The button doesn't exist when passwords can't be shown. |
100 if (!button) | 113 if (!button) |
101 return; | 114 return; |
102 | 115 |
103 if (this.selected) { | 116 if (this.selected) { |
104 input.classList.remove('inactive-password'); | 117 input.classList.remove('inactive-password'); |
105 button.hidden = false; | 118 button.hidden = false; |
106 } else { | 119 } else { |
107 input.classList.add('inactive-password'); | 120 input.classList.add('inactive-password'); |
108 button.hidden = true; | 121 button.hidden = true; |
109 } | 122 } |
110 }, | 123 }, |
111 | 124 |
| 125 /** @override */ |
| 126 get currentInputIsValid() { |
| 127 return !!this.passwordField.value; |
| 128 }, |
| 129 |
| 130 /** @override */ |
| 131 get hasBeenEdited() { |
| 132 return this.passwordField.value != this.password; |
| 133 }, |
| 134 |
112 /** | 135 /** |
113 * Reveals the plain text password of this entry. | 136 * Reveals the plain text password of this entry. |
114 */ | 137 */ |
115 showPassword: function(password) { | 138 showPassword: function(password) { |
| 139 this.password = password; |
116 this.passwordField.value = password; | 140 this.passwordField.value = password; |
117 this.passwordField.type = 'text'; | 141 this.passwordField.type = 'text'; |
| 142 this.passwordField.readOnly = false; |
118 | 143 |
119 var button = this.passwordShowButton; | 144 var button = this.passwordShowButton; |
120 if (button) | 145 if (button) |
121 button.textContent = loadTimeData.getString('passwordHideButton'); | 146 button.textContent = loadTimeData.getString('passwordHideButton'); |
122 }, | 147 }, |
123 | 148 |
124 /** | 149 /** |
125 * Hides the plain text password of this entry. | 150 * Hides the plain text password of this entry. |
126 */ | 151 */ |
127 hidePassword: function() { | 152 hidePassword: function() { |
128 this.passwordField.type = 'password'; | 153 this.passwordField.type = 'password'; |
| 154 this.passwordField.readOnly = true; |
129 | 155 |
130 var button = this.passwordShowButton; | 156 var button = this.passwordShowButton; |
131 if (button) | 157 if (button) |
132 button.textContent = loadTimeData.getString('passwordShowButton'); | 158 button.textContent = loadTimeData.getString('passwordShowButton'); |
133 }, | 159 }, |
134 | 160 |
135 /** | 161 /** |
136 * Get the original index of this item in the data model. | 162 * Get the original index of this item in the data model. |
137 * @return {number} The index. | 163 * @return {number} The index. |
138 * @private | 164 * @private |
(...skipping 11 matching lines...) Expand all Loading... |
150 onClick_: function(event) { | 176 onClick_: function(event) { |
151 if (this.passwordField.type == 'password') { | 177 if (this.passwordField.type == 'password') { |
152 // After the user is authenticated, showPassword() will be called. | 178 // After the user is authenticated, showPassword() will be called. |
153 PasswordManager.requestShowPassword(this.getOriginalIndex_()); | 179 PasswordManager.requestShowPassword(this.getOriginalIndex_()); |
154 } else { | 180 } else { |
155 this.hidePassword(); | 181 this.hidePassword(); |
156 } | 182 } |
157 }, | 183 }, |
158 | 184 |
159 /** | 185 /** |
| 186 * Called when cancelling a password edit. Resets the password input field. |
| 187 * @param {Event} event The canceledit event. |
| 188 * @private |
| 189 */ |
| 190 onEditCancelled_: function(event) { |
| 191 this.passwordField.value = this.password; |
| 192 }, |
| 193 |
| 194 /** |
| 195 * Called when committing a password edit. Updates the password. |
| 196 * @param {Event} event The commitedit event. |
| 197 * @private |
| 198 */ |
| 199 onEditCommitted_: function(event) { |
| 200 this.password = this.passwordField.value; |
| 201 PasswordManager.updatePassword( |
| 202 this.getOriginalIndex_(), this.passwordField.value); |
| 203 }, |
| 204 |
| 205 /** |
160 * Get and set the URL for the entry. | 206 * Get and set the URL for the entry. |
161 * @type {string} | 207 * @type {string} |
162 */ | 208 */ |
163 get url() { | 209 get url() { |
164 return this.dataItem[0]; | 210 return this.dataItem[0]; |
165 }, | 211 }, |
166 set url(url) { | 212 set url(url) { |
167 this.dataItem[0] = url; | 213 this.dataItem[0] = url; |
168 }, | 214 }, |
169 | 215 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 return this.dataItem; | 285 return this.dataItem; |
240 }, | 286 }, |
241 set url(url) { | 287 set url(url) { |
242 this.dataItem = url; | 288 this.dataItem = url; |
243 }, | 289 }, |
244 }; | 290 }; |
245 | 291 |
246 /** | 292 /** |
247 * Create a new passwords list. | 293 * Create a new passwords list. |
248 * @constructor | 294 * @constructor |
249 * @extends {cr.ui.List} | 295 * @extends {options.InlineEditableItemList} |
250 */ | 296 */ |
251 var PasswordsList = cr.ui.define('list'); | 297 var PasswordsList = cr.ui.define('list'); |
252 | 298 |
253 PasswordsList.prototype = { | 299 PasswordsList.prototype = { |
254 __proto__: DeletableItemList.prototype, | 300 __proto__: InlineEditableItemList.prototype, |
255 | 301 |
256 /** | 302 /** |
257 * Whether passwords can be revealed or not. | 303 * Whether passwords can be revealed or not. |
258 * @type {boolean} | 304 * @type {boolean} |
259 * @private | 305 * @private |
260 */ | 306 */ |
261 showPasswords_: true, | 307 showPasswords_: true, |
262 | 308 |
263 /** @override */ | 309 /** @override */ |
264 decorate: function() { | 310 decorate: function() { |
265 DeletableItemList.prototype.decorate.call(this); | 311 InlineEditableItemList.prototype.decorate.call(this); |
266 Preferences.getInstance().addEventListener( | 312 Preferences.getInstance().addEventListener( |
267 'profile.password_manager_allow_show_passwords', | 313 'profile.password_manager_allow_show_passwords', |
268 this.onPreferenceChanged_.bind(this)); | 314 this.onPreferenceChanged_.bind(this)); |
269 }, | 315 }, |
270 | 316 |
271 /** | 317 /** |
272 * Listener for changes on the preference. | 318 * Listener for changes on the preference. |
273 * @param {Event} event The preference update event. | 319 * @param {Event} event The preference update event. |
274 * @private | 320 * @private |
275 */ | 321 */ |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 }, | 380 }, |
335 }; | 381 }; |
336 | 382 |
337 return { | 383 return { |
338 PasswordListItem: PasswordListItem, | 384 PasswordListItem: PasswordListItem, |
339 PasswordExceptionsListItem: PasswordExceptionsListItem, | 385 PasswordExceptionsListItem: PasswordExceptionsListItem, |
340 PasswordsList: PasswordsList, | 386 PasswordsList: PasswordsList, |
341 PasswordExceptionsList: PasswordExceptionsList, | 387 PasswordExceptionsList: PasswordExceptionsList, |
342 }; | 388 }; |
343 }); | 389 }); |
OLD | NEW |