OLD | NEW |
| (Empty) |
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. | |
4 | |
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; | |
10 | |
11 /** | |
12 * Creates a new passwords list item. | |
13 * @param {Array} entry An array of the form [url, username, password]. When | |
14 * the list has been filtered, a fourth element [index] may be present. | |
15 * @constructor | |
16 * @extends {cr.ui.ListItem} | |
17 */ | |
18 function PasswordListItem(entry, showPasswords) { | |
19 var el = cr.doc.createElement('div'); | |
20 el.dataItem = entry; | |
21 el.__proto__ = PasswordListItem.prototype; | |
22 el.decorate(showPasswords); | |
23 | |
24 return el; | |
25 } | |
26 | |
27 PasswordListItem.prototype = { | |
28 __proto__: DeletableItem.prototype, | |
29 | |
30 /** @inheritDoc */ | |
31 decorate: function(showPasswords) { | |
32 DeletableItem.prototype.decorate.call(this); | |
33 | |
34 // The URL of the site. | |
35 var urlLabel = this.ownerDocument.createElement('div'); | |
36 urlLabel.classList.add('favicon-cell'); | |
37 urlLabel.classList.add('weakrtl'); | |
38 urlLabel.classList.add('url'); | |
39 urlLabel.setAttribute('title', this.url); | |
40 urlLabel.textContent = this.url; | |
41 | |
42 // The favicon URL is prefixed with "origin/", which essentially removes | |
43 // the URL path past the top-level domain and ensures that a scheme (e.g., | |
44 // http) is being used. This ensures that the favicon returned is the | |
45 // default favicon for the domain and that the URL has a scheme if none | |
46 // is present in the password manager. | |
47 urlLabel.style.backgroundImage = | |
48 url('chrome://favicon/origin/' + this.url); | |
49 this.contentElement.appendChild(urlLabel); | |
50 | |
51 // The stored username. | |
52 var usernameLabel = this.ownerDocument.createElement('div'); | |
53 usernameLabel.className = 'name'; | |
54 usernameLabel.textContent = this.username; | |
55 this.contentElement.appendChild(usernameLabel); | |
56 | |
57 // The stored password. | |
58 var passwordInputDiv = this.ownerDocument.createElement('div'); | |
59 passwordInputDiv.className = 'password'; | |
60 | |
61 // The password input field. | |
62 var passwordInput = this.ownerDocument.createElement('input'); | |
63 passwordInput.type = 'password'; | |
64 passwordInput.className = 'inactive-password'; | |
65 passwordInput.readOnly = true; | |
66 passwordInput.value = showPasswords ? this.password : '********'; | |
67 passwordInputDiv.appendChild(passwordInput); | |
68 | |
69 // The show/hide button. | |
70 if (showPasswords) { | |
71 var button = this.ownerDocument.createElement('button'); | |
72 button.hidden = true; | |
73 button.className = 'list-inline-button custom-appearance'; | |
74 button.textContent = loadTimeData.getString('passwordShowButton'); | |
75 button.addEventListener('click', this.onClick_, true); | |
76 passwordInputDiv.appendChild(button); | |
77 } | |
78 | |
79 this.contentElement.appendChild(passwordInputDiv); | |
80 }, | |
81 | |
82 /** @inheritDoc */ | |
83 selectionChanged: function() { | |
84 var passwordInput = this.querySelector('input[type=password]'); | |
85 var textInput = this.querySelector('input[type=text]'); | |
86 var input = passwordInput || textInput; | |
87 var button = input.nextSibling; | |
88 // |button| doesn't exist when passwords can't be shown. | |
89 if (!button) | |
90 return; | |
91 if (this.selected) { | |
92 input.classList.remove('inactive-password'); | |
93 button.hidden = false; | |
94 } else { | |
95 input.classList.add('inactive-password'); | |
96 button.hidden = true; | |
97 } | |
98 }, | |
99 | |
100 /** | |
101 * On-click event handler. Swaps the type of the input field from password | |
102 * to text and back. | |
103 * @private | |
104 */ | |
105 onClick_: function(event) { | |
106 // The password is the input element previous to the button. | |
107 var button = event.currentTarget; | |
108 var passwordInput = button.previousSibling; | |
109 if (passwordInput.type == 'password') { | |
110 passwordInput.type = 'text'; | |
111 button.textContent = loadTimeData.getString('passwordHideButton'); | |
112 } else { | |
113 passwordInput.type = 'password'; | |
114 button.textContent = loadTimeData.getString('passwordShowButton'); | |
115 } | |
116 }, | |
117 | |
118 /** | |
119 * Get and set the URL for the entry. | |
120 * @type {string} | |
121 */ | |
122 get url() { | |
123 return this.dataItem[0]; | |
124 }, | |
125 set url(url) { | |
126 this.dataItem[0] = url; | |
127 }, | |
128 | |
129 /** | |
130 * Get and set the username for the entry. | |
131 * @type {string} | |
132 */ | |
133 get username() { | |
134 return this.dataItem[1]; | |
135 }, | |
136 set username(username) { | |
137 this.dataItem[1] = username; | |
138 }, | |
139 | |
140 /** | |
141 * Get and set the password for the entry. | |
142 * @type {string} | |
143 */ | |
144 get password() { | |
145 return this.dataItem[2]; | |
146 }, | |
147 set password(password) { | |
148 this.dataItem[2] = password; | |
149 }, | |
150 }; | |
151 | |
152 /** | |
153 * Creates a new PasswordExceptions list item. | |
154 * @param {Array} entry A pair of the form [url, username]. | |
155 * @constructor | |
156 * @extends {Deletable.ListItem} | |
157 */ | |
158 function PasswordExceptionsListItem(entry) { | |
159 var el = cr.doc.createElement('div'); | |
160 el.dataItem = entry; | |
161 el.__proto__ = PasswordExceptionsListItem.prototype; | |
162 el.decorate(); | |
163 | |
164 return el; | |
165 } | |
166 | |
167 PasswordExceptionsListItem.prototype = { | |
168 __proto__: DeletableItem.prototype, | |
169 | |
170 /** | |
171 * Call when an element is decorated as a list item. | |
172 */ | |
173 decorate: function() { | |
174 DeletableItem.prototype.decorate.call(this); | |
175 | |
176 // The URL of the site. | |
177 var urlLabel = this.ownerDocument.createElement('div'); | |
178 urlLabel.className = 'url'; | |
179 urlLabel.classList.add('favicon-cell'); | |
180 urlLabel.classList.add('weakrtl'); | |
181 urlLabel.textContent = this.url; | |
182 | |
183 // The favicon URL is prefixed with "origin/", which essentially removes | |
184 // the URL path past the top-level domain and ensures that a scheme (e.g., | |
185 // http) is being used. This ensures that the favicon returned is the | |
186 // default favicon for the domain and that the URL has a scheme if none | |
187 // is present in the password manager. | |
188 urlLabel.style.backgroundImage = | |
189 url('chrome://favicon/origin/' + this.url); | |
190 this.contentElement.appendChild(urlLabel); | |
191 }, | |
192 | |
193 /** | |
194 * Get the url for the entry. | |
195 * @type {string} | |
196 */ | |
197 get url() { | |
198 return this.dataItem; | |
199 }, | |
200 set url(url) { | |
201 this.dataItem = url; | |
202 }, | |
203 }; | |
204 | |
205 /** | |
206 * Create a new passwords list. | |
207 * @constructor | |
208 * @extends {cr.ui.List} | |
209 */ | |
210 var PasswordsList = cr.ui.define('list'); | |
211 | |
212 PasswordsList.prototype = { | |
213 __proto__: DeletableItemList.prototype, | |
214 | |
215 /** | |
216 * Whether passwords can be revealed or not. | |
217 * @type {boolean} | |
218 * @private | |
219 */ | |
220 showPasswords_: true, | |
221 | |
222 /** @inheritDoc */ | |
223 decorate: function() { | |
224 DeletableItemList.prototype.decorate.call(this); | |
225 Preferences.getInstance().addEventListener( | |
226 'profile.password_manager_allow_show_passwords', | |
227 this.onPreferenceChanged_.bind(this)); | |
228 }, | |
229 | |
230 /** | |
231 * Listener for changes on the preference. | |
232 * @param {Event} event The preference update event. | |
233 * @private | |
234 */ | |
235 onPreferenceChanged_: function(event) { | |
236 this.showPasswords_ = event.value.value; | |
237 this.redraw(); | |
238 }, | |
239 | |
240 /** @inheritDoc */ | |
241 createItem: function(entry) { | |
242 return new PasswordListItem(entry, this.showPasswords_); | |
243 }, | |
244 | |
245 /** @inheritDoc */ | |
246 deleteItemAtIndex: function(index) { | |
247 var item = this.dataModel.item(index); | |
248 if (item && item.length > 3) { | |
249 // The fourth element, if present, is the original index to delete. | |
250 index = item[3]; | |
251 } | |
252 PasswordManager.removeSavedPassword(index); | |
253 }, | |
254 | |
255 /** | |
256 * The length of the list. | |
257 */ | |
258 get length() { | |
259 return this.dataModel.length; | |
260 }, | |
261 }; | |
262 | |
263 /** | |
264 * Create a new passwords list. | |
265 * @constructor | |
266 * @extends {cr.ui.List} | |
267 */ | |
268 var PasswordExceptionsList = cr.ui.define('list'); | |
269 | |
270 PasswordExceptionsList.prototype = { | |
271 __proto__: DeletableItemList.prototype, | |
272 | |
273 /** @inheritDoc */ | |
274 createItem: function(entry) { | |
275 return new PasswordExceptionsListItem(entry); | |
276 }, | |
277 | |
278 /** @inheritDoc */ | |
279 deleteItemAtIndex: function(index) { | |
280 PasswordManager.removePasswordException(index); | |
281 }, | |
282 | |
283 /** | |
284 * The length of the list. | |
285 */ | |
286 get length() { | |
287 return this.dataModel.length; | |
288 }, | |
289 }; | |
290 | |
291 return { | |
292 PasswordListItem: PasswordListItem, | |
293 PasswordExceptionsListItem: PasswordExceptionsListItem, | |
294 PasswordsList: PasswordsList, | |
295 PasswordExceptionsList: PasswordExceptionsList, | |
296 }; | |
297 }); | |
OLD | NEW |