blob: 4c0ee102637a66f7667ec257e42a056f3390044e [file] [log] [blame]
// Copyright 2017 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.
#ifndef ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_
#define ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_
#include <memory>
#include <string>
#include <vector>
#include "ash/ash_export.h"
#include "ash/login/lock_screen_apps_focus_observer.h"
#include "ash/login/ui/login_data_dispatcher.h"
#include "ash/login/ui/login_display_style.h"
#include "ash/login/ui/non_accessible_view.h"
#include "ash/session/session_observer.h"
#include "ash/shell_observer.h"
#include "ash/system/system_tray_focus_observer.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "ui/display/display_observer.h"
#include "ui/display/screen.h"
#include "ui/keyboard/keyboard_controller_observer.h"
#include "ui/views/controls/styled_label_listener.h"
#include "ui/views/view.h"
namespace keyboard {
class KeyboardController;
} // namespace keyboard
namespace views {
class BoxLayout;
class StyledLabel;
} // namespace views
namespace ash {
class LoginAuthUserView;
class LoginBubble;
class LoginDetachableBaseModel;
class NoteActionLaunchButton;
class ScrollableUsersListView;
namespace mojom {
enum class TrayActionState;
}
// 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 LockScreenAppsFocusObserver,
public LoginDataDispatcher::Observer,
public SystemTrayFocusObserver,
public display::DisplayObserver,
public views::StyledLabelListener,
public SessionObserver,
public keyboard::KeyboardControllerObserver,
public ShellObserver {
public:
// TestApi is used for tests to get internal implementation details.
class ASH_EXPORT TestApi {
public:
explicit TestApi(LockContentsView* view);
~TestApi();
LoginAuthUserView* primary_auth() const;
LoginAuthUserView* opt_secondary_auth() const;
ScrollableUsersListView* users_list() const;
views::View* note_action() const;
LoginBubble* tooltip_bubble() const;
LoginBubble* auth_error_bubble() const;
LoginBubble* detachable_base_error_bubble() const;
views::View* dev_channel_info() const;
private:
LockContentsView* const view_;
};
LockContentsView(
mojom::TrayActionState initial_note_action_state,
LoginDataDispatcher* data_dispatcher,
std::unique_ptr<LoginDetachableBaseModel> detachable_base_model);
~LockContentsView() override;
// views::View:
void Layout() override;
void AddedToWidget() override;
void OnFocus() override;
void AboutToRequestFocusFromTabTraversal(bool reverse) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
// LockScreenAppsFocusObserver:
void OnFocusLeavingLockScreenApps(bool reverse) override;
// LoginDataDispatcher::Observer:
void OnUsersChanged(
const std::vector<mojom::LoginUserInfoPtr>& users) override;
void OnPinEnabledForUserChanged(const AccountId& user, bool enabled) override;
void OnLockScreenNoteStateChanged(mojom::TrayActionState state) override;
void OnClickToUnlockEnabledForUserChanged(const AccountId& user,
bool enabled) override;
void OnShowEasyUnlockIcon(
const AccountId& user,
const mojom::EasyUnlockIconOptionsPtr& icon) override;
void OnDevChannelInfoChanged(const std::string& os_version_label_text,
const std::string& enterprise_info_text,
const std::string& bluetooth_name) override;
void OnPublicSessionDisplayNameChanged(
const AccountId& account_id,
const std::string& display_name) override;
void OnPublicSessionLocalesChanged(const AccountId& account_id,
const base::ListValue& locales,
const std::string& default_locale,
bool show_advanced_view) override;
void OnDetachableBasePairingStatusChanged(
DetachableBasePairingStatus pairing_status) override;
// SystemTrayFocusObserver:
void OnFocusLeavingSystemTray(bool reverse) override;
// display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
// views::StyledLabelListener:
void StyledLabelLinkClicked(views::StyledLabel* label,
const gfx::Range& range,
int event_flags) override{};
// SessionObserver:
void OnLockStateChanged(bool locked) override;
// ash::ShellObserver:
void OnVirtualKeyboardStateChanged(bool activated,
aura::Window* root_window) override;
// keyboard::KeyboardControllerObserver:
void OnStateChanged(const keyboard::KeyboardControllerState state) override;
private:
class UserState {
public:
explicit UserState(AccountId account_id);
UserState(UserState&&);
~UserState();
AccountId account_id;
bool show_pin = false;
bool enable_tap_auth = false;
mojom::EasyUnlockIconOptionsPtr easy_unlock_state;
private:
DISALLOW_COPY_AND_ASSIGN(UserState);
};
using OnRotate = base::RepeatingCallback<void(bool landscape)>;
// Focus the next/previous widget.
void FocusNextWidget(bool reverse);
// 1-2 users.
void CreateLowDensityLayout(
const std::vector<mojom::LoginUserInfoPtr>& users);
// 3-6 users.
void CreateMediumDensityLayout(
const std::vector<mojom::LoginUserInfoPtr>& users);
// 7+ users.
void CreateHighDensityLayout(
const std::vector<mojom::LoginUserInfoPtr>& users);
// 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();
// Creates a new view with |landscape| and |portrait| preferred sizes.
// |landscape| and |portrait| specify the width of the preferred size; the
// height is an arbitrary non-zero value. The correct size is chosen
// dynamically based on screen orientation. The view will respond to
// orientation changes.
views::View* MakeOrientationViewWithWidths(int landscape, int portrait);
// Adds |on_rotate| to |rotation_actions_| and immediately executes it with
// the current rotation.
void AddRotationAction(const OnRotate& on_rotate);
// Change the active |auth_user_|. If |is_primary| is true, the active auth
// switches to |opt_secondary_auth_|. If |is_primary| is false, the active
// auth switches to |primary_auth_|.
void SwapActiveAuthBetweenPrimaryAndSecondary(bool is_primary);
// Called when an authentication check is complete.
void OnAuthenticate(bool auth_success);
// 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.
// |to_hide| will be set to LoginAuthUserView::AUTH_NONE. At minimum,
// |to_update| will show a password prompt.
void LayoutAuth(LoginAuthUserView* to_update,
LoginAuthUserView* opt_to_hide,
bool animate);
// Make the user at |user_index| the auth user. We pass in the index because
// the actual user may change.
void SwapToAuthUser(int user_index);
// Called after the auth user change has taken place.
void OnAuthUserChanged();
// Shows the correct (cached) easy unlock icon for the given auth user.
void UpdateEasyUnlockIconForUser(const AccountId& user);
// Get the LoginAuthUserView of the current auth user.
LoginAuthUserView* CurrentAuthUserView();
// Opens an error bubble to indicate authentication failure.
void ShowAuthErrorMessage();
// Called when the easy unlock icon is hovered.
void OnEasyUnlockIconHovered();
// Called when the easy unlock icon is tapped.
void OnEasyUnlockIconTapped();
// 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::KeyboardController* GetKeyboardController() const;
// Helper method to allocate a LoginAuthUserView instance.
LoginAuthUserView* AllocateLoginAuthUserView(
const mojom::LoginUserInfoPtr& user,
bool is_primary);
// Returns the authentication view for |user| if |user| is one of the active
// authentication views. If |require_auth_active| is true then the view must
// also be actively displaying auth.
LoginAuthUserView* TryToFindAuthUser(const AccountId& user,
bool require_auth_active);
// Returns scrollable view with initialized size and rows for all |users|.
ScrollableUsersListView* BuildScrollableUsersListView(
const std::vector<mojom::LoginUserInfoPtr>& users,
LoginDisplayStyle display_style);
std::vector<UserState> users_;
LoginDataDispatcher* const data_dispatcher_; // Unowned.
std::unique_ptr<LoginDetachableBaseModel> detachable_base_model_;
LoginAuthUserView* primary_auth_ = nullptr;
LoginAuthUserView* opt_secondary_auth_ = nullptr;
ScrollableUsersListView* users_list_ = nullptr;
// View that contains the note action button and the dev channel info labels,
// placed on the top right corner of the screen without affecting layout of
// other views.
views::View* top_header_ = nullptr;
// View for launching a note taking action handler from the lock screen.
NoteActionLaunchButton* note_action_ = nullptr;
// View for showing the version, enterprise and bluetooth info in dev and
// canary channels.
views::View* dev_channel_info_ = nullptr;
// Contains authentication user and the additional user views.
NonAccessibleView* main_view_ = nullptr;
// Layout used for |main_view_|. Pointer owned by the View base class.
views::BoxLayout* main_layout_ = nullptr;
// Actions that should be executed when rotation changes. A full layout pass
// is performed after all actions are executed.
std::vector<OnRotate> rotation_actions_;
ScopedObserver<display::Screen, display::DisplayObserver> display_observer_;
ScopedSessionObserver session_observer_;
ScopedObserver<keyboard::KeyboardController,
keyboard::KeyboardControllerObserver>
keyboard_observer_;
// Bubbles for displaying authentication error.
std::unique_ptr<LoginBubble> auth_error_bubble_;
// Bubble for displaying error when the user's detachable base changes.
std::unique_ptr<LoginBubble> detachable_base_error_bubble_;
std::unique_ptr<LoginBubble> tooltip_bubble_;
int unlock_attempt_ = 0;
// 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;
DISALLOW_COPY_AND_ASSIGN(LockContentsView);
};
} // namespace ash
#endif // ASH_LOGIN_UI_LOCK_CONTENTS_VIEW_H_