Index: chrome/browser/resources/chromeos/login/user_pod_row.js |
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.js b/chrome/browser/resources/chromeos/login/user_pod_row.js |
index b5090e0424bd942789f72461b2c5e805a467315f..47f0d112b93d535d3bc50885d5cdb209a6a66def 100644 |
--- a/chrome/browser/resources/chromeos/login/user_pod_row.js |
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.js |
@@ -37,8 +37,8 @@ cr.define('login', function() { |
var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2; |
/** |
- * Variables used for pod placement processing. |
- * Width and height should be synced with computed CSS sizes of pods. |
+ * Variables used for pod placement processing. Width and height should be |
+ * synced with computed CSS sizes of pods. |
*/ |
var POD_WIDTH = 180; |
var POD_HEIGHT = 217; |
@@ -82,7 +82,7 @@ cr.define('login', function() { |
// |
// (1) all user pods have tab index 1 so they are traversed first; |
// (2) when a user pod is activated, its tab index is set to -1 and its |
- // main input field gets focus and tab index 1; |
+ // main input field gets focus and tab index 1; |
// (3) buttons on the header bar have tab index 2 so they follow user pods; |
// (4) Action box buttons have tab index 3 and follow header bar buttons; |
// (5) lastly, focus jumps to the Status Area and back to user pods. |
@@ -258,14 +258,22 @@ cr.define('login', function() { |
}, |
/** |
- * Gets user signin button. |
- * @type {!HTMLInputElement} |
+ * Gets user sign in button. |
+ * @type {!HTMLButtonElement} |
*/ |
get signinButtonElement() { |
return this.querySelector('.signin-button'); |
}, |
/** |
+ * Gets launch app button. |
+ * @type {!HTMLButtonElement} |
+ */ |
+ get launchAppButtonElement() { |
+ return this.querySelector('.launch-app-button'); |
+ }, |
+ |
+ /** |
* Gets action box area. |
* @type {!HTMLInputElement} |
*/ |
@@ -363,8 +371,8 @@ cr.define('login', function() { |
}, |
/** |
- * Gets the custom button. This button is normally hidden, but can be |
- * shown using the chrome.screenlockPrivate API. |
+ * Gets the custom button. This button is normally hidden, but can be shown |
+ * using the chrome.screenlockPrivate API. |
* @type {!HTMLInputElement} |
*/ |
get customButton() { |
@@ -394,7 +402,12 @@ cr.define('login', function() { |
}, |
updateActionBoxArea: function() { |
- this.actionBoxAreaElement.hidden = this.user_.publicAccount; |
+ if (this.user_.publicAccount || this.user_.isApp) { |
+ this.actionBoxAreaElement.hidden = true; |
+ return; |
+ } |
+ |
+ this.actionBoxAreaElement.hidden = false; |
this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove; |
this.actionBoxAreaElement.setAttribute( |
@@ -540,8 +553,8 @@ cr.define('login', function() { |
* Activates the pod. |
* @return {boolean} True if activated successfully. |
*/ |
- activate: function() { |
- if (!this.signinButtonElement.hidden) { |
+ activate: function(e) { |
+ if (this.forceOnlineSignin) { |
this.showSigninUI(); |
} else if (!this.passwordElement.value) { |
return false; |
@@ -718,7 +731,7 @@ cr.define('login', function() { |
if (this.parentNode.disabled) |
return; |
- if (!this.signinButtonElement.hidden && !this.isActionBoxMenuActive) { |
+ if (this.forceOnlineSignin && !this.isActionBoxMenuActive) { |
this.showSigninUI(); |
// Prevent default so that we don't trigger 'focus' event. |
e.preventDefault(); |
@@ -867,7 +880,7 @@ cr.define('login', function() { |
}, |
/** @override */ |
- activate: function() { |
+ activate: function(e) { |
this.expanded = true; |
this.focusInput(); |
return true; |
@@ -885,9 +898,8 @@ cr.define('login', function() { |
}, |
/** |
- * Handle mouse and keyboard events for the learn more button. |
- * Triggering the button causes information about public sessions to be |
- * shown. |
+ * Handle mouse and keyboard events for the learn more button. Triggering |
+ * the button causes information about public sessions to be shown. |
* @param {Event} event Mouse or keyboard event. |
*/ |
handleLearnMoreEvent: function(event) { |
@@ -985,7 +997,7 @@ cr.define('login', function() { |
}, |
/** @override */ |
- activate: function() { |
+ activate: function(e) { |
if (this.passwordElement.hidden) { |
Oobe.launchUser(this.user.emailAddress, this.user.displayName); |
} else if (!this.passwordElement.value) { |
@@ -1011,7 +1023,7 @@ cr.define('login', function() { |
// If this is an unlocked pod, then open a browser window. Otherwise |
// just activate the pod and show the password field. |
if (!this.user.needsSignin && !this.isActionBoxMenuActive) |
- this.activate(); |
+ this.activate(e); |
}, |
/** @override */ |
@@ -1021,6 +1033,110 @@ cr.define('login', function() { |
}; |
/** |
+ * Creates a user pod that represents kiosk app. |
+ * @constructor |
+ * @extends {UserPod} |
+ */ |
+ var AppUserPod = cr.ui.define(function() { |
+ var node = UserPod(); |
+ return node; |
+ }); |
+ |
+ AppUserPod.prototype = { |
+ __proto__: UserPod.prototype, |
+ |
+ /** @override */ |
+ decorate: function() { |
+ UserPod.prototype.decorate.call(this); |
+ this.launchAppButtonElement.addEventListener('click', |
+ this.activate.bind(this)); |
+ }, |
+ |
+ /** @override */ |
+ update: function() { |
+ this.imageElement.src = this.user.iconUrl; |
+ this.imageElement.alt = this.user.label; |
+ this.passwordElement.hidden = true; |
+ this.signinButtonElement.hidden = true; |
+ this.launchAppButtonElement.hidden = false; |
+ this.signedInIndicatorElement.hidden = true; |
+ this.nameElement.textContent = this.user.label; |
+ }, |
+ |
+ /** @override */ |
+ get mainInput() { |
+ return this.launchAppButtonElement; |
+ }, |
+ |
+ /** @override */ |
+ focusInput: function() { |
+ this.signinButtonElement.hidden = true; |
+ this.launchAppButtonElement.hidden = false; |
+ this.passwordElement.hidden = true; |
+ |
+ // Move tabIndex from the whole pod to the main input. |
+ this.tabIndex = -1; |
+ this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT; |
+ this.mainInput.focus(); |
+ }, |
+ |
+ /** @override */ |
+ get forceOnlineSignin() { |
+ return false; |
+ }, |
+ |
+ /** @override */ |
+ activate: function(e) { |
+ var diagnosticMode = e.originalEvent && e.originalEvent.ctrlKey; |
+ this.launchApp_(this.user, diagnosticMode); |
+ return true; |
+ }, |
+ |
+ /** @override */ |
+ handleClickOnPod_: function(e) { |
+ if (this.parentNode.disabled) |
+ return; |
+ |
+ Oobe.clearErrors(); |
+ this.parentNode.lastFocusedPod_ = this; |
+ |
+ // If this is an unlocked pod, then open a browser window. Otherwise |
+ // just activate the pod and show the password field. |
+ if (!this.user.needsSignin && !this.isActionBoxMenuActive) |
+ this.activate(e); |
+ }, |
+ |
+ /** |
+ * Launch the app. If |diagnosticMode| is true, ask user to confirm. |
+ * @param {Object} app App data. |
+ * @param {boolean} diagnosticMode Whether to run the app in diagnostic |
+ * mode. |
+ */ |
+ launchApp_: function(app, diagnosticMode) { |
+ if (!diagnosticMode) { |
+ chrome.send('launchKioskApp', [app.id, false]); |
+ return; |
+ } |
+ |
+ if (!this.confirmDiagnosticMode_) { |
+ this.confirmDiagnosticMode_ = |
+ new cr.ui.dialogs.ConfirmDialog(document.body); |
+ this.confirmDiagnosticMode_.setOkLabel( |
+ loadTimeData.getString('confirmKioskAppDiagnosticModeYes')); |
+ this.confirmDiagnosticMode_.setCancelLabel( |
+ loadTimeData.getString('confirmKioskAppDiagnosticModeNo')); |
+ } |
+ |
+ this.confirmDiagnosticMode_.show( |
+ loadTimeData.getStringF('confirmKioskAppDiagnosticModeFormat', |
+ app.label), |
+ function() { |
+ chrome.send('launchKioskApp', [app.id, true]); |
+ }); |
+ }, |
+ }; |
+ |
+ /** |
* Creates a new pod row element. |
* @constructor |
* @extends {HTMLDivElement} |
@@ -1048,6 +1164,15 @@ cr.define('login', function() { |
// Pods whose initial images haven't been loaded yet. |
podsWithPendingImages_: [], |
+ // Whether pod creation is animated. |
+ user_add_is_animated_: false, |
+ |
+ // Array of apps that are shown in addition to other user pods. |
+ apps_: [], |
+ |
+ // Array of users that are shown (public/supervised/regular). |
+ users_: [], |
+ |
/** @override */ |
decorate: function() { |
// Event listeners that are installed for the time period during which |
@@ -1080,7 +1205,7 @@ cr.define('login', function() { |
* Returns pod with the given username (null if there is no such pod). |
* @param {string} username Username to be matched. |
* @return {Object} Pod with the given username. null if pod hasn't been |
- * found. |
+ * 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.
|
*/ |
getPodWithUsername_: function(username) { |
for (var i = 0, pod; pod = this.pods[i]; ++i) { |
@@ -1108,7 +1233,7 @@ cr.define('login', function() { |
/** |
* Creates a user pod from given email. |
- * @param {string} email User's email. |
+ * @param {!Object} user User info dictionary. |
*/ |
createUserPod: function(user) { |
var userPod; |
@@ -1116,6 +1241,8 @@ cr.define('login', function() { |
userPod = new DesktopUserPod({user: user}); |
else if (user.publicAccount) |
userPod = new PublicAccountUserPod({user: user}); |
+ else if (user.isApp) |
+ userPod = new AppUserPod({user: user}); |
else |
userPod = new UserPod({user: user}); |
@@ -1202,6 +1329,17 @@ cr.define('login', function() { |
* @param {boolean} animated Whether to use init animation. |
*/ |
loadPods: function(users, animated) { |
+ this.users_ = users; |
+ this.user_add_is_animated_ = animated; |
+ |
+ this.rebuildPods(); |
+ }, |
+ |
+ /** |
+ * Rebuilds pod row using users_ and apps_ that were previously set or |
+ * updated. |
+ */ |
+ rebuildPods: function() { |
// Clear existing pods. |
this.innerHTML = ''; |
this.focusedPod_ = undefined; |
@@ -1212,12 +1350,16 @@ cr.define('login', function() { |
Oobe.getInstance().toggleClass('flying-pods', false); |
// Populate the pod row. |
- for (var i = 0; i < users.length; ++i) { |
- this.addUserPod(users[i], animated); |
- } |
- for (var i = 0, pod; pod = this.pods[i]; ++i) { |
+ for (var i = 0; i < this.users_.length; ++i) |
+ this.addUserPod(this.users_[i], this.user_add_is_animated_); |
+ |
+ for (var i = 0, pod; pod = this.pods[i]; ++i) |
this.podsWithPendingImages_.push(pod); |
- } |
+ |
+ // TODO: Edge case handling when kiosk apps are not fitting. |
+ for (var i = 0; i < this.apps_.length; ++i) |
+ this.addUserPod(this.apps_[i], this.user_add_is_animated_); |
+ |
// Make sure we eventually show the pod row, even if some image is stuck. |
setTimeout(function() { |
$('pod-row').classList.remove('images-loading'); |
@@ -1235,6 +1377,21 @@ cr.define('login', function() { |
}, |
/** |
+ * Adds given apps to the pod row. |
+ * @param {array} apps Array of apps. |
+ */ |
+ setApps: function(apps) { |
+ this.apps_ = apps; |
+ this.rebuildPods(); |
+ chrome.send('kioskAppsLoaded'); |
+ |
+ // Check whether there's a pending kiosk app error. |
+ window.setTimeout(function() { |
+ chrome.send('checkKioskAppLaunchError'); |
+ }, 500); |
+ }, |
+ |
+ /** |
* Shows a button on a user pod with an icon. Clicking on this button |
* triggers an event used by the chrome.screenlockPrivate API. |
* @param {string} username Username of pod to add button |
@@ -1377,7 +1534,7 @@ cr.define('login', function() { |
* Focuses a given user pod or clear focus when given null. |
* @param {UserPod=} podToFocus User pod to focus (undefined clears focus). |
* @param {boolean=} opt_force If true, forces focus update even when |
- * podToFocus is already focused. |
+ * 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.
|
*/ |
focusPod: function(podToFocus, opt_force) { |
if (this.isFocused(podToFocus) && !opt_force) { |
@@ -1423,7 +1580,8 @@ cr.define('login', function() { |
podToFocus.classList.add('focused'); |
podToFocus.reset(true); // Reset and give focus. |
// focusPod() automatically loads wallpaper |
- chrome.send('focusPod', [podToFocus.user.username]); |
+ if (!podToFocus.user.isApp) |
+ chrome.send('focusPod', [podToFocus.user.username]); |
this.firstShown_ = false; |
this.lastFocusedPod_ = podToFocus; |
} |
@@ -1435,7 +1593,7 @@ cr.define('login', function() { |
* Focuses a given user pod by index or clear focus when given null. |
* @param {int=} podToFocus index of User pod to focus. |
* @param {boolean=} opt_force If true, forces focus update even when |
- * podToFocus is already focused. |
+ * 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.
|
*/ |
focusPodByIndex: function(podToFocus, opt_force) { |
if (podToFocus < this.pods.length) |