OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 }); |
OLD | NEW |