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

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: review + fixes 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
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;
xiyuan 2014/02/12 17:35:04 nit: why remove the indent?
Nikita (slow) 2014/02/13 08:58:02 Done.
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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 this.passwordElement.hidden = forceOnlineSignin; 544 this.passwordElement.hidden = forceOnlineSignin;
532 545
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.
554 * @param {Event} e Event object.
541 * @return {boolean} True if activated successfully. 555 * @return {boolean} True if activated successfully.
542 */ 556 */
543 activate: function() { 557 activate: function(e) {
544 if (!this.signinButtonElement.hidden) { 558 if (this.forceOnlineSignin) {
545 this.showSigninUI(); 559 this.showSigninUI();
546 } else if (!this.passwordElement.value) { 560 } else if (!this.passwordElement.value) {
547 return false; 561 return false;
548 } else { 562 } else {
549 Oobe.disableSigninUI(); 563 Oobe.disableSigninUI();
550 chrome.send('authenticateUser', 564 chrome.send('authenticateUser',
551 [this.user.username, this.passwordElement.value]); 565 [this.user.username, this.passwordElement.value]);
552 } 566 }
553 567
554 return true; 568 return true;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 }, 725 },
712 726
713 /** 727 /**
714 * Handles click event on a user pod. 728 * Handles click event on a user pod.
715 * @param {Event} e Click event. 729 * @param {Event} e Click event.
716 */ 730 */
717 handleClickOnPod_: function(e) { 731 handleClickOnPod_: function(e) {
718 if (this.parentNode.disabled) 732 if (this.parentNode.disabled)
719 return; 733 return;
720 734
721 if (!this.signinButtonElement.hidden && !this.isActionBoxMenuActive) { 735 if (this.forceOnlineSignin && !this.isActionBoxMenuActive) {
722 this.showSigninUI(); 736 this.showSigninUI();
723 // Prevent default so that we don't trigger 'focus' event. 737 // Prevent default so that we don't trigger 'focus' event.
724 e.preventDefault(); 738 e.preventDefault();
725 } 739 }
726 }, 740 },
727 741
728 /** 742 /**
729 * Called when the custom button is clicked. 743 * Called when the custom button is clicked.
730 */ 744 */
731 handleCustomButtonClick_: function() { 745 handleCustomButtonClick_: function() {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 821
808 /** @override */ 822 /** @override */
809 decorate: function() { 823 decorate: function() {
810 UserPod.prototype.decorate.call(this); 824 UserPod.prototype.decorate.call(this);
811 825
812 this.classList.remove('need-password'); 826 this.classList.remove('need-password');
813 this.classList.add('public-account'); 827 this.classList.add('public-account');
814 828
815 this.nameElement.addEventListener('keydown', (function(e) { 829 this.nameElement.addEventListener('keydown', (function(e) {
816 if (e.keyIdentifier == 'Enter') { 830 if (e.keyIdentifier == 'Enter') {
817 this.parentNode.activatedPod = this; 831 this.parentNode.setActivatedPod(this, e);
818 // Stop this keydown event from bubbling up to PodRow handler. 832 // Stop this keydown event from bubbling up to PodRow handler.
819 e.stopPropagation(); 833 e.stopPropagation();
820 // Prevent default so that we don't trigger a 'click' event on the 834 // Prevent default so that we don't trigger a 'click' event on the
821 // newly focused "Enter" button. 835 // newly focused "Enter" button.
822 e.preventDefault(); 836 e.preventDefault();
823 } 837 }
824 }).bind(this)); 838 }).bind(this));
825 839
826 var learnMore = this.querySelector('.learn-more'); 840 var learnMore = this.querySelector('.learn-more');
827 learnMore.addEventListener('mousedown', stopEventPropagation); 841 learnMore.addEventListener('mousedown', stopEventPropagation);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 874
861 /** @override */ 875 /** @override */
862 reset: function(takeFocus) { 876 reset: function(takeFocus) {
863 if (!takeFocus) 877 if (!takeFocus)
864 this.expanded = false; 878 this.expanded = false;
865 this.enterButtonElement.disabled = false; 879 this.enterButtonElement.disabled = false;
866 UserPod.prototype.reset.call(this, takeFocus); 880 UserPod.prototype.reset.call(this, takeFocus);
867 }, 881 },
868 882
869 /** @override */ 883 /** @override */
870 activate: function() { 884 activate: function(e) {
871 this.expanded = true; 885 this.expanded = true;
872 this.focusInput(); 886 this.focusInput();
873 return true; 887 return true;
874 }, 888 },
875 889
876 /** @override */ 890 /** @override */
877 handleClickOnPod_: function(e) { 891 handleClickOnPod_: function(e) {
878 if (this.parentNode.disabled) 892 if (this.parentNode.disabled)
879 return; 893 return;
880 894
881 this.parentNode.focusPod(this); 895 this.parentNode.focusPod(this);
882 this.parentNode.activatedPod = this; 896 this.parentNode.setActivatedPod(this, e);
883 // Prevent default so that we don't trigger 'focus' event. 897 // Prevent default so that we don't trigger 'focus' event.
884 e.preventDefault(); 898 e.preventDefault();
885 }, 899 },
886 900
887 /** 901 /**
888 * Handle mouse and keyboard events for the learn more button. 902 * Handle mouse and keyboard events for the learn more button.
889 * Triggering the button causes information about public sessions to be 903 * Triggering the button causes information about public sessions to be
890 * shown. 904 * shown.
891 * @param {Event} event Mouse or keyboard event. 905 * @param {Event} event Mouse or keyboard event.
892 */ 906 */
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 992
979 /** @override */ 993 /** @override */
980 reset: function(takeFocus) { 994 reset: function(takeFocus) {
981 // Always display the user's name for unfocused pods. 995 // Always display the user's name for unfocused pods.
982 if (!takeFocus) 996 if (!takeFocus)
983 this.nameElement.hidden = false; 997 this.nameElement.hidden = false;
984 UserPod.prototype.reset.call(this, takeFocus); 998 UserPod.prototype.reset.call(this, takeFocus);
985 }, 999 },
986 1000
987 /** @override */ 1001 /** @override */
988 activate: function() { 1002 activate: function(e) {
989 if (this.passwordElement.hidden) { 1003 if (this.passwordElement.hidden) {
990 Oobe.launchUser(this.user.emailAddress, this.user.displayName); 1004 Oobe.launchUser(this.user.emailAddress, this.user.displayName);
991 } else if (!this.passwordElement.value) { 1005 } else if (!this.passwordElement.value) {
992 return false; 1006 return false;
993 } else { 1007 } else {
994 chrome.send('authenticatedLaunchUser', 1008 chrome.send('authenticatedLaunchUser',
995 [this.user.emailAddress, 1009 [this.user.emailAddress,
996 this.user.displayName, 1010 this.user.displayName,
997 this.passwordElement.value]); 1011 this.passwordElement.value]);
998 } 1012 }
999 this.passwordElement.value = ''; 1013 this.passwordElement.value = '';
1000 return true; 1014 return true;
1001 }, 1015 },
1002 1016
1003 /** @override */ 1017 /** @override */
1004 handleClickOnPod_: function(e) { 1018 handleClickOnPod_: function(e) {
1005 if (this.parentNode.disabled) 1019 if (this.parentNode.disabled)
1006 return; 1020 return;
1007 1021
1008 Oobe.clearErrors(); 1022 Oobe.clearErrors();
1009 this.parentNode.lastFocusedPod_ = this; 1023 this.parentNode.lastFocusedPod_ = this;
1010 1024
1011 // If this is an unlocked pod, then open a browser window. Otherwise 1025 // If this is an unlocked pod, then open a browser window. Otherwise
1012 // just activate the pod and show the password field. 1026 // just activate the pod and show the password field.
1013 if (!this.user.needsSignin && !this.isActionBoxMenuActive) 1027 if (!this.user.needsSignin && !this.isActionBoxMenuActive)
1014 this.activate(); 1028 this.activate(e);
1015 }, 1029 },
1016 1030
1017 /** @override */ 1031 /** @override */
1018 handleRemoveUserConfirmationClick_: function(e) { 1032 handleRemoveUserConfirmationClick_: function(e) {
1019 chrome.send('removeUser', [this.user.profilePath]); 1033 chrome.send('removeUser', [this.user.profilePath]);
1020 }, 1034 },
1021 }; 1035 };
1022 1036
1023 /** 1037 /**
1038 * Creates a user pod that represents kiosk app.
1039 * @constructor
1040 * @extends {UserPod}
1041 */
1042 var KioskAppPod = cr.ui.define(function() {
1043 var node = UserPod();
1044 return node;
1045 });
1046
1047 KioskAppPod.prototype = {
1048 __proto__: UserPod.prototype,
1049
1050 /** @override */
1051 decorate: function() {
1052 UserPod.prototype.decorate.call(this);
1053 this.launchAppButtonElement.addEventListener('click',
1054 this.activate.bind(this));
1055 },
1056
1057 /** @override */
1058 update: function() {
1059 this.imageElement.src = this.user.iconUrl;
1060 this.imageElement.alt = this.user.label;
1061 this.passwordElement.hidden = true;
1062 this.signinButtonElement.hidden = true;
1063 this.launchAppButtonElement.hidden = false;
1064 this.signedInIndicatorElement.hidden = true;
1065 this.nameElement.textContent = this.user.label;
1066 },
1067
1068 /** @override */
1069 get mainInput() {
1070 return this.launchAppButtonElement;
1071 },
1072
1073 /** @override */
1074 focusInput: function() {
1075 this.signinButtonElement.hidden = true;
1076 this.launchAppButtonElement.hidden = false;
1077 this.passwordElement.hidden = true;
1078
1079 // Move tabIndex from the whole pod to the main input.
1080 this.tabIndex = -1;
1081 this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
1082 this.mainInput.focus();
1083 },
1084
1085 /** @override */
1086 get forceOnlineSignin() {
1087 return false;
1088 },
1089
1090 /** @override */
1091 activate: function(e) {
1092 var diagnosticMode = e && e.ctrlKey;
1093 this.launchApp_(this.user, diagnosticMode);
1094 return true;
1095 },
1096
1097 /** @override */
1098 handleClickOnPod_: function(e) {
1099 if (this.parentNode.disabled)
1100 return;
1101
1102 Oobe.clearErrors();
1103 this.parentNode.lastFocusedPod_ = this;
1104 this.activate(e);
1105 },
1106
1107 /**
1108 * Launch the app. If |diagnosticMode| is true, ask user to confirm.
1109 * @param {Object} app App data.
1110 * @param {boolean} diagnosticMode Whether to run the app in diagnostic
1111 * mode.
1112 */
1113 launchApp_: function(app, diagnosticMode) {
1114 if (!diagnosticMode) {
1115 chrome.send('launchKioskApp', [app.id, false]);
1116 return;
1117 }
1118
1119 var podRow = $('pod-row');
1120 if (!podRow.confirmDiagnosticMode_) {
1121 podRow.confirmDiagnosticMode_ =
1122 new cr.ui.dialogs.ConfirmDialog(document.body);
1123 podRow.confirmDiagnosticMode_.setOkLabel(
1124 loadTimeData.getString('confirmKioskAppDiagnosticModeYes'));
1125 podRow.confirmDiagnosticMode_.setCancelLabel(
1126 loadTimeData.getString('confirmKioskAppDiagnosticModeNo'));
1127 }
1128
1129 podRow.confirmDiagnosticMode_.show(
1130 loadTimeData.getStringF('confirmKioskAppDiagnosticModeFormat',
1131 app.label),
1132 function() {
1133 chrome.send('launchKioskApp', [app.id, true]);
1134 });
1135 },
1136 };
1137
1138 /**
1024 * Creates a new pod row element. 1139 * Creates a new pod row element.
1025 * @constructor 1140 * @constructor
1026 * @extends {HTMLDivElement} 1141 * @extends {HTMLDivElement}
1027 */ 1142 */
1028 var PodRow = cr.ui.define('podrow'); 1143 var PodRow = cr.ui.define('podrow');
1029 1144
1030 PodRow.prototype = { 1145 PodRow.prototype = {
1031 __proto__: HTMLDivElement.prototype, 1146 __proto__: HTMLDivElement.prototype,
1032 1147
1033 // Whether this user pod row is shown for the first time. 1148 // Whether this user pod row is shown for the first time.
1034 firstShown_: true, 1149 firstShown_: true,
1035 1150
1036 // True if inside focusPod(). 1151 // True if inside focusPod().
1037 insideFocusPod_: false, 1152 insideFocusPod_: false,
1038 1153
1039 // Focused pod. 1154 // Focused pod.
1040 focusedPod_: undefined, 1155 focusedPod_: undefined,
1041 1156
1042 // Activated pod, i.e. the pod of current login attempt. 1157 // Activated pod, i.e. the pod of current login attempt.
1043 activatedPod_: undefined, 1158 activatedPod_: undefined,
1044 1159
1045 // Pod that was most recently focused, if any. 1160 // Pod that was most recently focused, if any.
1046 lastFocusedPod_: undefined, 1161 lastFocusedPod_: undefined,
1047 1162
1048 // Pods whose initial images haven't been loaded yet. 1163 // Pods whose initial images haven't been loaded yet.
1049 podsWithPendingImages_: [], 1164 podsWithPendingImages_: [],
1050 1165
1166 // Whether pod creation is animated.
1167 user_add_is_animated_: false,
1168
1169 // Array of apps that are shown in addition to other user pods.
1170 apps_: [],
1171
1172 // Array of users that are shown (public/supervised/regular).
1173 users_: [],
1174
1051 /** @override */ 1175 /** @override */
1052 decorate: function() { 1176 decorate: function() {
1053 // Event listeners that are installed for the time period during which 1177 // Event listeners that are installed for the time period during which
1054 // the element is visible. 1178 // the element is visible.
1055 this.listeners_ = { 1179 this.listeners_ = {
1056 focus: [this.handleFocus_.bind(this), true /* useCapture */], 1180 focus: [this.handleFocus_.bind(this), true /* useCapture */],
1057 click: [this.handleClick_.bind(this), true], 1181 click: [this.handleClick_.bind(this), true],
1058 mousemove: [this.handleMouseMove_.bind(this), false], 1182 mousemove: [this.handleMouseMove_.bind(this), false],
1059 keydown: [this.handleKeyDown.bind(this), false] 1183 keydown: [this.handleKeyDown.bind(this), false]
1060 }; 1184 };
1061 }, 1185 },
1062 1186
1063 /** 1187 /**
1064 * Returns all the pods in this pod row. 1188 * Returns all the pods in this pod row.
1065 * @type {NodeList} 1189 * @type {NodeList}
1066 */ 1190 */
1067 get pods() { 1191 get pods() {
1068 return Array.prototype.slice.call(this.children); 1192 return Array.prototype.slice.call(this.children);
1069 }, 1193 },
1070 1194
1071 /** 1195 /**
1072 * Return true if user pod row has only single user pod in it. 1196 * Return true if user pod row has only single user pod in it.
1073 * @type {boolean} 1197 * @type {boolean}
1074 */ 1198 */
1075 get isSinglePod() { 1199 get isSinglePod() {
1076 return this.children.length == 1; 1200 return this.children.length == 1;
1077 }, 1201 },
1078 1202
1079 /** 1203 /**
1204 * Returns pod with the given app id.
1205 * @param {!string} app_id Application id to be matched.
1206 * @return {Object} Pod with the given app id. null if pod hasn't been
1207 * found.
1208 */
1209 getPodWithAppId_: function(app_id) {
1210 for (var i = 0, pod; pod = this.pods[i]; ++i) {
1211 if (pod.user.isApp && pod.user.id == app_id)
1212 return pod;
1213 }
1214 return null;
1215 },
1216
1217 /**
1080 * Returns pod with the given username (null if there is no such pod). 1218 * Returns pod with the given username (null if there is no such pod).
1081 * @param {string} username Username to be matched. 1219 * @param {string} username Username to be matched.
1082 * @return {Object} Pod with the given username. null if pod hasn't been 1220 * @return {Object} Pod with the given username. null if pod hasn't been
1083 * found. 1221 * found.
1084 */ 1222 */
1085 getPodWithUsername_: function(username) { 1223 getPodWithUsername_: function(username) {
1086 for (var i = 0, pod; pod = this.pods[i]; ++i) { 1224 for (var i = 0, pod; pod = this.pods[i]; ++i) {
1087 if (pod.user.username == username) 1225 if (pod.user.username == username)
1088 return pod; 1226 return pod;
1089 } 1227 }
1090 return null; 1228 return null;
1091 }, 1229 },
1092 1230
1093 /** 1231 /**
1094 * True if the the pod row is disabled (handles no user interaction). 1232 * True if the the pod row is disabled (handles no user interaction).
1095 * @type {boolean} 1233 * @type {boolean}
1096 */ 1234 */
1097 disabled_: false, 1235 disabled_: false,
1098 get disabled() { 1236 get disabled() {
1099 return this.disabled_; 1237 return this.disabled_;
1100 }, 1238 },
1101 set disabled(value) { 1239 set disabled(value) {
1102 this.disabled_ = value; 1240 this.disabled_ = value;
1103 var controls = this.querySelectorAll('button,input'); 1241 var controls = this.querySelectorAll('button,input');
1104 for (var i = 0, control; control = controls[i]; ++i) { 1242 for (var i = 0, control; control = controls[i]; ++i) {
1105 control.disabled = value; 1243 control.disabled = value;
1106 } 1244 }
1107 }, 1245 },
1108 1246
1109 /** 1247 /**
1110 * Creates a user pod from given email. 1248 * Creates a user pod from given email.
1111 * @param {string} email User's email. 1249 * @param {!Object} user User info dictionary.
1112 */ 1250 */
1113 createUserPod: function(user) { 1251 createUserPod: function(user) {
1114 var userPod; 1252 var userPod;
1115 if (user.isDesktopUser) 1253 if (user.isDesktopUser)
1116 userPod = new DesktopUserPod({user: user}); 1254 userPod = new DesktopUserPod({user: user});
1117 else if (user.publicAccount) 1255 else if (user.publicAccount)
1118 userPod = new PublicAccountUserPod({user: user}); 1256 userPod = new PublicAccountUserPod({user: user});
1257 else if (user.isApp)
1258 userPod = new KioskAppPod({user: user});
1119 else 1259 else
1120 userPod = new UserPod({user: user}); 1260 userPod = new UserPod({user: user});
1121 1261
1122 userPod.hidden = false; 1262 userPod.hidden = false;
1123 return userPod; 1263 return userPod;
1124 }, 1264 },
1125 1265
1126 /** 1266 /**
1127 * Add an existing user pod to this pod row. 1267 * Add an existing user pod to this pod row.
1128 * @param {!Object} user User info dictionary. 1268 * @param {!Object} user User info dictionary.
1129 * @param {boolean} animated Whether to use init animation. 1269 * @param {boolean} animated Whether to use init animation.
1130 */ 1270 */
1131 addUserPod: function(user, animated) { 1271 addUserPod: function(user, animated) {
1132 var userPod = this.createUserPod(user); 1272 var userPod = this.createUserPod(user);
1133 if (animated) { 1273 if (animated) {
1134 userPod.classList.add('init'); 1274 userPod.classList.add('init');
1135 userPod.nameElement.classList.add('init'); 1275 userPod.nameElement.classList.add('init');
1136 } 1276 }
1137 1277
1138 this.appendChild(userPod); 1278 this.appendChild(userPod);
1139 userPod.initialize(); 1279 userPod.initialize();
1140 }, 1280 },
1141 1281
1142 /** 1282 /**
1283 * Runs app with a given id from the list of loaded apps.
1284 * @param {!string} app_id of an app to run.
1285 * @param {boolean=} opt_diagnostic_mode Whether to run the app in
1286 * diagnostic mode. Default is false.
1287 */
1288 findAndRunAppForTesting: function(app_id, opt_diagnostic_mode) {
1289 var app = this.getPodWithAppId_(app_id);
1290 if (app) {
1291 var activationEvent = cr.doc.createEvent('Event');
1292 activationEvent.initEvent('activate', true, true);
1293
1294 if (opt_diagnostic_mode) {
1295 var fakeCtrlEnterEvent = cr.doc.createEvent('KeyboardEvent');
1296 fakeCtrlEnterEvent.initKeyboardEvent('keypress', true, true, null,
1297 'Enter', 0,
1298 true, false, false, false);
1299 activationEvent.originalEvent = fakeCtrlEnterEvent;
xiyuan 2014/02/12 17:35:04 This is different from the expectation at line 109
Nikita (slow) 2014/02/13 08:58:02 Done. Yes, this one plus another JS error.
1300 }
1301
1302 app.dispatchEvent(activationEvent);
1303 }
1304 },
1305
1306 /**
1143 * Removes user pod from pod row. 1307 * Removes user pod from pod row.
1144 * @param {string} email User's email. 1308 * @param {string} email User's email.
1145 */ 1309 */
1146 removeUserPod: function(username) { 1310 removeUserPod: function(username) {
1147 var podToRemove = this.getPodWithUsername_(username); 1311 var podToRemove = this.getPodWithUsername_(username);
1148 if (podToRemove == null) { 1312 if (podToRemove == null) {
1149 console.warn('Attempt to remove not existing pod for ' + username + 1313 console.warn('Attempt to remove not existing pod for ' + username +
1150 '.'); 1314 '.');
1151 return; 1315 return;
1152 } 1316 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 pod.classList.add('zoom'); 1359 pod.classList.add('zoom');
1196 } 1360 }
1197 }, 1361 },
1198 1362
1199 /** 1363 /**
1200 * Populates pod row with given existing users and start init animation. 1364 * Populates pod row with given existing users and start init animation.
1201 * @param {array} users Array of existing user emails. 1365 * @param {array} users Array of existing user emails.
1202 * @param {boolean} animated Whether to use init animation. 1366 * @param {boolean} animated Whether to use init animation.
1203 */ 1367 */
1204 loadPods: function(users, animated) { 1368 loadPods: function(users, animated) {
1369 this.users_ = users;
1370 this.user_add_is_animated_ = animated;
1371
1372 this.rebuildPods();
1373 },
1374
1375 /**
1376 * Rebuilds pod row using users_ and apps_ that were previously set or
1377 * updated.
1378 */
1379 rebuildPods: function() {
1205 // Clear existing pods. 1380 // Clear existing pods.
1206 this.innerHTML = ''; 1381 this.innerHTML = '';
1207 this.focusedPod_ = undefined; 1382 this.focusedPod_ = undefined;
1208 this.activatedPod_ = undefined; 1383 this.activatedPod_ = undefined;
1209 this.lastFocusedPod_ = undefined; 1384 this.lastFocusedPod_ = undefined;
1210 1385
1211 // Switch off animation 1386 // Switch off animation
1212 Oobe.getInstance().toggleClass('flying-pods', false); 1387 Oobe.getInstance().toggleClass('flying-pods', false);
1213 1388
1214 // Populate the pod row. 1389 // Populate the pod row.
1215 for (var i = 0; i < users.length; ++i) { 1390 for (var i = 0; i < this.users_.length; ++i)
1216 this.addUserPod(users[i], animated); 1391 this.addUserPod(this.users_[i], this.user_add_is_animated_);
1217 } 1392
1218 for (var i = 0, pod; pod = this.pods[i]; ++i) { 1393 for (var i = 0, pod; pod = this.pods[i]; ++i)
1219 this.podsWithPendingImages_.push(pod); 1394 this.podsWithPendingImages_.push(pod);
1220 } 1395
1396 // TODO: Edge case handling when kiosk apps are not fitting.
1397 for (var i = 0; i < this.apps_.length; ++i)
1398 this.addUserPod(this.apps_[i], this.user_add_is_animated_);
1399
1221 // Make sure we eventually show the pod row, even if some image is stuck. 1400 // Make sure we eventually show the pod row, even if some image is stuck.
1222 setTimeout(function() { 1401 setTimeout(function() {
1223 $('pod-row').classList.remove('images-loading'); 1402 $('pod-row').classList.remove('images-loading');
1224 }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS); 1403 }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS);
1225 1404
1226 this.placePods_(); 1405 this.placePods_();
1227 1406
1228 // Without timeout changes in pods positions will be animated even though 1407 // Without timeout changes in pods positions will be animated even though
1229 // it happened when 'flying-pods' class was disabled. 1408 // it happened when 'flying-pods' class was disabled.
1230 setTimeout(function() { 1409 setTimeout(function() {
1231 Oobe.getInstance().toggleClass('flying-pods', true); 1410 Oobe.getInstance().toggleClass('flying-pods', true);
1232 }, 0); 1411 }, 0);
1233 1412
1234 this.focusPod(this.preselectedPod); 1413 this.focusPod(this.preselectedPod);
1235 }, 1414 },
1236 1415
1237 /** 1416 /**
1417 * Adds given apps to the pod row.
1418 * @param {array} apps Array of apps.
1419 */
1420 setApps: function(apps) {
1421 this.apps_ = apps;
1422 this.rebuildPods();
1423 chrome.send('kioskAppsLoaded');
1424
1425 // Check whether there's a pending kiosk app error.
1426 window.setTimeout(function() {
1427 chrome.send('checkKioskAppLaunchError');
1428 }, 500);
1429 },
1430
1431 /**
1238 * Shows a button on a user pod with an icon. Clicking on this button 1432 * Shows a button on a user pod with an icon. Clicking on this button
1239 * triggers an event used by the chrome.screenlockPrivate API. 1433 * triggers an event used by the chrome.screenlockPrivate API.
1240 * @param {string} username Username of pod to add button 1434 * @param {string} username Username of pod to add button
1241 * @param {string} iconURL URL of the button icon 1435 * @param {string} iconURL URL of the button icon
1242 */ 1436 */
1243 showUserPodButton: function(username, iconURL) { 1437 showUserPodButton: function(username, iconURL) {
1244 var pod = this.getPodWithUsername_(username); 1438 var pod = this.getPodWithUsername_(username);
1245 if (pod == null) { 1439 if (pod == null) {
1246 console.error('Unable to show user pod button for ' + username + 1440 console.error('Unable to show user pod button for ' + username +
1247 ': user pod not found.'); 1441 ': user pod not found.');
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 * @return {boolean} Pod focus status. 1564 * @return {boolean} Pod focus status.
1371 */ 1565 */
1372 isFocused: function(pod) { 1566 isFocused: function(pod) {
1373 return this.focusedPod_ == pod; 1567 return this.focusedPod_ == pod;
1374 }, 1568 },
1375 1569
1376 /** 1570 /**
1377 * Focuses a given user pod or clear focus when given null. 1571 * Focuses a given user pod or clear focus when given null.
1378 * @param {UserPod=} podToFocus User pod to focus (undefined clears focus). 1572 * @param {UserPod=} podToFocus User pod to focus (undefined clears focus).
1379 * @param {boolean=} opt_force If true, forces focus update even when 1573 * @param {boolean=} opt_force If true, forces focus update even when
1380 * podToFocus is already focused. 1574 * podToFocus is already focused.
1381 */ 1575 */
1382 focusPod: function(podToFocus, opt_force) { 1576 focusPod: function(podToFocus, opt_force) {
1383 if (this.isFocused(podToFocus) && !opt_force) { 1577 if (this.isFocused(podToFocus) && !opt_force) {
1384 this.keyboardActivated_ = false; 1578 this.keyboardActivated_ = false;
1385 return; 1579 return;
1386 } 1580 }
1387 1581
1388 // Make sure that we don't focus pods that are not allowed to be focused. 1582 // 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 1583 // TODO(nkostylev): Fix various keyboard focus related issues caused
1390 // by this approach. http://crbug.com/339042 1584 // by this approach. http://crbug.com/339042
(...skipping 25 matching lines...) Expand all
1416 if (!this.isFocused(podToFocus)) 1610 if (!this.isFocused(podToFocus))
1417 Oobe.clearErrors(); 1611 Oobe.clearErrors();
1418 1612
1419 var hadFocus = !!this.focusedPod_; 1613 var hadFocus = !!this.focusedPod_;
1420 this.focusedPod_ = podToFocus; 1614 this.focusedPod_ = podToFocus;
1421 if (podToFocus) { 1615 if (podToFocus) {
1422 podToFocus.classList.remove('faded'); 1616 podToFocus.classList.remove('faded');
1423 podToFocus.classList.add('focused'); 1617 podToFocus.classList.add('focused');
1424 podToFocus.reset(true); // Reset and give focus. 1618 podToFocus.reset(true); // Reset and give focus.
1425 // focusPod() automatically loads wallpaper 1619 // focusPod() automatically loads wallpaper
1426 chrome.send('focusPod', [podToFocus.user.username]); 1620 if (!podToFocus.user.isApp)
1621 chrome.send('focusPod', [podToFocus.user.username]);
1427 this.firstShown_ = false; 1622 this.firstShown_ = false;
1428 this.lastFocusedPod_ = podToFocus; 1623 this.lastFocusedPod_ = podToFocus;
1429 } 1624 }
1430 this.insideFocusPod_ = false; 1625 this.insideFocusPod_ = false;
1431 this.keyboardActivated_ = false; 1626 this.keyboardActivated_ = false;
1432 }, 1627 },
1433 1628
1434 /** 1629 /**
1435 * Focuses a given user pod by index or clear focus when given null. 1630 * Focuses a given user pod by index or clear focus when given null.
1436 * @param {int=} podToFocus index of User pod to focus. 1631 * @param {int=} podToFocus index of User pod to focus.
1437 * @param {boolean=} opt_force If true, forces focus update even when 1632 * @param {boolean=} opt_force If true, forces focus update even when
1438 * podToFocus is already focused. 1633 * podToFocus is already focused.
1439 */ 1634 */
1440 focusPodByIndex: function(podToFocus, opt_force) { 1635 focusPodByIndex: function(podToFocus, opt_force) {
1441 if (podToFocus < this.pods.length) 1636 if (podToFocus < this.pods.length)
1442 this.focusPod(this.pods[podToFocus], opt_force); 1637 this.focusPod(this.pods[podToFocus], opt_force);
1443 }, 1638 },
1444 1639
1445 /** 1640 /**
1446 * Resets wallpaper to the last active user's wallpaper, if any. 1641 * Resets wallpaper to the last active user's wallpaper, if any.
1447 */ 1642 */
1448 loadLastWallpaper: function() { 1643 loadLastWallpaper: function() {
1449 if (this.lastFocusedPod_) 1644 if (this.lastFocusedPod_ && !this.lastFocusedPod_.user.isApp)
1450 chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]); 1645 chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]);
1451 }, 1646 },
1452 1647
1453 /** 1648 /**
1454 * Returns the currently activated pod. 1649 * Returns the currently activated pod.
1455 * @type {UserPod} 1650 * @type {UserPod}
1456 */ 1651 */
1457 get activatedPod() { 1652 get activatedPod() {
1458 return this.activatedPod_; 1653 return this.activatedPod_;
1459 }, 1654 },
1460 set activatedPod(pod) { 1655
1461 if (pod && pod.activate()) 1656 /**
1657 * Sets currently activated pod.
1658 * @param {UserPod} pod Pod to check for focus.
1659 * @param {Event} e Event object.
1660 */
1661 setActivatedPod: function(pod, e) {
1662 if (pod && pod.activate(e))
1462 this.activatedPod_ = pod; 1663 this.activatedPod_ = pod;
1463 }, 1664 },
1464 1665
1465 /** 1666 /**
1466 * The pod of the signed-in user, if any; null otherwise. 1667 * The pod of the signed-in user, if any; null otherwise.
1467 * @type {?UserPod} 1668 * @type {?UserPod}
1468 */ 1669 */
1469 get lockedPod() { 1670 get lockedPod() {
1470 for (var i = 0, pod; pod = this.pods[i]; ++i) { 1671 for (var i = 0, pod; pod = this.pods[i]; ++i) {
1471 if (pod.user.signedIn) 1672 if (pod.user.signedIn)
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 if (this.focusedPod_ && this.focusedPod_.nextElementSibling) 1876 if (this.focusedPod_ && this.focusedPod_.nextElementSibling)
1676 this.focusPod(this.focusedPod_.nextElementSibling); 1877 this.focusPod(this.focusedPod_.nextElementSibling);
1677 else 1878 else
1678 this.focusPod(this.firstElementChild); 1879 this.focusPod(this.firstElementChild);
1679 1880
1680 e.stopPropagation(); 1881 e.stopPropagation();
1681 } 1882 }
1682 break; 1883 break;
1683 case 'Enter': 1884 case 'Enter':
1684 if (this.focusedPod_) { 1885 if (this.focusedPod_) {
1685 this.activatedPod = this.focusedPod_; 1886 this.setActivatedPod(this.focusedPod_, e);
1686 e.stopPropagation(); 1887 e.stopPropagation();
1687 } 1888 }
1688 break; 1889 break;
1689 case 'U+001B': // Esc 1890 case 'U+001B': // Esc
1690 if (!this.isSinglePod) 1891 if (!this.isSinglePod)
1691 this.focusPod(); 1892 this.focusPod();
1692 break; 1893 break;
1693 } 1894 }
1694 }, 1895 },
1695 1896
(...skipping 10 matching lines...) Expand all
1706 if (this.focusedPod_) { 1907 if (this.focusedPod_) {
1707 var focusedPod = this.focusedPod_; 1908 var focusedPod = this.focusedPod_;
1708 var screen = this.parentNode; 1909 var screen = this.parentNode;
1709 var self = this; 1910 var self = this;
1710 focusedPod.addEventListener('webkitTransitionEnd', function f(e) { 1911 focusedPod.addEventListener('webkitTransitionEnd', function f(e) {
1711 if (e.target == focusedPod) { 1912 if (e.target == focusedPod) {
1712 focusedPod.removeEventListener('webkitTransitionEnd', f); 1913 focusedPod.removeEventListener('webkitTransitionEnd', f);
1713 focusedPod.reset(true); 1914 focusedPod.reset(true);
1714 // Notify screen that it is ready. 1915 // Notify screen that it is ready.
1715 screen.onShow(); 1916 screen.onShow();
1716 chrome.send('loadWallpaper', [focusedPod.user.username]); 1917 if (!focusedPod.user.isApp)
1918 chrome.send('loadWallpaper', [focusedPod.user.username]);
1717 } 1919 }
1718 }); 1920 });
1719 // Guard timer for 1 second -- it would conver all possible animations. 1921 // Guard timer for 1 second -- it would conver all possible animations.
1720 ensureTransitionEndEvent(focusedPod, 1000); 1922 ensureTransitionEndEvent(focusedPod, 1000);
1721 } 1923 }
1722 }, 1924 },
1723 1925
1724 /** 1926 /**
1725 * Called right before the pod row is shown. 1927 * Called right before the pod row is shown.
1726 */ 1928 */
(...skipping 30 matching lines...) Expand all
1757 if (this.podsWithPendingImages_.length == 0) { 1959 if (this.podsWithPendingImages_.length == 0) {
1758 this.classList.remove('images-loading'); 1960 this.classList.remove('images-loading');
1759 } 1961 }
1760 } 1962 }
1761 }; 1963 };
1762 1964
1763 return { 1965 return {
1764 PodRow: PodRow 1966 PodRow: PodRow
1765 }; 1967 };
1766 }); 1968 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698