| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_ |
| #define ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "ash/ash_export.h" |
| #include "ash/keyboard/ui/keyboard_ui_controller.h" |
| #include "ash/login/ui/auth_error_bubble.h" |
| #include "ash/login/ui/bottom_status_indicator.h" |
| #include "ash/login/ui/lock_screen.h" |
| #include "ash/login/ui/login_data_dispatcher.h" |
| #include "ash/login/ui/login_display_style.h" |
| #include "ash/login/ui/login_error_bubble.h" |
| #include "ash/login/ui/login_tooltip_view.h" |
| #include "ash/login/ui/management_bubble.h" |
| #include "ash/login/ui/non_accessible_view.h" |
| #include "ash/login/ui/user_state.h" |
| #include "ash/public/cpp/keyboard/keyboard_controller_observer.h" |
| #include "ash/public/cpp/login_accelerators.h" |
| #include "ash/public/cpp/login_types.h" |
| #include "ash/public/cpp/smartlock_state.h" |
| #include "ash/public/cpp/system_tray_observer.h" |
| #include "ash/system/enterprise/enterprise_domain_observer.h" |
| #include "ash/system/model/enterprise_domain_model.h" |
| #include "base/containers/flat_map.h" |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "chromeos/ash/components/login/auth/auth_metrics_recorder.h" |
| #include "chromeos/dbus/power/power_manager_client.h" |
| #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" |
| #include "components/account_id/account_id.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "ui/base/metadata/metadata_header_macros.h" |
| #include "ui/display/display_observer.h" |
| #include "ui/display/screen.h" |
| #include "ui/views/view.h" |
| |
| namespace keyboard { |
| class KeyboardUIController; |
| } // namespace keyboard |
| |
| namespace views { |
| class BoxLayout; |
| } // namespace views |
| |
| namespace ash { |
| |
| class KioskAppDefaultMessage; |
| class LockScreenMediaControlsView; |
| class LoginAuthUserView; |
| class LoginBigUserView; |
| class LoginCameraTimeoutView; |
| class LoginDetachableBaseModel; |
| class LoginExpandedPublicAccountView; |
| class LoginUserView; |
| class NoteActionLaunchButton; |
| class ScrollableUsersListView; |
| |
| namespace mojom { |
| enum class TrayActionState; |
| } |
| |
| enum class BottomIndicatorState { |
| kNone, |
| kManagedDevice, |
| kAdbSideLoadingEnabled, |
| }; |
| |
| // LockContentsView hosts the root view for the lock screen. All other lock |
| // screen views are embedded within this one. LockContentsView is per-display, |
| // but it is always shown on the primary display. There is only one instance |
| // at a time. |
| class ASH_EXPORT LockContentsView |
| : public NonAccessibleView, |
| public LoginDataDispatcher::Observer, |
| public SystemTrayObserver, |
| public display::DisplayObserver, |
| public KeyboardControllerObserver, |
| public chromeos::PowerManagerClient::Observer, |
| public EnterpriseDomainObserver { |
| public: |
| METADATA_HEADER(LockContentsView); |
| friend class LockContentsViewTestApi; |
| |
| enum class DisplayStyle { |
| // Display all the user views, top header view in LockContentsView. |
| kAll, |
| // Display only the public account expanded view, other views in |
| // LockContentsView are hidden. |
| kExclusivePublicAccountExpandedView, |
| }; |
| |
| // Number of login attempts before a login dialog is shown. For example, if |
| // this value is 4 then the user can submit their password 4 times, and on the |
| // 4th bad attempt the login dialog is shown. This only applies to the login |
| // screen. |
| static const int kLoginAttemptsBeforeGaiaDialog; |
| |
| LockContentsView( |
| mojom::TrayActionState initial_note_action_state, |
| LockScreen::ScreenType screen_type, |
| LoginDataDispatcher* data_dispatcher, |
| std::unique_ptr<LoginDetachableBaseModel> detachable_base_model); |
| |
| LockContentsView(const LockContentsView&) = delete; |
| LockContentsView& operator=(const LockContentsView&) = delete; |
| |
| ~LockContentsView() override; |
| |
| void FocusNextUser(); |
| void FocusPreviousUser(); |
| void ShowEnterpriseDomainManager( |
| const std::string& entreprise_domain_manager); |
| void ShowAdbEnabled(); |
| void ToggleSystemInfo(); |
| void ShowParentAccessDialog(); |
| void SetHasKioskApp(bool has_kiosk_apps); |
| |
| // views::View: |
| void Layout() override; |
| void AddedToWidget() override; |
| void OnFocus() override; |
| bool OnKeyPressed(const ui::KeyEvent& event) override; |
| void AboutToRequestFocusFromTabTraversal(bool reverse) override; |
| void GetAccessibleNodeData(ui::AXNodeData* node_data) override; |
| bool AcceleratorPressed(const ui::Accelerator& accelerator) override; |
| |
| // LoginDataDispatcher::Observer: |
| void OnUsersChanged(const std::vector<LoginUserInfo>& users) override; |
| void OnUserAvatarChanged(const AccountId& account_id, |
| const UserAvatar& avatar) override; |
| void OnPinEnabledForUserChanged(const AccountId& user, bool enabled) override; |
| void OnChallengeResponseAuthEnabledForUserChanged(const AccountId& user, |
| bool enabled) override; |
| void OnFingerprintStateChanged(const AccountId& account_id, |
| FingerprintState state) override; |
| void OnResetFingerprintUIState(const AccountId& account_id) override; |
| void OnFingerprintAuthResult(const AccountId& account_id, |
| bool success) override; |
| void OnSmartLockStateChanged(const AccountId& account_id, |
| SmartLockState state) override; |
| void OnSmartLockAuthResult(const AccountId& account_id, |
| bool success) override; |
| void OnAuthEnabledForUser(const AccountId& user) override; |
| void OnAuthDisabledForUser( |
| const AccountId& user, |
| const AuthDisabledData& auth_disabled_data) override; |
| void OnSetTpmLockedState(const AccountId& user, |
| bool is_locked, |
| base::TimeDelta time_left) override; |
| void OnLockScreenNoteStateChanged(mojom::TrayActionState state) override; |
| void OnTapToUnlockEnabledForUserChanged(const AccountId& user, |
| bool enabled) override; |
| void OnForceOnlineSignInForUser(const AccountId& user) override; |
| // TODO(https://crbug.com/1233614): Delete this method in favor of |
| // OnSmartLockStateChanged once Smart Lock UI revamp is enabled. |
| void OnShowEasyUnlockIcon(const AccountId& user, |
| const EasyUnlockIconInfo& icon_info) override; |
| void OnWarningMessageUpdated(const std::u16string& message) override; |
| void OnSystemInfoChanged(bool show, |
| bool enforced, |
| const std::string& os_version_label_text, |
| const std::string& enterprise_info_text, |
| const std::string& bluetooth_name, |
| bool adb_sideloading_enabled) override; |
| void OnPublicSessionDisplayNameChanged( |
| const AccountId& account_id, |
| const std::string& display_name) override; |
| void OnPublicSessionLocalesChanged(const AccountId& account_id, |
| const std::vector<LocaleItem>& locales, |
| const std::string& default_locale, |
| bool show_advanced_view) override; |
| void OnPublicSessionKeyboardLayoutsChanged( |
| const AccountId& account_id, |
| const std::string& locale, |
| const std::vector<InputMethodItem>& keyboard_layouts) override; |
| void OnPublicSessionShowFullManagementDisclosureChanged( |
| bool show_full_management_disclosure) override; |
| void OnDetachableBasePairingStatusChanged( |
| DetachableBasePairingStatus pairing_status) override; |
| void OnFocusLeavingLockScreenApps(bool reverse) override; |
| void OnOobeDialogStateChanged(OobeDialogState state) override; |
| |
| void MaybeUpdateExpandedView(const AccountId& account_id, |
| const LoginUserInfo& user_info); |
| |
| // SystemTrayObserver: |
| void OnFocusLeavingSystemTray(bool reverse) override; |
| |
| // display::DisplayObserver: |
| void OnDisplayMetricsChanged(const display::Display& display, |
| uint32_t changed_metrics) override; |
| |
| // KeyboardControllerObserver: |
| void OnKeyboardVisibilityChanged(bool is_visible) override; |
| |
| // chromeos::PowerManagerClient::Observer: |
| void SuspendImminent(power_manager::SuspendImminent::Reason reason) override; |
| |
| // ash::EnterpriseDomainObserver |
| void OnDeviceEnterpriseInfoChanged() override; |
| void OnEnterpriseAccountDomainChanged() override; |
| |
| void ShowAuthErrorMessageForDebug(int unlock_attempt); |
| |
| // Called for debugging to make |user| managed and display an icon along with |
| // a note in the menu user view. |
| void ToggleManagementForUserForDebug(const AccountId& user); |
| |
| // Called for debugging to make |user| having a multiprofile policy. |
| void SetMultiprofilePolicyForUserForDebug( |
| const AccountId& user, |
| const MultiProfileUserBehavior& multiprofile_policy); |
| |
| // Called for debugging to toggle forced online sign-in form |user|. |
| void ToggleForceOnlineSignInForUserForDebug(const AccountId& user); |
| |
| // Called for debugging to remove forced online sign-in form |user|. |
| void UndoForceOnlineSignInForUserForDebug(const AccountId& user); |
| |
| // Test API. Set device to have kiosk license. |
| void SetKioskLicenseModeForTesting(bool is_kiosk_license_mode); |
| |
| // Called by LockScreenMediaControlsView. |
| void CreateMediaControlsLayout(); |
| void HideMediaControlsLayout(); |
| bool AreMediaControlsEnabled() const; |
| |
| private: |
| using DisplayLayoutAction = base::RepeatingCallback<void(bool landscape)>; |
| |
| // Focus the next/previous widget. |
| void FocusNextWidget(bool reverse); |
| |
| // Set |spacing_middle| to the correct size for low density layouts. If there |
| // is less spacing available than desired, use up to the available. |
| void SetLowDensitySpacing(views::View* spacing_middle, |
| views::View* secondary_view, |
| int landscape_dist, |
| int portrait_dist, |
| bool landscape); |
| |
| // Set |spacing_middle| for media controls. |
| void SetMediaControlsSpacing(bool landscape); |
| |
| // 1-2 users. |
| void CreateLowDensityLayout( |
| const std::vector<LoginUserInfo>& users, |
| std::unique_ptr<LoginBigUserView> primary_big_view); |
| // 3-6 users. |
| void CreateMediumDensityLayout( |
| const std::vector<LoginUserInfo>& users, |
| std::unique_ptr<LoginBigUserView> primary_big_view); |
| // 7+ users. |
| void CreateHighDensityLayout( |
| const std::vector<LoginUserInfo>& users, |
| views::BoxLayout* main_layout, |
| std::unique_ptr<LoginBigUserView> primary_big_view); |
| |
| // Lay out the entire view. This is called when the view is attached to a |
| // widget and when the screen is rotated. |
| void DoLayout(); |
| |
| // Lay out the top header. This is called when the children of the top header |
| // change contents or visibility. |
| void LayoutTopHeader(); |
| |
| // Lay out the bottom status indicator. This is called when system information |
| // is shown if ADB is enabled and at the initialization of lock screen if the |
| // device is enrolled. |
| void LayoutBottomStatusIndicator(); |
| |
| // Lay out the user adding screen indicator. This is called when a secondary |
| // user is being added. |
| void LayoutUserAddingScreenIndicator(); |
| |
| // Lay out the expanded public session view. |
| void LayoutPublicSessionView(); |
| |
| // Adds |layout_action| to |layout_actions_| and immediately executes it with |
| // the current rotation. |
| void AddDisplayLayoutAction(const DisplayLayoutAction& layout_action); |
| |
| // Change the active |auth_user_|. If |is_primary| is true, the active auth |
| // switches to |opt_secondary_big_view_|. If |is_primary| is false, the active |
| // auth switches to |primary_big_view_|. |
| void SwapActiveAuthBetweenPrimaryAndSecondary(bool is_primary); |
| |
| // Called when an authentication check is complete. |
| void OnAuthenticate(bool auth_success, |
| bool display_error_messages, |
| bool authenticated_by_pin); |
| |
| // Tries to lookup the stored state for |user|. Returns an unowned pointer |
| // that is invalidated whenver |users_| changes. |
| UserState* FindStateForUser(const AccountId& user); |
| |
| // Updates the auth methods for |to_update| and |to_hide|, if passed. |
| // For auth users: |
| // |to_hide| will be set to LoginAuthUserView::AUTH_NONE. At minimum, |
| // |to_update| will show a password prompt. |
| // For pubic account users: |
| // |to_hide| will set to disable auth. |
| // |to_update| will show an arrow button. |
| void LayoutAuth(LoginBigUserView* to_update, |
| LoginBigUserView* opt_to_hide, |
| bool animate); |
| |
| // Make the user at |user_index| the big user with auth enabled. |
| // We pass in the index because the actual user may change. |
| void SwapToBigUser(int user_index); |
| |
| // Warning to remove a user is shown. |
| void OnRemoveUserWarningShown(bool is_primary); |
| // Remove one of the auth users. |
| void RemoveUser(bool is_primary); |
| |
| // Called after the big user change has taken place. |
| void OnBigUserChanged(); |
| |
| // Shows the correct (cached) easy unlock icon for the given auth user. |
| void UpdateEasyUnlockIconForUser(const AccountId& user); |
| |
| // Get the current active big user view. |
| LoginBigUserView* CurrentBigUserView(); |
| |
| // Opens an error bubble to indicate authentication failure. |
| void ShowAuthErrorMessage(); |
| |
| // Hides the error bubble indicating authentication failure if open. |
| void HideAuthErrorMessage(); |
| |
| // Called when the easy unlock icon is hovered. |
| void OnEasyUnlockIconHovered(); |
| |
| // Called when LoginAuthFactorsView enters/exits a state where an auth |
| // factor wants to hide the password and pin fields. |
| void OnAuthFactorIsHidingPasswordChanged(const AccountId& account_id, |
| bool auth_factor_is_hiding_password); |
| |
| // Called when parent access validation finished for the user with |
| // |account_id|. |
| void OnParentAccessValidationFinished(const AccountId& account_id, |
| bool access_granted); |
| |
| // Returns keyboard controller for the view. Returns nullptr if keyboard is |
| // not activated, view has not been added to the widget yet or keyboard is not |
| // displayed in this window. |
| keyboard::KeyboardUIController* GetKeyboardControllerForView() const; |
| |
| // Called when the public account is tapped. |
| void OnPublicAccountTapped(bool is_primary); |
| |
| // Called when the user presses buttons in the authentication error bubble. |
| void LearnMoreButtonPressed(); |
| void RecoverUserButtonPressed(); |
| |
| // Helper method to allocate a LoginBigUserView instance. |
| std::unique_ptr<LoginBigUserView> AllocateLoginBigUserView( |
| const LoginUserInfo& user, |
| bool is_primary); |
| |
| // Returns the big view for |user| if |user| is one of the active |
| // big views. If |require_auth_active| is true then the view must |
| // have auth enabled. |
| LoginBigUserView* TryToFindBigUser(const AccountId& user, |
| bool require_auth_active); |
| |
| // Returns the user view for |user|. |
| LoginUserView* TryToFindUserView(const AccountId& user); |
| |
| // Change the visibility of child views based on the |style|. |
| void SetDisplayStyle(DisplayStyle style); |
| |
| // Register accelerators used in login screen. |
| void RegisterAccelerators(); |
| |
| // Performs the specified accelerator action. |
| void PerformAction(LoginAcceleratorAction action); |
| |
| // Check whether the view should display the system information based on all |
| // factors including policy settings, channel and Alt-V accelerator. |
| bool GetSystemInfoVisibility() const; |
| |
| // Updates the colors of the system info view. |
| void UpdateSystemInfoColors(); |
| |
| // Updates the colors of the bottom status indicator. |
| void UpdateBottomStatusIndicatorColors(); |
| |
| // Toggles the visibility of the |bottom_status_indicator_| based on its |
| // content type and whether the extension UI window is opened. |
| void UpdateBottomStatusIndicatorVisibility(); |
| |
| // Shows a pop-up including more details about device management. It is |
| // triggered when the bottom status indicator is clicked while displaying a |
| // "device is managed" type message. |
| void OnBottomStatusIndicatorTapped(); |
| |
| // Shows GAIA sign-in page. |
| void OnBackToSigninButtonTapped(); |
| |
| // Update visibility of Kiosk default message. Called only if |
| // kiosk_license_mode_ is true. |
| void UpdateKioskDefaultMessageVisibility(); |
| |
| // Record the number of password attempts for the given account id to UMA. |
| // Afterwards reset the number of attempts. |
| void RecordAndResetPasswordAttempts( |
| AuthMetricsRecorder::AuthenticationOutcome outcome, |
| AccountId account_id); |
| |
| const LockScreen::ScreenType screen_type_; |
| |
| std::vector<UserState> users_; |
| |
| const raw_ptr<LoginDataDispatcher, ExperimentalAsh> |
| data_dispatcher_; // Unowned. |
| std::unique_ptr<LoginDetachableBaseModel> detachable_base_model_; |
| |
| raw_ptr<LoginBigUserView, ExperimentalAsh> primary_big_view_ = nullptr; |
| raw_ptr<LoginBigUserView, ExperimentalAsh> opt_secondary_big_view_ = nullptr; |
| raw_ptr<ScrollableUsersListView, ExperimentalAsh> users_list_ = nullptr; |
| |
| // View for media controls that appear on the lock screen if user enabled. |
| raw_ptr<LockScreenMediaControlsView, ExperimentalAsh> media_controls_view_ = |
| nullptr; |
| raw_ptr<views::View, ExperimentalAsh> middle_spacing_view_ = nullptr; |
| |
| // View that contains the note action button and the system info labels, |
| // placed on the top right corner of the screen without affecting layout of |
| // other views. |
| raw_ptr<views::View, ExperimentalAsh> top_header_ = nullptr; |
| |
| // View for launching a note taking action handler from the lock screen. |
| raw_ptr<NoteActionLaunchButton, ExperimentalAsh> note_action_ = nullptr; |
| |
| // View for showing the version, enterprise and bluetooth info. |
| raw_ptr<views::View, ExperimentalAsh> system_info_ = nullptr; |
| |
| // Contains authentication user and the additional user views. |
| raw_ptr<NonAccessibleView, ExperimentalAsh> main_view_ = nullptr; |
| |
| // If the kiosk app button is not visible, the kiosk app default message would |
| // be shown. |
| raw_ptr<KioskAppDefaultMessage, DanglingUntriaged> kiosk_default_message_ = |
| nullptr; |
| |
| // Actions that should be executed before a new layout happens caused by a |
| // display change (eg. screen rotation). A full layout pass is performed after |
| // all actions are executed. |
| std::vector<DisplayLayoutAction> layout_actions_; |
| |
| display::ScopedDisplayObserver display_observer_{this}; |
| |
| base::ScopedObservation<EnterpriseDomainModel, EnterpriseDomainObserver> |
| enterprise_domain_model_observation_{this}; |
| |
| // All error bubbles and the tooltip view are child views of LockContentsView, |
| // and will be torn down when LockContentsView is torn down. |
| // Bubble for displaying authentication error. |
| raw_ptr<AuthErrorBubble, ExperimentalAsh> auth_error_bubble_; |
| // Bubble for displaying detachable base errors. |
| raw_ptr<LoginErrorBubble, ExperimentalAsh> detachable_base_error_bubble_; |
| // Bubble for displaying easy-unlock tooltips. |
| raw_ptr<LoginTooltipView, ExperimentalAsh> tooltip_bubble_; |
| // Bubble for displaying management details. |
| raw_ptr<ManagementBubble, ExperimentalAsh> management_bubble_; |
| // Indicator at top of screen for displaying a warning message when a |
| // secondary user is being added. |
| raw_ptr<views::View, ExperimentalAsh> user_adding_screen_indicator_ = nullptr; |
| // Bubble for displaying warning banner message. |
| raw_ptr<LoginErrorBubble, ExperimentalAsh> warning_banner_bubble_; |
| |
| // View that is shown on login timeout with camera usage. |
| base::raw_ptr<LoginCameraTimeoutView, DanglingUntriaged> |
| login_camera_timeout_view_ = nullptr; |
| |
| // Bottom status indicator displaying entreprise domain or ADB enabled alert |
| raw_ptr<BottomStatusIndicator, ExperimentalAsh> bottom_status_indicator_; |
| |
| // Tracks the visibility of the extension Ui window. |
| bool extension_ui_visible_ = false; |
| |
| // Tracks the unlock attempt of each user before a successful sign-in. |
| base::flat_map<AccountId, int> unlock_attempt_by_user_; |
| base::flat_map<AccountId, int> pin_unlock_attempt_by_user_; |
| |
| // Whether a lock screen app is currently active (i.e. lock screen note action |
| // state is reported as kActive by the data dispatcher). |
| bool lock_screen_apps_active_ = false; |
| |
| // Tracks the visibility of the OOBE dialog. |
| bool oobe_dialog_visible_ = false; |
| |
| // Whether the lock screen note is disabled. Used to override the actual lock |
| // screen note state. |
| bool disable_lock_screen_note_ = false; |
| |
| // Whether the device is enrolled with Kiosk SKU. |
| bool kiosk_license_mode_ = false; |
| // Whether any kiosk app is added. |
| bool has_kiosk_apps_ = false; |
| |
| // Whether the system information should be displayed or not be displayed |
| // forcedly according to policy settings. |
| absl::optional<bool> enable_system_info_enforced_ = absl::nullopt; |
| |
| // Whether the system information is intended to be displayed if possible. |
| // (e.g., Alt-V is pressed, particular OS channels) |
| bool enable_system_info_if_possible_ = false; |
| |
| // Expanded view for public account user to select language and keyboard. |
| raw_ptr<LoginExpandedPublicAccountView, ExperimentalAsh> expanded_view_ = |
| nullptr; |
| |
| // Whether the virtual keyboard is currently shown. Used to determine whether |
| // to show the PIN keyboard or not. |
| bool keyboard_shown_ = false; |
| |
| // Whether there is an ongoing auth layout. The keyboard visibility might |
| // change during an auth layout, if triggered by a focus request on the |
| // password view. Since a keyboard visibility change triggers an auth layout |
| // and since we do not want an auth layout during an auth layout, we cancel |
| // the new layout request (the new keyboard visibility info is useless). |
| bool ongoing_auth_layout_ = false; |
| |
| // Accelerators handled by login screen. |
| std::map<ui::Accelerator, LoginAcceleratorAction> accel_map_; |
| |
| BottomIndicatorState bottom_status_indicator_state_ = |
| BottomIndicatorState::kNone; |
| |
| base::WeakPtrFactory<LockContentsView> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_ |