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

Unified 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: pngcrush 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 side-by-side diff with in-line comments
Download patch
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..d3918ac3897f98efb460b24ffc8dfedf0c87ea24 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() {
@@ -390,11 +398,16 @@ cr.define('login', function() {
this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
'passwordFieldAccessibleName', this.user_.emailAddress));
- this.updateUserTypeIcon();
+ this.customizeUserPodPerUserType();
},
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(
@@ -414,28 +427,33 @@ cr.define('login', function() {
loadTimeData.getString('removeUser');
},
- updateUserTypeIcon: function() {
+ customizeUserPodPerUserType: function() {
var isMultiProfilesUI =
(Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING);
if (this.user_.locallyManagedUser) {
- this.userTypeIconAreaElement.classList.add('supervised');
- this.userTypeIconAreaElement.hidden = false;
+ this.setUserPodIconType('supervised');
} else if (isMultiProfilesUI && !this.user_.isMultiProfilesAllowed) {
- // Mark user pod as not focusable.
+ // Mark user pod as not focusable which in addition to the grayed out
+ // filter makes it look in disabled state.
this.classList.add('not-focusable');
-
- this.userTypeIconAreaElement.classList.add('policy');
- this.userTypeIconAreaElement.hidden = false;
+ this.setUserPodIconType('policy');
this.querySelector('.mp-policy-title').hidden = false;
- if (this.user_.multiProfilesPolicy == 'primary-only')
+ if (this.user.multiProfilesPolicy == 'primary-only')
this.querySelector('.mp-policy-primary-only-msg').hidden = false;
else
this.querySelector('.mp-policy-not-allowed-msg').hidden = false;
+ } else if (this.user_.isApp) {
+ this.setUserPodIconType('app');
}
},
+ setUserPodIconType: function(userTypeClass) {
+ this.userTypeIconAreaElement.classList.add(userTypeClass);
+ this.userTypeIconAreaElement.hidden = false;
+ },
+
/**
* The user that this pod represents.
* @type {!Object}
@@ -538,10 +556,11 @@ cr.define('login', function() {
/**
* Activates the pod.
+ * @param {Event} e Event object.
* @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 +737,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();
@@ -814,7 +833,7 @@ cr.define('login', function() {
this.nameElement.addEventListener('keydown', (function(e) {
if (e.keyIdentifier == 'Enter') {
- this.parentNode.activatedPod = this;
+ this.parentNode.setActivatedPod(this, e);
// Stop this keydown event from bubbling up to PodRow handler.
e.stopPropagation();
// Prevent default so that we don't trigger a 'click' event on the
@@ -867,7 +886,7 @@ cr.define('login', function() {
},
/** @override */
- activate: function() {
+ activate: function(e) {
this.expanded = true;
this.focusInput();
return true;
@@ -879,15 +898,14 @@ cr.define('login', function() {
return;
this.parentNode.focusPod(this);
- this.parentNode.activatedPod = this;
+ this.parentNode.setActivatedPod(this, e);
// Prevent default so that we don't trigger 'focus' event.
e.preventDefault();
},
/**
- * 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 +1003,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 +1029,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 +1039,110 @@ cr.define('login', function() {
};
/**
+ * Creates a user pod that represents kiosk app.
+ * @constructor
+ * @extends {UserPod}
+ */
+ var KioskAppPod = cr.ui.define(function() {
+ var node = UserPod();
+ return node;
+ });
+
+ KioskAppPod.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;
+
+ UserPod.prototype.updateActionBoxArea.call(this);
+ UserPod.prototype.customizeUserPodPerUserType.call(this);
+ },
+
+ /** @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 && e.ctrlKey;
+ this.launchApp_(this.user, diagnosticMode);
+ return true;
+ },
+
+ /** @override */
+ handleClickOnPod_: function(e) {
+ if (this.parentNode.disabled)
+ return;
+
+ Oobe.clearErrors();
+ this.parentNode.lastFocusedPod_ = this;
+ 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;
+ }
+
+ var oobe = $('oobe');
+ if (!oobe.confirmDiagnosticMode_) {
+ oobe.confirmDiagnosticMode_ =
+ new cr.ui.dialogs.ConfirmDialog(document.body);
+ oobe.confirmDiagnosticMode_.setOkLabel(
+ loadTimeData.getString('confirmKioskAppDiagnosticModeYes'));
+ oobe.confirmDiagnosticMode_.setCancelLabel(
+ loadTimeData.getString('confirmKioskAppDiagnosticModeNo'));
+ }
+
+ oobe.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 +1170,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
@@ -1077,10 +1208,24 @@ cr.define('login', function() {
},
/**
+ * Returns pod with the given app id.
+ * @param {!string} app_id Application id to be matched.
+ * @return {Object} Pod with the given app id. null if pod hasn't been
+ * found.
+ */
+ getPodWithAppId_: function(app_id) {
+ for (var i = 0, pod; pod = this.pods[i]; ++i) {
+ if (pod.user.isApp && pod.user.id == app_id)
+ return pod;
+ }
+ return null;
+ },
+
+ /**
* 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.
*/
getPodWithUsername_: function(username) {
for (var i = 0, pod; pod = this.pods[i]; ++i) {
@@ -1108,7 +1253,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 +1261,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 KioskAppPod({user: user});
else
userPod = new UserPod({user: user});
@@ -1140,6 +1287,23 @@ cr.define('login', function() {
},
/**
+ * Runs app with a given id from the list of loaded apps.
+ * @param {!string} app_id of an app to run.
+ * @param {boolean=} opt_diagnostic_mode Whether to run the app in
+ * diagnostic mode. Default is false.
+ */
+ findAndRunAppForTesting: function(app_id, opt_diagnostic_mode) {
+ var app = this.getPodWithAppId_(app_id);
+ if (app) {
+ var activationEvent = cr.doc.createEvent('MouseEvents');
+ var ctrlKey = opt_diagnostic_mode;
+ activationEvent.initMouseEvent('click', true, true, null,
+ 0, 0, 0, 0, 0, ctrlKey, false, false, false, 0, null);
+ app.dispatchEvent(activationEvent);
+ }
+ },
+
+ /**
* Removes user pod from pod row.
* @param {string} email User's email.
*/
@@ -1202,6 +1366,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 +1387,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 +1414,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 +1571,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.
*/
focusPod: function(podToFocus, opt_force) {
if (this.isFocused(podToFocus) && !opt_force) {
@@ -1423,7 +1617,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 +1630,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.
*/
focusPodByIndex: function(podToFocus, opt_force) {
if (podToFocus < this.pods.length)
@@ -1446,7 +1641,7 @@ cr.define('login', function() {
* Resets wallpaper to the last active user's wallpaper, if any.
*/
loadLastWallpaper: function() {
- if (this.lastFocusedPod_)
+ if (this.lastFocusedPod_ && !this.lastFocusedPod_.user.isApp)
chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]);
},
@@ -1457,8 +1652,14 @@ cr.define('login', function() {
get activatedPod() {
return this.activatedPod_;
},
- set activatedPod(pod) {
- if (pod && pod.activate())
+
+ /**
+ * Sets currently activated pod.
+ * @param {UserPod} pod Pod to check for focus.
+ * @param {Event} e Event object.
+ */
+ setActivatedPod: function(pod, e) {
+ if (pod && pod.activate(e))
this.activatedPod_ = pod;
},
@@ -1682,7 +1883,7 @@ cr.define('login', function() {
break;
case 'Enter':
if (this.focusedPod_) {
- this.activatedPod = this.focusedPod_;
+ this.setActivatedPod(this.focusedPod_, e);
e.stopPropagation();
}
break;
@@ -1713,7 +1914,8 @@ cr.define('login', function() {
focusedPod.reset(true);
// Notify screen that it is ready.
screen.onShow();
- chrome.send('loadWallpaper', [focusedPod.user.username]);
+ if (!focusedPod.user.isApp)
+ chrome.send('loadWallpaper', [focusedPod.user.username]);
}
});
// Guard timer for 1 second -- it would conver all possible animations.

Powered by Google App Engine
This is Rietveld 408576698