Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(447)

Side by Side Diff: ui/login/account_picker/user_pod_row.js

Issue 456943003: Easy Unlock: Add support for hard locking (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 /** 5 /**
6 * @fileoverview User pod row implementation. 6 * @fileoverview User pod row implementation.
7 */ 7 */
8 8
9 cr.define('login', function() { 9 cr.define('login', function() {
10 /** 10 /**
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 * @const 78 * @const
79 */ 79 */
80 var HELP_TOPIC_PUBLIC_SESSION = 3041033; 80 var HELP_TOPIC_PUBLIC_SESSION = 3041033;
81 81
82 /** 82 /**
83 * Tab order for user pods. Update these when adding new controls. 83 * Tab order for user pods. Update these when adding new controls.
84 * @enum {number} 84 * @enum {number}
85 * @const 85 * @const
86 */ 86 */
87 var UserPodTabOrder = { 87 var UserPodTabOrder = {
88 POD_INPUT: 1, // Password input fields (and whole pods themselves). 88 POD_INPUT: 1, // Password input fields (and whole pods themselves).
89 HEADER_BAR: 2, // Buttons on the header bar (Shutdown, Add User). 89 POD_CUSTOM_ICON: 2, // Pod custom icon next to passwrod input field.
90 ACTION_BOX: 3, // Action box buttons. 90 HEADER_BAR: 3, // Buttons on the header bar (Shutdown, Add User).
91 PAD_MENU_ITEM: 4 // User pad menu items (Remove this user). 91 ACTION_BOX: 4, // Action box buttons.
92 PAD_MENU_ITEM: 5 // User pad menu items (Remove this user).
92 }; 93 };
93 94
94 /** 95 /**
95 * Supported authentication types. Keep in sync with the enum in 96 * Supported authentication types. Keep in sync with the enum in
96 * chrome/browser/signin/screenlock_bridge.h 97 * chrome/browser/signin/screenlock_bridge.h
97 * @enum {number} 98 * @enum {number}
98 * @const 99 * @const
99 */ 100 */
100 var AUTH_TYPE = { 101 var AUTH_TYPE = {
101 OFFLINE_PASSWORD: 0, 102 OFFLINE_PASSWORD: 0,
102 ONLINE_SIGN_IN: 1, 103 ONLINE_SIGN_IN: 1,
103 NUMERIC_PIN: 2, 104 NUMERIC_PIN: 2,
104 USER_CLICK: 3, 105 USER_CLICK: 3,
105 EXPAND_THEN_USER_CLICK: 4, 106 EXPAND_THEN_USER_CLICK: 4,
107 FORCE_OFFLINE_PASSWORD: 5
106 }; 108 };
107 109
108 /** 110 /**
109 * Names of authentication types. 111 * Names of authentication types.
110 */ 112 */
111 var AUTH_TYPE_NAMES = { 113 var AUTH_TYPE_NAMES = {
112 0: 'offlinePassword', 114 0: 'offlinePassword',
113 1: 'onlineSignIn', 115 1: 'onlineSignIn',
114 2: 'numericPin', 116 2: 'numericPin',
115 3: 'userClick', 117 3: 'userClick',
116 4: 'expandThenUserClick', 118 4: 'expandThenUserClick',
119 5: 'forceOfflinePassword'
117 }; 120 };
118 121
119 // Focus and tab order are organized as follows: 122 // Focus and tab order are organized as follows:
120 // 123 //
121 // (1) all user pods have tab index 1 so they are traversed first; 124 // (1) all user pods have tab index 1 so they are traversed first;
122 // (2) when a user pod is activated, its tab index is set to -1 and its 125 // (2) when a user pod is activated, its tab index is set to -1 and its
123 // main input field gets focus and tab index 1; 126 // main input field gets focus and tab index 1;
124 // (3) buttons on the header bar have tab index 2 so they follow user pods; 127 // (3) if user pod custom icon is interactive, it has tab index 2 so it
125 // (4) Action box buttons have tab index 3 and follow header bar buttons; 128 // follows the input.
126 // (5) lastly, focus jumps to the Status Area and back to user pods. 129 // (4) buttons on the header bar have tab index 3 so they follow the custom
130 // icon, or user pod if custom icon is not interactive;
131 // (5) Action box buttons have tab index 4 and follow header bar buttons;
132 // (6) lastly, focus jumps to the Status Area and back to user pods.
127 // 133 //
128 // 'Focus' event is handled by a capture handler for the whole document 134 // 'Focus' event is handled by a capture handler for the whole document
129 // and in some cases 'mousedown' event handlers are used instead of 'click' 135 // and in some cases 'mousedown' event handlers are used instead of 'click'
130 // handlers where it's necessary to prevent 'focus' event from being fired. 136 // handlers where it's necessary to prevent 'focus' event from being fired.
131 137
132 /** 138 /**
133 * Helper function to remove a class from given element. 139 * Helper function to remove a class from given element.
134 * @param {!HTMLElement} el Element whose class list to change. 140 * @param {!HTMLElement} el Element whose class list to change.
135 * @param {string} cl Class to remove. 141 * @param {string} cl Class to remove.
136 */ 142 */
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 animationInterval_: null, 251 animationInterval_: null,
246 252
247 /** 253 /**
248 * The width of the resource that contains representations for different 254 * The width of the resource that contains representations for different
249 * animation stages. 255 * animation stages.
250 * @type {number} 256 * @type {number}
251 * @private 257 * @private
252 */ 258 */
253 animationResourceSize_: 0, 259 animationResourceSize_: 0,
254 260
261 /**
262 * When {@code fadeOut} is called, the element gets hidden using fadeout
263 * animation. This is reference to the listener for transition end added to
264 * the icon element while it's fading out.
265 * @type {?function(Event)}
266 * @private
267 */
268 hideTransitionListener_: null,
269
270 /**
271 * Callback for click and 'Enter' key events that gets set if the icon is
272 * interactive.
273 * @type {?function()}
274 * @private
275 */
276 actionHandler_: null,
277
255 /** @override */ 278 /** @override */
256 decorate: function() { 279 decorate: function() {
257 this.iconElement.addEventListener('mouseover', 280 this.iconElement.addEventListener('mouseover',
258 this.showTooltipSoon_.bind(this)); 281 this.showTooltipSoon_.bind(this));
259 this.iconElement.addEventListener('mouseout', 282 this.iconElement.addEventListener('mouseout',
260 this.hideTooltip_.bind(this, false)); 283 this.hideTooltip_.bind(this, false));
261 this.iconElement.addEventListener('mousedown', 284 this.iconElement.addEventListener('mousedown',
262 this.hideTooltip_.bind(this, false)); 285 this.hideTooltip_.bind(this, false));
286 this.iconElement.addEventListener('click',
287 this.handleClick_.bind(this));
288 this.iconElement.addEventListener('keydown',
289 this.handleKeyDown_.bind(this));
290
291 // When the icon is focused using mouse, there should be no outline shown.
292 // Preventing default mousedown event accomplishes this.
293 this.iconElement.addEventListener('mousedown', function(e) {
294 e.preventDefault();
295 });
263 }, 296 },
264 297
265 /** 298 /**
266 * Getter for the icon element's div. 299 * Getter for the icon element's div.
267 * @return {HTMLDivElement} 300 * @return {HTMLDivElement}
268 */ 301 */
269 get iconElement() { 302 get iconElement() {
270 return this.querySelector('.custom-icon'); 303 return this.querySelector('.custom-icon');
271 }, 304 },
272 305
(...skipping 18 matching lines...) Expand all
291 this.iconElement.style.backgroundImage = 324 this.iconElement.style.backgroundImage =
292 '-webkit-image-set(' + 325 '-webkit-image-set(' +
293 'url(' + iconUrl + '@1x) 1x,' + 326 'url(' + iconUrl + '@1x) 1x,' +
294 'url(' + iconUrl + '@2x) 2x)'; 327 'url(' + iconUrl + '@2x) 2x)';
295 }, 328 },
296 329
297 /** 330 /**
298 * Shows the icon. 331 * Shows the icon.
299 */ 332 */
300 show: function() { 333 show: function() {
334 this.resetHideTransitionState_();
301 this.hidden = false; 335 this.hidden = false;
302 }, 336 },
303 337
304 /** 338 /**
305 * Hides the icon. Makes sure the tooltip is hidden and animation reset. 339 * Hides the icon using a fade-out animation.
306 */ 340 */
307 hide: function() { 341 fadeOut: function() {
342 // The icon is already being hidden.
343 if (this.iconElement.classList.contains('faded'))
344 return;
345
308 this.hideTooltip_(true); 346 this.hideTooltip_(true);
309 this.setAnimation(null); 347 this.iconElement.classList.add('faded');
310 this.hidden = true; 348 this.hideTransitionListener_ = this.hide_.bind(this);
349 this.iconElement.addEventListener('webkitTransitionEnd',
350 this.hideTransitionListener_);
351 ensureTransitionEndEvent(this.iconElement, 200);
311 }, 352 },
312 353
313 /** 354 /**
314 * Sets the icon size element size. 355 * Sets the icon size element size.
315 * @param {!{width: number, height: number}} size The icon size. 356 * @param {!{width: number, height: number}} size The icon size.
316 */ 357 */
317 setSize: function(size) { 358 setSize: function(size) {
318 this.height_ = size.height < CUSTOM_ICON_CONTAINER_SIZE ? 359 this.height_ = size.height < CUSTOM_ICON_CONTAINER_SIZE ?
319 size.height : CUSTOM_ICON_COTAINER_SIZE; 360 size.height : CUSTOM_ICON_COTAINER_SIZE;
320 this.iconElement.style.height = this.height_ + 'px'; 361 this.iconElement.style.height = this.height_ + 'px';
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 this.iconElement.style.backgroundPosition = 'center'; 437 this.iconElement.style.backgroundPosition = 'center';
397 if (!animation) 438 if (!animation)
398 return; 439 return;
399 this.lastAnimationOffset_ = 0; 440 this.lastAnimationOffset_ = 0;
400 this.animationResourceSize_ = animation.resourceWidth; 441 this.animationResourceSize_ = animation.resourceWidth;
401 this.animationInterval_ = setInterval(this.progressAnimation_.bind(this), 442 this.animationInterval_ = setInterval(this.progressAnimation_.bind(this),
402 animation.frameLengthMs); 443 animation.frameLengthMs);
403 }, 444 },
404 445
405 /** 446 /**
447 * Sets up icon tabIndex attribute and handler for click and 'Enter' key
448 * down events.
449 * @param {?function()} callback If icon should be interactive, the
450 * function to get called on click and 'Enter' key down events. Should
451 * be null to make the icon non interactive.
452 */
453 setInteractive: function(callback) {
454 // Update tabIndex property if needed.
455 if (!!this.actionHandler_ != !!callback) {
456 if (callback) {
457 this.iconElement.setAttribute('tabIndex',
458 UserPodTabOrder.POD_CUSTOM_ICON);
459 } else {
460 this.iconElement.removeAttribute('tabIndex');
461 }
462 }
463
464 // Set the new action handler.
465 this.actionHandler_ = callback;
466 },
467
468 /**
469 * Hides the icon. Makes sure the tooltip is hidden and animation reset.
470 * @private
471 */
472 hide_: function() {
473 this.hideTooltip_(true);
474 this.hidden = true;
475 this.setAnimation(null);
476 this.setInteractive(null);
477 this.resetHideTransitionState_();
478 },
479
480 /**
481 * Ensures the icon's transition state potentially set by a call to
482 * {@code fadeOut} is cleared.
483 * @private
484 */
485 resetHideTransitionState_: function() {
486 if (this.hideTransitionListener_) {
487 this.iconElement.removeEventListener('webkitTransitionEnd',
488 this.hideTransitionListener_);
489 this.hideTransitionListener_ = null;
490 }
491 this.iconElement.classList.toggle('faded', false);
492 },
493
494 /**
495 * Handles click event on the icon element. No-op if
496 * {@code this.actionHandler_} is not set.
497 * @param {Event} e The click event.
498 * @private
499 */
500 handleClick_: function(e) {
501 if (!this.actionHandler_)
502 return;
503 this.actionHandler_();
504 stopEventPropagation(e);
505 },
506
507 /**
508 * Handles key down event on the icon element. Only 'Enter' key is handled.
509 * No-op if {@code this.actionHandler_} is not set.
510 * @param {Event} e The key down event.
511 * @private
512 */
513 handleKeyDown_: function(e) {
514 if (!this.actionHandler_ || e.keyIdentifier != 'Enter')
515 return;
516 this.actionHandler_(e);
517 stopEventPropagation(e);
518 },
519
520 /**
406 * Called when mouse enters the icon. It sets timeout for showing the 521 * Called when mouse enters the icon. It sets timeout for showing the
407 * tooltip. 522 * tooltip.
408 * @private 523 * @private
409 */ 524 */
410 showTooltipSoon_: function() { 525 showTooltipSoon_: function() {
411 if (this.showTooltipTimeout_ || this.tooltipActive_) 526 if (this.showTooltipTimeout_ || this.tooltipActive_)
412 return; 527 return;
413 this.showTooltipTimeout_ = 528 this.showTooltipTimeout_ =
414 setTimeout(this.showTooltip_.bind(this), 1000); 529 setTimeout(this.showTooltip_.bind(this), 1000);
415 }, 530 },
416 531
417 /** 532 /**
418 * Shows the current tooltip, if one is set. 533 * Shows the current tooltip if one is set.
419 * @private 534 * @private
420 */ 535 */
421 showTooltip_: function() { 536 showTooltip_: function() {
422 if (this.hidden || !this.tooltip_ || this.tooltipActive_) 537 if (this.hidden || !this.tooltip_ || this.tooltipActive_)
423 return; 538 return;
424 539
425 // If autoshown bubble got hidden, clear the autoshown flag. 540 // If autoshown bubble got hidden, clear the autoshown flag.
426 if ($('bubble').hidden && this.tooltipAutoshown_) 541 if ($('bubble').hidden && this.tooltipAutoshown_)
427 this.tooltipAutoshown_ = false; 542 this.tooltipAutoshown_ = false;
428 543
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 */ 1081 */
967 get authValue() { 1082 get authValue() {
968 return this.authValue_; 1083 return this.authValue_;
969 }, 1084 },
970 1085
971 /** 1086 /**
972 * True if the the user pod uses a password to authenticate. 1087 * True if the the user pod uses a password to authenticate.
973 * @type {bool} 1088 * @type {bool}
974 */ 1089 */
975 get isAuthTypePassword() { 1090 get isAuthTypePassword() {
976 return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD; 1091 return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD ||
1092 this.authType_ == AUTH_TYPE.FORCE_OFFLINE_PASSWORD;
977 }, 1093 },
978 1094
979 /** 1095 /**
980 * True if the the user pod uses a user click to authenticate. 1096 * True if the the user pod uses a user click to authenticate.
981 * @type {bool} 1097 * @type {bool}
982 */ 1098 */
983 get isAuthTypeUserClick() { 1099 get isAuthTypeUserClick() {
984 return this.authType_ == AUTH_TYPE.USER_CLICK; 1100 return this.authType_ == AUTH_TYPE.USER_CLICK;
985 }, 1101 },
986 1102
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 pod.customIconElement.setIconAsResourceUrl(icon.resourceUrl); 2308 pod.customIconElement.setIconAsResourceUrl(icon.resourceUrl);
2193 } else if (icon.data) { 2309 } else if (icon.data) {
2194 pod.customIconElement.setIconAsImageSet(icon.data); 2310 pod.customIconElement.setIconAsImageSet(icon.data);
2195 } else { 2311 } else {
2196 return; 2312 return;
2197 } 2313 }
2198 2314
2199 pod.customIconElement.setSize(icon.size || {width: 0, height: 0}); 2315 pod.customIconElement.setSize(icon.size || {width: 0, height: 0});
2200 pod.customIconElement.setAnimation(icon.animation || null); 2316 pod.customIconElement.setAnimation(icon.animation || null);
2201 pod.customIconElement.setOpacity(icon.opacity || 100); 2317 pod.customIconElement.setOpacity(icon.opacity || 100);
2318 if (icon.hardlockOnClick) {
2319 pod.customIconElement.setInteractive(
2320 this.hardlockUserPod_.bind(this, username));
2321 } else {
2322 pod.customIconElement.setInteractive(null);
2323 }
2202 pod.customIconElement.show(); 2324 pod.customIconElement.show();
2203 // This has to be called after |show| in case the tooltip should be shown 2325 // This has to be called after |show| in case the tooltip should be shown
2204 // immediatelly. 2326 // immediatelly.
2205 pod.customIconElement.setTooltip( 2327 pod.customIconElement.setTooltip(
2206 icon.tooltip || {text: '', autoshow: false}); 2328 icon.tooltip || {text: '', autoshow: false});
2207 }, 2329 },
2208 2330
2209 /** 2331 /**
2332 * Hard-locks user pod for the user. If user pod is hard-locked, it can be
2333 * only unlocked using password, and the authentication type cannot be
2334 * changed.
2335 * @param {!string} username The user's username.
2336 * @private
2337 */
2338 hardlockUserPod_: function(username) {
2339 chrome.send('hardlockPod', [username]);
2340 },
2341
2342 /**
2210 * Hides the custom icon in the user pod added by showUserPodCustomIcon(). 2343 * Hides the custom icon in the user pod added by showUserPodCustomIcon().
2211 * @param {string} username Username of pod to remove button 2344 * @param {string} username Username of pod to remove button
2212 */ 2345 */
2213 hideUserPodCustomIcon: function(username) { 2346 hideUserPodCustomIcon: function(username) {
2214 var pod = this.getPodWithUsername_(username); 2347 var pod = this.getPodWithUsername_(username);
2215 if (pod == null) { 2348 if (pod == null) {
2216 console.error('Unable to hide user pod button for ' + username + 2349 console.error('Unable to hide user pod button for ' + username +
2217 ': user pod not found.'); 2350 ': user pod not found.');
2218 return; 2351 return;
2219 } 2352 }
2220 2353
2221 pod.customIconElement.hide(); 2354 pod.customIconElement.fadeOut();
2222 }, 2355 },
2223 2356
2224 /** 2357 /**
2225 * Sets the authentication type used to authenticate the user. 2358 * Sets the authentication type used to authenticate the user.
2226 * @param {string} username Username of selected user 2359 * @param {string} username Username of selected user
2227 * @param {number} authType Authentication type, must be one of the 2360 * @param {number} authType Authentication type, must be one of the
2228 * values listed in AUTH_TYPE enum. 2361 * values listed in AUTH_TYPE enum.
2229 * @param {string} value The initial value to use for authentication. 2362 * @param {string} value The initial value to use for authentication.
2230 */ 2363 */
2231 setAuthType: function(username, authType, value) { 2364 setAuthType: function(username, authType, value) {
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
2856 if (pod && pod.multiProfilesPolicyApplied) { 2989 if (pod && pod.multiProfilesPolicyApplied) {
2857 pod.userTypeBubbleElement.classList.remove('bubble-shown'); 2990 pod.userTypeBubbleElement.classList.remove('bubble-shown');
2858 } 2991 }
2859 } 2992 }
2860 }; 2993 };
2861 2994
2862 return { 2995 return {
2863 PodRow: PodRow 2996 PodRow: PodRow
2864 }; 2997 };
2865 }); 2998 });
OLDNEW
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698