| Index: chrome/browser/resources/login/user_pod_row.js
|
| diff --git a/chrome/browser/resources/login/user_pod_row.js b/chrome/browser/resources/login/user_pod_row.js
|
| deleted file mode 100644
|
| index 940feef29ed31cc9f0bc244e1cc1096786e89884..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/resources/login/user_pod_row.js
|
| +++ /dev/null
|
| @@ -1,2399 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -/**
|
| - * @fileoverview User pod row implementation.
|
| - */
|
| -
|
| -cr.define('login', function() {
|
| - /**
|
| - * Number of displayed columns depending on user pod count.
|
| - * @type {Array.<number>}
|
| - * @const
|
| - */
|
| - var COLUMNS = [0, 1, 2, 3, 4, 5, 4, 4, 4, 5, 5, 6, 6, 5, 5, 6, 6, 6, 6];
|
| -
|
| - /**
|
| - * Mapping between number of columns in pod-row and margin between user pods
|
| - * for such layout.
|
| - * @type {Array.<number>}
|
| - * @const
|
| - */
|
| - var MARGIN_BY_COLUMNS = [undefined, 40, 40, 40, 40, 40, 12];
|
| -
|
| - /**
|
| - * Mapping between number of columns in the desktop pod-row and margin
|
| - * between user pods for such layout.
|
| - * @type {Array.<number>}
|
| - * @const
|
| - */
|
| - var DESKTOP_MARGIN_BY_COLUMNS = [undefined, 15, 15, 15, 15, 15, 15];
|
| -
|
| - /**
|
| - * Maximal number of columns currently supported by pod-row.
|
| - * @type {number}
|
| - * @const
|
| - */
|
| - var MAX_NUMBER_OF_COLUMNS = 6;
|
| -
|
| - /**
|
| - * Maximal number of rows if sign-in banner is displayed alonside.
|
| - * @type {number}
|
| - * @const
|
| - */
|
| - 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.
|
| - */
|
| - var POD_WIDTH = 180;
|
| - var PUBLIC_EXPANDED_BASIC_WIDTH = 500;
|
| - var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610;
|
| - var CROS_POD_HEIGHT = 213;
|
| - var DESKTOP_POD_HEIGHT = 226;
|
| - var POD_ROW_PADDING = 10;
|
| - var DESKTOP_ROW_PADDING = 15;
|
| -
|
| - /**
|
| - * Minimal padding between user pod and virtual keyboard.
|
| - * @type {number}
|
| - * @const
|
| - */
|
| - var USER_POD_KEYBOARD_MIN_PADDING = 20;
|
| -
|
| - /**
|
| - * Whether to preselect the first pod automatically on login screen.
|
| - * @type {boolean}
|
| - * @const
|
| - */
|
| - var PRESELECT_FIRST_POD = true;
|
| -
|
| - /**
|
| - * Maximum time for which the pod row remains hidden until all user images
|
| - * have been loaded.
|
| - * @type {number}
|
| - * @const
|
| - */
|
| - var POD_ROW_IMAGES_LOAD_TIMEOUT_MS = 3000;
|
| -
|
| - /**
|
| - * Public session help topic identifier.
|
| - * @type {number}
|
| - * @const
|
| - */
|
| - var HELP_TOPIC_PUBLIC_SESSION = 3041033;
|
| -
|
| - /**
|
| - * Tab order for user pods. Update these when adding new controls.
|
| - * @enum {number}
|
| - * @const
|
| - */
|
| - var UserPodTabOrder = {
|
| - POD_INPUT: 1, // Password input fields (and whole pods themselves).
|
| - HEADER_BAR: 2, // Buttons on the header bar (Shutdown, Add User).
|
| - ACTION_BOX: 3, // Action box buttons.
|
| - PAD_MENU_ITEM: 4 // User pad menu items (Remove this user).
|
| - };
|
| -
|
| - /**
|
| - * Supported authentication types. Keep in sync with the enum in
|
| - * chrome/browser/signin/screenlock_bridge.h
|
| - * @enum {number}
|
| - * @const
|
| - */
|
| - var AUTH_TYPE = {
|
| - OFFLINE_PASSWORD: 0,
|
| - ONLINE_SIGN_IN: 1,
|
| - NUMERIC_PIN: 2,
|
| - USER_CLICK: 3,
|
| - EXPAND_THEN_USER_CLICK: 4,
|
| - };
|
| -
|
| - /**
|
| - * Names of authentication types.
|
| - */
|
| - var AUTH_TYPE_NAMES = {
|
| - 0: 'offlinePassword',
|
| - 1: 'onlineSignIn',
|
| - 2: 'numericPin',
|
| - 3: 'userClick',
|
| - 4: 'expandThenUserClick',
|
| - };
|
| -
|
| - // Focus and tab order are organized as follows:
|
| - //
|
| - // (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;
|
| - // (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.
|
| - //
|
| - // 'Focus' event is handled by a capture handler for the whole document
|
| - // and in some cases 'mousedown' event handlers are used instead of 'click'
|
| - // handlers where it's necessary to prevent 'focus' event from being fired.
|
| -
|
| - /**
|
| - * Helper function to remove a class from given element.
|
| - * @param {!HTMLElement} el Element whose class list to change.
|
| - * @param {string} cl Class to remove.
|
| - */
|
| - function removeClass(el, cl) {
|
| - el.classList.remove(cl);
|
| - }
|
| -
|
| - /**
|
| - * Creates a user pod.
|
| - * @constructor
|
| - * @extends {HTMLDivElement}
|
| - */
|
| - var UserPod = cr.ui.define(function() {
|
| - var node = $('user-pod-template').cloneNode(true);
|
| - node.removeAttribute('id');
|
| - return node;
|
| - });
|
| -
|
| - /**
|
| - * Stops event propagation from the any user pod child element.
|
| - * @param {Event} e Event to handle.
|
| - */
|
| - function stopEventPropagation(e) {
|
| - // Prevent default so that we don't trigger a 'focus' event.
|
| - e.preventDefault();
|
| - e.stopPropagation();
|
| - }
|
| -
|
| - /**
|
| - * Unique salt added to user image URLs to prevent caching. Dictionary with
|
| - * user names as keys.
|
| - * @type {Object}
|
| - */
|
| - UserPod.userImageSalt_ = {};
|
| -
|
| - UserPod.prototype = {
|
| - __proto__: HTMLDivElement.prototype,
|
| -
|
| - /** @override */
|
| - decorate: function() {
|
| - this.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - this.actionBoxAreaElement.tabIndex = UserPodTabOrder.ACTION_BOX;
|
| -
|
| - this.addEventListener('keydown', this.handlePodKeyDown_.bind(this));
|
| - this.addEventListener('click', this.handleClickOnPod_.bind(this));
|
| -
|
| - this.signinButtonElement.addEventListener('click',
|
| - this.activate.bind(this));
|
| -
|
| - this.actionBoxAreaElement.addEventListener('mousedown',
|
| - stopEventPropagation);
|
| - this.actionBoxAreaElement.addEventListener('click',
|
| - this.handleActionAreaButtonClick_.bind(this));
|
| - this.actionBoxAreaElement.addEventListener('keydown',
|
| - this.handleActionAreaButtonKeyDown_.bind(this));
|
| -
|
| - this.actionBoxMenuRemoveElement.addEventListener('click',
|
| - this.handleRemoveCommandClick_.bind(this));
|
| - this.actionBoxMenuRemoveElement.addEventListener('keydown',
|
| - this.handleRemoveCommandKeyDown_.bind(this));
|
| - this.actionBoxMenuRemoveElement.addEventListener('blur',
|
| - this.handleRemoveCommandBlur_.bind(this));
|
| - this.actionBoxRemoveUserWarningButtonElement.addEventListener(
|
| - 'click',
|
| - this.handleRemoveUserConfirmationClick_.bind(this));
|
| - this.actionBoxRemoveUserWarningButtonElement.addEventListener(
|
| - 'keydown',
|
| - this.handleRemoveUserConfirmationKeyDown_.bind(this));
|
| - },
|
| -
|
| - /**
|
| - * Initializes the pod after its properties set and added to a pod row.
|
| - */
|
| - initialize: function() {
|
| - this.passwordElement.addEventListener('keydown',
|
| - this.parentNode.handleKeyDown.bind(this.parentNode));
|
| - this.passwordElement.addEventListener('keypress',
|
| - this.handlePasswordKeyPress_.bind(this));
|
| -
|
| - this.imageElement.addEventListener('load',
|
| - this.parentNode.handlePodImageLoad.bind(this.parentNode, this));
|
| -
|
| - var initialAuthType = this.user.initialAuthType ||
|
| - AUTH_TYPE.OFFLINE_PASSWORD;
|
| - this.setAuthType(initialAuthType, null);
|
| - },
|
| -
|
| - /**
|
| - * Resets tab order for pod elements to its initial state.
|
| - */
|
| - resetTabOrder: function() {
|
| - // Note: the |mainInput| can be the pod itself.
|
| - this.mainInput.tabIndex = -1;
|
| - this.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - },
|
| -
|
| - /**
|
| - * Handles keypress event (i.e. any textual input) on password input.
|
| - * @param {Event} e Keypress Event object.
|
| - * @private
|
| - */
|
| - handlePasswordKeyPress_: function(e) {
|
| - // When tabbing from the system tray a tab key press is received. Suppress
|
| - // this so as not to type a tab character into the password field.
|
| - if (e.keyCode == 9) {
|
| - e.preventDefault();
|
| - return;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Top edge margin number of pixels.
|
| - * @type {?number}
|
| - */
|
| - set top(top) {
|
| - this.style.top = cr.ui.toCssPx(top);
|
| - },
|
| -
|
| - /**
|
| - * Top edge margin number of pixels.
|
| - */
|
| - get top() {
|
| - return parseInt(this.style.top);
|
| - },
|
| -
|
| - /**
|
| - * Left edge margin number of pixels.
|
| - * @type {?number}
|
| - */
|
| - set left(left) {
|
| - this.style.left = cr.ui.toCssPx(left);
|
| - },
|
| -
|
| - /**
|
| - * Left edge margin number of pixels.
|
| - */
|
| - get left() {
|
| - return parseInt(this.style.left);
|
| - },
|
| -
|
| - /**
|
| - * Height number of pixels.
|
| - */
|
| - get height() {
|
| - return this.offsetHeight;
|
| - },
|
| -
|
| - /**
|
| - * Gets image element.
|
| - * @type {!HTMLImageElement}
|
| - */
|
| - get imageElement() {
|
| - return this.querySelector('.user-image');
|
| - },
|
| -
|
| - /**
|
| - * Gets name element.
|
| - * @type {!HTMLDivElement}
|
| - */
|
| - get nameElement() {
|
| - return this.querySelector('.name');
|
| - },
|
| -
|
| - /**
|
| - * Gets the container holding the password field.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get passwordEntryContainerElement() {
|
| - return this.querySelector('.password-entry-container');
|
| - },
|
| -
|
| - /**
|
| - * Gets password field.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get passwordElement() {
|
| - return this.querySelector('.password');
|
| - },
|
| -
|
| - /**
|
| - * Gets the password label, which is used to show a message where the
|
| - * password field is normally.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get passwordLabelElement() {
|
| - return this.querySelector('.password-label');
|
| - },
|
| -
|
| - /**
|
| - * Gets user sign in button.
|
| - * @type {!HTMLButtonElement}
|
| - */
|
| - get signinButtonElement() {
|
| - return this.querySelector('.signin-button');
|
| - },
|
| -
|
| - /**
|
| - * Gets the container holding the launch app button.
|
| - * @type {!HTMLButtonElement}
|
| - */
|
| - get launchAppButtonContainerElement() {
|
| - return this.querySelector('.launch-app-button-container');
|
| - },
|
| -
|
| - /**
|
| - * Gets launch app button.
|
| - * @type {!HTMLButtonElement}
|
| - */
|
| - get launchAppButtonElement() {
|
| - return this.querySelector('.launch-app-button');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box area.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxAreaElement() {
|
| - return this.querySelector('.action-box-area');
|
| - },
|
| -
|
| - /**
|
| - * Gets user type icon area.
|
| - * @type {!HTMLDivElement}
|
| - */
|
| - get userTypeIconAreaElement() {
|
| - return this.querySelector('.user-type-icon-area');
|
| - },
|
| -
|
| - /**
|
| - * Gets user type bubble like multi-profiles policy restriction message.
|
| - * @type {!HTMLDivElement}
|
| - */
|
| - get userTypeBubbleElement() {
|
| - return this.querySelector('.user-type-bubble');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu title, user name item.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxMenuTitleNameElement() {
|
| - return this.querySelector('.action-box-menu-title-name');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu title, user email item.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxMenuTitleEmailElement() {
|
| - return this.querySelector('.action-box-menu-title-email');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove user command item.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxMenuCommandElement() {
|
| - return this.querySelector('.action-box-menu-remove-command');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove user command item div.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxMenuRemoveElement() {
|
| - return this.querySelector('.action-box-menu-remove');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove user warning text div.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxRemoveUserWarningTextElement() {
|
| - return this.querySelector('.action-box-remove-user-warning-text');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove supervised user warning text div.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxRemoveSupervisedUserWarningTextElement() {
|
| - return this.querySelector(
|
| - '.action-box-remove-supervised-user-warning-text');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove user command item div.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxRemoveUserWarningElement() {
|
| - return this.querySelector('.action-box-remove-user-warning');
|
| - },
|
| -
|
| - /**
|
| - * Gets action box menu, remove user command item div.
|
| - * @type {!HTMLInputElement}
|
| - */
|
| - get actionBoxRemoveUserWarningButtonElement() {
|
| - return this.querySelector('.remove-warning-button');
|
| - },
|
| -
|
| - /**
|
| - * Gets the custom icon. This icon is normally hidden, but can be shown
|
| - * using the chrome.screenlockPrivate API.
|
| - * @type {!HTMLDivElement}
|
| - */
|
| - get customIconElement() {
|
| - return this.querySelector('.custom-icon');
|
| - },
|
| -
|
| - /**
|
| - * Updates the user pod element.
|
| - */
|
| - update: function() {
|
| - this.imageElement.src = 'chrome://userimage/' + this.user.username +
|
| - '?id=' + UserPod.userImageSalt_[this.user.username];
|
| -
|
| - this.nameElement.textContent = this.user_.displayName;
|
| - this.classList.toggle('signed-in', this.user_.signedIn);
|
| -
|
| - if (this.isAuthTypeUserClick)
|
| - this.passwordLabelElement.textContent = this.authValue;
|
| -
|
| - this.updateActionBoxArea();
|
| -
|
| - this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
|
| - 'passwordFieldAccessibleName', this.user_.emailAddress));
|
| -
|
| - this.customizeUserPodPerUserType();
|
| - },
|
| -
|
| - updateActionBoxArea: function() {
|
| - if (this.user_.publicAccount || this.user_.isApp) {
|
| - this.actionBoxAreaElement.hidden = true;
|
| - return;
|
| - }
|
| -
|
| - this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;
|
| -
|
| - this.actionBoxAreaElement.setAttribute(
|
| - 'aria-label', loadTimeData.getStringF(
|
| - 'podMenuButtonAccessibleName', this.user_.emailAddress));
|
| - this.actionBoxMenuRemoveElement.setAttribute(
|
| - 'aria-label', loadTimeData.getString(
|
| - 'podMenuRemoveItemAccessibleName'));
|
| - this.actionBoxMenuTitleNameElement.textContent = this.user_.isOwner ?
|
| - loadTimeData.getStringF('ownerUserPattern', this.user_.displayName) :
|
| - this.user_.displayName;
|
| - this.actionBoxMenuTitleEmailElement.textContent = this.user_.emailAddress;
|
| - this.actionBoxMenuTitleEmailElement.hidden =
|
| - this.user_.locallyManagedUser;
|
| -
|
| - this.actionBoxMenuCommandElement.textContent =
|
| - loadTimeData.getString('removeUser');
|
| - },
|
| -
|
| - customizeUserPodPerUserType: function() {
|
| - if (this.user_.locallyManagedUser && !this.user_.isDesktopUser) {
|
| - this.setUserPodIconType('supervised');
|
| - } else if (this.multiProfilesPolicyApplied) {
|
| - // Mark user pod as not focusable which in addition to the grayed out
|
| - // filter makes it look in disabled state.
|
| - this.classList.add('multiprofiles-policy-applied');
|
| - this.setUserPodIconType('policy');
|
| -
|
| - if (this.user.multiProfilesPolicy == 'primary-only')
|
| - this.querySelector('.mp-policy-primary-only-msg').hidden = false;
|
| - else if (this.user.multiProfilesPolicy == 'owner-primary-only')
|
| - this.querySelector('.mp-owner-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}
|
| - */
|
| - user_: undefined,
|
| - get user() {
|
| - return this.user_;
|
| - },
|
| - set user(userDict) {
|
| - this.user_ = userDict;
|
| - this.update();
|
| - },
|
| -
|
| - /**
|
| - * Returns true if multi-profiles sign in is currently active and this
|
| - * user pod is restricted per policy.
|
| - * @type {boolean}
|
| - */
|
| - get multiProfilesPolicyApplied() {
|
| - var isMultiProfilesUI =
|
| - (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING);
|
| - return isMultiProfilesUI && !this.user_.isMultiProfilesAllowed;
|
| - },
|
| -
|
| - /**
|
| - * Gets main input element.
|
| - * @type {(HTMLButtonElement|HTMLInputElement)}
|
| - */
|
| - get mainInput() {
|
| - if (this.isAuthTypePassword) {
|
| - return this.passwordElement;
|
| - } else if (this.isAuthTypeOnlineSignIn) {
|
| - return this.signinButtonElement;
|
| - } else if (this.isAuthTypeUserClick) {
|
| - return this;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Whether action box button is in active state.
|
| - * @type {boolean}
|
| - */
|
| - get isActionBoxMenuActive() {
|
| - return this.actionBoxAreaElement.classList.contains('active');
|
| - },
|
| - set isActionBoxMenuActive(active) {
|
| - if (active == this.isActionBoxMenuActive)
|
| - return;
|
| -
|
| - if (active) {
|
| - this.actionBoxMenuRemoveElement.hidden = !this.user_.canRemove;
|
| - this.actionBoxRemoveUserWarningElement.hidden = true;
|
| -
|
| - // Clear focus first if another pod is focused.
|
| - if (!this.parentNode.isFocused(this)) {
|
| - this.parentNode.focusPod(undefined, true);
|
| - this.actionBoxAreaElement.focus();
|
| - }
|
| -
|
| - // Hide user-type-bubble.
|
| - this.userTypeBubbleElement.classList.remove('bubble-shown');
|
| -
|
| - this.actionBoxAreaElement.classList.add('active');
|
| - } else {
|
| - this.actionBoxAreaElement.classList.remove('active');
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Whether action box button is in hovered state.
|
| - * @type {boolean}
|
| - */
|
| - get isActionBoxMenuHovered() {
|
| - return this.actionBoxAreaElement.classList.contains('hovered');
|
| - },
|
| - set isActionBoxMenuHovered(hovered) {
|
| - if (hovered == this.isActionBoxMenuHovered)
|
| - return;
|
| -
|
| - if (hovered) {
|
| - this.actionBoxAreaElement.classList.add('hovered');
|
| - this.classList.add('hovered');
|
| - } else {
|
| - if (this.multiProfilesPolicyApplied)
|
| - this.userTypeBubbleElement.classList.remove('bubble-shown');
|
| - this.actionBoxAreaElement.classList.remove('hovered');
|
| - this.classList.remove('hovered');
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Set the authentication type for the pod.
|
| - * @param {number} An auth type value defined in the AUTH_TYPE enum.
|
| - * @param {string} authValue The initial value used for the auth type.
|
| - */
|
| - setAuthType: function(authType, authValue) {
|
| - this.authType_ = authType;
|
| - this.authValue_ = authValue;
|
| - this.setAttribute('auth-type', AUTH_TYPE_NAMES[this.authType_]);
|
| - this.update();
|
| - this.reset(this.parentNode.isFocused(this));
|
| - },
|
| -
|
| - /**
|
| - * The auth type of the user pod. This value is one of the enum
|
| - * values in AUTH_TYPE.
|
| - * @type {number}
|
| - */
|
| - get authType() {
|
| - return this.authType_;
|
| - },
|
| -
|
| - /**
|
| - * The initial value used for the pod's authentication type.
|
| - * eg. a prepopulated password input when using password authentication.
|
| - */
|
| - get authValue() {
|
| - return this.authValue_;
|
| - },
|
| -
|
| - /**
|
| - * True if the the user pod uses a password to authenticate.
|
| - * @type {bool}
|
| - */
|
| - get isAuthTypePassword() {
|
| - return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD;
|
| - },
|
| -
|
| - /**
|
| - * True if the the user pod uses a user click to authenticate.
|
| - * @type {bool}
|
| - */
|
| - get isAuthTypeUserClick() {
|
| - return this.authType_ == AUTH_TYPE.USER_CLICK;
|
| - },
|
| -
|
| - /**
|
| - * True if the the user pod uses a online sign in to authenticate.
|
| - * @type {bool}
|
| - */
|
| - get isAuthTypeOnlineSignIn() {
|
| - return this.authType_ == AUTH_TYPE.ONLINE_SIGN_IN;
|
| - },
|
| -
|
| - /**
|
| - * Updates the image element of the user.
|
| - */
|
| - updateUserImage: function() {
|
| - UserPod.userImageSalt_[this.user.username] = new Date().getTime();
|
| - this.update();
|
| - },
|
| -
|
| - /**
|
| - * Focuses on input element.
|
| - */
|
| - focusInput: function() {
|
| - // Move tabIndex from the whole pod to the main input.
|
| - // Note: the |mainInput| can be the pod itself.
|
| - this.tabIndex = -1;
|
| - this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - this.mainInput.focus();
|
| - },
|
| -
|
| - /**
|
| - * Activates the pod.
|
| - * @param {Event} e Event object.
|
| - * @return {boolean} True if activated successfully.
|
| - */
|
| - activate: function(e) {
|
| - if (this.isAuthTypeOnlineSignIn) {
|
| - this.showSigninUI();
|
| - } else if (this.isAuthTypeUserClick) {
|
| - Oobe.disableSigninUI();
|
| - chrome.send('attemptUnlock', [this.user.username]);
|
| - } else if (this.isAuthTypePassword) {
|
| - if (!this.passwordElement.value)
|
| - return false;
|
| - Oobe.disableSigninUI();
|
| - chrome.send('authenticateUser',
|
| - [this.user.username, this.passwordElement.value]);
|
| - } else {
|
| - console.error('Activating user pod with invalid authentication type: ' +
|
| - this.authType);
|
| - }
|
| -
|
| - return true;
|
| - },
|
| -
|
| - showSupervisedUserSigninWarning: function() {
|
| - // Locally managed user token has been invalidated.
|
| - // Make sure that pod is focused i.e. "Sign in" button is seen.
|
| - this.parentNode.focusPod(this);
|
| -
|
| - var error = document.createElement('div');
|
| - var messageDiv = document.createElement('div');
|
| - messageDiv.className = 'error-message-bubble';
|
| - messageDiv.textContent =
|
| - loadTimeData.getString('supervisedUserExpiredTokenWarning');
|
| - error.appendChild(messageDiv);
|
| -
|
| - $('bubble').showContentForElement(
|
| - this.signinButtonElement,
|
| - cr.ui.Bubble.Attachment.TOP,
|
| - error,
|
| - this.signinButtonElement.offsetWidth / 2,
|
| - 4);
|
| - },
|
| -
|
| - /**
|
| - * Shows signin UI for this user.
|
| - */
|
| - showSigninUI: function() {
|
| - if (this.user.locallyManagedUser && !this.user.isDesktopUser) {
|
| - this.showSupervisedUserSigninWarning();
|
| - } else {
|
| - // Special case for multi-profiles sign in. We show users even if they
|
| - // are not allowed per policy. Restrict those users from starting GAIA.
|
| - if (this.multiProfilesPolicyApplied)
|
| - return;
|
| -
|
| - this.parentNode.showSigninUI(this.user.emailAddress);
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Resets the input field and updates the tab order of pod controls.
|
| - * @param {boolean} takeFocus If true, input field takes focus.
|
| - */
|
| - reset: function(takeFocus) {
|
| - this.passwordElement.value = '';
|
| - if (takeFocus) {
|
| - if (!this.multiProfilesPolicyApplied)
|
| - this.focusInput(); // This will set a custom tab order.
|
| - }
|
| - else
|
| - this.resetTabOrder();
|
| - },
|
| -
|
| - /**
|
| - * Removes a user using the correct identifier based on user type.
|
| - * @param {Object} user User to be removed.
|
| - */
|
| - removeUser: function(user) {
|
| - chrome.send('removeUser',
|
| - [user.isDesktopUser ? user.profilePath : user.username]);
|
| - },
|
| -
|
| - /**
|
| - * Handles a click event on action area button.
|
| - * @param {Event} e Click event.
|
| - */
|
| - handleActionAreaButtonClick_: function(e) {
|
| - if (this.parentNode.disabled)
|
| - return;
|
| - this.isActionBoxMenuActive = !this.isActionBoxMenuActive;
|
| - e.stopPropagation();
|
| - },
|
| -
|
| - /**
|
| - * Handles a keydown event on action area button.
|
| - * @param {Event} e KeyDown event.
|
| - */
|
| - handleActionAreaButtonKeyDown_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - switch (e.keyIdentifier) {
|
| - case 'Enter':
|
| - case 'U+0020': // Space
|
| - if (this.parentNode.focusedPod_ && !this.isActionBoxMenuActive)
|
| - this.isActionBoxMenuActive = true;
|
| - e.stopPropagation();
|
| - break;
|
| - case 'Up':
|
| - case 'Down':
|
| - if (this.isActionBoxMenuActive) {
|
| - this.actionBoxMenuRemoveElement.tabIndex =
|
| - UserPodTabOrder.PAD_MENU_ITEM;
|
| - this.actionBoxMenuRemoveElement.focus();
|
| - }
|
| - e.stopPropagation();
|
| - break;
|
| - case 'U+001B': // Esc
|
| - this.isActionBoxMenuActive = false;
|
| - e.stopPropagation();
|
| - break;
|
| - case 'U+0009': // Tab
|
| - if (!this.parentNode.alwaysFocusSinglePod)
|
| - this.parentNode.focusPod();
|
| - default:
|
| - this.isActionBoxMenuActive = false;
|
| - break;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handles a click event on remove user command.
|
| - * @param {Event} e Click event.
|
| - */
|
| - handleRemoveCommandClick_: function(e) {
|
| - if (this.user.locallyManagedUser || this.user.isDesktopUser) {
|
| - this.showRemoveWarning_();
|
| - return;
|
| - }
|
| - if (this.isActionBoxMenuActive)
|
| - chrome.send('removeUser', [this.user.username]);
|
| - },
|
| -
|
| - /**
|
| - * Shows remove user warning. Used for supervised users on CrOS, and for all
|
| - * users on desktop.
|
| - */
|
| - showRemoveWarning_: function() {
|
| - this.actionBoxMenuRemoveElement.hidden = true;
|
| - this.actionBoxRemoveUserWarningElement.hidden = false;
|
| - this.actionBoxRemoveUserWarningButtonElement.focus();
|
| - },
|
| -
|
| - /**
|
| - * Handles a click event on remove user confirmation button.
|
| - * @param {Event} e Click event.
|
| - */
|
| - handleRemoveUserConfirmationClick_: function(e) {
|
| - if (this.isActionBoxMenuActive) {
|
| - this.isActionBoxMenuActive = false;
|
| - this.removeUser(this.user);
|
| - e.stopPropagation();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handles a keydown event on remove user confirmation button.
|
| - * @param {Event} e KeyDown event.
|
| - */
|
| - handleRemoveUserConfirmationKeyDown_: function(e) {
|
| - if (!this.isActionBoxMenuActive)
|
| - return;
|
| -
|
| - // Only handle pressing 'Enter' or 'Space', and let all other events
|
| - // bubble to the action box menu.
|
| - if (e.keyIdentifier == 'Enter' || e.keyIdentifier == 'U+0020') {
|
| - this.isActionBoxMenuActive = false;
|
| - this.removeUser(this.user);
|
| - e.stopPropagation();
|
| - // Prevent default so that we don't trigger a 'click' event.
|
| - e.preventDefault();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handles a keydown event on remove command.
|
| - * @param {Event} e KeyDown event.
|
| - */
|
| - handleRemoveCommandKeyDown_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - switch (e.keyIdentifier) {
|
| - case 'Enter':
|
| - if (this.user.locallyManagedUser || this.user.isDesktopUser) {
|
| - // Prevent default so that we don't trigger a 'click' event on the
|
| - // remove button that will be focused.
|
| - e.preventDefault();
|
| - this.showRemoveWarning_();
|
| - } else {
|
| - this.removeUser(this.user);
|
| - }
|
| - e.stopPropagation();
|
| - break;
|
| - case 'Up':
|
| - case 'Down':
|
| - e.stopPropagation();
|
| - break;
|
| - case 'U+001B': // Esc
|
| - this.actionBoxAreaElement.focus();
|
| - this.isActionBoxMenuActive = false;
|
| - e.stopPropagation();
|
| - break;
|
| - default:
|
| - this.actionBoxAreaElement.focus();
|
| - this.isActionBoxMenuActive = false;
|
| - break;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handles a blur event on remove command.
|
| - * @param {Event} e Blur event.
|
| - */
|
| - handleRemoveCommandBlur_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - this.actionBoxMenuRemoveElement.tabIndex = -1;
|
| - },
|
| -
|
| - /**
|
| - * Handles click event on a user pod.
|
| - * @param {Event} e Click event.
|
| - */
|
| - handleClickOnPod_: function(e) {
|
| - if (this.parentNode.disabled)
|
| - return;
|
| -
|
| - if (!this.isActionBoxMenuActive) {
|
| - if (this.isAuthTypeOnlineSignIn) {
|
| - this.showSigninUI();
|
| - } else if (this.isAuthTypeUserClick) {
|
| - this.parentNode.setActivatedPod(this);
|
| - }
|
| -
|
| - if (this.multiProfilesPolicyApplied)
|
| - this.userTypeBubbleElement.classList.add('bubble-shown');
|
| -
|
| - // Prevent default so that we don't trigger 'focus' event.
|
| - e.preventDefault();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handles keydown event for a user pod.
|
| - * @param {Event} e Key event.
|
| - */
|
| - handlePodKeyDown_: function(e) {
|
| - if (!this.isAuthTypeUserClick || this.disabled)
|
| - return;
|
| - switch (e.keyIdentifier) {
|
| - case 'Enter':
|
| - case 'U+0020': // Space
|
| - if (this.parentNode.isFocused(this))
|
| - this.parentNode.setActivatedPod(this);
|
| - break;
|
| - }
|
| - }
|
| - };
|
| -
|
| - /**
|
| - * Creates a public account user pod.
|
| - * @constructor
|
| - * @extends {UserPod}
|
| - */
|
| - var PublicAccountUserPod = cr.ui.define(function() {
|
| - var node = UserPod();
|
| -
|
| - var extras = $('public-account-user-pod-extras-template').children;
|
| - for (var i = 0; i < extras.length; ++i) {
|
| - var el = extras[i].cloneNode(true);
|
| - node.appendChild(el);
|
| - }
|
| -
|
| - return node;
|
| - });
|
| -
|
| - PublicAccountUserPod.prototype = {
|
| - __proto__: UserPod.prototype,
|
| -
|
| - /**
|
| - * "Enter" button in expanded side pane.
|
| - * @type {!HTMLButtonElement}
|
| - */
|
| - get enterButtonElement() {
|
| - return this.querySelector('.enter-button');
|
| - },
|
| -
|
| - /**
|
| - * Boolean flag of whether the pod is showing the side pane. The flag
|
| - * controls whether 'expanded' class is added to the pod's class list and
|
| - * resets tab order because main input element changes when the 'expanded'
|
| - * state changes.
|
| - * @type {boolean}
|
| - */
|
| - get expanded() {
|
| - return this.classList.contains('expanded');
|
| - },
|
| -
|
| - set expanded(expanded) {
|
| - if (this.expanded == expanded)
|
| - return;
|
| -
|
| - this.resetTabOrder();
|
| - this.classList.toggle('expanded', expanded);
|
| - if (expanded) {
|
| - this.usualLeft = this.left;
|
| - this.makeSpaceForExpandedPod_();
|
| - } else if (typeof(this.usualLeft) != 'undefined') {
|
| - this.left = this.usualLeft;
|
| - }
|
| -
|
| - var self = this;
|
| - this.classList.add('animating');
|
| - this.addEventListener('webkitTransitionEnd', function f(e) {
|
| - self.removeEventListener('webkitTransitionEnd', f);
|
| - self.classList.remove('animating');
|
| -
|
| - // Accessibility focus indicator does not move with the focused
|
| - // element. Sends a 'focus' event on the currently focused element
|
| - // so that accessibility focus indicator updates its location.
|
| - if (document.activeElement)
|
| - document.activeElement.dispatchEvent(new Event('focus'));
|
| - });
|
| - // Guard timer set to animation duration + 20ms.
|
| - ensureTransitionEndEvent(this, 200);
|
| - },
|
| -
|
| - /** @override */
|
| - get mainInput() {
|
| - if (this.expanded)
|
| - return this.enterButtonElement;
|
| - else
|
| - return this.nameElement;
|
| - },
|
| -
|
| - /** @override */
|
| - decorate: function() {
|
| - UserPod.prototype.decorate.call(this);
|
| -
|
| - this.classList.add('public-account');
|
| -
|
| - this.nameElement.addEventListener('keydown', (function(e) {
|
| - if (e.keyIdentifier == 'Enter') {
|
| - 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
|
| - // newly focused "Enter" button.
|
| - e.preventDefault();
|
| - }
|
| - }).bind(this));
|
| -
|
| - var learnMore = this.querySelector('.learn-more');
|
| - learnMore.addEventListener('mousedown', stopEventPropagation);
|
| - learnMore.addEventListener('click', this.handleLearnMoreEvent);
|
| - learnMore.addEventListener('keydown', this.handleLearnMoreEvent);
|
| -
|
| - learnMore = this.querySelector('.expanded-pane-learn-more');
|
| - learnMore.addEventListener('click', this.handleLearnMoreEvent);
|
| - learnMore.addEventListener('keydown', this.handleLearnMoreEvent);
|
| -
|
| - var languageSelect = this.querySelector('.language-select');
|
| - languageSelect.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - languageSelect.addEventListener('change', function() {
|
| - chrome.send('getPublicSessionKeyboardLayouts', [
|
| - this.user.username,
|
| - languageSelect.options[languageSelect.selectedIndex].value]);
|
| - }.bind(this));
|
| -
|
| - this.querySelector('.keyboard-select').tabIndex =
|
| - UserPodTabOrder.POD_INPUT;
|
| -
|
| - var languageAndInput = this.querySelector('.language-and-input');
|
| - languageAndInput.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - languageAndInput.addEventListener('click',
|
| - this.transitionToAdvanced_.bind(this));
|
| -
|
| - this.enterButtonElement.addEventListener('click', (function(e) {
|
| - this.enterButtonElement.disabled = true;
|
| - chrome.send('launchPublicAccount', [this.user.username]);
|
| - }).bind(this));
|
| - },
|
| -
|
| - /** @override **/
|
| - initialize: function() {
|
| - UserPod.prototype.initialize.call(this);
|
| -
|
| - var id = this.user.username + '-language';
|
| - this.querySelector('.language-select-label').htmlFor = id;
|
| - var languageSelect = this.querySelector('.language-select');
|
| - languageSelect.setAttribute('id', id);
|
| - var list = this.user.initialLocales;
|
| - languageSelect.innerHTML = '';
|
| - var group = languageSelect;
|
| - for (var i = 0; i < list.length; ++i) {
|
| - var item = list[i];
|
| - if (item.optionGroupName) {
|
| - group = document.createElement('optgroup');
|
| - group.label = item.optionGroupName;
|
| - languageSelect.appendChild(group);
|
| - } else {
|
| - group.appendChild(
|
| - new Option(item.title, item.value, item.selected, item.selected));
|
| - }
|
| - }
|
| -
|
| - id = this.user.username + '-keyboard';
|
| - this.querySelector('.keyboard-select-label').htmlFor = id;
|
| - this.querySelector('.keyboard-select').setAttribute('id', id);
|
| - this.populateKeyboardSelect_(this.user.initialKeyboardLayouts);
|
| - },
|
| -
|
| - /** @override **/
|
| - update: function() {
|
| - UserPod.prototype.update.call(this);
|
| - this.querySelector('.expanded-pane-name').textContent =
|
| - this.user_.displayName;
|
| - this.querySelector('.info').textContent =
|
| - loadTimeData.getStringF('publicAccountInfoFormat',
|
| - this.user_.enterpriseDomain);
|
| - },
|
| -
|
| - /** @override */
|
| - focusInput: function() {
|
| - // Move tabIndex from the whole pod to the main input.
|
| - this.tabIndex = -1;
|
| - this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - this.mainInput.focus();
|
| - },
|
| -
|
| - /** @override */
|
| - reset: function(takeFocus) {
|
| - if (!takeFocus)
|
| - this.expanded = false;
|
| - this.enterButtonElement.disabled = false;
|
| - UserPod.prototype.reset.call(this, takeFocus);
|
| - },
|
| -
|
| - /** @override */
|
| - activate: function(e) {
|
| - if (!this.expanded) {
|
| - this.expanded = true;
|
| - this.focusInput();
|
| - }
|
| - return true;
|
| - },
|
| -
|
| - /** @override */
|
| - handleClickOnPod_: function(e) {
|
| - if (this.parentNode.disabled)
|
| - return;
|
| -
|
| - this.parentNode.focusPod(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.
|
| - * @param {Event} event Mouse or keyboard event.
|
| - */
|
| - handleLearnMoreEvent: function(event) {
|
| - switch (event.type) {
|
| - // Show informaton on left click. Let any other clicks propagate.
|
| - case 'click':
|
| - if (event.button != 0)
|
| - return;
|
| - break;
|
| - // Show informaton when <Return> or <Space> is pressed. Let any other
|
| - // key presses propagate.
|
| - case 'keydown':
|
| - switch (event.keyCode) {
|
| - case 13: // Return.
|
| - case 32: // Space.
|
| - break;
|
| - default:
|
| - return;
|
| - }
|
| - break;
|
| - }
|
| - chrome.send('launchHelpApp', [HELP_TOPIC_PUBLIC_SESSION]);
|
| - stopEventPropagation(event);
|
| - },
|
| -
|
| - makeSpaceForExpandedPod_: function() {
|
| - var width = this.classList.contains('advanced') ?
|
| - PUBLIC_EXPANDED_ADVANCED_WIDTH : PUBLIC_EXPANDED_BASIC_WIDTH;
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| - var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
|
| - POD_ROW_PADDING;
|
| - if (this.left + width > $('pod-row').offsetWidth - rowPadding)
|
| - this.left = $('pod-row').offsetWidth - rowPadding - width;
|
| - },
|
| -
|
| - /**
|
| - * Transition the expanded pod from the basic to the advanced view.
|
| - */
|
| - transitionToAdvanced_: function() {
|
| - var pod = this;
|
| - var languageAndInputSection =
|
| - this.querySelector('.language-and-input-section');
|
| - this.classList.add('transitioning-to-advanced');
|
| - setTimeout(function() {
|
| - pod.classList.add('advanced');
|
| - pod.makeSpaceForExpandedPod_();
|
| - languageAndInputSection.addEventListener('webkitTransitionEnd',
|
| - function observer() {
|
| - languageAndInputSection.removeEventListener('webkitTransitionEnd',
|
| - observer);
|
| - pod.classList.remove('transitioning-to-advanced');
|
| - pod.querySelector('.language-select').focus();
|
| - });
|
| - // Guard timer set to animation duration + 20ms.
|
| - ensureTransitionEndEvent(languageAndInputSection, 380);
|
| - }, 0);
|
| - },
|
| -
|
| - /**
|
| - * Populates the keyboard layout "select" element with a list of layouts.
|
| - * @param {!Object} list List of available keyboard layouts
|
| - */
|
| - populateKeyboardSelect_: function(list) {
|
| - var keyboardSelect = this.querySelector('.keyboard-select');
|
| - keyboardSelect.innerHTML = '';
|
| - for (var i = 0; i < list.length; ++i) {
|
| - var item = list[i];
|
| - keyboardSelect.appendChild(
|
| - new Option(item.title, item.value, item.selected, item.selected));
|
| - }
|
| - }
|
| - };
|
| -
|
| - /**
|
| - * Creates a user pod to be used only in desktop chrome.
|
| - * @constructor
|
| - * @extends {UserPod}
|
| - */
|
| - var DesktopUserPod = cr.ui.define(function() {
|
| - // Don't just instantiate a UserPod(), as this will call decorate() on the
|
| - // parent object, and add duplicate event listeners.
|
| - var node = $('user-pod-template').cloneNode(true);
|
| - node.removeAttribute('id');
|
| - return node;
|
| - });
|
| -
|
| - DesktopUserPod.prototype = {
|
| - __proto__: UserPod.prototype,
|
| -
|
| - /** @override */
|
| - get mainInput() {
|
| - if (this.user.needsSignin)
|
| - return this.passwordElement;
|
| - else
|
| - return this.nameElement;
|
| - },
|
| -
|
| - /** @override */
|
| - update: function() {
|
| - this.imageElement.src = this.user.userImage;
|
| - this.nameElement.textContent = this.user.displayName;
|
| -
|
| - var isLockedUser = this.user.needsSignin;
|
| - var isSupervisedUser = this.user.locallyManagedUser;
|
| - this.classList.toggle('locked', isLockedUser);
|
| - this.classList.toggle('supervised-user', isSupervisedUser);
|
| -
|
| - if (this.isAuthTypeUserClick)
|
| - this.passwordLabelElement.textContent = this.authValue;
|
| -
|
| - this.actionBoxRemoveUserWarningTextElement.hidden = isSupervisedUser;
|
| - this.actionBoxRemoveSupervisedUserWarningTextElement.hidden =
|
| - !isSupervisedUser;
|
| -
|
| - UserPod.prototype.updateActionBoxArea.call(this);
|
| - },
|
| -
|
| - /** @override */
|
| - focusInput: function() {
|
| - // Move tabIndex from the whole pod to the main input.
|
| - this.tabIndex = -1;
|
| - this.mainInput.tabIndex = UserPodTabOrder.POD_INPUT;
|
| - this.mainInput.focus();
|
| - },
|
| -
|
| - /** @override */
|
| - activate: function(e) {
|
| - if (!this.user.needsSignin) {
|
| - Oobe.launchUser(this.user.emailAddress, this.user.displayName);
|
| - } else if (!this.passwordElement.value) {
|
| - return false;
|
| - } else {
|
| - chrome.send('authenticatedLaunchUser',
|
| - [this.user.emailAddress,
|
| - this.user.displayName,
|
| - this.passwordElement.value]);
|
| - }
|
| - this.passwordElement.value = '';
|
| - 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);
|
| -
|
| - if (this.isAuthTypeUserClick)
|
| - chrome.send('attemptUnlock', [this.user.emailAddress]);
|
| - },
|
| - };
|
| -
|
| - /**
|
| - * 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.imageElement.title = this.user.label;
|
| - this.passwordEntryContainerElement.hidden = true;
|
| - this.launchAppButtonContainerElement.hidden = false;
|
| - 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() {
|
| - // 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}
|
| - */
|
| - var PodRow = cr.ui.define('podrow');
|
| -
|
| - PodRow.prototype = {
|
| - __proto__: HTMLDivElement.prototype,
|
| -
|
| - // Whether this user pod row is shown for the first time.
|
| - firstShown_: true,
|
| -
|
| - // True if inside focusPod().
|
| - insideFocusPod_: false,
|
| -
|
| - // Focused pod.
|
| - focusedPod_: undefined,
|
| -
|
| - // Activated pod, i.e. the pod of current login attempt.
|
| - activatedPod_: undefined,
|
| -
|
| - // Pod that was most recently focused, if any.
|
| - lastFocusedPod_: undefined,
|
| -
|
| - // Pods whose initial images haven't been loaded yet.
|
| - podsWithPendingImages_: [],
|
| -
|
| - // Whether pod placement has been postponed.
|
| - podPlacementPostponed_: false,
|
| -
|
| - // Standard user pod height/width.
|
| - userPodHeight_: 0,
|
| - userPodWidth_: 0,
|
| -
|
| - // Array of apps that are shown in addition to other user pods.
|
| - apps_: [],
|
| -
|
| - // True to show app pods along with user pods.
|
| - shouldShowApps_: true,
|
| -
|
| - // Array of users that are shown (public/supervised/regular).
|
| - users_: [],
|
| -
|
| - /** @override */
|
| - decorate: function() {
|
| - // Event listeners that are installed for the time period during which
|
| - // the element is visible.
|
| - this.listeners_ = {
|
| - focus: [this.handleFocus_.bind(this), true /* useCapture */],
|
| - click: [this.handleClick_.bind(this), true],
|
| - mousemove: [this.handleMouseMove_.bind(this), false],
|
| - keydown: [this.handleKeyDown.bind(this), false]
|
| - };
|
| -
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| - this.userPodHeight_ = isDesktopUserManager ? DESKTOP_POD_HEIGHT :
|
| - CROS_POD_HEIGHT;
|
| - // Same for Chrome OS and desktop.
|
| - this.userPodWidth_ = POD_WIDTH;
|
| - },
|
| -
|
| - /**
|
| - * Returns all the pods in this pod row.
|
| - * @type {NodeList}
|
| - */
|
| - get pods() {
|
| - return Array.prototype.slice.call(this.children);
|
| - },
|
| -
|
| - /**
|
| - * Return true if user pod row has only single user pod in it, which should
|
| - * always be focused.
|
| - * @type {boolean}
|
| - */
|
| - get alwaysFocusSinglePod() {
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| -
|
| - return isDesktopUserManager ? false : this.children.length == 1;
|
| - },
|
| -
|
| - /**
|
| - * 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.
|
| - */
|
| - getPodWithUsername_: function(username) {
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i) {
|
| - if (pod.user.username == username)
|
| - return pod;
|
| - }
|
| - return null;
|
| - },
|
| -
|
| - /**
|
| - * True if the the pod row is disabled (handles no user interaction).
|
| - * @type {boolean}
|
| - */
|
| - disabled_: false,
|
| - get disabled() {
|
| - return this.disabled_;
|
| - },
|
| - set disabled(value) {
|
| - this.disabled_ = value;
|
| - var controls = this.querySelectorAll('button,input');
|
| - for (var i = 0, control; control = controls[i]; ++i) {
|
| - control.disabled = value;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Creates a user pod from given email.
|
| - * @param {!Object} user User info dictionary.
|
| - */
|
| - createUserPod: function(user) {
|
| - var userPod;
|
| - if (user.isDesktopUser)
|
| - 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});
|
| -
|
| - userPod.hidden = false;
|
| - return userPod;
|
| - },
|
| -
|
| - /**
|
| - * Add an existing user pod to this pod row.
|
| - * @param {!Object} user User info dictionary.
|
| - */
|
| - addUserPod: function(user) {
|
| - var userPod = this.createUserPod(user);
|
| - this.appendChild(userPod);
|
| - userPod.initialize();
|
| - },
|
| -
|
| - /**
|
| - * 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.
|
| - */
|
| - removeUserPod: function(username) {
|
| - var podToRemove = this.getPodWithUsername_(username);
|
| - if (podToRemove == null) {
|
| - console.warn('Attempt to remove not existing pod for ' + username +
|
| - '.');
|
| - return;
|
| - }
|
| - this.removeChild(podToRemove);
|
| - if (this.pods.length > 0)
|
| - this.placePods_();
|
| - },
|
| -
|
| - /**
|
| - * Returns index of given pod or -1 if not found.
|
| - * @param {UserPod} pod Pod to look up.
|
| - * @private
|
| - */
|
| - indexOf_: function(pod) {
|
| - for (var i = 0; i < this.pods.length; ++i) {
|
| - if (pod == this.pods[i])
|
| - return i;
|
| - }
|
| - return -1;
|
| - },
|
| -
|
| - /**
|
| - * Populates pod row with given existing users and start init animation.
|
| - * @param {array} users Array of existing user emails.
|
| - */
|
| - loadPods: function(users) {
|
| - this.users_ = users;
|
| -
|
| - this.rebuildPods();
|
| - },
|
| -
|
| - /**
|
| - * Scrolls focused user pod into view.
|
| - */
|
| - scrollFocusedPodIntoView: function() {
|
| - var pod = this.focusedPod_;
|
| - if (!pod)
|
| - return;
|
| -
|
| - // First check whether focused pod is already fully visible.
|
| - var visibleArea = $('scroll-container');
|
| - var scrollTop = visibleArea.scrollTop;
|
| - var clientHeight = visibleArea.clientHeight;
|
| - var podTop = $('oobe').offsetTop + pod.offsetTop;
|
| - var padding = USER_POD_KEYBOARD_MIN_PADDING;
|
| - if (podTop + pod.height + padding <= scrollTop + clientHeight &&
|
| - podTop - padding >= scrollTop) {
|
| - return;
|
| - }
|
| -
|
| - // Scroll so that user pod is as centered as possible.
|
| - visibleArea.scrollTop = podTop - (clientHeight - pod.offsetHeight) / 2;
|
| - },
|
| -
|
| - /**
|
| - * Rebuilds pod row using users_ and apps_ that were previously set or
|
| - * updated.
|
| - */
|
| - rebuildPods: function() {
|
| - var emptyPodRow = this.pods.length == 0;
|
| -
|
| - // Clear existing pods.
|
| - this.innerHTML = '';
|
| - this.focusedPod_ = undefined;
|
| - this.activatedPod_ = undefined;
|
| - this.lastFocusedPod_ = undefined;
|
| -
|
| - // Switch off animation
|
| - Oobe.getInstance().toggleClass('flying-pods', false);
|
| -
|
| - // Populate the pod row.
|
| - for (var i = 0; i < this.users_.length; ++i)
|
| - this.addUserPod(this.users_[i]);
|
| -
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i)
|
| - this.podsWithPendingImages_.push(pod);
|
| -
|
| - // TODO(nkostylev): Edge case handling when kiosk apps are not fitting.
|
| - if (this.shouldShowApps_) {
|
| - for (var i = 0; i < this.apps_.length; ++i)
|
| - this.addUserPod(this.apps_[i]);
|
| - }
|
| -
|
| - // Make sure we eventually show the pod row, even if some image is stuck.
|
| - setTimeout(function() {
|
| - $('pod-row').classList.remove('images-loading');
|
| - }, POD_ROW_IMAGES_LOAD_TIMEOUT_MS);
|
| -
|
| - var isCrosAccountPicker = $('login-header-bar').signinUIState ==
|
| - SIGNIN_UI_STATE.ACCOUNT_PICKER;
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| -
|
| - // Chrome OS: immediately recalculate pods layout only when current UI
|
| - // is account picker. Otherwise postpone it.
|
| - // Desktop: recalculate pods layout right away.
|
| - if (isDesktopUserManager || isCrosAccountPicker) {
|
| - this.placePods_();
|
| -
|
| - // Without timeout changes in pods positions will be animated even
|
| - // though it happened when 'flying-pods' class was disabled.
|
| - setTimeout(function() {
|
| - Oobe.getInstance().toggleClass('flying-pods', true);
|
| - }, 0);
|
| -
|
| - // On desktop, don't pre-select a pod if it's the only one.
|
| - if (isDesktopUserManager && this.pods.length == 1)
|
| - this.focusPod();
|
| - else
|
| - this.focusPod(this.preselectedPod);
|
| - } else {
|
| - this.podPlacementPostponed_ = true;
|
| -
|
| - // Update [Cancel] button state.
|
| - if ($('login-header-bar').signinUIState ==
|
| - SIGNIN_UI_STATE.GAIA_SIGNIN &&
|
| - emptyPodRow &&
|
| - this.pods.length > 0) {
|
| - login.GaiaSigninScreen.updateCancelButtonState();
|
| - }
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * 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);
|
| - },
|
| -
|
| - /**
|
| - * Sets whether should show app pods.
|
| - * @param {boolean} shouldShowApps Whether app pods should be shown.
|
| - */
|
| - setShouldShowApps: function(shouldShowApps) {
|
| - if (this.shouldShowApps_ == shouldShowApps)
|
| - return;
|
| -
|
| - this.shouldShowApps_ = shouldShowApps;
|
| - this.rebuildPods();
|
| - },
|
| -
|
| - /**
|
| - * Shows a custom icon on a user pod besides the input field.
|
| - * @param {string} username Username of pod to add button
|
| - * @param {{scale1x: string, scale2x: string}} icon Dictionary of URLs of
|
| - * the custom icon's representations for 1x and 2x scale factors.
|
| - */
|
| - showUserPodCustomIcon: function(username, icon) {
|
| - var pod = this.getPodWithUsername_(username);
|
| - if (pod == null) {
|
| - console.error('Unable to show user pod button for ' + username +
|
| - ': user pod not found.');
|
| - return;
|
| - }
|
| -
|
| - pod.customIconElement.hidden = false;
|
| - pod.customIconElement.style.backgroundImage =
|
| - '-webkit-image-set(' +
|
| - 'url(' + icon.scale1x + ') 1x,' +
|
| - 'url(' + icon.scale2x + ') 2x)';
|
| - },
|
| -
|
| - /**
|
| - * Hides the custom icon in the user pod added by showUserPodCustomIcon().
|
| - * @param {string} username Username of pod to remove button
|
| - */
|
| - hideUserPodCustomIcon: function(username) {
|
| - var pod = this.getPodWithUsername_(username);
|
| - if (pod == null) {
|
| - console.error('Unable to hide user pod button for ' + username +
|
| - ': user pod not found.');
|
| - return;
|
| - }
|
| -
|
| - pod.customIconElement.hidden = true;
|
| - },
|
| -
|
| - /**
|
| - * Sets the authentication type used to authenticate the user.
|
| - * @param {string} username Username of selected user
|
| - * @param {number} authType Authentication type, must be one of the
|
| - * values listed in AUTH_TYPE enum.
|
| - * @param {string} value The initial value to use for authentication.
|
| - */
|
| - setAuthType: function(username, authType, value) {
|
| - var pod = this.getPodWithUsername_(username);
|
| - if (pod == null) {
|
| - console.error('Unable to set auth type for ' + username +
|
| - ': user pod not found.');
|
| - return;
|
| - }
|
| - pod.setAuthType(authType, value);
|
| - },
|
| -
|
| - /**
|
| - * Shows a tooltip bubble explaining Easy Unlock for the focused pod.
|
| - */
|
| - showEasyUnlockBubble: function() {
|
| - if (!this.focusedPod_) {
|
| - console.error('No focused pod to show Easy Unlock bubble.');
|
| - return;
|
| - }
|
| -
|
| - var bubbleContent = document.createElement('div');
|
| - bubbleContent.classList.add('easy-unlock-button-content');
|
| - bubbleContent.textContent = loadTimeData.getString('easyUnlockTooltip');
|
| -
|
| - var attachElement = this.focusedPod_.customIconElement;
|
| - /** @const */ var BUBBLE_OFFSET = 20;
|
| - /** @const */ var BUBBLE_PADDING = 8;
|
| - $('bubble').showContentForElement(attachElement,
|
| - cr.ui.Bubble.Attachment.RIGHT,
|
| - bubbleContent,
|
| - BUBBLE_OFFSET,
|
| - BUBBLE_PADDING);
|
| - },
|
| -
|
| - /**
|
| - * Updates the list of available keyboard layouts for a public session pod.
|
| - * @param {string} userID The user ID of the public session
|
| - * @param {!Object} list List of available keyboard layouts
|
| - */
|
| - setPublicSessionKeyboardLayouts: function(userID, list) {
|
| - var pod = this.getPodWithUsername_(userID);
|
| - if (pod != null)
|
| - pod.populateKeyboardSelect_(list);
|
| - },
|
| -
|
| - /**
|
| - * Called when window was resized.
|
| - */
|
| - onWindowResize: function() {
|
| - var layout = this.calculateLayout_();
|
| - if (layout.columns != this.columns || layout.rows != this.rows)
|
| - this.placePods_();
|
| -
|
| - if (Oobe.getInstance().virtualKeyboardShown)
|
| - this.scrollFocusedPodIntoView();
|
| - },
|
| -
|
| - /**
|
| - * Returns width of podrow having |columns| number of columns.
|
| - * @private
|
| - */
|
| - columnsToWidth_: function(columns) {
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| - var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
|
| - MARGIN_BY_COLUMNS[columns];
|
| - var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
|
| - POD_ROW_PADDING;
|
| - return 2 * rowPadding + columns * this.userPodWidth_ +
|
| - (columns - 1) * margin;
|
| - },
|
| -
|
| - /**
|
| - * Returns height of podrow having |rows| number of rows.
|
| - * @private
|
| - */
|
| - rowsToHeight_: function(rows) {
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| - var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
|
| - POD_ROW_PADDING;
|
| - return 2 * rowPadding + rows * this.userPodHeight_;
|
| - },
|
| -
|
| - /**
|
| - * Calculates number of columns and rows that podrow should have in order to
|
| - * hold as much its pods as possible for current screen size. Also it tries
|
| - * to choose layout that looks good.
|
| - * @return {{columns: number, rows: number}}
|
| - */
|
| - calculateLayout_: function() {
|
| - var preferredColumns = this.pods.length < COLUMNS.length ?
|
| - COLUMNS[this.pods.length] : COLUMNS[COLUMNS.length - 1];
|
| - var maxWidth = Oobe.getInstance().clientAreaSize.width;
|
| - var columns = preferredColumns;
|
| - while (maxWidth < this.columnsToWidth_(columns) && columns > 1)
|
| - --columns;
|
| - var rows = Math.floor((this.pods.length - 1) / columns) + 1;
|
| - if (getComputedStyle(
|
| - $('signin-banner'), null).getPropertyValue('display') != 'none') {
|
| - rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER);
|
| - }
|
| - var maxHeigth = Oobe.getInstance().clientAreaSize.height;
|
| - while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
|
| - --rows;
|
| - // One more iteration if it's not enough cells to place all pods.
|
| - while (maxWidth >= this.columnsToWidth_(columns + 1) &&
|
| - columns * rows < this.pods.length &&
|
| - columns < MAX_NUMBER_OF_COLUMNS) {
|
| - ++columns;
|
| - }
|
| - return {columns: columns, rows: rows};
|
| - },
|
| -
|
| - /**
|
| - * Places pods onto their positions onto pod grid.
|
| - * @private
|
| - */
|
| - placePods_: function() {
|
| - var layout = this.calculateLayout_();
|
| - var columns = this.columns = layout.columns;
|
| - var rows = this.rows = layout.rows;
|
| - var maxPodsNumber = columns * rows;
|
| - var isDesktopUserManager = Oobe.getInstance().displayType ==
|
| - DISPLAY_TYPE.DESKTOP_USER_MANAGER;
|
| - var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
|
| - MARGIN_BY_COLUMNS[columns];
|
| - this.parentNode.setPreferredSize(
|
| - this.columnsToWidth_(columns), this.rowsToHeight_(rows));
|
| - var height = this.userPodHeight_;
|
| - var width = this.userPodWidth_;
|
| - this.pods.forEach(function(pod, index) {
|
| - if (pod.offsetHeight != height) {
|
| - console.error('Pod offsetHeight (' + pod.offsetHeight +
|
| - ') and POD_HEIGHT (' + height + ') are not equal.');
|
| - }
|
| - if (pod.offsetWidth != width) {
|
| - console.error('Pod offsetWidth (' + pod.offsetWidth +
|
| - ') and POD_WIDTH (' + width + ') are not equal.');
|
| - }
|
| - if (index >= maxPodsNumber) {
|
| - pod.hidden = true;
|
| - return;
|
| - }
|
| - pod.hidden = false;
|
| - var column = index % columns;
|
| - var row = Math.floor(index / columns);
|
| - var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING :
|
| - POD_ROW_PADDING;
|
| - pod.left = rowPadding + column * (width + margin);
|
| -
|
| - // On desktop, we want the rows to always be equally spaced.
|
| - pod.top = isDesktopUserManager ? row * (height + rowPadding) :
|
| - row * height + rowPadding;
|
| - });
|
| - Oobe.getInstance().updateScreenSize(this.parentNode);
|
| - },
|
| -
|
| - /**
|
| - * Number of columns.
|
| - * @type {?number}
|
| - */
|
| - set columns(columns) {
|
| - // Cannot use 'columns' here.
|
| - this.setAttribute('ncolumns', columns);
|
| - },
|
| - get columns() {
|
| - return parseInt(this.getAttribute('ncolumns'));
|
| - },
|
| -
|
| - /**
|
| - * Number of rows.
|
| - * @type {?number}
|
| - */
|
| - set rows(rows) {
|
| - // Cannot use 'rows' here.
|
| - this.setAttribute('nrows', rows);
|
| - },
|
| - get rows() {
|
| - return parseInt(this.getAttribute('nrows'));
|
| - },
|
| -
|
| - /**
|
| - * Whether the pod is currently focused.
|
| - * @param {UserPod} pod Pod to check for focus.
|
| - * @return {boolean} Pod focus status.
|
| - */
|
| - isFocused: function(pod) {
|
| - return this.focusedPod_ == pod;
|
| - },
|
| -
|
| - /**
|
| - * 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.
|
| - */
|
| - focusPod: function(podToFocus, opt_force) {
|
| - if (this.isFocused(podToFocus) && !opt_force) {
|
| - // Calling focusPod w/o podToFocus means reset.
|
| - if (!podToFocus)
|
| - Oobe.clearErrors();
|
| - this.keyboardActivated_ = false;
|
| - return;
|
| - }
|
| -
|
| - // Make sure there's only one focusPod operation happening at a time.
|
| - if (this.insideFocusPod_) {
|
| - this.keyboardActivated_ = false;
|
| - return;
|
| - }
|
| - this.insideFocusPod_ = true;
|
| -
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i) {
|
| - if (!this.alwaysFocusSinglePod) {
|
| - pod.isActionBoxMenuActive = false;
|
| - }
|
| - if (pod != podToFocus) {
|
| - pod.isActionBoxMenuHovered = false;
|
| - pod.classList.remove('focused');
|
| - // On Desktop, the faded style is not set correctly, so we should
|
| - // manually fade out non-focused pods if there is a focused pod.
|
| - if (pod.user.isDesktopUser && podToFocus)
|
| - pod.classList.add('faded');
|
| - else
|
| - pod.classList.remove('faded');
|
| - pod.reset(false);
|
| - }
|
| - }
|
| -
|
| - // Clear any error messages for previous pod.
|
| - if (!this.isFocused(podToFocus))
|
| - Oobe.clearErrors();
|
| -
|
| - var hadFocus = !!this.focusedPod_;
|
| - this.focusedPod_ = podToFocus;
|
| - if (podToFocus) {
|
| - podToFocus.classList.remove('faded');
|
| - podToFocus.classList.add('focused');
|
| - if (!podToFocus.multiProfilesPolicyApplied)
|
| - podToFocus.reset(true); // Reset and give focus.
|
| - else {
|
| - podToFocus.userTypeBubbleElement.classList.add('bubble-shown');
|
| - podToFocus.focus();
|
| - }
|
| -
|
| - // focusPod() automatically loads wallpaper
|
| - if (!podToFocus.user.isApp)
|
| - chrome.send('focusPod', [podToFocus.user.username]);
|
| - this.firstShown_ = false;
|
| - this.lastFocusedPod_ = podToFocus;
|
| -
|
| - if (Oobe.getInstance().virtualKeyboardShown)
|
| - this.scrollFocusedPodIntoView();
|
| - }
|
| - this.insideFocusPod_ = false;
|
| - this.keyboardActivated_ = false;
|
| - },
|
| -
|
| - /**
|
| - * 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.
|
| - */
|
| - focusPodByIndex: function(podToFocus, opt_force) {
|
| - if (podToFocus < this.pods.length)
|
| - this.focusPod(this.pods[podToFocus], opt_force);
|
| - },
|
| -
|
| - /**
|
| - * Resets wallpaper to the last active user's wallpaper, if any.
|
| - */
|
| - loadLastWallpaper: function() {
|
| - if (this.lastFocusedPod_ && !this.lastFocusedPod_.user.isApp)
|
| - chrome.send('loadWallpaper', [this.lastFocusedPod_.user.username]);
|
| - },
|
| -
|
| - /**
|
| - * Returns the currently activated pod.
|
| - * @type {UserPod}
|
| - */
|
| - get activatedPod() {
|
| - return this.activatedPod_;
|
| - },
|
| -
|
| - /**
|
| - * 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;
|
| - },
|
| -
|
| - /**
|
| - * The pod of the signed-in user, if any; null otherwise.
|
| - * @type {?UserPod}
|
| - */
|
| - get lockedPod() {
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i) {
|
| - if (pod.user.signedIn)
|
| - return pod;
|
| - }
|
| - return null;
|
| - },
|
| -
|
| - /**
|
| - * The pod that is preselected on user pod row show.
|
| - * @type {?UserPod}
|
| - */
|
| - get preselectedPod() {
|
| - var lockedPod = this.lockedPod;
|
| - if (lockedPod || !PRESELECT_FIRST_POD)
|
| - return lockedPod;
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i) {
|
| - if (!pod.multiProfilesPolicyApplied) {
|
| - return pod;
|
| - }
|
| - }
|
| - return this.pods[0];
|
| - },
|
| -
|
| - /**
|
| - * Resets input UI.
|
| - * @param {boolean} takeFocus True to take focus.
|
| - */
|
| - reset: function(takeFocus) {
|
| - this.disabled = false;
|
| - if (this.activatedPod_)
|
| - this.activatedPod_.reset(takeFocus);
|
| - },
|
| -
|
| - /**
|
| - * Restores input focus to current selected pod, if there is any.
|
| - */
|
| - refocusCurrentPod: function() {
|
| - if (this.focusedPod_ && !this.focusedPod_.multiProfilesPolicyApplied) {
|
| - this.focusedPod_.focusInput();
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Clears focused pod password field.
|
| - */
|
| - clearFocusedPod: function() {
|
| - if (!this.disabled && this.focusedPod_)
|
| - this.focusedPod_.reset(true);
|
| - },
|
| -
|
| - /**
|
| - * Shows signin UI.
|
| - * @param {string} email Email for signin UI.
|
| - */
|
| - showSigninUI: function(email) {
|
| - // Clear any error messages that might still be around.
|
| - Oobe.clearErrors();
|
| - this.disabled = true;
|
| - this.lastFocusedPod_ = this.getPodWithUsername_(email);
|
| - Oobe.showSigninUI(email);
|
| - },
|
| -
|
| - /**
|
| - * Updates current image of a user.
|
| - * @param {string} username User for which to update the image.
|
| - */
|
| - updateUserImage: function(username) {
|
| - var pod = this.getPodWithUsername_(username);
|
| - if (pod)
|
| - pod.updateUserImage();
|
| - },
|
| -
|
| - /**
|
| - * Handler of click event.
|
| - * @param {Event} e Click Event object.
|
| - * @private
|
| - */
|
| - handleClick_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| -
|
| - // Clear all menus if the click is outside pod menu and its
|
| - // button area.
|
| - if (!findAncestorByClass(e.target, 'action-box-menu') &&
|
| - !findAncestorByClass(e.target, 'action-box-area')) {
|
| - for (var i = 0, pod; pod = this.pods[i]; ++i)
|
| - pod.isActionBoxMenuActive = false;
|
| - }
|
| -
|
| - // Clears focus if not clicked on a pod and if there's more than one pod.
|
| - var pod = findAncestorByClass(e.target, 'pod');
|
| - if ((!pod || pod.parentNode != this) && !this.alwaysFocusSinglePod) {
|
| - this.focusPod();
|
| - }
|
| -
|
| - if (pod)
|
| - pod.isActionBoxMenuHovered = true;
|
| -
|
| - // Return focus back to single pod.
|
| - if (this.alwaysFocusSinglePod && !pod) {
|
| - this.focusPod(this.focusedPod_, true /* force */);
|
| - this.focusedPod_.userTypeBubbleElement.classList.remove('bubble-shown');
|
| - this.focusedPod_.isActionBoxMenuHovered = false;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handler of mouse move event.
|
| - * @param {Event} e Click Event object.
|
| - * @private
|
| - */
|
| - handleMouseMove_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - if (e.webkitMovementX == 0 && e.webkitMovementY == 0)
|
| - return;
|
| -
|
| - // Defocus (thus hide) action box, if it is focused on a user pod
|
| - // and the pointer is not hovering over it.
|
| - var pod = findAncestorByClass(e.target, 'pod');
|
| - if (document.activeElement &&
|
| - document.activeElement.parentNode != pod &&
|
| - document.activeElement.classList.contains('action-box-area')) {
|
| - document.activeElement.parentNode.focus();
|
| - }
|
| -
|
| - if (pod)
|
| - pod.isActionBoxMenuHovered = true;
|
| -
|
| - // Hide action boxes on other user pods.
|
| - for (var i = 0, p; p = this.pods[i]; ++i)
|
| - if (p != pod && !p.isActionBoxMenuActive)
|
| - p.isActionBoxMenuHovered = false;
|
| - },
|
| -
|
| - /**
|
| - * Handles focus event.
|
| - * @param {Event} e Focus Event object.
|
| - * @private
|
| - */
|
| - handleFocus_: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - if (e.target.parentNode == this) {
|
| - // Focus on a pod
|
| - if (e.target.classList.contains('focused')) {
|
| - if (!e.target.multiProfilesPolicyApplied)
|
| - e.target.focusInput();
|
| - else
|
| - e.target.userTypeBubbleElement.classList.add('bubble-shown');
|
| - } else
|
| - this.focusPod(e.target);
|
| - return;
|
| - }
|
| -
|
| - var pod = findAncestorByClass(e.target, 'pod');
|
| - if (pod && pod.parentNode == this) {
|
| - // Focus on a control of a pod but not on the action area button.
|
| - if (!pod.classList.contains('focused') &&
|
| - !e.target.classList.contains('action-box-button')) {
|
| - this.focusPod(pod);
|
| - pod.userTypeBubbleElement.classList.remove('bubble-shown');
|
| - e.target.focus();
|
| - }
|
| - return;
|
| - }
|
| -
|
| - // Clears pod focus when we reach here. It means new focus is neither
|
| - // on a pod nor on a button/input for a pod.
|
| - // Do not "defocus" user pod when it is a single pod.
|
| - // That means that 'focused' class will not be removed and
|
| - // input field/button will always be visible.
|
| - if (!this.alwaysFocusSinglePod)
|
| - this.focusPod();
|
| - else {
|
| - // Hide user-type-bubble in case this is one pod and we lost focus of
|
| - // it.
|
| - this.focusedPod_.userTypeBubbleElement.classList.remove('bubble-shown');
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Handler of keydown event.
|
| - * @param {Event} e KeyDown Event object.
|
| - */
|
| - handleKeyDown: function(e) {
|
| - if (this.disabled)
|
| - return;
|
| - var editing = e.target.tagName == 'INPUT' && e.target.value;
|
| - switch (e.keyIdentifier) {
|
| - case 'Left':
|
| - if (!editing) {
|
| - this.keyboardActivated_ = true;
|
| - if (this.focusedPod_ && this.focusedPod_.previousElementSibling)
|
| - this.focusPod(this.focusedPod_.previousElementSibling);
|
| - else
|
| - this.focusPod(this.lastElementChild);
|
| -
|
| - e.stopPropagation();
|
| - }
|
| - break;
|
| - case 'Right':
|
| - if (!editing) {
|
| - this.keyboardActivated_ = true;
|
| - if (this.focusedPod_ && this.focusedPod_.nextElementSibling)
|
| - this.focusPod(this.focusedPod_.nextElementSibling);
|
| - else
|
| - this.focusPod(this.firstElementChild);
|
| -
|
| - e.stopPropagation();
|
| - }
|
| - break;
|
| - case 'Enter':
|
| - if (this.focusedPod_) {
|
| - var targetTag = e.target.tagName;
|
| - if (e.target == this.focusedPod_.passwordElement ||
|
| - (targetTag != 'INPUT' &&
|
| - targetTag != 'BUTTON' &&
|
| - targetTag != 'A')) {
|
| - this.setActivatedPod(this.focusedPod_, e);
|
| - e.stopPropagation();
|
| - }
|
| - }
|
| - break;
|
| - case 'U+001B': // Esc
|
| - if (!this.alwaysFocusSinglePod)
|
| - this.focusPod();
|
| - break;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Called right after the pod row is shown.
|
| - */
|
| - handleAfterShow: function() {
|
| - // Without timeout changes in pods positions will be animated even though
|
| - // it happened when 'flying-pods' class was disabled.
|
| - setTimeout(function() {
|
| - Oobe.getInstance().toggleClass('flying-pods', true);
|
| - }, 0);
|
| - // Force input focus for user pod on show and once transition ends.
|
| - if (this.focusedPod_) {
|
| - var focusedPod = this.focusedPod_;
|
| - var screen = this.parentNode;
|
| - var self = this;
|
| - focusedPod.addEventListener('webkitTransitionEnd', function f(e) {
|
| - focusedPod.removeEventListener('webkitTransitionEnd', f);
|
| - focusedPod.reset(true);
|
| - // Notify screen that it is ready.
|
| - screen.onShow();
|
| - });
|
| - // Guard timer for 1 second -- it would conver all possible animations.
|
| - ensureTransitionEndEvent(focusedPod, 1000);
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Called right before the pod row is shown.
|
| - */
|
| - handleBeforeShow: function() {
|
| - Oobe.getInstance().toggleClass('flying-pods', false);
|
| - for (var event in this.listeners_) {
|
| - this.ownerDocument.addEventListener(
|
| - event, this.listeners_[event][0], this.listeners_[event][1]);
|
| - }
|
| - $('login-header-bar').buttonsTabIndex = UserPodTabOrder.HEADER_BAR;
|
| -
|
| - if (this.podPlacementPostponed_) {
|
| - this.podPlacementPostponed_ = false;
|
| - this.placePods_();
|
| - pod = this.preselectedPod;
|
| - this.focusPod(pod);
|
| - // Hide user-type-bubble in case all user pods are disabled and we focus
|
| - // first pod.
|
| - if (pod && pod.multiProfilesPolicyApplied) {
|
| - pod.userTypeBubbleElement.classList.remove('bubble-shown');
|
| - }
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Called when the element is hidden.
|
| - */
|
| - handleHide: function() {
|
| - for (var event in this.listeners_) {
|
| - this.ownerDocument.removeEventListener(
|
| - event, this.listeners_[event][0], this.listeners_[event][1]);
|
| - }
|
| - $('login-header-bar').buttonsTabIndex = 0;
|
| - },
|
| -
|
| - /**
|
| - * Called when a pod's user image finishes loading.
|
| - */
|
| - handlePodImageLoad: function(pod) {
|
| - var index = this.podsWithPendingImages_.indexOf(pod);
|
| - if (index == -1) {
|
| - return;
|
| - }
|
| -
|
| - this.podsWithPendingImages_.splice(index, 1);
|
| - if (this.podsWithPendingImages_.length == 0) {
|
| - this.classList.remove('images-loading');
|
| - }
|
| - }
|
| - };
|
| -
|
| - return {
|
| - PodRow: PodRow
|
| - };
|
| -});
|
|
|