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

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.
dzhioev (left Google) 2014/08/14 10:46:28 All you need is: this.iconElement.addEventListener
tbarzic 2014/08/14 18:15:51 yes, that's much cleaner, thanks
292 this.iconElement.addEventListener(
293 'mousedown',
294 this.toggleFocusOutline_.bind(this, true));
295
296 // Reenable focus outline when the icon gets blured. It may get focused
297 // using keyboard later, in which case there should be an outline.
298 this.iconElement.addEventListener(
299 'blur',
300 this.toggleFocusOutline_.bind(this, false));
263 }, 301 },
264 302
265 /** 303 /**
266 * Getter for the icon element's div. 304 * Getter for the icon element's div.
267 * @return {HTMLDivElement} 305 * @return {HTMLDivElement}
268 */ 306 */
269 get iconElement() { 307 get iconElement() {
270 return this.querySelector('.custom-icon'); 308 return this.querySelector('.custom-icon');
271 }, 309 },
272 310
(...skipping 18 matching lines...) Expand all
291 this.iconElement.style.backgroundImage = 329 this.iconElement.style.backgroundImage =
292 '-webkit-image-set(' + 330 '-webkit-image-set(' +
293 'url(' + iconUrl + '@1x) 1x,' + 331 'url(' + iconUrl + '@1x) 1x,' +
294 'url(' + iconUrl + '@2x) 2x)'; 332 'url(' + iconUrl + '@2x) 2x)';
295 }, 333 },
296 334
297 /** 335 /**
298 * Shows the icon. 336 * Shows the icon.
299 */ 337 */
300 show: function() { 338 show: function() {
339 this.resetHideTransitionState_();
301 this.hidden = false; 340 this.hidden = false;
302 }, 341 },
303 342
304 /** 343 /**
305 * Hides the icon. Makes sure the tooltip is hidden and animation reset. 344 * Hides the icon using a fade-out animation.
306 */ 345 */
307 hide: function() { 346 fadeOut: function() {
347 // The icon is already being hidden.
348 if (this.iconElement.classList.contains('faded'))
349 return;
350
308 this.hideTooltip_(true); 351 this.hideTooltip_(true);
309 this.setAnimation(null); 352 this.iconElement.classList.add('faded');
310 this.hidden = true; 353 this.hideTransitionListener_ = this.hide_.bind(this);
354 this.iconElement.addEventListener('webkitTransitionEnd',
355 this.hideTransitionListener_);
356 ensureTransitionEndEvent(this.iconElement, 200);
311 }, 357 },
312 358
313 /** 359 /**
314 * Sets the icon size element size. 360 * Sets the icon size element size.
315 * @param {!{width: number, height: number}} size The icon size. 361 * @param {!{width: number, height: number}} size The icon size.
316 */ 362 */
317 setSize: function(size) { 363 setSize: function(size) {
318 this.height_ = size.height < CUSTOM_ICON_CONTAINER_SIZE ? 364 this.height_ = size.height < CUSTOM_ICON_CONTAINER_SIZE ?
319 size.height : CUSTOM_ICON_COTAINER_SIZE; 365 size.height : CUSTOM_ICON_COTAINER_SIZE;
320 this.iconElement.style.height = this.height_ + 'px'; 366 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'; 442 this.iconElement.style.backgroundPosition = 'center';
397 if (!animation) 443 if (!animation)
398 return; 444 return;
399 this.lastAnimationOffset_ = 0; 445 this.lastAnimationOffset_ = 0;
400 this.animationResourceSize_ = animation.resourceWidth; 446 this.animationResourceSize_ = animation.resourceWidth;
401 this.animationInterval_ = setInterval(this.progressAnimation_.bind(this), 447 this.animationInterval_ = setInterval(this.progressAnimation_.bind(this),
402 animation.frameLengthMs); 448 animation.frameLengthMs);
403 }, 449 },
404 450
405 /** 451 /**
452 * Sets up icon tabIndex attribute and handler for click and 'Enter' key
453 * down events.
454 * @param {boolean} value Whether the icon is interactive (i.e. doesn't
455 * ignore click/keydown events). Iff set the tabIndex attribute for the
456 * icon element will be set.
457 * @param {function()=} opt_callback If icon is interactive, the function to
458 * get called on click and 'Enter' key down events. If not set,
459 * {@code value} argument is ignored, and the icon is considered non
460 * interactive.
461 */
462 setInteractive: function(value, opt_callback) {
463 if (!!this.actionHandler_ == value)
464 return;
dzhioev (left Google) 2014/08/14 10:46:28 What if we want to replace callback?
xiyuan 2014/08/14 17:41:07 Looks like we should just do this.hardlockUserPod_
tbarzic 2014/08/14 18:15:51 Done.
tbarzic 2014/08/14 18:15:51 hardlockUserPod_ is defined on UserPod, not UserPo
dzhioev (left Google) 2014/08/14 19:38:21 No I just meant, that if you call 'setInteractive(
xiyuan 2014/08/14 19:40:01 I see. In this case, passing the callback is right
tbarzic 2014/08/14 20:35:07 yeah, I got there (and fixed it). I was replying t
tbarzic 2014/08/14 21:03:07 Done.
465
466 if (value && opt_callback) {
467 this.iconElement.setAttribute('tabIndex',
468 UserPodTabOrder.POD_CUSTOM_ICON);
469 this.actionHandler_ = opt_callback;
470 } else {
471 this.iconElement.removeAttribute('tabIndex');
472 this.actionHandler_ = null;
473 }
474 },
475
476 /**
477 * Hides the icon. Makes sure the tooltip is hidden and animation reset.
478 * @private
479 */
480 hide_: function() {
481 this.hideTooltip_(true);
482 this.hidden = true;
483 this.setAnimation(null);
484 this.setInteractive(false);
485 this.resetHideTransitionState_();
486 },
487
488 /**
489 * Ensures the icon's transition state potentially set by a call to
490 * {@code fadeOut} is cleared.
491 * @private
492 */
493 resetHideTransitionState_: function() {
494 if (this.hideTransitionListener_) {
495 this.iconElement.removeEventListener('webkitTransitionEnd',
496 this.hideTransitionListener_);
497 this.hideTransitionListener_ = null;
498 }
499 this.iconElement.classList.toggle('faded', false);
500 },
501
502 /**
503 * Handles click event on the icon element. No-op if
504 * {@code this.actionHandler_} is not set.
505 * @param {Event} e The click event.
506 * @private
507 */
508 handleClick_: function(e) {
509 if (!this.actionHandler_)
510 return;
511 this.actionHandler_();
512 stopEventPropagation(e);
513 },
514
515 /**
516 * Handles key down event on the icon element. Only 'Enter' key is handled.
517 * No-op if {@code this.actionHandler_} is not set.
518 * @param {Event} e The key down event.
519 * @private
520 */
521 handleKeyDown_: function(e) {
522 if (!this.actionHandler_ || e.keyIdentifier != 'Enter')
523 return;
524 this.actionHandler_(e);
525 stopEventPropagation(e);
526 },
527
528 /**
529 * Toggles 'focus-outline-invisible' class on the icon element.
530 * @param {boolean} value Whether the class should be added or removed from
531 * the class list.
532 * @private
533 */
534 toggleFocusOutline_: function(value) {
535 this.iconElement.classList.toggle('focus-outline-invisible', value);
536 },
537
538 /**
406 * Called when mouse enters the icon. It sets timeout for showing the 539 * Called when mouse enters the icon. It sets timeout for showing the
407 * tooltip. 540 * tooltip.
408 * @private 541 * @private
409 */ 542 */
410 showTooltipSoon_: function() { 543 showTooltipSoon_: function() {
411 if (this.showTooltipTimeout_ || this.tooltipActive_) 544 if (this.showTooltipTimeout_ || this.tooltipActive_)
412 return; 545 return;
413 this.showTooltipTimeout_ = 546 this.showTooltipTimeout_ =
414 setTimeout(this.showTooltip_.bind(this), 1000); 547 setTimeout(this.showTooltip_.bind(this), 1000);
415 }, 548 },
416 549
417 /** 550 /**
418 * Shows the current tooltip, if one is set. 551 * Shows the current tooltip if one is set.
419 * @private 552 * @private
420 */ 553 */
421 showTooltip_: function() { 554 showTooltip_: function() {
422 if (this.hidden || !this.tooltip_ || this.tooltipActive_) 555 if (this.hidden || !this.tooltip_ || this.tooltipActive_)
423 return; 556 return;
424 557
425 // If autoshown bubble got hidden, clear the autoshown flag. 558 // If autoshown bubble got hidden, clear the autoshown flag.
426 if ($('bubble').hidden && this.tooltipAutoshown_) 559 if ($('bubble').hidden && this.tooltipAutoshown_)
427 this.tooltipAutoshown_ = false; 560 this.tooltipAutoshown_ = false;
428 561
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 */ 1099 */
967 get authValue() { 1100 get authValue() {
968 return this.authValue_; 1101 return this.authValue_;
969 }, 1102 },
970 1103
971 /** 1104 /**
972 * True if the the user pod uses a password to authenticate. 1105 * True if the the user pod uses a password to authenticate.
973 * @type {bool} 1106 * @type {bool}
974 */ 1107 */
975 get isAuthTypePassword() { 1108 get isAuthTypePassword() {
976 return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD; 1109 return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD ||
1110 this.authType_ == AUTH_TYPE.FORCE_OFFLINE_PASSWORD;
977 }, 1111 },
978 1112
979 /** 1113 /**
980 * True if the the user pod uses a user click to authenticate. 1114 * True if the the user pod uses a user click to authenticate.
981 * @type {bool} 1115 * @type {bool}
982 */ 1116 */
983 get isAuthTypeUserClick() { 1117 get isAuthTypeUserClick() {
984 return this.authType_ == AUTH_TYPE.USER_CLICK; 1118 return this.authType_ == AUTH_TYPE.USER_CLICK;
985 }, 1119 },
986 1120
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 pod.customIconElement.setIconAsResourceUrl(icon.resourceUrl); 2326 pod.customIconElement.setIconAsResourceUrl(icon.resourceUrl);
2193 } else if (icon.data) { 2327 } else if (icon.data) {
2194 pod.customIconElement.setIconAsImageSet(icon.data); 2328 pod.customIconElement.setIconAsImageSet(icon.data);
2195 } else { 2329 } else {
2196 return; 2330 return;
2197 } 2331 }
2198 2332
2199 pod.customIconElement.setSize(icon.size || {width: 0, height: 0}); 2333 pod.customIconElement.setSize(icon.size || {width: 0, height: 0});
2200 pod.customIconElement.setAnimation(icon.animation || null); 2334 pod.customIconElement.setAnimation(icon.animation || null);
2201 pod.customIconElement.setOpacity(icon.opacity || 100); 2335 pod.customIconElement.setOpacity(icon.opacity || 100);
2336 pod.customIconElement.setInteractive(
2337 icon.hardlockOnClick,
2338 this.hardlockUserPod_.bind(this, username));
2202 pod.customIconElement.show(); 2339 pod.customIconElement.show();
2203 // This has to be called after |show| in case the tooltip should be shown 2340 // This has to be called after |show| in case the tooltip should be shown
2204 // immediatelly. 2341 // immediatelly.
2205 pod.customIconElement.setTooltip( 2342 pod.customIconElement.setTooltip(
2206 icon.tooltip || {text: '', autoshow: false}); 2343 icon.tooltip || {text: '', autoshow: false});
2207 }, 2344 },
2208 2345
2209 /** 2346 /**
2347 * Hard-locks user pod for the user. If user pod is hard-locked, it can be
2348 * only unlocked using password, and the authentication type cannot be
2349 * changed.
2350 * @param {!string} username The user's username.
2351 * @private
2352 */
2353 hardlockUserPod_: function(username) {
2354 chrome.send('hardlockPod', [username]);
2355 },
2356
2357 /**
2210 * Hides the custom icon in the user pod added by showUserPodCustomIcon(). 2358 * Hides the custom icon in the user pod added by showUserPodCustomIcon().
2211 * @param {string} username Username of pod to remove button 2359 * @param {string} username Username of pod to remove button
2212 */ 2360 */
2213 hideUserPodCustomIcon: function(username) { 2361 hideUserPodCustomIcon: function(username) {
2214 var pod = this.getPodWithUsername_(username); 2362 var pod = this.getPodWithUsername_(username);
2215 if (pod == null) { 2363 if (pod == null) {
2216 console.error('Unable to hide user pod button for ' + username + 2364 console.error('Unable to hide user pod button for ' + username +
2217 ': user pod not found.'); 2365 ': user pod not found.');
2218 return; 2366 return;
2219 } 2367 }
2220 2368
2221 pod.customIconElement.hide(); 2369 pod.customIconElement.fadeOut();
2222 }, 2370 },
2223 2371
2224 /** 2372 /**
2225 * Sets the authentication type used to authenticate the user. 2373 * Sets the authentication type used to authenticate the user.
2226 * @param {string} username Username of selected user 2374 * @param {string} username Username of selected user
2227 * @param {number} authType Authentication type, must be one of the 2375 * @param {number} authType Authentication type, must be one of the
2228 * values listed in AUTH_TYPE enum. 2376 * values listed in AUTH_TYPE enum.
2229 * @param {string} value The initial value to use for authentication. 2377 * @param {string} value The initial value to use for authentication.
2230 */ 2378 */
2231 setAuthType: function(username, authType, value) { 2379 setAuthType: function(username, authType, value) {
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
2856 if (pod && pod.multiProfilesPolicyApplied) { 3004 if (pod && pod.multiProfilesPolicyApplied) {
2857 pod.userTypeBubbleElement.classList.remove('bubble-shown'); 3005 pod.userTypeBubbleElement.classList.remove('bubble-shown');
2858 } 3006 }
2859 } 3007 }
2860 }; 3008 };
2861 3009
2862 return { 3010 return {
2863 PodRow: PodRow 3011 PodRow: PodRow
2864 }; 3012 };
2865 }); 3013 });
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