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

Side by Side Diff: chrome/browser/resources/chromeos/login/user_pod_row.js

Issue 158833003: Represent kiosk apps as user pods instead of menu items. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: launch button, added kiosk error bubble Created 6 years, 10 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 19 matching lines...) Expand all
30 var MAX_NUMBER_OF_COLUMNS = 6; 30 var MAX_NUMBER_OF_COLUMNS = 6;
31 31
32 /** 32 /**
33 * Maximal number of rows if sign-in banner is displayed alonside. 33 * Maximal number of rows if sign-in banner is displayed alonside.
34 * @type {number} 34 * @type {number}
35 * @const 35 * @const
36 */ 36 */
37 var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2; 37 var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2;
38 38
39 /** 39 /**
40 * Variables used for pod placement processing. 40 * Variables used for pod placement processing. Width and height should be
41 * Width and height should be synced with computed CSS sizes of pods. 41 * synced with computed CSS sizes of pods.
42 */ 42 */
43 var POD_WIDTH = 180; 43 var POD_WIDTH = 180;
44 var POD_HEIGHT = 217; 44 var POD_HEIGHT = 217;
45 var POD_ROW_PADDING = 10; 45 var POD_ROW_PADDING = 10;
46 46
47 /** 47 /**
48 * Whether to preselect the first pod automatically on login screen. 48 * Whether to preselect the first pod automatically on login screen.
49 * @type {boolean} 49 * @type {boolean}
50 * @const 50 * @const
51 */ 51 */
(...skipping 23 matching lines...) Expand all
75 POD_INPUT: 1, // Password input fields (and whole pods themselves). 75 POD_INPUT: 1, // Password input fields (and whole pods themselves).
76 HEADER_BAR: 2, // Buttons on the header bar (Shutdown, Add User). 76 HEADER_BAR: 2, // Buttons on the header bar (Shutdown, Add User).
77 ACTION_BOX: 3, // Action box buttons. 77 ACTION_BOX: 3, // Action box buttons.
78 PAD_MENU_ITEM: 4 // User pad menu items (Remove this user). 78 PAD_MENU_ITEM: 4 // User pad menu items (Remove this user).
79 }; 79 };
80 80
81 // Focus and tab order are organized as follows: 81 // Focus and tab order are organized as follows:
82 // 82 //
83 // (1) all user pods have tab index 1 so they are traversed first; 83 // (1) all user pods have tab index 1 so they are traversed first;
84 // (2) when a user pod is activated, its tab index is set to -1 and its 84 // (2) when a user pod is activated, its tab index is set to -1 and its
85 // main input field gets focus and tab index 1; 85 // main input field gets focus and tab index 1;
86 // (3) buttons on the header bar have tab index 2 so they follow user pods; 86 // (3) buttons on the header bar have tab index 2 so they follow user pods;
87 // (4) Action box buttons have tab index 3 and follow header bar buttons; 87 // (4) Action box buttons have tab index 3 and follow header bar buttons;
88 // (5) lastly, focus jumps to the Status Area and back to user pods. 88 // (5) lastly, focus jumps to the Status Area and back to user pods.
89 // 89 //
90 // 'Focus' event is handled by a capture handler for the whole document 90 // 'Focus' event is handled by a capture handler for the whole document
91 // and in some cases 'mousedown' event handlers are used instead of 'click' 91 // and in some cases 'mousedown' event handlers are used instead of 'click'
92 // handlers where it's necessary to prevent 'focus' event from being fired. 92 // handlers where it's necessary to prevent 'focus' event from being fired.
93 93
94 /** 94 /**
95 * Helper function to remove a class from given element. 95 * Helper function to remove a class from given element.
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 251
252 /** 252 /**
253 * Gets Caps Lock hint image. 253 * Gets Caps Lock hint image.
254 * @type {!HTMLImageElement} 254 * @type {!HTMLImageElement}
255 */ 255 */
256 get capslockHintElement() { 256 get capslockHintElement() {
257 return this.querySelector('.capslock-hint'); 257 return this.querySelector('.capslock-hint');
258 }, 258 },
259 259
260 /** 260 /**
261 * Gets user signin button. 261 * Gets user sign in button.
262 * @type {!HTMLInputElement} 262 * @type {!HTMLButtonElement}
263 */ 263 */
264 get signinButtonElement() { 264 get signinButtonElement() {
265 return this.querySelector('.signin-button'); 265 return this.querySelector('.signin-button');
266 }, 266 },
267 267
268 /** 268 /**
269 * Gets launch app button.
270 * @type {!HTMLButtonElement}
271 */
272 get launchAppButtonElement() {
273 return this.querySelector('.launch-app-button');
274 },
275
276 /**
269 * Gets action box area. 277 * Gets action box area.
270 * @type {!HTMLInputElement} 278 * @type {!HTMLInputElement}
271 */ 279 */
272 get actionBoxAreaElement() { 280 get actionBoxAreaElement() {
273 return this.querySelector('.action-box-area'); 281 return this.querySelector('.action-box-area');
274 }, 282 },
275 283
276 /** 284 /**
277 * Gets user type icon area. 285 * Gets user type icon area.
278 * @type {!HTMLDivElement} 286 * @type {!HTMLDivElement}
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 364
357 /** 365 /**
358 * Gets the locked user indicator box. 366 * Gets the locked user indicator box.
359 * @type {!HTMLInputElement} 367 * @type {!HTMLInputElement}
360 */ 368 */
361 get lockedIndicatorElement() { 369 get lockedIndicatorElement() {
362 return this.querySelector('.locked-indicator'); 370 return this.querySelector('.locked-indicator');
363 }, 371 },
364 372
365 /** 373 /**
366 * Gets the custom button. This button is normally hidden, but can be 374 * Gets the custom button. This button is normally hidden, but can be shown
367 * shown using the chrome.screenlockPrivate API. 375 * using the chrome.screenlockPrivate API.
368 * @type {!HTMLInputElement} 376 * @type {!HTMLInputElement}
369 */ 377 */
370 get customButton() { 378 get customButton() {
371 return this.querySelector('.custom-button'); 379 return this.querySelector('.custom-button');
372 }, 380 },
373 381
374 /** 382 /**
375 * Updates the user pod element. 383 * Updates the user pod element.
376 */ 384 */
377 update: function() { 385 update: function() {
378 this.imageElement.src = 'chrome://userimage/' + this.user.username + 386 this.imageElement.src = 'chrome://userimage/' + this.user.username +
379 '?id=' + UserPod.userImageSalt_[this.user.username]; 387 '?id=' + UserPod.userImageSalt_[this.user.username];
380 388
381 this.nameElement.textContent = this.user_.displayName; 389 this.nameElement.textContent = this.user_.displayName;
382 this.signedInIndicatorElement.hidden = !this.user_.signedIn; 390 this.signedInIndicatorElement.hidden = !this.user_.signedIn;
383 391
384 var forceOnlineSignin = this.forceOnlineSignin; 392 var forceOnlineSignin = this.forceOnlineSignin;
385 this.passwordElement.hidden = forceOnlineSignin; 393 this.passwordElement.hidden = forceOnlineSignin;
386 this.signinButtonElement.hidden = !forceOnlineSignin; 394 this.signinButtonElement.hidden = !forceOnlineSignin;
387 395
388 this.updateActionBoxArea(); 396 this.updateActionBoxArea();
389 397
390 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF( 398 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
391 'passwordFieldAccessibleName', this.user_.emailAddress)); 399 'passwordFieldAccessibleName', this.user_.emailAddress));
392 400
393 this.updateUserTypeIcon(); 401 this.updateUserTypeIcon();
394 }, 402 },
395 403
396 updateActionBoxArea: function() { 404 updateActionBoxArea: function() {
397 this.actionBoxAreaElement.hidden = this.user_.publicAccount; 405 if (this.user_.publicAccount || this.user_.isApp) {
406 this.actionBoxAreaElement.hidden = true;
407 return;
408 }
409
410 this.actionBoxAreaElement.hidden = false;
398 this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove; 411 this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;
399 412
400 this.actionBoxAreaElement.setAttribute( 413 this.actionBoxAreaElement.setAttribute(
401 'aria-label', loadTimeData.getStringF( 414 'aria-label', loadTimeData.getStringF(
402 'podMenuButtonAccessibleName', this.user_.emailAddress)); 415 'podMenuButtonAccessibleName', this.user_.emailAddress));
403 this.actionBoxMenuRemoveElement.setAttribute( 416 this.actionBoxMenuRemoveElement.setAttribute(
404 'aria-label', loadTimeData.getString( 417 'aria-label', loadTimeData.getString(
405 'podMenuRemoveItemAccessibleName')); 418 'podMenuRemoveItemAccessibleName'));
406 this.actionBoxMenuTitleNameElement.textContent = this.user_.isOwner ? 419 this.actionBoxMenuTitleNameElement.textContent = this.user_.isOwner ?
407 loadTimeData.getStringF('ownerUserPattern', this.user_.displayName) : 420 loadTimeData.getStringF('ownerUserPattern', this.user_.displayName) :
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // Move tabIndex from the whole pod to the main input. 546 // Move tabIndex from the whole pod to the main input.
534 this.tabIndex = -1; 547 this.tabIndex = -1;
535 this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT; 548 this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
536 this.mainInput.focus(); 549 this.mainInput.focus();
537 }, 550 },
538 551
539 /** 552 /**
540 * Activates the pod. 553 * Activates the pod.
541 * @return {boolean} True if activated successfully. 554 * @return {boolean} True if activated successfully.
542 */ 555 */
543 activate: function() { 556 activate: function(e) {
544 if (!this.signinButtonElement.hidden) { 557 if (this.forceOnlineSignin) {
545 this.showSigninUI(); 558 this.showSigninUI();
546 } else if (!this.passwordElement.value) { 559 } else if (!this.passwordElement.value) {
547 return false; 560 return false;
548 } else { 561 } else {
549 Oobe.disableSigninUI(); 562 Oobe.disableSigninUI();
550 chrome.send('authenticateUser', 563 chrome.send('authenticateUser',
551 [this.user.username, this.passwordElement.value]); 564 [this.user.username, this.passwordElement.value]);
552 } 565 }
553 566
554 return true; 567 return true;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 }, 724 },
712 725
713 /** 726 /**
714 * Handles click event on a user pod. 727 * Handles click event on a user pod.
715 * @param {Event} e Click event. 728 * @param {Event} e Click event.
716 */ 729 */
717 handleClickOnPod_: function(e) { 730 handleClickOnPod_: function(e) {
718 if (this.parentNode.disabled) 731 if (this.parentNode.disabled)
719 return; 732 return;
720 733
721 if (!this.signinButtonElement.hidden && !this.isActionBoxMenuActive) { 734 if (this.forceOnlineSignin && !this.isActionBoxMenuActive) {
722 this.showSigninUI(); 735 this.showSigninUI();
723 // Prevent default so that we don't trigger 'focus' event. 736 // Prevent default so that we don't trigger 'focus' event.
724 e.preventDefault(); 737 e.preventDefault();
725 } 738 }
726 }, 739 },
727 740
728 /** 741 /**
729 * Called when the custom button is clicked. 742 * Called when the custom button is clicked.
730 */ 743 */
731 handleCustomButtonClick_: function() { 744 handleCustomButtonClick_: function() {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 873
861 /** @override */ 874 /** @override */
862 reset: function(takeFocus) { 875 reset: function(takeFocus) {
863 if (!takeFocus) 876 if (!takeFocus)
864 this.expanded = false; 877 this.expanded = false;
865 this.enterButtonElement.disabled = false; 878 this.enterButtonElement.disabled = false;
866 UserPod.prototype.reset.call(this, takeFocus); 879 UserPod.prototype.reset.call(this, takeFocus);
867 }, 880 },
868 881
869 /** @override */ 882 /** @override */
870 activate: function() { 883 activate: function(e) {
871 this.expanded = true; 884 this.expanded = true;
872 this.focusInput(); 885 this.focusInput();
873 return true; 886 return true;
874 }, 887 },
875 888
876 /** @override */ 889 /** @override */
877 handleClickOnPod_: function(e) { 890 handleClickOnPod_: function(e) {
878 if (this.parentNode.disabled) 891 if (this.parentNode.disabled)
879 return; 892 return;
880 893
881 this.parentNode.focusPod(this); 894 this.parentNode.focusPod(this);
882 this.parentNode.activatedPod = this; 895 this.parentNode.activatedPod = this;
883 // Prevent default so that we don't trigger 'focus' event. 896 // Prevent default so that we don't trigger 'focus' event.
884 e.preventDefault(); 897 e.preventDefault();
885 }, 898 },
886 899
887 /** 900 /**
888 * Handle mouse and keyboard events for the learn more button. 901 * Handle mouse and keyboard events for the learn more button. Triggering
889 * Triggering the button causes information about public sessions to be 902 * the button causes information about public sessions to be shown.
890 * shown.
891 * @param {Event} event Mouse or keyboard event. 903 * @param {Event} event Mouse or keyboard event.
892 */ 904 */
893 handleLearnMoreEvent: function(event) { 905 handleLearnMoreEvent: function(event) {
894 switch (event.type) { 906 switch (event.type) {
895 // Show informaton on left click. Let any other clicks propagate. 907 // Show informaton on left click. Let any other clicks propagate.
896 case 'click': 908 case 'click':
897 if (event.button != 0) 909 if (event.button != 0)
898 return; 910 return;
899 break; 911 break;
900 // Show informaton when <Return> or <Space> is pressed. Let any other 912 // Show informaton when <Return> or <Space> is pressed. Let any other
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 990
979 /** @override */ 991 /** @override */
980 reset: function(takeFocus) { 992 reset: function(takeFocus) {
981 // Always display the user's name for unfocused pods. 993 // Always display the user's name for unfocused pods.
982 if (!takeFocus) 994 if (!takeFocus)
983 this.nameElement.hidden = false; 995 this.nameElement.hidden = false;
984 UserPod.prototype.reset.call(this, takeFocus); 996 UserPod.prototype.reset.call(this, takeFocus);
985 }, 997 },
986 998
987 /** @override */ 999 /** @override */
988 activate: function() { 1000 activate: function(e) {
989 if (this.passwordElement.hidden) { 1001 if (this.passwordElement.hidden) {
990 Oobe.launchUser(this.user.emailAddress, this.user.displayName); 1002 Oobe.launchUser(this.user.emailAddress, this.user.displayName);
991 } else if (!this.passwordElement.value) { 1003 } else if (!this.passwordElement.value) {
992 return false; 1004 return false;
993 } else { 1005 } else {
994 chrome.send('authenticatedLaunchUser', 1006 chrome.send('authenticatedLaunchUser',
995 [this.user.emailAddress, 1007 [this.user.emailAddress,
996 this.user.displayName, 1008 this.user.displayName,
997 this.passwordElement.value]); 1009 this.passwordElement.value]);
998 } 1010 }
999 this.passwordElement.value = ''; 1011 this.passwordElement.value = '';
1000 return true; 1012 return true;
1001 }, 1013 },
1002 1014
1003 /** @override */ 1015 /** @override */
1004 handleClickOnPod_: function(e) { 1016 handleClickOnPod_: function(e) {
1005 if (this.parentNode.disabled) 1017 if (this.parentNode.disabled)
1006 return; 1018 return;
1007 1019
1008 Oobe.clearErrors(); 1020 Oobe.clearErrors();
1009 this.parentNode.lastFocusedPod_ = this; 1021 this.parentNode.lastFocusedPod_ = this;
1010 1022
1011 // If this is an unlocked pod, then open a browser window. Otherwise 1023 // If this is an unlocked pod, then open a browser window. Otherwise
1012 // just activate the pod and show the password field. 1024 // just activate the pod and show the password field.
1013 if (!this.user.needsSignin && !this.isActionBoxMenuActive) 1025 if (!this.user.needsSignin && !this.isActionBoxMenuActive)
1014 this.activate(); 1026 this.activate(e);
1015 }, 1027 },
1016 1028
1017 /** @override */ 1029 /** @override */
1018 handleRemoveUserConfirmationClick_: function(e) { 1030 handleRemoveUserConfirmationClick_: function(e) {
1019 chrome.send('removeUser', [this.user.profilePath]); 1031 chrome.send('removeUser', [this.user.profilePath]);
1020 }, 1032 },
1021 }; 1033 };
1022 1034
1023 /** 1035 /**
1036 * Creates a user pod that represents kiosk app.
1037 * @constructor
1038 * @extends {UserPod}
1039 */
1040 var AppUserPod = cr.ui.define(function() {
1041 var node = UserPod();
1042 return node;
1043 });
1044
1045 AppUserPod.prototype = {
1046 __proto__: UserPod.prototype,
1047
1048 /** @override */
1049 decorate: function() {
1050 UserPod.prototype.decorate.call(this);
1051 this.launchAppButtonElement.addEventListener('click',
1052 this.activate.bind(this));
1053 },
1054
1055 /** @override */
1056 update: function() {
1057 this.imageElement.src = this.user.iconUrl;
1058 this.imageElement.alt = this.user.label;
1059 this.passwordElement.hidden = true;
1060 this.signinButtonElement.hidden = true;
1061 this.launchAppButtonElement.hidden = false;
1062 this.signedInIndicatorElement.hidden = true;
1063 this.nameElement.textContent = this.user.label;
1064 },
1065
1066 /** @override */
1067 get mainInput() {
1068 return this.launchAppButtonElement;
1069 },
1070
1071 /** @override */
1072 focusInput: function() {
1073 this.signinButtonElement.hidden = true;
1074 this.launchAppButtonElement.hidden = false;
1075 this.passwordElement.hidden = true;
1076
1077 // Move tabIndex from the whole pod to the main input.
1078 this.tabIndex = -1;
1079 this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
1080 this.mainInput.focus();
1081 },
1082
1083 /** @override */
1084 get forceOnlineSignin() {
1085 return false;
1086 },
1087
1088 /** @override */
1089 activate: function(e) {
1090 var diagnosticMode = e.originalEvent && e.originalEvent.ctrlKey;
1091 this.launchApp_(this.user, diagnosticMode);
1092 return true;
1093 },
1094
1095 /** @override */
1096 handleClickOnPod_: function(e) {
1097 if (this.parentNode.disabled)
1098 return;
1099
1100 Oobe.clearErrors();
1101 this.parentNode.lastFocusedPod_ = this;
1102
1103 // If this is an unlocked pod, then open a browser window. Otherwise
1104 // just activate the pod and show the password field.
1105 if (!this.user.needsSignin && !this.isActionBoxMenuActive)
1106 this.activate(e);
1107 },
1108
1109 /**
1110 * Launch the app. If |diagnosticMode| is true, ask user to confirm.
1111 * @param {Object} app App data.
1112 * @param {boolean} diagnosticMode Whether to run the app in diagnostic
1113 * mode.
1114 */
1115 launchApp_: function(app, diagnosticMode) {
1116 if (!diagnosticMode) {
1117 chrome.send('launchKioskApp', [app.id, false]);
1118 return;
1119 }
1120
1121 if (!this.confirmDiagnosticMode_) {
1122 this.confirmDiagnosticMode_ =
1123 new cr.ui.dialogs.ConfirmDialog(document.body);
1124 this.confirmDiagnosticMode_.setOkLabel(
1125 loadTimeData.getString('confirmKioskAppDiagnosticModeYes'));
1126 this.confirmDiagnosticMode_.setCancelLabel(
1127 loadTimeData.getString('confirmKioskAppDiagnosticModeNo'));
1128 }
1129
1130 this.confirmDiagnosticMode_.show(
1131 loadTimeData.getStringF('confirmKioskAppDiagnosticModeFormat',
1132 app.label),
1133 function() {
1134 chrome.send('launchKioskApp', [app.id, true]);
1135 });
1136 },
1137 };
1138
1139 /**
1024 * Creates a new pod row element. 1140 * Creates a new pod row element.
1025 * @constructor 1141 * @constructor
1026 * @extends {HTMLDivElement} 1142 * @extends {HTMLDivElement}
1027 */ 1143 */
1028 var PodRow = cr.ui.define('podrow'); 1144 var PodRow = cr.ui.define('podrow');
1029 1145
1030 PodRow.prototype = { 1146 PodRow.prototype = {
1031 __proto__: HTMLDivElement.prototype, 1147 __proto__: HTMLDivElement.prototype,
1032 1148
1033 // Whether this user pod row is shown for the first time. 1149 // Whether this user pod row is shown for the first time.
1034 firstShown_: true, 1150 firstShown_: true,
1035 1151
1036 // True if inside focusPod(). 1152 // True if inside focusPod().
1037 insideFocusPod_: false, 1153 insideFocusPod_: false,
1038 1154
1039 // Focused pod. 1155 // Focused pod.
1040 focusedPod_: undefined, 1156 focusedPod_: undefined,
1041 1157
1042 // Activated pod, i.e. the pod of current login attempt. 1158 // Activated pod, i.e. the pod of current login attempt.
1043 activatedPod_: undefined, 1159 activatedPod_: undefined,
1044 1160
1045 // Pod that was most recently focused, if any. 1161 // Pod that was most recently focused, if any.
1046 lastFocusedPod_: undefined, 1162 lastFocusedPod_: undefined,
1047 1163
1048 // Pods whose initial images haven't been loaded yet. 1164 // Pods whose initial images haven't been loaded yet.
1049 podsWithPendingImages_: [], 1165 podsWithPendingImages_: [],
1050 1166
1167 // Whether pod creation is animated.
1168 user_add_is_animated_: false,
1169
1170 // Array of apps that are shown in addition to other user pods.
1171 apps_: [],
1172
1173 // Array of users that are shown (public/supervised/regular).
1174 users_: [],
1175
1051 /** @override */ 1176 /** @override */
1052 decorate: function() { 1177 decorate: function() {
1053 // Event listeners that are installed for the time period during which 1178 // Event listeners that are installed for the time period during which
1054 // the element is visible. 1179 // the element is visible.
1055 this.listeners_ = { 1180 this.listeners_ = {
1056 focus: [this.handleFocus_.bind(this), true /* useCapture */], 1181 focus: [this.handleFocus_.bind(this), true /* useCapture */],
1057 click: [this.handleClick_.bind(this), true], 1182 click: [this.handleClick_.bind(this), true],
1058 mousemove: [this.handleMouseMove_.bind(this), false], 1183 mousemove: [this.handleMouseMove_.bind(this), false],
1059 keydown: [this.handleKeyDown.bind(this), false] 1184 keydown: [this.handleKeyDown.bind(this), false]
1060 }; 1185 };
(...skipping 12 matching lines...) Expand all
1073 * @type {boolean} 1198 * @type {boolean}
1074 */ 1199 */
1075 get isSinglePod() { 1200 get isSinglePod() {
1076 return this.children.length == 1; 1201 return this.children.length == 1;
1077 }, 1202 },
1078 1203
1079 /** 1204 /**
1080 * Returns pod with the given username (null if there is no such pod). 1205 * Returns pod with the given username (null if there is no such pod).
1081 * @param {string} username Username to be matched. 1206 * @param {string} username Username to be matched.
1082 * @return {Object} Pod with the given username. null if pod hasn't been 1207 * @return {Object} Pod with the given username. null if pod hasn't been
1083 * found. 1208 * found.
xiyuan 2014/02/10 21:15:56 nit: should 4-space indent from @ at previous line
Nikita (slow) 2014/02/12 17:19:25 Done.
1084 */ 1209 */
1085 getPodWithUsername_: function(username) { 1210 getPodWithUsername_: function(username) {
1086 for (var i = 0, pod; pod = this.pods[i]; ++i) { 1211 for (var i = 0, pod; pod = this.pods[i]; ++i) {
1087 if (pod.user.username == username) 1212 if (pod.user.username == username)
1088 return pod; 1213 return pod;
1089 } 1214 }
1090 return null; 1215 return null;
1091 }, 1216 },
1092 1217
1093 /** 1218 /**
1094 * True if the the pod row is disabled (handles no user interaction). 1219 * True if the the pod row is disabled (handles no user interaction).
1095 * @type {boolean} 1220 * @type {boolean}
1096 */ 1221 */
1097 disabled_: false, 1222 disabled_: false,
1098 get disabled() { 1223 get disabled() {
1099 return this.disabled_; 1224 return this.disabled_;
1100 }, 1225 },
1101 set disabled(value) { 1226 set disabled(value) {
1102 this.disabled_ = value; 1227 this.disabled_ = value;
1103 var controls = this.querySelectorAll('button,input'); 1228 var controls = this.querySelectorAll('button,input');
1104 for (var i = 0, control; control = controls[i]; ++i) { 1229 for (var i = 0, control; control = controls[i]; ++i) {
1105 control.disabled = value; 1230 control.disabled = value;
1106 } 1231 }
1107 }, 1232 },
1108 1233
1109 /** 1234 /**
1110 * Creates a user pod from given email. 1235 * Creates a user pod from given email.
1111 * @param {string} email User's email. 1236 * @param {!Object} user User info dictionary.
1112 */ 1237 */
1113 createUserPod: function(user) { 1238 createUserPod: function(user) {
1114 var userPod; 1239 var userPod;
1115 if (user.isDesktopUser) 1240 if (user.isDesktopUser)
1116 userPod = new DesktopUserPod({user: user}); 1241 userPod = new DesktopUserPod({user: user});
1117 else if (user.publicAccount) 1242 else if (user.publicAccount)
1118 userPod = new PublicAccountUserPod({user: user}); 1243 userPod = new PublicAccountUserPod({user: user});
1244 else if (user.isApp)
1245 userPod = new AppUserPod({user: user});
1119 else 1246 else
1120 userPod = new UserPod({user: user}); 1247 userPod = new UserPod({user: user});
1121 1248
1122 userPod.hidden = false; 1249 userPod.hidden = false;
1123 return userPod; 1250 return userPod;
1124 }, 1251 },
1125 1252
1126 /** 1253 /**
1127 * Add an existing user pod to this pod row. 1254 * Add an existing user pod to this pod row.
1128 * @param {!Object} user User info dictionary. 1255 * @param {!Object} user User info dictionary.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 pod.classList.add('zoom'); 1322 pod.classList.add('zoom');
1196 } 1323 }
1197 }, 1324 },
1198 1325
1199 /** 1326 /**
1200 * Populates pod row with given existing users and start init animation. 1327 * Populates pod row with given existing users and start init animation.
1201 * @param {array} users Array of existing user emails. 1328 * @param {array} users Array of existing user emails.
1202 * @param {boolean} animated Whether to use init animation. 1329 * @param {boolean} animated Whether to use init animation.
1203 */ 1330 */
1204 loadPods: function(users, animated) { 1331 loadPods: function(users, animated) {
1332 this.users_ = users;
1333 this.user_add_is_animated_ = animated;
1334
1335 this.rebuildPods();
1336 },
1337
1338 /**
1339 * Rebuilds pod row using users_ and apps_ that were previously set or
1340 * updated.
1341 */
1342 rebuildPods: function() {
1205 // Clear existing pods. 1343 // Clear existing pods.
1206 this.innerHTML = ''; 1344 this.innerHTML = '';
1207 this.focusedPod_ = undefined; 1345 this.focusedPod_ = undefined;
1208 this.activatedPod_ = undefined; 1346 this.activatedPod_ = undefined;
1209 this.lastFocusedPod_ = undefined; 1347 this.lastFocusedPod_ = undefined;
1210 1348
1211 // Switch off animation 1349 // Switch off animation
1212 Oobe.getInstance().toggleClass('flying-pods', false); 1350 Oobe.getInstance().toggleClass('flying-pods', false);
1213 1351
1214 // Populate the pod row. 1352 // Populate the pod row.
1215 for (var i = 0; i < users.length; ++i) { 1353 for (var i = 0; i < this.users_.length; ++i)
1216 this.addUserPod(users[i], animated); 1354 this.addUserPod(this.users_[i], this.user_add_is_animated_);
1217 } 1355
1218 for (var i = 0, pod; pod = this.pods[i]; ++i) { 1356 for (var i = 0, pod; pod = this.pods[i]; ++i)
1219 this.podsWithPendingImages_.push(pod); 1357 this.podsWithPendingImages_.push(pod);
1220 } 1358
1359 // TODO: Edge case handling when kiosk apps are not fitting.
1360 for (var i = 0; i < this.apps_.length; ++i)
1361 this.addUserPod(this.apps_[i], this.user_add_is_animated_);
1362
1221 // Make sure we eventually show the pod row, even if some image is stuck. 1363 // Make sure we eventually show the pod row, even if some image is stuck.
1222 setTimeout(function() { 1364 setTimeout(function() {
1223 $('pod-row').classList.remove('images-loading'); 1365 $('pod-row').classList.remove('images-loading');
1224 }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS); 1366 }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS);
1225 1367
1226 this.placePods_(); 1368 this.placePods_();
1227 1369
1228 // Without timeout changes in pods positions will be animated even though 1370 // Without timeout changes in pods positions will be animated even though
1229 // it happened when 'flying-pods' class was disabled. 1371 // it happened when 'flying-pods' class was disabled.
1230 setTimeout(function() { 1372 setTimeout(function() {
1231 Oobe.getInstance().toggleClass('flying-pods', true); 1373 Oobe.getInstance().toggleClass('flying-pods', true);
1232 }, 0); 1374 }, 0);
1233 1375
1234 this.focusPod(this.preselectedPod); 1376 this.focusPod(this.preselectedPod);
1235 }, 1377 },
1236 1378
1237 /** 1379 /**
1380 * Adds given apps to the pod row.
1381 * @param {array} apps Array of apps.
1382 */
1383 setApps: function(apps) {
1384 this.apps_ = apps;
1385 this.rebuildPods();
1386 chrome.send('kioskAppsLoaded');
1387
1388 // Check whether there's a pending kiosk app error.
1389 window.setTimeout(function() {
1390 chrome.send('checkKioskAppLaunchError');
1391 }, 500);
1392 },
1393
1394 /**
1238 * Shows a button on a user pod with an icon. Clicking on this button 1395 * Shows a button on a user pod with an icon. Clicking on this button
1239 * triggers an event used by the chrome.screenlockPrivate API. 1396 * triggers an event used by the chrome.screenlockPrivate API.
1240 * @param {string} username Username of pod to add button 1397 * @param {string} username Username of pod to add button
1241 * @param {string} iconURL URL of the button icon 1398 * @param {string} iconURL URL of the button icon
1242 */ 1399 */
1243 showUserPodButton: function(username, iconURL) { 1400 showUserPodButton: function(username, iconURL) {
1244 var pod = this.getPodWithUsername_(username); 1401 var pod = this.getPodWithUsername_(username);
1245 if (pod == null) { 1402 if (pod == null) {
1246 console.error('Unable to show user pod button for ' + username + 1403 console.error('Unable to show user pod button for ' + username +
1247 ': user pod not found.'); 1404 ': user pod not found.');
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 * @return {boolean} Pod focus status. 1527 * @return {boolean} Pod focus status.
1371 */ 1528 */
1372 isFocused: function(pod) { 1529 isFocused: function(pod) {
1373 return this.focusedPod_ == pod; 1530 return this.focusedPod_ == pod;
1374 }, 1531 },
1375 1532
1376 /** 1533 /**
1377 * Focuses a given user pod or clear focus when given null. 1534 * Focuses a given user pod or clear focus when given null.
1378 * @param {UserPod=} podToFocus User pod to focus (undefined clears focus). 1535 * @param {UserPod=} podToFocus User pod to focus (undefined clears focus).
1379 * @param {boolean=} opt_force If true, forces focus update even when 1536 * @param {boolean=} opt_force If true, forces focus update even when
1380 * podToFocus is already focused. 1537 * podToFocus is already focused.
xiyuan 2014/02/10 21:15:56 nit: 4-space indent from @
Nikita (slow) 2014/02/12 17:19:25 Done.
1381 */ 1538 */
1382 focusPod: function(podToFocus, opt_force) { 1539 focusPod: function(podToFocus, opt_force) {
1383 if (this.isFocused(podToFocus) && !opt_force) { 1540 if (this.isFocused(podToFocus) && !opt_force) {
1384 this.keyboardActivated_ = false; 1541 this.keyboardActivated_ = false;
1385 return; 1542 return;
1386 } 1543 }
1387 1544
1388 // Make sure that we don't focus pods that are not allowed to be focused. 1545 // Make sure that we don't focus pods that are not allowed to be focused.
1389 // TODO(nkostylev): Fix various keyboard focus related issues caused 1546 // TODO(nkostylev): Fix various keyboard focus related issues caused
1390 // by this approach. http://crbug.com/339042 1547 // by this approach. http://crbug.com/339042
(...skipping 25 matching lines...) Expand all
1416 if (!this.isFocused(podToFocus)) 1573 if (!this.isFocused(podToFocus))
1417 Oobe.clearErrors(); 1574 Oobe.clearErrors();
1418 1575
1419 var hadFocus = !!this.focusedPod_; 1576 var hadFocus = !!this.focusedPod_;
1420 this.focusedPod_ = podToFocus; 1577 this.focusedPod_ = podToFocus;
1421 if (podToFocus) { 1578 if (podToFocus) {
1422 podToFocus.classList.remove('faded'); 1579 podToFocus.classList.remove('faded');
1423 podToFocus.classList.add('focused'); 1580 podToFocus.classList.add('focused');
1424 podToFocus.reset(true); // Reset and give focus. 1581 podToFocus.reset(true); // Reset and give focus.
1425 // focusPod() automatically loads wallpaper 1582 // focusPod() automatically loads wallpaper
1426 chrome.send('focusPod', [podToFocus.user.username]); 1583 if (!podToFocus.user.isApp)
1584 chrome.send('focusPod', [podToFocus.user.username]);
1427 this.firstShown_ = false; 1585 this.firstShown_ = false;
1428 this.lastFocusedPod_ = podToFocus; 1586 this.lastFocusedPod_ = podToFocus;
1429 } 1587 }
1430 this.insideFocusPod_ = false; 1588 this.insideFocusPod_ = false;
1431 this.keyboardActivated_ = false; 1589 this.keyboardActivated_ = false;
1432 }, 1590 },
1433 1591
1434 /** 1592 /**
1435 * Focuses a given user pod by index or clear focus when given null. 1593 * Focuses a given user pod by index or clear focus when given null.
1436 * @param {int=} podToFocus index of User pod to focus. 1594 * @param {int=} podToFocus index of User pod to focus.
1437 * @param {boolean=} opt_force If true, forces focus update even when 1595 * @param {boolean=} opt_force If true, forces focus update even when
1438 * podToFocus is already focused. 1596 * podToFocus is already focused.
xiyuan 2014/02/10 21:15:56 nit: 4-space indent from @
Nikita (slow) 2014/02/12 17:19:25 Done.
1439 */ 1597 */
1440 focusPodByIndex: function(podToFocus, opt_force) { 1598 focusPodByIndex: function(podToFocus, opt_force) {
1441 if (podToFocus < this.pods.length) 1599 if (podToFocus < this.pods.length)
1442 this.focusPod(this.pods[podToFocus], opt_force); 1600 this.focusPod(this.pods[podToFocus], opt_force);
1443 }, 1601 },
1444 1602
1445 /** 1603 /**
1446 * Resets wallpaper to the last active user's wallpaper, if any. 1604 * Resets wallpaper to the last active user's wallpaper, if any.
1447 */ 1605 */
1448 loadLastWallpaper: function() { 1606 loadLastWallpaper: function() {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 if (this.podsWithPendingImages_.length == 0) { 1915 if (this.podsWithPendingImages_.length == 0) {
1758 this.classList.remove('images-loading'); 1916 this.classList.remove('images-loading');
1759 } 1917 }
1760 } 1918 }
1761 }; 1919 };
1762 1920
1763 return { 1921 return {
1764 PodRow: PodRow 1922 PodRow: PodRow
1765 }; 1923 };
1766 }); 1924 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698