Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / options / password_manager_list.js
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 {ArrayDataModel} dataModel The data model that contains this item.
14    * @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.
16    * @param {boolean} showPasswords If true, add a button to the element to
17    *     allow the user to reveal the saved password.
18    * @constructor
19    * @extends {cr.ui.ListItem}
20    */
21   function PasswordListItem(dataModel, entry, showPasswords) {
22     var el = cr.doc.createElement('div');
23     el.dataItem = entry;
24     el.dataModel = dataModel;
25     el.__proto__ = PasswordListItem.prototype;
26     el.decorate(showPasswords);
27
28     return el;
29   }
30
31   PasswordListItem.prototype = {
32     __proto__: DeletableItem.prototype,
33
34     /** @override */
35     decorate: function(showPasswords) {
36       DeletableItem.prototype.decorate.call(this);
37
38       // The URL of the site.
39       var urlLabel = this.ownerDocument.createElement('div');
40       urlLabel.classList.add('favicon-cell');
41       urlLabel.classList.add('weakrtl');
42       urlLabel.classList.add('url');
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');
64       passwordInputDiv.className = 'password';
65
66       // The password input field.
67       var passwordInput = this.ownerDocument.createElement('input');
68       passwordInput.type = 'password';
69       passwordInput.className = 'inactive-password';
70       passwordInput.readOnly = true;
71       passwordInput.value = showPasswords ? this.password : '********';
72       passwordInputDiv.appendChild(passwordInput);
73       this.passwordField = passwordInput;
74
75       // The show/hide button.
76       if (showPasswords) {
77         var button = this.ownerDocument.createElement('button');
78         button.hidden = true;
79         button.className = 'list-inline-button custom-appearance';
80         button.textContent = loadTimeData.getString('passwordShowButton');
81         button.addEventListener('click', this.onClick_.bind(this), true);
82         button.addEventListener('mousedown', function(event) {
83           // Don't focus on this button by mousedown.
84           event.preventDefault();
85           // Don't handle list item selection. It causes focus change.
86           event.stopPropagation();
87         }, false);
88         passwordInputDiv.appendChild(button);
89         this.passwordShowButton = button;
90       }
91
92       this.contentElement.appendChild(passwordInputDiv);
93     },
94
95     /** @override */
96     selectionChanged: function() {
97       var input = this.passwordField;
98       var button = this.passwordShowButton;
99       // The button doesn't exist when passwords can't be shown.
100       if (!button)
101         return;
102
103       if (this.selected) {
104         input.classList.remove('inactive-password');
105         button.hidden = false;
106       } else {
107         input.classList.add('inactive-password');
108         button.hidden = true;
109       }
110     },
111
112     /**
113      * Reveals the plain text password of this entry.
114      */
115     showPassword: function(password) {
116       this.passwordField.value = password;
117       this.passwordField.type = 'text';
118
119       var button = this.passwordShowButton;
120       if (button)
121         button.textContent = loadTimeData.getString('passwordHideButton');
122     },
123
124     /**
125      * Hides the plain text password of this entry.
126      */
127     hidePassword: function() {
128       this.passwordField.type = 'password';
129
130       var button = this.passwordShowButton;
131       if (button)
132         button.textContent = loadTimeData.getString('passwordShowButton');
133     },
134
135     /**
136      * Get the original index of this item in the data model.
137      * @return {number} The index.
138      * @private
139      */
140     getOriginalIndex_: function() {
141       var index = this.dataItem[3];
142       return index ? index : this.dataModel.indexOf(this.dataItem);
143     },
144
145     /**
146      * On-click event handler. Swaps the type of the input field from password
147      * to text and back.
148      * @private
149      */
150     onClick_: function(event) {
151       if (this.passwordField.type == 'password') {
152         // After the user is authenticated, showPassword() will be called.
153         PasswordManager.requestShowPassword(this.getOriginalIndex_());
154       } else {
155         this.hidePassword();
156       }
157     },
158
159     /**
160      * Get and set the URL for the entry.
161      * @type {string}
162      */
163     get url() {
164       return this.dataItem[0];
165     },
166     set url(url) {
167       this.dataItem[0] = url;
168     },
169
170     /**
171      * Get and set the username for the entry.
172      * @type {string}
173      */
174     get username() {
175       return this.dataItem[1];
176     },
177     set username(username) {
178       this.dataItem[1] = username;
179     },
180
181     /**
182      * Get and set the password for the entry.
183      * @type {string}
184      */
185     get password() {
186       return this.dataItem[2];
187     },
188     set password(password) {
189       this.dataItem[2] = password;
190     },
191   };
192
193   /**
194    * Creates a new PasswordExceptions list item.
195    * @param {Array} entry A pair of the form [url, username].
196    * @constructor
197    * @extends {Deletable.ListItem}
198    */
199   function PasswordExceptionsListItem(entry) {
200     var el = cr.doc.createElement('div');
201     el.dataItem = entry;
202     el.__proto__ = PasswordExceptionsListItem.prototype;
203     el.decorate();
204
205     return el;
206   }
207
208   PasswordExceptionsListItem.prototype = {
209     __proto__: DeletableItem.prototype,
210
211     /**
212      * Call when an element is decorated as a list item.
213      */
214     decorate: function() {
215       DeletableItem.prototype.decorate.call(this);
216
217       // The URL of the site.
218       var urlLabel = this.ownerDocument.createElement('div');
219       urlLabel.className = 'url';
220       urlLabel.classList.add('favicon-cell');
221       urlLabel.classList.add('weakrtl');
222       urlLabel.textContent = this.url;
223
224       // 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.,
226       // 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
228       // is present in the password manager.
229       urlLabel.style.backgroundImage = getFaviconImageSet(
230           'origin/' + this.url, 16);
231       this.contentElement.appendChild(urlLabel);
232     },
233
234     /**
235      * Get the url for the entry.
236      * @type {string}
237      */
238     get url() {
239       return this.dataItem;
240     },
241     set url(url) {
242       this.dataItem = url;
243     },
244   };
245
246   /**
247    * Create a new passwords list.
248    * @constructor
249    * @extends {cr.ui.List}
250    */
251   var PasswordsList = cr.ui.define('list');
252
253   PasswordsList.prototype = {
254     __proto__: DeletableItemList.prototype,
255
256     /**
257      * Whether passwords can be revealed or not.
258      * @type {boolean}
259      * @private
260      */
261     showPasswords_: true,
262
263     /** @override */
264     decorate: function() {
265       DeletableItemList.prototype.decorate.call(this);
266       Preferences.getInstance().addEventListener(
267           'profile.password_manager_allow_show_passwords',
268           this.onPreferenceChanged_.bind(this));
269     },
270
271     /**
272      * Listener for changes on the preference.
273      * @param {Event} event The preference update event.
274      * @private
275      */
276     onPreferenceChanged_: function(event) {
277       this.showPasswords_ = event.value.value;
278       this.redraw();
279     },
280
281     /** @override */
282     createItem: function(entry) {
283       var showPasswords = this.showPasswords_;
284
285       if (loadTimeData.getBoolean('disableShowPasswords'))
286         showPasswords = false;
287
288       return new PasswordListItem(this.dataModel, entry, showPasswords);
289     },
290
291     /** @override */
292     deleteItemAtIndex: function(index) {
293       var item = this.dataModel.item(index);
294       if (item && item.length > 3) {
295         // The fourth element, if present, is the original index to delete.
296         index = item[3];
297       }
298       PasswordManager.removeSavedPassword(index);
299     },
300
301     /**
302      * The length of the list.
303      */
304     get length() {
305       return this.dataModel.length;
306     },
307   };
308
309   /**
310    * Create a new passwords list.
311    * @constructor
312    * @extends {cr.ui.List}
313    */
314   var PasswordExceptionsList = cr.ui.define('list');
315
316   PasswordExceptionsList.prototype = {
317     __proto__: DeletableItemList.prototype,
318
319     /** @override */
320     createItem: function(entry) {
321       return new PasswordExceptionsListItem(entry);
322     },
323
324     /** @override */
325     deleteItemAtIndex: function(index) {
326       PasswordManager.removePasswordException(index);
327     },
328
329     /**
330      * The length of the list.
331      */
332     get length() {
333       return this.dataModel.length;
334     },
335   };
336
337   return {
338     PasswordListItem: PasswordListItem,
339     PasswordExceptionsListItem: PasswordExceptionsListItem,
340     PasswordsList: PasswordsList,
341     PasswordExceptionsList: PasswordExceptionsList,
342   };
343 });