1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/session_manager/core/session_manager.h"
#include "base/check.h"
#include "base/check_deref.h"
#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/session_manager/core/session.h"
#include "components/session_manager/core/session_manager_observer.h"
#include "components/user_manager/user_manager.h"
namespace session_manager {
// static
SessionManager* SessionManager::instance = nullptr;
SessionManager::SessionManager() {
DCHECK(!SessionManager::Get());
SessionManager::SetInstance(this);
}
SessionManager::~SessionManager() {
DCHECK_EQ(instance, this);
SessionManager::SetInstance(nullptr);
}
// static
SessionManager* SessionManager::Get() {
return SessionManager::instance;
}
void SessionManager::SetSessionState(SessionState state) {
if (session_state_ == state)
return;
VLOG(1) << "Changing session state to: " << static_cast<int>(state);
session_state_ = state;
for (auto& observer : observers_)
observer.OnSessionStateChanged();
}
void SessionManager::CreateSession(const AccountId& user_account_id,
const std::string& username_hash,
bool new_user,
bool has_active_session) {
// For secondary user log-in in common cases, we switch the active
// session after user Profile is created, so data needed for UI update,
// such as wallpaper, can be ready on activation.
// We do not switch if this is for recovering multi-sign-in user sessions
// because in the case we do not switch every user on starting, but
// only for the last active user after all sessions are created.
if (!has_active_session && !sessions_.empty()) {
pending_active_account_id_ = user_account_id;
}
CreateSessionInternal(user_account_id, username_hash, new_user,
/*browser_restart=*/false);
}
void SessionManager::CreateSessionForRestart(const AccountId& user_account_id,
const std::string& username_hash,
bool new_user) {
CreateSessionInternal(user_account_id, username_hash, new_user,
/*browser_restart=*/true);
}
void SessionManager::SwitchActiveSession(const AccountId& account_id) {
CHECK(user_manager_);
CHECK(HasSessionForAccountId(account_id));
user_manager_->SwitchActiveUser(account_id);
}
void SessionManager::OnUserManagerCreated(
user_manager::UserManager* user_manager) {
user_manager_ = user_manager;
user_manager_observation_.Observe(user_manager_);
}
bool SessionManager::IsSessionStarted() const {
return session_started_;
}
bool SessionManager::IsUserSessionStartUpTaskCompleted() const {
return user_session_start_up_task_completed_;
}
void SessionManager::SessionStarted() {
TRACE_EVENT0("login", "SessionManager::SessionStarted");
session_started_ = true;
bool is_primary = sessions_.size() == 1;
for (auto& observer : observers_)
observer.OnUserSessionStarted(is_primary);
}
bool SessionManager::HasSessionForAccountId(
const AccountId& user_account_id) const {
return base::Contains(sessions_, user_account_id, [](const auto& session) {
return session->account_id();
});
}
bool SessionManager::IsInSecondaryLoginScreen() const {
return session_state_ == SessionState::LOGIN_SECONDARY;
}
bool SessionManager::IsScreenLocked() const {
return session_state_ == SessionState::LOCKED;
}
bool SessionManager::IsUserSessionBlocked() const {
return session_state_ != SessionState::ACTIVE;
}
void SessionManager::AddObserver(SessionManagerObserver* observer) {
observers_.AddObserver(observer);
}
void SessionManager::RemoveObserver(SessionManagerObserver* observer) {
observers_.RemoveObserver(observer);
}
void SessionManager::NotifyUserProfileLoaded(const AccountId& account_id) {
for (auto& observer : observers_)
observer.OnUserProfileLoaded(account_id);
}
void SessionManager::NotifyLoginOrLockScreenVisible() {
login_or_lock_screen_shown_for_test_ = true;
for (auto& observer : observers_)
observer.OnLoginOrLockScreenVisible();
}
void SessionManager::NotifyUnlockAttempt(const bool success,
const UnlockType unlock_type) {
for (auto& observer : observers_)
observer.OnUnlockScreenAttempt(success, unlock_type);
}
void SessionManager::HandleUserSessionStartUpTaskCompleted() {
// This method must not be called twice.
CHECK(!user_session_start_up_task_completed_);
user_session_start_up_task_completed_ = true;
for (auto& observer : observers_) {
observer.OnUserSessionStartUpTaskCompleted();
}
}
// Note: there're *two* types of timing that are considered "profile created".
// 1) ProfileManager has responsibility to create a Profile
// then it invokes ProfileManagerObserver::OnProfileAdded().
// UserManager::OnUserProfileCreated() is called at the timing.
// 2) After finishing Profile creation, there are several more tasks to
// run for ash-chrome's Profile initialization. After all the tasks
// UserSessionManager (indirectly) calls NotifyUserProfileLoaded(). This
// practically happens after 1).
// The gap of the timing looks source of the confusion. We probably want to
// revisit here to unify the timing of "profile creation completion".
void SessionManager::OnUserProfileCreated(const user_manager::User& user) {
if (pending_active_account_id_.is_valid()) {
user_manager_->SwitchActiveUser(
std::exchange(pending_active_account_id_, EmptyAccountId()));
}
}
// static
void SessionManager::SetInstance(SessionManager* session_manager) {
SessionManager::instance = session_manager;
}
void SessionManager::CreateSessionInternal(const AccountId& user_account_id,
const std::string& username_hash,
bool new_user,
bool browser_restart) {
CHECK(user_manager_);
DCHECK(!HasSessionForAccountId(user_account_id));
const auto& user = CHECK_DEREF(user_manager_->FindUser(user_account_id));
// TODO(crbug.com/278643115): This attribute looks like the one for Session
// rather than UserManager. Move the field.
// Note: For KioskApp user, this may be updated later in UserSessionManager.
user_manager_->SetIsCurrentUserNew(
(new_user && user.HasGaiaAccount()) ||
user.GetType() == user_manager::UserType::kPublicAccount);
observers_.Notify(&SessionManagerObserver::OnSessionCreationStarted,
user_account_id);
sessions_.push_back(std::make_unique<Session>(next_id_++, user_account_id));
user_manager_->UserLoggedIn(user_account_id, username_hash);
OnSessionCreated(browser_restart);
observers_.Notify(&SessionManagerObserver::OnSessionCreated, user_account_id);
}
} // namespace session_manager
|