blob: 74e1d6d62f0b63819735d7b3ee4381024b57c1a1 [file] [log] [blame]
// Copyright 2016 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_SESSION_SESSION_CONTROLLER_IMPL_H_
#define ASH_SESSION_SESSION_CONTROLLER_IMPL_H_
#include <stdint.h>
#include <memory>
#include <vector>
#include "ash/ash_export.h"
#include "ash/login_status.h"
#include "ash/public/cpp/session/session_controller.h"
#include "ash/public/cpp/session/session_types.h"
#include "ash/session/session_activation_observer_holder.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
class AccountId;
class PrefRegistrySimple;
class PrefService;
namespace ash {
class FullscreenController;
class ScopedScreenLockBlocker;
class SessionControllerClient;
class SessionObserver;
class TestSessionControllerClient;
// Implements mojom::SessionController to cache session related info such as
// session state, meta data about user sessions to support synchronous
// queries for ash.
class ASH_EXPORT SessionControllerImpl : public SessionController {
public:
using UserSessions = std::vector<std::unique_ptr<UserSession>>;
SessionControllerImpl();
SessionControllerImpl(const SessionControllerImpl&) = delete;
SessionControllerImpl& operator=(const SessionControllerImpl&) = delete;
~SessionControllerImpl() override;
// Registers syncable user profile prefs with the specified `registry`.
static void RegisterUserProfilePrefs(PrefRegistrySimple* registry);
base::TimeDelta session_length_limit() const { return session_length_limit_; }
base::Time session_start_time() const { return session_start_time_; }
// Returns the number of signed in users. If 0 is returned, there is either
// no session in progress or no active user.
int NumberOfLoggedInUsers() const;
// Returns the active account. If no users are logged in this returns an empty
// AccountId.
AccountId GetActiveAccountId() const;
// Gets the policy of adding a user session to ash.
AddUserSessionPolicy GetAddUserPolicy() const;
// Returns true if the active user account is under any policy management.
// NOTE: This function should only be called if the active account exists.
bool IsActiveAccountManaged() const;
// Returns |true| if the session has been fully started for the active user.
// When a user becomes active, the profile and browser UI are not immediately
// available. Only once this method starts returning |true| is the browser
// startup complete and both profile and UI are fully available.
bool IsActiveUserSessionStarted() const;
// Returns true if the screen can be locked.
bool CanLockScreen() const;
// Returns true if the screen should be locked automatically when the screen
// is turned off or the system is suspended.
bool ShouldLockScreenAutomatically() const;
// Returns true if the session is in a kiosk-like mode running a single app.
bool IsRunningInAppMode() const;
// Returns true if the current session is a demo session for Demo Mode.
bool IsDemoSession() const;
// Returns true if user session blocked by some overlying UI. It can be
// login screen, lock screen or screen for adding users into multi-profile
// session.
bool IsUserSessionBlocked() const;
// Convenience function that returns true if session state is LOGIN_SECONDARY.
bool IsInSecondaryLoginScreen() const;
// Returns true if the settings icon should be enabled in the system tray.
bool ShouldEnableSettings() const;
// Returns true if the notification tray should appear.
bool ShouldShowNotificationTray() const;
// Gets the ash session state.
session_manager::SessionState GetSessionState() const;
// Gets the user sessions in LRU order with the active session being first.
const UserSessions& GetUserSessions() const;
// Convenience helper to get the user session at a given index. Returns
// nullptr if no user session is found for the index.
const UserSession* GetUserSession(UserIndex index) const;
// Convenience helper to get the user session with the given account id.
// Returns nullptr if no user session is found for the account id.
const UserSession* GetUserSessionByAccountId(
const AccountId& account_id) const;
// Gets the primary user session.
const UserSession* GetPrimaryUserSession() const;
// Returns true if the current user is a child account.
bool IsUserChild() const;
// Returns true if the current user is a guest account.
bool IsUserGuest() const;
// Returns true if the current user is a public account.
bool IsUserPublicAccount() const;
// Returns the type of the current user, or empty if there is no current user
// logged in.
std::optional<user_manager::UserType> GetUserType() const;
// Returns true if the current user is the primary user in a multi-profile
// scenario. This always return true if there is only one user logged in.
bool IsUserPrimary() const;
// Returns true if the current user has the profile newly created on the
// device (i.e. first time login on the device).
bool IsUserFirstLogin() const;
// Returns true if should display managed icon for current session,
// and false otherwise.
bool ShouldDisplayManagedUI() const;
// Locks the screen. The locking happens asynchronously.
void LockScreen();
// Hides the lock screen.
void HideLockScreen();
// Requests signing out all users, ending the current session.
void RequestSignOut();
// Requests a system restart to apply an OS update.
void RequestRestartForUpdate();
// Attempts to restart the chrome browser.
void AttemptRestartChrome();
// Switches to another active user with `account_id` (if that user has
// already signed in).
void SwitchActiveUser(const AccountId& account_id);
// Switches the active user to the next or previous user, with the same
// ordering as user sessions are created.
void CycleActiveUser(CycleUserDirection direction);
// Show the multi-profile login UI to add another user to this session.
void ShowMultiProfileLogin();
// Returns the PrefService used at the signin screen, which is tied to an
// incognito profile in chrome and is valid until the browser exits.
PrefService* GetSigninScreenPrefService() const;
// Returns the PrefService for `account_id` or null if one does not exist.
PrefService* GetUserPrefServiceForUser(const AccountId& account_id) const;
// Returns the profile path for `account_id` or empty if one does not exist.
base::FilePath GetProfilePath(const AccountId& account_id) const;
// Returns the PrefService for the primary user or null if no user is signed
// in or the PrefService connection hasn't been established.
PrefService* GetPrimaryUserPrefService() const;
// Returns the PrefService for the last active user that had one or null if no
// PrefService connection has been successfully established.
PrefService* GetLastActiveUserPrefService() const;
// Before login returns the signin screen profile prefs. After login returns
// the active user profile prefs. Returns null early during startup.
PrefService* GetActivePrefService() const;
// Returns the ash notion of login status.
// NOTE: Prefer GetSessionState() in new code because the concept of
// SessionState more closes matches the state in chrome.
LoginStatus login_status() const { return login_status_; }
// Returns an object of `ScopedScreenLockBlocker`.
// `CanLockScreen()` returns false while there is one or more living object.
std::unique_ptr<ScopedScreenLockBlocker> GetScopedScreenLockBlocker();
// SessionController
void SetClient(SessionControllerClient* client) override;
void SetSessionInfo(const SessionInfo& info) override;
void UpdateUserSession(const UserSession& user_session) override;
void SetUserSessionOrder(
const std::vector<uint32_t>& user_session_order) override;
void PrepareForLock(PrepareForLockCallback callback) override;
void StartLock(StartLockCallback callback) override;
void NotifyChromeLockAnimationsComplete() override;
void RunUnlockAnimation(RunUnlockAnimationCallback callback) override;
void NotifyChromeTerminating() override;
void SetSessionLengthLimit(base::TimeDelta length_limit,
base::Time start_time) override;
void CanSwitchActiveUser(CanSwitchActiveUserCallback callback) override;
void ShowMultiprofilesIntroDialog(
ShowMultiprofilesIntroDialogCallback callback) override;
void ShowTeleportWarningDialog(
ShowTeleportWarningDialogCallback callback) override;
void ShowMultiprofilesSessionAbortedDialog(
const std::string& user_email) override;
void AddSessionActivationObserverForAccountId(
const AccountId& account_id,
SessionActivationObserver* observer) override;
void RemoveSessionActivationObserverForAccountId(
const AccountId& account_id,
SessionActivationObserver* observer) override;
void AddObserver(SessionObserver* observer) override;
void RemoveObserver(SessionObserver* observer) override;
bool IsScreenLocked() const override;
bool IsEnterpriseManaged() const override;
std::optional<int> GetExistingUsersCount() const override;
// Test helpers.
void ClearUserSessionsForTest();
private:
friend class TestSessionControllerClient;
// Provides the implementation of `ScopedScreenLockBlocker`.
// Defined as a private class of `SessionControllerImpl` so that it can call
// `RemoveScopedScreenLockBlocker()` in its dtor.
class ScopedScreenLockBlockerImpl;
// Marks the session as a demo session for Demo Mode.
void SetIsDemoSession();
void SetSessionState(session_manager::SessionState state);
void AddUserSession(const UserSession& user_session);
// Calculate login status based on session state and active user session.
LoginStatus CalculateLoginStatus() const;
// Helper that returns login status when the session state is ACTIVE.
LoginStatus CalculateLoginStatusForActiveSession() const;
// Update the |login_status_| and notify observers.
void UpdateLoginStatus();
// Used as lock screen displayed callback of LockStateController and invoked
// when post lock animation finishes and ash is fully locked. It would then
// run |start_lock_callback_| to indicate ash is locked successfully.
void OnLockAnimationFinished();
// Ensure that the sign-in screen PrefService is obtained.
void EnsureSigninScreenPrefService();
void OnSigninScreenPrefServiceInitialized(PrefService* pref_service);
void OnProfilePrefServiceInitialized(const AccountId& account_id,
PrefService* pref_service);
// Notifies observers that the active user pref service changed only if the
// signin profile pref service has been connected and observers were notified
// via OnSigninScreenPrefServiceInitialized(). Otherwise, defer the
// notification until that happens.
void MaybeNotifyOnActiveUserPrefServiceChanged();
// Called when IsUserSessionBlocked() becomes true. If there isn't an active
// window, tries to activate one.
void EnsureActiveWindowAfterUnblockingUserSession();
// Called when an object of `ScopedScreenLockBlockerImpl` is destroyed.
void RemoveScopedScreenLockBlocker();
// Client interface to session manager code (chrome).
raw_ptr<SessionControllerClient> client_ = nullptr;
// Cached session info.
bool can_lock_ = false;
bool should_lock_screen_automatically_ = false;
bool is_running_in_app_mode_ = false;
bool is_demo_session_ = false;
AddUserSessionPolicy add_user_session_policy_ = AddUserSessionPolicy::ALLOWED;
session_manager::SessionState state_ = session_manager::SessionState::UNKNOWN;
// Cached user session info sorted by the order from SetUserSessionOrder.
// Currently the session manager code (chrome) sets a LRU order with the
// active session being the first.
UserSessions user_sessions_;
// The user session id of the current active user session. User session id
// is managed by session manager code, starting at 1. 0u is an invalid id
// to detect first active user session.
uint32_t active_session_id_ = 0u;
// The user session id of the primary user session. The primary user session
// is the very first user session of the current ash session.
uint32_t primary_session_id_ = 0u;
// Last known login status. Used to track login status changes.
LoginStatus login_status_ = LoginStatus::NOT_LOGGED_IN;
// Whether unlocking is in progress. The flag is set when the pre-unlock
// animation starts and reset when session state is no longer LOCKED.
bool is_unlocking_ = false;
// Pending callback for the StartLock request.
base::OnceCallback<void(bool)> start_lock_callback_;
// The session length limit; set to zero if there is no limit.
base::TimeDelta session_length_limit_;
// The session start time, set at login or on the first user activity; set to
// null if there is no session length limit. This value is also stored in a
// pref in case of a crash during the session.
base::Time session_start_time_;
// Set to true if the active user's pref is received before the signin prefs.
// This is so that we can guarantee that observers are notified with
// OnActiveUserPrefServiceChanged() after
// OnSigninScreenPrefServiceInitialized().
bool on_active_user_prefs_changed_notify_deferred_ = false;
base::ObserverList<SessionObserver> observers_;
SessionActivationObserverHolder session_activation_observer_holder_;
bool signin_screen_prefs_obtained_ = false;
raw_ptr<PrefService> last_active_user_prefs_ = nullptr;
std::unique_ptr<FullscreenController> fullscreen_controller_;
int scoped_screen_lock_blocker_count_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<SessionControllerImpl> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_SESSION_SESSION_CONTROLLER_IMPL_H_