// Copyright 2016 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.

#include "ash/session/session_controller.h"

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

#include "ash/metrics/user_metrics_recorder.h"
#include "ash/public/interfaces/pref_connector.mojom.h"
#include "ash/public/interfaces/user_info.mojom.h"
#include "ash/session/multiprofiles_intro_dialog.h"
#include "ash/session/session_aborted_dialog.h"
#include "ash/session/session_observer.h"
#include "ash/session/teleport_warning_dialog.h"
#include "ash/shell.h"
#include "ash/system/power/power_event_observer.h"
#include "ash/system/screen_security/screen_switch_check_controller.h"
#include "ash/wm/lock_state_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_type.h"
#include "services/preferences/public/cpp/pref_service_factory.h"
#include "services/preferences/public/mojom/preferences.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/message_center/message_center.h"

using session_manager::SessionState;

namespace ash {

namespace {

// Get the default session state. Default session state is ACTIVE when the
// process starts with a user session, i.e. the process has kLoginUser command
// line switch. This is needed because ash focus rules depends on whether
// session is blocked to pick an activatable window and chrome needs to create a
// focused browser window when starting with a user session (both in production
// and in tests). Using ACTIVE as default in this situation allows chrome to run
// without having to wait for session state to reach to ash. For other cases
// (oobe/login), there is only one login window. The login window always gets
// focus so default session state does not matter. Use UNKNOWN and wait for
// chrome to update ash for such cases.
SessionState GetDefaultSessionState() {
  const bool start_with_user =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kLoginUser);
  return start_with_user ? SessionState::ACTIVE : SessionState::UNKNOWN;
}

}  // namespace

SessionController::SessionController(service_manager::Connector* connector)
    : state_(GetDefaultSessionState()),
      connector_(connector),
      weak_ptr_factory_(this) {}

SessionController::~SessionController() {
  // Abort pending start lock request.
  if (!start_lock_callback_.is_null())
    std::move(start_lock_callback_).Run(false /* locked */);
}

void SessionController::BindRequest(mojom::SessionControllerRequest request) {
  bindings_.AddBinding(this, std::move(request));
}

int SessionController::NumberOfLoggedInUsers() const {
  return static_cast<int>(user_sessions_.size());
}

AccountId SessionController::GetActiveAccountId() const {
  return user_sessions_.empty() ? AccountId()
                                : user_sessions_[0]->user_info->account_id;
}

AddUserSessionPolicy SessionController::GetAddUserPolicy() const {
  return add_user_session_policy_;
}

bool SessionController::IsActiveUserSessionStarted() const {
  return !user_sessions_.empty();
}

bool SessionController::CanLockScreen() const {
  return IsActiveUserSessionStarted() && can_lock_;
}

bool SessionController::IsScreenLocked() const {
  return state_ == SessionState::LOCKED;
}

bool SessionController::ShouldLockScreenAutomatically() const {
  return should_lock_screen_automatically_;
}

bool SessionController::IsRunningInAppMode() const {
  return is_running_in_app_mode_;
}

bool SessionController::IsDemoSession() const {
  return is_demo_session_;
}

bool SessionController::IsUserSessionBlocked() const {
  // User sessions are blocked when session state is not ACTIVE, with two
  // exceptions:
  // - LOGGED_IN_NOT_ACTIVE state. This is needed so that browser windows
  //   created by session restore (or a default new browser window) are properly
  //   activated before session state changes to ACTIVE.
  // - LOCKED state with a running unlocking animation. This is needed because
  //   the unlocking animation hides the lock container at the end. During the
  //   unlock animation, IsUserSessionBlocked needs to return unblocked so that
  //   user windows are deemed activatable and ash correctly restores the active
  //   window before locking.
  return state_ != SessionState::ACTIVE &&
         state_ != SessionState::LOGGED_IN_NOT_ACTIVE &&
         !(state_ == SessionState::LOCKED && is_unlocking_);
}

bool SessionController::IsInSecondaryLoginScreen() const {
  return state_ == SessionState::LOGIN_SECONDARY;
}

SessionState SessionController::GetSessionState() const {
  return state_;
}

bool SessionController::ShouldEnableSettings() const {
  // Settings opens a web UI window, so it is not available at the lock screen.
  if (!IsActiveUserSessionStarted() || IsScreenLocked() ||
      IsInSecondaryLoginScreen()) {
    return false;
  }

  return user_sessions_[0]->should_enable_settings;
}

bool SessionController::ShouldShowNotificationTray() const {
  if (!IsActiveUserSessionStarted() || IsInSecondaryLoginScreen())
    return false;

  return user_sessions_[0]->should_show_notification_tray;
}

const std::vector<mojom::UserSessionPtr>& SessionController::GetUserSessions()
    const {
  return user_sessions_;
}

const mojom::UserSession* SessionController::GetUserSession(
    UserIndex index) const {
  if (index < 0 || index >= static_cast<UserIndex>(user_sessions_.size()))
    return nullptr;

  return user_sessions_[index].get();
}

const mojom::UserSession* SessionController::GetPrimaryUserSession() const {
  auto it = std::find_if(user_sessions_.begin(), user_sessions_.end(),
                         [this](const mojom::UserSessionPtr& session) {
                           return session->session_id == primary_session_id_;
                         });
  if (it == user_sessions_.end())
    return nullptr;

  return (*it).get();
}

bool SessionController::IsUserSupervised() const {
  if (!IsActiveUserSessionStarted())
    return false;

  user_manager::UserType active_user_type = GetUserSession(0)->user_info->type;
  return active_user_type == user_manager::USER_TYPE_SUPERVISED ||
         active_user_type == user_manager::USER_TYPE_CHILD;
}

bool SessionController::IsUserLegacySupervised() const {
  if (!IsActiveUserSessionStarted())
    return false;

  user_manager::UserType active_user_type = GetUserSession(0)->user_info->type;
  return active_user_type == user_manager::USER_TYPE_SUPERVISED;
}

bool SessionController::IsUserChild() const {
  if (!IsActiveUserSessionStarted())
    return false;

  user_manager::UserType active_user_type = GetUserSession(0)->user_info->type;
  return active_user_type == user_manager::USER_TYPE_CHILD;
}

bool SessionController::IsUserPublicAccount() const {
  if (!IsActiveUserSessionStarted())
    return false;

  user_manager::UserType active_user_type = GetUserSession(0)->user_info->type;
  return active_user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
}

base::Optional<user_manager::UserType> SessionController::GetUserType() const {
  if (!IsActiveUserSessionStarted())
    return base::nullopt;

  return base::make_optional(GetUserSession(0)->user_info->type);
}

bool SessionController::IsUserPrimary() const {
  if (!IsActiveUserSessionStarted())
    return false;

  return GetUserSession(0)->session_id == primary_session_id_;
}

bool SessionController::IsUserFirstLogin() const {
  if (!IsActiveUserSessionStarted())
    return false;

  return GetUserSession(0)->user_info->is_new_profile;
}

void SessionController::LockScreen() {
  if (client_)
    client_->RequestLockScreen();
}

void SessionController::RequestSignOut() {
  if (client_)
    client_->RequestSignOut();
}

void SessionController::SwitchActiveUser(const AccountId& account_id) {
  if (client_)
    client_->SwitchActiveUser(account_id);
}

void SessionController::CycleActiveUser(CycleUserDirection direction) {
  if (client_)
    client_->CycleActiveUser(direction);
}

void SessionController::ShowMultiProfileLogin() {
  if (client_)
    client_->ShowMultiProfileLogin();
}

PrefService* SessionController::GetSigninScreenPrefService() const {
  return signin_screen_prefs_.get();
}

PrefService* SessionController::GetUserPrefServiceForUser(
    const AccountId& account_id) const {
  auto it = per_user_prefs_.find(account_id);
  if (it != per_user_prefs_.end())
    return it->second.get();

  return nullptr;
}

PrefService* SessionController::GetPrimaryUserPrefService() const {
  const mojom::UserSession* session = GetPrimaryUserSession();
  return session ? GetUserPrefServiceForUser(session->user_info->account_id)
                 : nullptr;
}

PrefService* SessionController::GetLastActiveUserPrefService() const {
  return last_active_user_prefs_;
}

PrefService* SessionController::GetActivePrefService() const {
  // Use the active user prefs once they become available. Check the PrefService
  // object instead of session state because prefs load is async after login.
  if (last_active_user_prefs_)
    return last_active_user_prefs_;
  return signin_screen_prefs_.get();
}

void SessionController::AddObserver(SessionObserver* observer) {
  observers_.AddObserver(observer);
}

void SessionController::RemoveObserver(SessionObserver* observer) {
  observers_.RemoveObserver(observer);
}

void SessionController::SetClient(mojom::SessionControllerClientPtr client) {
  client_ = std::move(client);
}

void SessionController::SetSessionInfo(mojom::SessionInfoPtr info) {
  can_lock_ = info->can_lock_screen;
  should_lock_screen_automatically_ = info->should_lock_screen_automatically;
  is_running_in_app_mode_ = info->is_running_in_app_mode;
  if (info->is_demo_session)
    SetIsDemoSession();
  add_user_session_policy_ = info->add_user_session_policy;
  SetSessionState(info->state);
}

void SessionController::UpdateUserSession(mojom::UserSessionPtr user_session) {
  auto it =
      std::find_if(user_sessions_.begin(), user_sessions_.end(),
                   [&user_session](const mojom::UserSessionPtr& session) {
                     return session->session_id == user_session->session_id;
                   });
  if (it == user_sessions_.end()) {
    AddUserSession(std::move(user_session));
    return;
  }

  *it = std::move(user_session);
  for (auto& observer : observers_)
    observer.OnUserSessionUpdated((*it)->user_info->account_id);

  UpdateLoginStatus();
}

void SessionController::SetUserSessionOrder(
    const std::vector<uint32_t>& user_session_order) {
  DCHECK_EQ(user_sessions_.size(), user_session_order.size());

  AccountId last_active_account_id;
  if (user_sessions_.size())
    last_active_account_id = user_sessions_[0]->user_info->account_id;

  // Adjusts |user_sessions_| to match the given order.
  std::vector<mojom::UserSessionPtr> sessions;
  for (const auto& session_id : user_session_order) {
    auto it =
        std::find_if(user_sessions_.begin(), user_sessions_.end(),
                     [session_id](const mojom::UserSessionPtr& session) {
                       return session && session->session_id == session_id;
                     });
    if (it == user_sessions_.end()) {
      LOG(ERROR) << "Unknown session id =" << session_id;
      continue;
    }

    sessions.push_back(std::move(*it));
  }

  user_sessions_.swap(sessions);

  // Check active user change and notifies observers.
  if (user_sessions_[0]->session_id != active_session_id_) {
    const bool is_first_session = active_session_id_ == 0u;
    active_session_id_ = user_sessions_[0]->session_id;

    if (is_first_session) {
      for (auto& observer : observers_)
        observer.OnFirstSessionStarted();
    }

    session_activation_observer_holder_.NotifyActiveSessionChanged(
        last_active_account_id, user_sessions_[0]->user_info->account_id);

    // When switching to a user for whose PrefService is not ready,
    // |last_active_user_prefs_| continues to point to the PrefService of the
    // most-recently active user with a loaded PrefService.
    auto it = per_user_prefs_.find(user_sessions_[0]->user_info->account_id);
    if (it != per_user_prefs_.end())
      last_active_user_prefs_ = it->second.get();

    for (auto& observer : observers_) {
      observer.OnActiveUserSessionChanged(
          user_sessions_[0]->user_info->account_id);
    }

    if (it != per_user_prefs_.end())
      MaybeNotifyOnActiveUserPrefServiceChanged();

    UpdateLoginStatus();
  }
}

void SessionController::PrepareForLock(PrepareForLockCallback callback) {
  // If the active window is fullscreen, exit fullscreen to avoid the web page
  // or app mimicking the lock screen. Do not exit fullscreen if the shelf is
  // visible while in fullscreen because the shelf makes it harder for a web
  // page or app to mimick the lock screen.
  wm::WindowState* active_window_state = wm::GetActiveWindowState();
  if (active_window_state && active_window_state->IsFullscreen() &&
      active_window_state->GetHideShelfWhenFullscreen()) {
    const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
    active_window_state->OnWMEvent(&event);
  }

  std::move(callback).Run();
}

void SessionController::StartLock(StartLockCallback callback) {
  DCHECK(start_lock_callback_.is_null());
  start_lock_callback_ = std::move(callback);

  LockStateController* const lock_state_controller =
      Shell::Get()->lock_state_controller();

  lock_state_controller->SetLockScreenDisplayedCallback(
      base::Bind(&SessionController::OnLockAnimationFinished,
                 weak_ptr_factory_.GetWeakPtr()));
  lock_state_controller->OnStartingLock();
}

void SessionController::NotifyChromeLockAnimationsComplete() {
  Shell::Get()->power_event_observer()->OnLockAnimationsComplete();
}

void SessionController::RunUnlockAnimation(
    RunUnlockAnimationCallback callback) {
  is_unlocking_ = true;

  // Shell could have no instance in tests.
  if (Shell::HasInstance())
    Shell::Get()->lock_state_controller()->OnLockScreenHide(
        std::move(callback));
}

void SessionController::NotifyChromeTerminating() {
  for (auto& observer : observers_)
    observer.OnChromeTerminating();
}

void SessionController::SetSessionLengthLimit(base::TimeDelta length_limit,
                                              base::TimeTicks start_time) {
  session_length_limit_ = length_limit;
  session_start_time_ = start_time;
  for (auto& observer : observers_)
    observer.OnSessionLengthLimitChanged();
}

void SessionController::CanSwitchActiveUser(
    CanSwitchActiveUserCallback callback) {
  // Cancel overview mode when switching user profiles.
  OverviewController* controller = Shell::Get()->overview_controller();
  if (controller->IsSelecting())
    controller->ToggleOverview();

  ash::Shell::Get()
      ->screen_switch_check_controller()
      ->CanSwitchAwayFromActiveUser(std::move(callback));
}

void SessionController::ShowMultiprofilesIntroDialog(
    ShowMultiprofilesIntroDialogCallback callback) {
  MultiprofilesIntroDialog::Show(std::move(callback));
}

void SessionController::ShowTeleportWarningDialog(
    ShowTeleportWarningDialogCallback callback) {
  TeleportWarningDialog::Show(std::move(callback));
}

void SessionController::ShowMultiprofilesSessionAbortedDialog(
    const std::string& user_email) {
  SessionAbortedDialog::Show(user_email);
}

void SessionController::AddSessionActivationObserverForAccountId(
    const AccountId& account_id,
    mojom::SessionActivationObserverPtr observer) {
  bool locked = state_ == SessionState::LOCKED;
  observer->OnLockStateChanged(locked);
  observer->OnSessionActivated(user_sessions_.size() &&
                               user_sessions_[0]->user_info->account_id ==
                                   account_id);
  session_activation_observer_holder_.AddSessionActivationObserverForAccountId(
      account_id, std::move(observer));
}

void SessionController::ClearUserSessionsForTest() {
  user_sessions_.clear();
  last_active_user_prefs_ = nullptr;
  active_session_id_ = 0u;
  primary_session_id_ = 0u;
}

void SessionController::FlushMojoForTest() {
  client_.FlushForTesting();
}

void SessionController::LockScreenAndFlushForTest() {
  LockScreen();
  FlushMojoForTest();
}

void SessionController::SetSigninScreenPrefServiceForTest(
    std::unique_ptr<PrefService> prefs) {
  OnSigninScreenPrefServiceInitialized(std::move(prefs));
}

void SessionController::ProvideUserPrefServiceForTest(
    const AccountId& account_id,
    std::unique_ptr<PrefService> pref_service) {
  OnProfilePrefServiceInitialized(account_id, std::move(pref_service));
}

void SessionController::SetIsDemoSession() {
  if (is_demo_session_)
    return;

  is_demo_session_ = true;
  Shell::Get()->metrics()->StartDemoSessionMetricsRecording();
  // Notifications should be silenced during demo sessions.
  message_center::MessageCenter::Get()->SetQuietMode(true);
}

void SessionController::SetSessionState(SessionState state) {
  if (state_ == state)
    return;

  const bool was_user_session_blocked = IsUserSessionBlocked();
  const bool was_locked = state_ == SessionState::LOCKED;
  state_ = state;
  for (auto& observer : observers_)
    observer.OnSessionStateChanged(state_);

  UpdateLoginStatus();

  const bool locked = state_ == SessionState::LOCKED;
  if (was_locked != locked) {
    if (!locked)
      is_unlocking_ = false;

    for (auto& observer : observers_)
      observer.OnLockStateChanged(locked);

    session_activation_observer_holder_.NotifyLockStateChanged(locked);
  }

  // Request signin profile prefs only once.
  if (!signin_screen_prefs_requested_) {
    ConnectToSigninScreenPrefService();
    signin_screen_prefs_requested_ = true;
  }

  if (was_user_session_blocked && !IsUserSessionBlocked())
    EnsureActiveWindowAfterUnblockingUserSession();
}

void SessionController::AddUserSession(mojom::UserSessionPtr user_session) {
  const AccountId account_id(user_session->user_info->account_id);

  if (primary_session_id_ == 0u)
    primary_session_id_ = user_session->session_id;

  user_sessions_.push_back(std::move(user_session));

  if (connector_) {
    auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>();
    Shell::RegisterUserProfilePrefs(pref_registry.get());
    ash::mojom::PrefConnectorPtr pref_connector_connector;
    connector_->BindInterface(mojom::kPrefConnectorServiceName,
                              &pref_connector_connector);
    prefs::mojom::PrefStoreConnectorPtr pref_connector;
    pref_connector_connector->GetPrefStoreConnectorForUser(
        account_id, mojo::MakeRequest(&pref_connector));

    prefs::ConnectToPrefService(
        std::move(pref_connector), std::move(pref_registry),
        base::Bind(&SessionController::OnProfilePrefServiceInitialized,
                   weak_ptr_factory_.GetWeakPtr(), account_id));
  }

  UpdateLoginStatus();
  for (auto& observer : observers_)
    observer.OnUserSessionAdded(account_id);
}

LoginStatus SessionController::CalculateLoginStatus() const {
  // TODO(jamescook|xiyuan): There is not a 1:1 mapping of SessionState to
  // LoginStatus. Fix the cases that don't match. http://crbug.com/701193
  switch (state_) {
    case SessionState::UNKNOWN:
    case SessionState::OOBE:
    case SessionState::LOGIN_PRIMARY:
    case SessionState::LOGGED_IN_NOT_ACTIVE:
      return LoginStatus::NOT_LOGGED_IN;

    case SessionState::ACTIVE:
      return CalculateLoginStatusForActiveSession();

    case SessionState::LOCKED:
      return LoginStatus::LOCKED;

    case SessionState::LOGIN_SECONDARY:
      // TODO: There is no LoginStatus for this.
      return LoginStatus::USER;
  }
  NOTREACHED();
  return LoginStatus::NOT_LOGGED_IN;
}

LoginStatus SessionController::CalculateLoginStatusForActiveSession() const {
  DCHECK(state_ == SessionState::ACTIVE);

  if (user_sessions_.empty())  // Can be empty in tests.
    return LoginStatus::USER;

  switch (user_sessions_[0]->user_info->type) {
    case user_manager::USER_TYPE_REGULAR:
      return user_sessions_[0]->user_info->is_device_owner ? LoginStatus::OWNER
                                                           : LoginStatus::USER;
    case user_manager::USER_TYPE_GUEST:
      return LoginStatus::GUEST;
    case user_manager::USER_TYPE_PUBLIC_ACCOUNT:
      return LoginStatus::PUBLIC;
    case user_manager::USER_TYPE_SUPERVISED:
      return LoginStatus::SUPERVISED;
    case user_manager::USER_TYPE_KIOSK_APP:
      return LoginStatus::KIOSK_APP;
    case user_manager::USER_TYPE_CHILD:
      return LoginStatus::SUPERVISED;
    case user_manager::USER_TYPE_ARC_KIOSK_APP:
      return LoginStatus::ARC_KIOSK_APP;
    case user_manager::USER_TYPE_ACTIVE_DIRECTORY:
      // TODO: There is no LoginStatus for this.
      return LoginStatus::USER;
    case user_manager::NUM_USER_TYPES:
      // Avoid having a "default" case so the compiler catches new enum values.
      NOTREACHED();
      return LoginStatus::USER;
  }
  NOTREACHED();
  return LoginStatus::USER;
}

void SessionController::UpdateLoginStatus() {
  const LoginStatus new_login_status = CalculateLoginStatus();
  if (new_login_status == login_status_)
    return;

  login_status_ = new_login_status;
  for (auto& observer : observers_)
    observer.OnLoginStatusChanged(login_status_);
}

void SessionController::OnLockAnimationFinished() {
  if (!start_lock_callback_.is_null())
    std::move(start_lock_callback_).Run(true /* locked */);
}

void SessionController::ConnectToSigninScreenPrefService() {
  DCHECK(!signin_screen_prefs_requested_);

  // Null in tests.
  if (!connector_)
    return;

  // Connect to the PrefService for the signin profile.
  auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>();
  Shell::RegisterSigninProfilePrefs(pref_registry.get());
  ash::mojom::PrefConnectorPtr pref_connector_connector;
  connector_->BindInterface(mojom::kPrefConnectorServiceName,
                            &pref_connector_connector);
  prefs::mojom::PrefStoreConnectorPtr pref_connector;
  pref_connector_connector->GetPrefStoreConnectorForSigninScreen(
      mojo::MakeRequest(&pref_connector));
  prefs::ConnectToPrefService(
      std::move(pref_connector), std::move(pref_registry),
      base::Bind(&SessionController::OnSigninScreenPrefServiceInitialized,
                 weak_ptr_factory_.GetWeakPtr()));
}

void SessionController::OnSigninScreenPrefServiceInitialized(
    std::unique_ptr<PrefService> pref_service) {
  // |pref_service| can be null when running standalone without chrome.
  if (!pref_service)
    return;

  DCHECK(!signin_screen_prefs_);
  signin_screen_prefs_ = std::move(pref_service);

  for (auto& observer : observers_) {
    observer.OnSigninScreenPrefServiceInitialized(signin_screen_prefs_.get());
  }

  if (on_active_user_prefs_changed_notify_deferred_) {
    // Notify obsevers with the deferred OnActiveUserPrefServiceChanged(). Do
    // this in a separate loop from the above since observers might depend on
    // each other and we want to avoid having inconsistent states.
    for (auto& observer : observers_)
      observer.OnActiveUserPrefServiceChanged(last_active_user_prefs_);
    on_active_user_prefs_changed_notify_deferred_ = false;
  }
}

void SessionController::OnProfilePrefServiceInitialized(
    const AccountId& account_id,
    std::unique_ptr<PrefService> pref_service) {
  // |pref_service| can be null when running standalone without chrome.
  if (!pref_service)
    return;

  PrefService* pref_service_ptr = pref_service.get();
  bool inserted =
      per_user_prefs_.emplace(account_id, std::move(pref_service)).second;
  DCHECK(inserted);
  DCHECK(!user_sessions_.empty());
  if (account_id == user_sessions_[0]->user_info->account_id) {
    last_active_user_prefs_ = pref_service_ptr;

    MaybeNotifyOnActiveUserPrefServiceChanged();
  }
}

void SessionController::MaybeNotifyOnActiveUserPrefServiceChanged() {
  DCHECK(last_active_user_prefs_);

  if (!signin_screen_prefs_) {
    // We must guarantee that OnSigninScreenPrefServiceInitialized() is called
    // before OnActiveUserPrefServiceChanged(), so defer notifying the
    // observers until the sign in prefs are received.
    on_active_user_prefs_changed_notify_deferred_ = true;
    return;
  }

  for (auto& observer : observers_)
    observer.OnActiveUserPrefServiceChanged(last_active_user_prefs_);
}

void SessionController::EnsureActiveWindowAfterUnblockingUserSession() {
  // This happens only in tests (See SessionControllerTest).
  if (!Shell::HasInstance())
    return;

  auto mru_list = Shell::Get()->mru_window_tracker()->BuildMruWindowList();
  if (!mru_list.empty())
    mru_list.front()->Focus();
}

}  // namespace ash
