Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 6 const ArrayDataModel = cr.ui.ArrayDataModel; |
| 7 const DeletableItemList = options.DeletableItemList; | |
| 7 const List = cr.ui.List; | 8 const List = cr.ui.List; |
| 8 const ListItem = cr.ui.ListItem; | 9 const ListItem = cr.ui.ListItem; |
| 9 const ArrayDataModel = cr.ui.ArrayDataModel; | |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * Creates a new passwords list item. | 12 * Creates a new passwords list item. |
| 13 * @param {Array} entry A pair of the form [url, username]. | 13 * @param {Array} entry An array of the form [url, username, password]. |
| 14 * @constructor | 14 * @constructor |
| 15 * @extends {cr.ui.ListItem} | 15 * @extends {cr.ui.ListItem} |
| 16 */ | 16 */ |
| 17 function PasswordsListItem(entry) { | 17 function PasswordListItem(entry) { |
| 18 var el = cr.doc.createElement('li'); | 18 var el = cr.doc.createElement('div'); |
| 19 el.dataItem = entry; | 19 el.dataItem = entry; |
| 20 el.__proto__ = PasswordsListItem.prototype; | 20 el.__proto__ = PasswordListItem.prototype; |
| 21 el.decorate(); | 21 el.decorate(); |
| 22 | 22 |
| 23 return el; | 23 return el; |
| 24 } | 24 } |
| 25 | 25 |
| 26 PasswordsListItem.prototype = { | 26 PasswordListItem.prototype = { |
| 27 __proto__: ListItem.prototype, | 27 __proto__: ListItem.prototype, |
| 28 | 28 |
| 29 /** | 29 /** @inheritDoc */ |
| 30 * Call when an element is decorated as a list item. | |
| 31 */ | |
| 32 decorate: function() { | 30 decorate: function() { |
| 33 ListItem.prototype.decorate.call(this); | 31 ListItem.prototype.decorate.call(this); |
| 34 | 32 |
| 35 // Labels for display | 33 // The URL of the site. |
| 36 var urlLabel = cr.doc.createElement('span'); | 34 var urlLabel = this.ownerDocument.createElement('div'); |
| 35 urlLabel.className = 'url'; | |
| 36 urlLabel.classList.add('favicon-cell'); | |
| 37 urlLabel.textContent = this.url; | 37 urlLabel.textContent = this.url; |
| 38 urlLabel.style.backgroundImage = url('chrome://favicon/' + this.url); | |
| 38 this.appendChild(urlLabel); | 39 this.appendChild(urlLabel); |
| 39 this.urlLabel = urlLabel; | |
| 40 | 40 |
| 41 var usernameLabel = cr.doc.createElement('span'); | 41 // The stored username. |
| 42 var usernameLabel = this.ownerDocument.createElement('div'); | |
| 43 usernameLabel.className = 'name'; | |
| 42 usernameLabel.textContent = this.username; | 44 usernameLabel.textContent = this.username; |
| 43 usernameLabel.className = 'passwordsUsername'; | |
| 44 this.appendChild(usernameLabel); | 45 this.appendChild(usernameLabel); |
| 45 this.usernameLabel = usernameLabel; | 46 |
| 47 // The stored password. | |
| 48 var passwordInputDiv = this.ownerDocument.createElement('div'); | |
| 49 passwordInputDiv.className = 'password'; | |
| 50 | |
| 51 // The password input field. | |
| 52 var passwordInput = this.ownerDocument.createElement('input'); | |
| 53 passwordInput.className = 'inactive-password'; | |
| 54 passwordInput.type = 'password'; | |
| 55 passwordInput.value = this.password; | |
| 56 passwordInputDiv.appendChild(passwordInput); | |
| 57 | |
| 58 // The show/hide button. | |
| 59 var buttonSpan = this.ownerDocument.createElement('span'); | |
| 60 buttonSpan.className = 'hidden'; | |
| 61 buttonSpan.addEventListener('click', this.onClick_, true); | |
| 62 passwordInputDiv.appendChild(buttonSpan); | |
| 63 | |
| 64 this.appendChild(passwordInputDiv); | |
| 65 }, | |
| 66 | |
| 67 /** @inheritDoc */ | |
| 68 selectionChanged: function() { | |
| 69 var passwordInput = this.querySelector('input[type=password]'); | |
| 70 var buttonSpan = passwordInput.nextSibling; | |
| 71 if (this.selected) { | |
| 72 passwordInput.classList.remove('inactive-password'); | |
| 73 buttonSpan.classList.remove('hidden'); | |
| 74 } else { | |
| 75 passwordInput.classList.add('inactive-password'); | |
| 76 buttonSpan.classList.add('hidden'); | |
| 77 } | |
| 46 }, | 78 }, |
| 47 | 79 |
| 48 /** | 80 /** |
| 49 * Get the url for the entry. | 81 * On-click event handler. Swaps the type of the input field from password |
| 82 * to text and back. | |
| 83 * @private | |
| 84 */ | |
| 85 onClick_: function(event) { | |
| 86 // The password is the input element previous to the button span. | |
| 87 var buttonSpan = event.currentTarget; | |
| 88 var passwordInput = buttonSpan.previousSibling; | |
| 89 var type = passwordInput.type; | |
| 90 passwordInput.type = (type == 'password') ? 'text' : 'password'; | |
|
arv (Not doing code reviews)
2010/12/17 20:07:34
useless parens
James Hawkins
2010/12/17 21:32:40
Done.
| |
| 91 }, | |
| 92 | |
| 93 /** | |
| 94 * Get and set the URL for the entry. | |
| 50 * @type {string} | 95 * @type {string} |
| 51 */ | 96 */ |
| 52 get url() { | 97 get url() { |
| 53 return this.dataItem[0]; | 98 return this.dataItem[0]; |
| 54 }, | 99 }, |
| 55 set url(url) { | 100 set url(url) { |
| 56 this.dataItem[0] = url; | 101 this.dataItem[0] = url; |
| 57 }, | 102 }, |
| 58 | 103 |
| 59 /** | 104 /** |
| 60 * Get the username for the entry. | 105 * Get and set the username for the entry. |
| 61 * @type {string} | 106 * @type {string} |
| 62 */ | 107 */ |
| 63 get username() { | 108 get username() { |
| 64 return this.dataItem[1]; | 109 return this.dataItem[1]; |
| 65 }, | 110 }, |
| 66 set username(username) { | 111 set username(username) { |
| 67 this.dataItem[1] = username; | 112 this.dataItem[1] = username; |
| 68 }, | 113 }, |
| 114 | |
| 115 /** | |
| 116 * Get and set the password for the entry. | |
| 117 * @type {string} | |
| 118 */ | |
| 119 get password() { | |
| 120 return this.dataItem[2]; | |
| 121 }, | |
| 122 set password(password) { | |
| 123 this.dataItem[2] = password; | |
| 124 }, | |
| 69 }; | 125 }; |
| 70 | 126 |
| 71 /** | 127 /** |
| 72 * Creates a new PasswordExceptions list item. | 128 * Creates a new PasswordExceptions list item. |
| 73 * @param {Array} entry A pair of the form [url, username]. | 129 * @param {Array} entry A pair of the form [url, username]. |
| 74 * @constructor | 130 * @constructor |
| 75 * @extends {cr.ui.ListItem} | 131 * @extends {cr.ui.ListItem} |
| 76 */ | 132 */ |
| 77 function PasswordExceptionsListItem(entry) { | 133 function PasswordExceptionsListItem(entry) { |
| 78 var el = cr.doc.createElement('li'); | 134 var el = cr.doc.createElement('div'); |
| 79 el.dataItem = entry; | 135 el.dataItem = entry; |
| 80 el.__proto__ = PasswordExceptionsListItem.prototype; | 136 el.__proto__ = PasswordExceptionsListItem.prototype; |
| 81 el.decorate(); | 137 el.decorate(); |
| 82 | 138 |
| 83 return el; | 139 return el; |
| 84 } | 140 } |
| 85 | 141 |
| 86 PasswordExceptionsListItem.prototype = { | 142 PasswordExceptionsListItem.prototype = { |
| 87 __proto__: ListItem.prototype, | 143 __proto__: ListItem.prototype, |
| 88 | 144 |
| 89 /** | 145 /** |
| 90 * Call when an element is decorated as a list item. | 146 * Call when an element is decorated as a list item. |
| 91 */ | 147 */ |
| 92 decorate: function() { | 148 decorate: function() { |
| 93 ListItem.prototype.decorate.call(this); | 149 ListItem.prototype.decorate.call(this); |
| 94 | 150 |
| 95 // Labels for display | 151 // The URL of the site. |
| 96 var urlLabel = cr.doc.createElement('span'); | 152 var urlLabel = this.ownerDocument.createElement('div'); |
| 153 urlLabel.className = 'url'; | |
| 154 urlLabel.classList.add('favicon-cell'); | |
| 97 urlLabel.textContent = this.url; | 155 urlLabel.textContent = this.url; |
| 156 urlLabel.style.backgroundImage = url('chrome://favicon/' + this.url); | |
| 98 this.appendChild(urlLabel); | 157 this.appendChild(urlLabel); |
| 99 this.urlLabel = urlLabel; | |
| 100 }, | 158 }, |
| 101 | 159 |
| 102 /** | 160 /** |
| 103 * Get the url for the entry. | 161 * Get the url for the entry. |
| 104 * @type {string} | 162 * @type {string} |
| 105 */ | 163 */ |
| 106 get url() { | 164 get url() { |
| 107 return this.dataItem; | 165 return this.dataItem; |
| 108 }, | 166 }, |
| 109 set url(url) { | 167 set url(url) { |
| 110 this.dataItem = url; | 168 this.dataItem = url; |
| 111 }, | 169 }, |
| 112 }; | 170 }; |
| 113 | 171 |
| 114 | |
| 115 /** | 172 /** |
| 116 * Create a new passwords list. | 173 * Create a new passwords list. |
| 117 * @constructor | 174 * @constructor |
| 118 * @extends {cr.ui.List} | 175 * @extends {cr.ui.List} |
| 119 */ | 176 */ |
| 120 var PasswordsList = cr.ui.define('list'); | 177 var PasswordsList = cr.ui.define('list'); |
| 121 | 178 |
| 122 PasswordsList.prototype = { | 179 PasswordsList.prototype = { |
| 123 __proto__: List.prototype, | 180 __proto__: DeletableItemList.prototype, |
| 124 /** | |
| 125 * Called when an element is decorated as a list. | |
| 126 */ | |
| 127 decorate: function() { | |
| 128 List.prototype.decorate.call(this); | |
| 129 | 181 |
| 130 this.dataModel = new ArrayDataModel([]); | 182 /** @inheritDoc */ |
| 183 createItemContents: function(entry) { | |
| 184 return new PasswordListItem(entry); | |
| 185 }, | |
| 186 | |
| 187 /** @inheritDoc */ | |
| 188 deleteItemAtIndex: function(index) { | |
| 189 PasswordManager.removeSavedPassword(index); | |
| 131 }, | 190 }, |
| 132 | 191 |
| 133 /** | 192 /** |
| 134 * Creates an item to go in the list. | |
| 135 * @param {Object} entry The element from the data model for this row. | |
| 136 */ | |
| 137 createItem: function(entry) { | |
| 138 return new PasswordsListItem(entry); | |
| 139 }, | |
| 140 | |
| 141 /** | |
| 142 * Adds an entry to the js model. | |
| 143 * @param {Array} entry A pair of the form [url, username]. | |
| 144 */ | |
| 145 addEntry: function(entry) { | |
| 146 this.dataModel.push(entry); | |
| 147 this.listArea.updateButtonSensitivity(); | |
| 148 }, | |
| 149 | |
| 150 /** | |
| 151 * Remove all entries from the js model. | |
| 152 */ | |
| 153 clear: function() { | |
| 154 this.dataModel = new ArrayDataModel([]); | |
| 155 this.listArea.updateButtonSensitivity(); | |
| 156 }, | |
| 157 | |
| 158 /** | |
| 159 * Remove selected row from browser's model. | |
| 160 */ | |
| 161 removeSelectedRow: function() { | |
| 162 var selectedIndex = this.selectionModel.selectedIndex; | |
| 163 PasswordManager.removeSavedPassword(selectedIndex); | |
| 164 }, | |
| 165 | |
| 166 showSelectedPassword: function() { | |
| 167 var selectedIndex = this.selectionModel.selectedIndex; | |
| 168 PasswordManager.showSelectedPassword(selectedIndex); | |
| 169 }, | |
| 170 | |
| 171 /** | |
| 172 * The length of the list. | 193 * The length of the list. |
| 173 */ | 194 */ |
| 174 get length() { | 195 get length() { |
| 175 return this.dataModel.length; | 196 return this.dataModel.length; |
| 176 }, | 197 }, |
| 177 }; | 198 }; |
| 178 | 199 |
| 179 /** | 200 /** |
| 180 * Create a new passwords list. | 201 * Create a new passwords list. |
| 181 * @constructor | 202 * @constructor |
| 182 * @extends {cr.ui.List} | 203 * @extends {cr.ui.List} |
| 183 */ | 204 */ |
| 184 var PasswordExceptionsList = cr.ui.define('list'); | 205 var PasswordExceptionsList = cr.ui.define('list'); |
| 185 | 206 |
| 186 PasswordExceptionsList.prototype = { | 207 PasswordExceptionsList.prototype = { |
| 187 __proto__: List.prototype, | 208 __proto__: DeletableItemList.prototype, |
| 188 /** | |
| 189 * Called when an element is decorated as a list. | |
| 190 */ | |
| 191 decorate: function() { | |
| 192 List.prototype.decorate.call(this); | |
| 193 | 209 |
| 194 this.dataModel = new ArrayDataModel([]); | 210 /** @inheritDoc */ |
| 211 createItemContents: function(entry) { | |
| 212 return new PasswordExceptionsListItem(entry); | |
| 213 }, | |
| 214 | |
| 215 /** @inheritDoc */ | |
| 216 deleteItemAtIndex: function(index) { | |
| 217 PasswordManager.removePasswordException(index); | |
| 195 }, | 218 }, |
| 196 | 219 |
| 197 /** | 220 /** |
| 198 * Creates an item to go in the list. | |
| 199 * @param {Object} entry The element from the data model for this row. | |
| 200 */ | |
| 201 createItem: function(entry) { | |
| 202 return new PasswordExceptionsListItem(entry); | |
| 203 }, | |
| 204 | |
| 205 /** | |
| 206 * Adds an entry to the js model. | |
| 207 * @param {Array} entry A pair of the form [url, username]. | |
| 208 */ | |
| 209 addEntry: function(entry) { | |
| 210 this.dataModel.push(entry); | |
| 211 this.listArea.updateButtonSensitivity(); | |
| 212 }, | |
| 213 | |
| 214 /** | |
| 215 * Remove all entries from the js model. | |
| 216 */ | |
| 217 clear: function() { | |
| 218 this.dataModel = new ArrayDataModel([]); | |
| 219 this.listArea.updateButtonSensitivity(); | |
| 220 }, | |
| 221 | |
| 222 /** | |
| 223 * Remove selected row from browser's model. | |
| 224 */ | |
| 225 removeSelectedRow: function() { | |
| 226 var selectedIndex = this.selectionModel.selectedIndex; | |
| 227 PasswordManager.removePasswordException(selectedIndex); | |
| 228 }, | |
| 229 | |
| 230 /** | |
| 231 * The length of the list. | 221 * The length of the list. |
| 232 */ | 222 */ |
| 233 get length() { | 223 get length() { |
| 234 return this.dataModel.length; | 224 return this.dataModel.length; |
| 235 }, | 225 }, |
| 236 }; | 226 }; |
| 237 | 227 |
| 238 /** | |
| 239 * Create a new passwords list area. | |
| 240 * @constructor | |
| 241 * @extends {cr.ui.div} | |
| 242 */ | |
| 243 var PasswordsListArea = cr.ui.define('div'); | |
| 244 | |
| 245 PasswordsListArea.prototype = { | |
| 246 __proto__: HTMLDivElement.prototype, | |
| 247 | |
| 248 decorate: function() { | |
| 249 this.passwordsList = this.querySelector('list'); | |
| 250 this.passwordsList.listArea = this; | |
| 251 | |
| 252 PasswordsList.decorate(this.passwordsList); | |
| 253 this.passwordsList.selectionModel.addEventListener( | |
| 254 'change', this.handleOnSelectionChange_.bind(this)); | |
| 255 | |
| 256 var removeRow = cr.doc.createElement('button'); | |
| 257 removeRow.textContent = templateData.passwordsRemoveButton; | |
| 258 this.appendChild(removeRow); | |
| 259 this.removeRow = removeRow; | |
| 260 | |
| 261 var removeAll = cr.doc.createElement('button'); | |
| 262 removeAll.textContent = templateData.passwordsRemoveAllButton; | |
| 263 this.appendChild(removeAll); | |
| 264 this.removeAll = removeAll; | |
| 265 | |
| 266 var showHidePassword = cr.doc.createElement('button'); | |
| 267 showHidePassword.textContent = templateData.passwordsShowButton; | |
| 268 this.appendChild(showHidePassword); | |
| 269 this.showHidePassword = showHidePassword; | |
| 270 this.showingPassword = false | |
| 271 | |
| 272 var passwordLabel = cr.doc.createElement('span'); | |
| 273 this.appendChild(passwordLabel); | |
| 274 this.passwordLabel = passwordLabel; | |
| 275 | |
| 276 var self = this; | |
| 277 removeRow.onclick = function(event) { | |
| 278 self.passwordsList.removeSelectedRow(); | |
| 279 }; | |
| 280 | |
| 281 removeAll.onclick = function(event) { | |
| 282 AlertOverlay.show( | |
| 283 undefined, | |
| 284 localStrings.getString('passwordsRemoveAllWarning'), | |
| 285 localStrings.getString('yesButtonLabel'), | |
| 286 localStrings.getString('noButtonLabel'), | |
| 287 function() { PasswordManager.removeAllPasswords(); }); | |
| 288 }; | |
| 289 | |
| 290 showHidePassword.onclick = function(event) { | |
| 291 if(self.showingPassword) { | |
| 292 self.passwordLabel.textContent = ""; | |
| 293 this.textContent = templateData.passwordsShowButton; | |
| 294 } else { | |
| 295 self.passwordsList.showSelectedPassword(); | |
| 296 this.textContent = templateData.passwordsHideButton; | |
| 297 } | |
| 298 self.showingPassword = !self.showingPassword; | |
| 299 }; | |
| 300 | |
| 301 this.updateButtonSensitivity(); | |
| 302 }, | |
| 303 | |
| 304 displayReturnedPassword: function(password) { | |
| 305 this.passwordLabel.textContent = password; | |
| 306 }, | |
| 307 | |
| 308 /** | |
| 309 * Update the button's states | |
| 310 */ | |
| 311 updateButtonSensitivity: function() { | |
| 312 var selectionSize = this.passwordsList.selectedItems.length; | |
| 313 this.removeRow.disabled = selectionSize == 0; | |
| 314 this.showHidePassword.disabled = selectionSize == 0; | |
| 315 this.removeAll.disabled = this.passwordsList.length == 0; | |
| 316 }, | |
| 317 | |
| 318 /** | |
| 319 * Callback from selection model | |
| 320 * @param {!cr.Event} ce Event with change info. | |
| 321 * @private | |
| 322 */ | |
| 323 handleOnSelectionChange_: function(ce) { | |
| 324 this.passwordLabel.textContent = ""; | |
| 325 this.showHidePassword.textContent = templateData.passwordsShowButton; | |
| 326 this.showingPassword = false; | |
| 327 this.updateButtonSensitivity(); | |
| 328 }, | |
| 329 }; | |
| 330 | |
| 331 /** | |
| 332 * Create a new passwords list area. | |
| 333 * @constructor | |
| 334 * @extends {cr.ui.div} | |
| 335 */ | |
| 336 var PasswordExceptionsListArea = cr.ui.define('div'); | |
| 337 | |
| 338 PasswordExceptionsListArea.prototype = { | |
| 339 __proto__: HTMLDivElement.prototype, | |
| 340 | |
| 341 decorate: function() { | |
| 342 this.passwordExceptionsList = this.querySelector('list'); | |
| 343 this.passwordExceptionsList.listArea = this; | |
| 344 | |
| 345 PasswordExceptionsList.decorate(this.passwordExceptionsList); | |
| 346 this.passwordExceptionsList.selectionModel.addEventListener( | |
| 347 'change', this.handleOnSelectionChange_.bind(this)); | |
| 348 | |
| 349 var removeRow = cr.doc.createElement('button'); | |
| 350 removeRow.textContent = templateData.passwordsRemoveButton; | |
| 351 this.appendChild(removeRow); | |
| 352 this.removeRow = removeRow; | |
| 353 | |
| 354 var removeAll = cr.doc.createElement('button'); | |
| 355 removeAll.textContent = templateData.passwordsRemoveAllButton; | |
| 356 this.appendChild(removeAll); | |
| 357 this.removeAll = removeAll; | |
| 358 | |
| 359 var self = this; | |
| 360 removeRow.onclick = function(event) { | |
| 361 self.passwordExceptionsList.removeSelectedRow(); | |
| 362 }; | |
| 363 | |
| 364 removeAll.onclick = function(event) { | |
| 365 PasswordManager.removeAllPasswordExceptions(); | |
| 366 }; | |
| 367 | |
| 368 this.updateButtonSensitivity(); | |
| 369 }, | |
| 370 | |
| 371 /** | |
| 372 * Update the button's states | |
| 373 */ | |
| 374 updateButtonSensitivity: function() { | |
| 375 var selectionSize = this.passwordExceptionsList.selectedItems.length; | |
| 376 this.removeRow.disabled = selectionSize == 0; | |
| 377 this.removeAll.disabled = this.passwordExceptionsList.length == 0; | |
| 378 }, | |
| 379 | |
| 380 /** | |
| 381 * Callback from selection model | |
| 382 * @param {!cr.Event} ce Event with change info. | |
| 383 * @private | |
| 384 */ | |
| 385 handleOnSelectionChange_: function(ce) { | |
| 386 this.updateButtonSensitivity(); | |
| 387 }, | |
| 388 }; | |
| 389 | |
| 390 | |
| 391 return { | 228 return { |
| 392 PasswordsListItem: PasswordsListItem, | 229 PasswordListItem: PasswordListItem, |
| 393 PasswordExceptionsListItem: PasswordExceptionsListItem, | 230 PasswordExceptionsListItem: PasswordExceptionsListItem, |
| 394 PasswordsList: PasswordsList, | 231 PasswordsList: PasswordsList, |
| 395 PasswordExceptionsList: PasswordExceptionsList, | 232 PasswordExceptionsList: PasswordExceptionsList, |
| 396 PasswordsListArea: PasswordsListArea, | |
| 397 PasswordExceptionsListArea: PasswordExceptionsListArea | |
| 398 }; | 233 }; |
| 399 }); | 234 }); |
| OLD | NEW |