Index: ui/login/account_picker/md_screen_account_picker.js |
diff --git a/ui/login/account_picker/md_screen_account_picker.js b/ui/login/account_picker/md_screen_account_picker.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1db4ae69288300816650d1b984eccca5fcd7cfa6 |
--- /dev/null |
+++ b/ui/login/account_picker/md_screen_account_picker.js |
@@ -0,0 +1,476 @@ |
+// 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 Account picker screen implementation. |
+ */ |
+ |
+login.createScreen('AccountPickerScreen', 'account-picker', function() { |
+ /** |
+ * Maximum number of offline login failures before online login. |
+ * @type {number} |
+ * @const |
+ */ |
+ var MAX_LOGIN_ATTEMPTS_IN_POD = 3; |
+ |
+ /** |
+ * Distance between error bubble and user POD. |
+ * @type {number} |
+ * @const |
+ */ |
+ var BUBBLE_POD_OFFSET = 4; |
+ |
+ return { |
+ EXTERNAL_API: [ |
+ 'loadUsers', |
+ 'runAppForTesting', |
+ 'setApps', |
+ 'setShouldShowApps', |
+ 'showAppError', |
+ 'updateUserImage', |
+ 'setCapsLockState', |
+ 'forceLockedUserPodFocus', |
+ 'removeUser', |
+ 'showBannerMessage', |
+ 'showUserPodCustomIcon', |
+ 'hideUserPodCustomIcon', |
+ 'setUserPodFingerprintIcon', |
+ 'removeUserPodFingerprintIcon', |
+ 'setPinEnabledForUser', |
+ 'setAuthType', |
+ 'setTouchViewState', |
+ 'setPublicSessionDisplayName', |
+ 'setPublicSessionLocales', |
+ 'setPublicSessionKeyboardLayouts', |
+ ], |
+ |
+ preferredWidth_: 0, |
+ preferredHeight_: 0, |
+ |
+ // Whether this screen is shown for the first time. |
+ firstShown_: true, |
+ |
+ // Whether this screen is currently being shown. |
+ showing_: false, |
+ |
+ /** @override */ |
+ decorate: function() { |
+ login.PodRow.decorate($('pod-row')); |
+ }, |
+ |
+ /** @override */ |
+ getPreferredSize: function() { |
+ return {width: this.preferredWidth_, height: this.preferredHeight_}; |
+ }, |
+ |
+ /** @override */ |
+ onWindowResize: function() { |
+ $('pod-row').onWindowResize(); |
+ |
+ // Reposition the error bubble, if it is showing. Since we are just |
+ // moving the bubble, the number of login attempts tried doesn't matter. |
+ var errorBubble = $('bubble'); |
+ if (errorBubble && !errorBubble.hidden) |
+ this.showErrorBubble(0, undefined /* Reuses the existing message. */); |
+ }, |
+ |
+ /** |
+ * Sets preferred size for account picker screen. |
+ */ |
+ setPreferredSize: function(width, height) { |
+ this.preferredWidth_ = width; |
+ this.preferredHeight_ = height; |
+ }, |
+ |
+ /** |
+ * When the account picker is being used to lock the screen, pressing the |
+ * exit accelerator key will sign out the active user as it would when |
+ * they are signed in. |
+ */ |
+ exit: function() { |
+ // Check and disable the sign out button so that we can never have two |
+ // sign out requests generated in a row. |
+ if ($('pod-row').lockedPod && !$('sign-out-user-button').disabled) { |
+ $('sign-out-user-button').disabled = true; |
+ chrome.send('signOutUser'); |
+ } |
+ }, |
+ |
+ /* Cancel user adding if ESC was pressed. |
+ */ |
+ cancel: function() { |
+ if (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING) |
+ chrome.send('cancelUserAdding'); |
+ }, |
+ |
+ /** |
+ * Event handler that is invoked just after the frame is shown. |
+ * @param {string} data Screen init payload. |
+ */ |
+ onAfterShow: function(data) { |
+ $('pod-row').handleAfterShow(); |
+ }, |
+ |
+ /** |
+ * Event handler that is invoked just before the frame is shown. |
+ * @param {string} data Screen init payload. |
+ */ |
+ onBeforeShow: function(data) { |
+ this.showing_ = true; |
+ chrome.send('loginUIStateChanged', ['account-picker', true]); |
+ $('login-header-bar').signinUIState = SIGNIN_UI_STATE.ACCOUNT_PICKER; |
+ // Header bar should be always visible on Account Picker screen. |
+ Oobe.getInstance().headerHidden = false; |
+ chrome.send('hideCaptivePortal'); |
+ var podRow = $('pod-row'); |
+ podRow.handleBeforeShow(); |
+ |
+ // In case of the preselected pod onShow will be called once pod |
+ // receives focus. |
+ if (!podRow.preselectedPod) |
+ this.onShow(); |
+ }, |
+ |
+ /** |
+ * Event handler invoked when the page is shown and ready. |
+ */ |
+ onShow: function() { |
+ if (!this.showing_) { |
+ // This method may be called asynchronously when the pod row finishes |
+ // initializing. However, at that point, the screen may have been hidden |
+ // again already. If that happens, ignore the onShow() call. |
+ return; |
+ } |
+ chrome.send('getTouchViewState'); |
+ if (!this.firstShown_) return; |
+ this.firstShown_ = false; |
+ |
+ // Ensure that login is actually visible. |
+ window.requestAnimationFrame(function() { |
+ chrome.send('accountPickerReady'); |
+ chrome.send('loginVisible', ['account-picker']); |
+ }); |
+ }, |
+ |
+ /** |
+ * Event handler that is invoked just before the frame is hidden. |
+ */ |
+ onBeforeHide: function() { |
+ $('pod-row').clearFocusedPod(); |
+ this.showing_ = false; |
+ chrome.send('loginUIStateChanged', ['account-picker', false]); |
+ $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN; |
+ $('pod-row').handleHide(); |
+ }, |
+ |
+ /** |
+ * Shows sign-in error bubble. |
+ * @param {number} loginAttempts Number of login attemps tried. |
+ * @param {HTMLElement} content Content to show in bubble. |
+ */ |
+ showErrorBubble: function(loginAttempts, error) { |
+ var activatedPod = $('pod-row').activatedPod; |
+ if (!activatedPod) { |
+ $('bubble').showContentForElement($('pod-row'), |
+ cr.ui.Bubble.Attachment.RIGHT, |
+ error); |
+ return; |
+ } |
+ // Show web authentication if this is not a supervised user. |
+ if (loginAttempts > MAX_LOGIN_ATTEMPTS_IN_POD && |
+ !activatedPod.user.supervisedUser) { |
+ chrome.send('maxIncorrectPasswordAttempts', |
+ [activatedPod.user.emailAddress]); |
+ activatedPod.showSigninUI(); |
+ } else { |
+ if (loginAttempts == 1) { |
+ chrome.send('firstIncorrectPasswordAttempt', |
+ [activatedPod.user.emailAddress]); |
+ } |
+ // Update the pod row display if incorrect password. |
+ $('pod-row').setFocusedPodErrorDisplay(true); |
+ |
+ /** @const */ var BUBBLE_OFFSET = 25; |
+ // -8 = 4(BUBBLE_POD_OFFSET) - 2(bubble margin) |
+ // - 10(internal bubble adjustment) |
+ var bubblePositioningPadding = -8; |
+ |
+ var bubbleAnchor; |
+ var attachment; |
+ if (activatedPod.pinContainer) { |
+ // Anchor the bubble to the input field. |
+ bubbleAnchor = ( |
+ activatedPod.getElementsByClassName('auth-container'))[0]; |
+ if (!bubbleAnchor) { |
+ console.error('auth-container not found!'); |
+ bubbleAnchor = activatedPod.mainInput; |
+ } |
+ attachment = cr.ui.Bubble.Attachment.RIGHT; |
+ } else { |
+ // Anchor the bubble to the pod instead of the input. |
+ bubbleAnchor = activatedPod; |
+ attachment = cr.ui.Bubble.Attachment.BOTTOM; |
+ } |
+ |
+ var bubble = $('bubble'); |
+ |
+ // Cannot use cr.ui.LoginUITools.get* on bubble until it is attached to |
+ // the element. getMaxHeight/Width rely on the correct up/left element |
+ // side positioning that doesn't happen until bubble is attached. |
+ var maxHeight = |
+ cr.ui.LoginUITools.getMaxHeightBeforeShelfOverlapping(bubbleAnchor) |
+ - bubbleAnchor.offsetHeight - BUBBLE_POD_OFFSET; |
+ var maxWidth = cr.ui.LoginUITools.getMaxWidthToFit(bubbleAnchor) |
+ - bubbleAnchor.offsetWidth - BUBBLE_POD_OFFSET; |
+ |
+ // Change bubble visibility temporary to calculate height. |
+ var bubbleVisibility = bubble.style.visibility; |
+ bubble.style.visibility = 'hidden'; |
+ bubble.hidden = false; |
+ // Now we need the bubble to have the new content before calculating |
+ // size. Undefined |error| == reuse old content. |
+ if (error !== undefined) |
+ bubble.replaceContent(error); |
+ |
+ // Get bubble size. |
+ var bubbleOffsetHeight = parseInt(bubble.offsetHeight); |
+ var bubbleOffsetWidth = parseInt(bubble.offsetWidth); |
+ // Restore attributes. |
+ bubble.style.visibility = bubbleVisibility; |
+ bubble.hidden = true; |
+ |
+ if (attachment == cr.ui.Bubble.Attachment.BOTTOM) { |
+ // Move error bubble if it overlaps the shelf. |
+ if (maxHeight < bubbleOffsetHeight) |
+ attachment = cr.ui.Bubble.Attachment.TOP; |
+ } else { |
+ // Move error bubble if it doesn't fit screen. |
+ if (maxWidth < bubbleOffsetWidth) { |
+ bubblePositioningPadding = 2; |
+ attachment = cr.ui.Bubble.Attachment.LEFT; |
+ } |
+ } |
+ var showBubbleCallback = function() { |
+ activatedPod.removeEventListener("transitionend", |
+ showBubbleCallback); |
+ $('bubble').showContentForElement(bubbleAnchor, |
+ attachment, |
+ error, |
+ BUBBLE_OFFSET, |
+ bubblePositioningPadding, true); |
+ }; |
+ activatedPod.addEventListener("transitionend", |
+ showBubbleCallback); |
+ ensureTransitionEndEvent(activatedPod); |
+ } |
+ }, |
+ |
+ /** |
+ * Loads given users in pod row. |
+ * @param {array} users Array of user. |
+ * @param {boolean} showGuest Whether to show guest session button. |
+ */ |
+ loadUsers: function(users, showGuest) { |
+ $('pod-row').loadPods(users); |
+ $('login-header-bar').showGuestButton = showGuest; |
+ // On Desktop, #login-header-bar has a shadow if there are 8+ profiles. |
+ if (Oobe.getInstance().displayType == DISPLAY_TYPE.DESKTOP_USER_MANAGER) |
+ $('login-header-bar').classList.toggle('shadow', users.length > 8); |
+ }, |
+ |
+ /** |
+ * 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. |
+ */ |
+ runAppForTesting: function(app_id, opt_diagnostic_mode) { |
+ $('pod-row').findAndRunAppForTesting(app_id, opt_diagnostic_mode); |
+ }, |
+ |
+ /** |
+ * Adds given apps to the pod row. |
+ * @param {array} apps Array of apps. |
+ */ |
+ setApps: function(apps) { |
+ $('pod-row').setApps(apps); |
+ }, |
+ |
+ /** |
+ * Sets the flag of whether app pods should be visible. |
+ * @param {boolean} shouldShowApps Whether to show app pods. |
+ */ |
+ setShouldShowApps: function(shouldShowApps) { |
+ $('pod-row').setShouldShowApps(shouldShowApps); |
+ }, |
+ |
+ /** |
+ * Shows the given kiosk app error message. |
+ * @param {!string} message Error message to show. |
+ */ |
+ showAppError: function(message) { |
+ // TODO(nkostylev): Figure out a way to show kiosk app launch error |
+ // pointing to the kiosk app pod. |
+ /** @const */ var BUBBLE_PADDING = 12; |
+ $('bubble').showTextForElement($('pod-row'), |
+ message, |
+ cr.ui.Bubble.Attachment.BOTTOM, |
+ $('pod-row').offsetWidth / 2, |
+ BUBBLE_PADDING); |
+ }, |
+ |
+ /** |
+ * Updates current image of a user. |
+ * @param {string} username User for which to update the image. |
+ */ |
+ updateUserImage: function(username) { |
+ $('pod-row').updateUserImage(username); |
+ }, |
+ |
+ /** |
+ * Updates Caps Lock state (for Caps Lock hint in password input field). |
+ * @param {boolean} enabled Whether Caps Lock is on. |
+ */ |
+ setCapsLockState: function(enabled) { |
+ $('pod-row').classList.toggle('capslock-on', enabled); |
+ }, |
+ |
+ /** |
+ * Enforces focus on user pod of locked user. |
+ */ |
+ forceLockedUserPodFocus: function() { |
+ var row = $('pod-row'); |
+ if (row.lockedPod) |
+ row.focusPod(row.lockedPod, true); |
+ }, |
+ |
+ /** |
+ * Remove given user from pod row if it is there. |
+ * @param {string} user name. |
+ */ |
+ removeUser: function(username) { |
+ $('pod-row').removeUserPod(username); |
+ }, |
+ |
+ /** |
+ * Displays a banner containing |message|. If the banner is already present |
+ * this function updates the message in the banner. This function is used |
+ * by the chrome.screenlockPrivate.showMessage API. |
+ * @param {string} message Text to be displayed or empty to hide the banner. |
+ */ |
+ showBannerMessage: function(message) { |
+ var banner = $('signin-banner'); |
+ banner.textContent = message; |
+ banner.classList.toggle('message-set', !!message); |
+ }, |
+ |
+ /** |
+ * Shows a custom icon in the user pod of |username|. This function |
+ * is used by the chrome.screenlockPrivate API. |
+ * @param {string} username Username of pod to add button |
+ * @param {!{id: !string, |
+ * hardlockOnClick: boolean, |
+ * isTrialRun: boolean, |
+ * tooltip: ({text: string, autoshow: boolean} | undefined)}} icon |
+ * The icon parameters. |
+ */ |
+ showUserPodCustomIcon: function(username, icon) { |
+ $('pod-row').showUserPodCustomIcon(username, icon); |
+ }, |
+ |
+ /** |
+ * Hides the custom icon in the user pod of |username| added by |
+ * showUserPodCustomIcon(). This function is used by the |
+ * chrome.screenlockPrivate API. |
+ * @param {string} username Username of pod to remove button |
+ */ |
+ hideUserPodCustomIcon: function(username) { |
+ $('pod-row').hideUserPodCustomIcon(username); |
+ }, |
+ |
+ /** |
+ * Set a fingerprint icon in the user pod of |username|. |
+ * @param {string} username Username of the selected user |
+ * @param {number} state Fingerprint unlock state |
+ */ |
+ setUserPodFingerprintIcon: function(username, state) { |
+ $('pod-row').setUserPodFingerprintIcon(username, state); |
+ }, |
+ |
+ /** |
+ * Removes the fingerprint icon in the user pod of |username|. |
+ * @param {string} username Username of the selected user. |
+ */ |
+ removeUserPodFingerprintIcon: function(username) { |
+ $('pod-row').removeUserPodFingerprintIcon(username); |
+ }, |
+ |
+ /** |
+ * Sets the authentication type used to authenticate the user. |
+ * @param {string} username Username of selected user |
+ * @param {number} authType Authentication type, must be a valid value in |
+ * the AUTH_TYPE enum in user_pod_row.js. |
+ * @param {string} value The initial value to use for authentication. |
+ */ |
+ setAuthType: function(username, authType, value) { |
+ $('pod-row').setAuthType(username, authType, value); |
+ }, |
+ |
+ /** |
+ * Sets the state of touch view mode. |
+ * @param {boolean} isTouchViewEnabled true if the mode is on. |
+ */ |
+ setTouchViewState: function(isTouchViewEnabled) { |
+ $('pod-row').setTouchViewState(isTouchViewEnabled); |
+ }, |
+ |
+ /** |
+ * Enables or disables the pin keyboard for the given user. This may change |
+ * pin keyboard visibility. |
+ * @param {!string} user |
+ * @param {boolean} enabled |
+ */ |
+ setPinEnabledForUser: function(user, enabled) { |
+ $('pod-row').setPinEnabled(user, enabled); |
+ }, |
+ |
+ /** |
+ * Updates the display name shown on a public session pod. |
+ * @param {string} userID The user ID of the public session |
+ * @param {string} displayName The new display name |
+ */ |
+ setPublicSessionDisplayName: function(userID, displayName) { |
+ $('pod-row').setPublicSessionDisplayName(userID, displayName); |
+ }, |
+ |
+ /** |
+ * Updates the list of locales available for a public session. |
+ * @param {string} userID The user ID of the public session |
+ * @param {!Object} locales The list of available locales |
+ * @param {string} defaultLocale The locale to select by default |
+ * @param {boolean} multipleRecommendedLocales Whether |locales| contains |
+ * two or more recommended locales |
+ */ |
+ setPublicSessionLocales: function(userID, |
+ locales, |
+ defaultLocale, |
+ multipleRecommendedLocales) { |
+ $('pod-row').setPublicSessionLocales(userID, |
+ locales, |
+ defaultLocale, |
+ multipleRecommendedLocales); |
+ }, |
+ |
+ /** |
+ * Updates the list of available keyboard layouts for a public session pod. |
+ * @param {string} userID The user ID of the public session |
+ * @param {string} locale The locale to which this list of keyboard layouts |
+ * applies |
+ * @param {!Object} list List of available keyboard layouts |
+ */ |
+ setPublicSessionKeyboardLayouts: function(userID, locale, list) { |
+ $('pod-row').setPublicSessionKeyboardLayouts(userID, locale, list); |
+ } |
+ }; |
+}); |