This source file includes following definitions.
- OnRemoveUserComplete
- ParseUserList
- ResolveLocale
- OnGetNSSCertDatabaseForUser
- RegisterPrefs
- multi_profile_first_run_notification_
- Shutdown
- GetMultiProfileUserController
- GetUserImageManager
- GetSupervisedUserManager
- GetUsers
- GetUsersAdmittedForMultiProfile
- GetLoggedInUsers
- GetLRULoggedInUsers
- GetUnlockUsers
- GetOwnerEmail
- UserLoggedIn
- SwitchActiveUser
- RestoreActiveSessions
- SessionStarted
- RemoveUser
- RemoveUserInternal
- RemoveNonOwnerUserInternal
- RemoveUserFromList
- IsKnownUser
- FindUser
- FindUserAndModify
- GetLoggedInUser
- GetLoggedInUser
- GetActiveUser
- GetActiveUser
- GetPrimaryUser
- GetUserByProfile
- GetProfileByUser
- SaveUserOAuthStatus
- SaveForceOnlineSignin
- SaveUserDisplayName
- GetUserDisplayName
- SaveUserDisplayEmail
- GetUserDisplayEmail
- UpdateUserAccountData
- RespectLocalePreference
- StopPolicyObserverForTesting
- Observe
- OnExternalDataSet
- OnExternalDataCleared
- OnExternalDataFetched
- OnPolicyUpdated
- OnDeviceLocalAccountsChanged
- IsCurrentUserOwner
- SetCurrentUserIsOwner
- IsCurrentUserNew
- IsCurrentUserNonCryptohomeDataEphemeral
- CanCurrentUserLock
- IsUserLoggedIn
- IsLoggedInAsRegularUser
- IsLoggedInAsDemoUser
- IsLoggedInAsPublicAccount
- IsLoggedInAsGuest
- IsLoggedInAsLocallyManagedUser
- IsLoggedInAsKioskApp
- IsLoggedInAsStub
- IsSessionStarted
- UserSessionsRestored
- HasBrowserRestarted
- IsUserNonCryptohomeDataEphemeral
- AddObserver
- RemoveObserver
- AddSessionStateObserver
- RemoveSessionStateObserver
- NotifyLocalStateChanged
- OnProfilePrepared
- EnsureUsersLoaded
- RetrieveTrustedDevicePolicies
- AreEphemeralUsersEnabled
- GetUsersAndModify
- FindUserInList
- UserExistsInList
- FindUserInListAndModify
- GuestUserLoggedIn
- AddUserRecord
- RegularUserLoggedIn
- RegularUserLoggedInAsEphemeral
- LocallyManagedUserLoggedIn
- PublicAccountUserLoggedIn
- KioskAppLoggedIn
- DemoAccountLoggedIn
- RetailModeUserLoggedIn
- NotifyOnLogin
- LoadUserOAuthStatus
- LoadForceOnlineSignin
- UpdateOwnership
- RemoveNonCryptohomeData
- RemoveRegularOrLocallyManagedUserFromList
- CleanUpPublicAccountNonCryptohomeDataPendingRemoval
- CleanUpPublicAccountNonCryptohomeData
- UpdateAndCleanUpPublicAccounts
- UpdatePublicAccountDisplayName
- GetCurrentUserFlow
- GetUserFlow
- SetUserFlow
- ResetUserFlow
- GetAppModeChromeClientOAuthInfo
- SetAppModeChromeClientOAuthInfo
- AreLocallyManagedUsersAllowed
- GetUserProfileDir
- GetDefaultUserFlow
- NotifyUserListChanged
- NotifyActiveUserChanged
- NotifyUserAddedToSession
- NotifyActiveUserHashChanged
- NotifyPendingUserSessionsRestoreFinished
- UpdateLoginState
- SetLRUUser
- OnRestoreActiveSessions
- RestorePendingUserSessions
- SendRegularUserLoginMetrics
- OnUserNotAllowed
- UpdateUserAccountLocale
- DoUpdateAccountLocale
- UpdateNumberOfUsers
- DeleteUser
#include "chrome/browser/chromeos/login/user_manager_impl.h"
#include <cstddef>
#include <set>
#include "ash/multi_profile_uma.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/threading/worker_pool.h"
#include "base/values.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/login/auth_sync_observer.h"
#include "chrome/browser/chromeos/login/auth_sync_observer_factory.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/multi_profile_first_run_notification.h"
#include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
#include "chrome/browser/chromeos/login/remove_user_delegate.h"
#include "chrome/browser/chromeos/login/supervised_user_manager_impl.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/multiprofiles_session_aborted_dialog.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/session_length_limiter.h"
#include "chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.h"
#include "chrome/browser/managed_mode/chromeos/manager_password_service_factory.h"
#include "chrome/browser/net/nss_context.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/pref_names.h"
#include "chromeos/cert_loader.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/login/login_state.h"
#include "chromeos/settings/cros_settings_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "policy/policy_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/wm/core/wm_core_switches.h"
using content::BrowserThread;
namespace chromeos {
namespace {
const char kRegularUsers[] = "LoggedInUsers";
const char kPublicAccounts[] = "PublicAccounts";
const char kPublicAccountPendingDataRemoval[] =
"PublicAccountPendingDataRemoval";
const char kUserDisplayName[] = "UserDisplayName";
const char kUserGivenName[] = "UserGivenName";
const char kUserDisplayEmail[] = "UserDisplayEmail";
const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
const char kUserForceOnlineSignin[] = "UserForceOnlineSignin";
const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser";
const int kLogoutToLoginDelayMaxSec = 1800;
void OnRemoveUserComplete(const std::string& user_email,
bool success,
cryptohome::MountError return_code) {
if (!success) {
LOG(ERROR) << "Removal of cryptohome for " << user_email
<< " failed, return code: " << return_code;
}
}
void ParseUserList(const base::ListValue& users_list,
const std::set<std::string>& existing_users,
std::vector<std::string>* users_vector,
std::set<std::string>* users_set) {
users_vector->clear();
users_set->clear();
for (size_t i = 0; i < users_list.GetSize(); ++i) {
std::string email;
if (!users_list.GetString(i, &email) || email.empty()) {
LOG(ERROR) << "Corrupt entry in user list at index " << i << ".";
continue;
}
if (existing_users.find(email) != existing_users.end() ||
!users_set->insert(email).second) {
LOG(ERROR) << "Duplicate user: " << email;
continue;
}
users_vector->push_back(email);
}
}
class UserHashMatcher {
public:
explicit UserHashMatcher(const std::string& h) : username_hash(h) {}
bool operator()(const User* user) const {
return user->username_hash() == username_hash;
}
private:
const std::string& username_hash;
};
void ResolveLocale(
const std::string& raw_locale,
base::Callback<void(const std::string&)> on_resolve_callback) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
std::string resolved_locale;
l10n_util::CheckAndResolveLocale(raw_locale, &resolved_locale);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(on_resolve_callback, resolved_locale));
}
void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) {
if (!CertLoader::IsInitialized())
return;
CertLoader::Get()->StartWithNSSDB(database);
}
}
void UserManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kRegularUsers);
registry->RegisterListPref(kPublicAccounts);
registry->RegisterStringPref(kPublicAccountPendingDataRemoval, "");
registry->RegisterStringPref(kLastLoggedInRegularUser, "");
registry->RegisterDictionaryPref(kUserDisplayName);
registry->RegisterDictionaryPref(kUserGivenName);
registry->RegisterDictionaryPref(kUserDisplayEmail);
registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
registry->RegisterDictionaryPref(kUserForceOnlineSignin);
SupervisedUserManager::RegisterPrefs(registry);
SessionLengthLimiter::RegisterPrefs(registry);
}
UserManagerImpl::UserManagerImpl()
: cros_settings_(CrosSettings::Get()),
device_local_account_policy_service_(NULL),
user_loading_stage_(STAGE_NOT_LOADED),
active_user_(NULL),
primary_user_(NULL),
session_started_(false),
user_sessions_restored_(false),
is_current_user_owner_(false),
is_current_user_new_(false),
is_current_user_ephemeral_regular_user_(false),
ephemeral_users_enabled_(false),
supervised_user_manager_(new SupervisedUserManagerImpl(this)),
manager_creation_time_(base::TimeTicks::Now()),
multi_profile_first_run_notification_(
new MultiProfileFirstRunNotification) {
UpdateNumberOfUsers();
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
content::NotificationService::AllSources());
registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
content::NotificationService::AllSources());
registrar_.Add(this,
chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
RetrieveTrustedDevicePolicies();
local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
kAccountsPrefDeviceLocalAccounts,
base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
base::Unretained(this)));
supervised_users_subscription_ = cros_settings_->AddSettingsObserver(
kAccountsPrefSupervisedUsersEnabled,
base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
base::Unretained(this)));
multi_profile_user_controller_.reset(new MultiProfileUserController(
this, g_browser_process->local_state()));
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
avatar_policy_observer_.reset(new policy::CloudExternalDataPolicyObserver(
cros_settings_,
this,
connector->GetDeviceLocalAccountPolicyService(),
policy::key::kUserAvatarImage,
this));
avatar_policy_observer_->Init();
wallpaper_policy_observer_.reset(new policy::CloudExternalDataPolicyObserver(
cros_settings_,
this,
connector->GetDeviceLocalAccountPolicyService(),
policy::key::kWallpaperImage,
this));
wallpaper_policy_observer_->Init();
UpdateLoginState();
}
UserManagerImpl::~UserManagerImpl() {
for (UserList::iterator it = users_.begin(); it != users_.end();
it = users_.erase(it)) {
DeleteUser(*it);
}
logged_in_users_.clear();
lru_logged_in_users_.clear();
DeleteUser(active_user_);
}
void UserManagerImpl::Shutdown() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
local_accounts_subscription_.reset();
supervised_users_subscription_.reset();
session_length_limiter_.reset();
if (device_local_account_policy_service_)
device_local_account_policy_service_->RemoveObserver(this);
for (UserImageManagerMap::iterator it = user_image_managers_.begin(),
ie = user_image_managers_.end();
it != ie; ++it) {
it->second->Shutdown();
}
multi_profile_user_controller_.reset();
avatar_policy_observer_.reset();
wallpaper_policy_observer_.reset();
}
MultiProfileUserController* UserManagerImpl::GetMultiProfileUserController() {
return multi_profile_user_controller_.get();
}
UserImageManager* UserManagerImpl::GetUserImageManager(
const std::string& user_id) {
UserImageManagerMap::iterator ui = user_image_managers_.find(user_id);
if (ui != user_image_managers_.end())
return ui->second.get();
linked_ptr<UserImageManagerImpl> mgr(new UserImageManagerImpl(user_id, this));
user_image_managers_[user_id] = mgr;
return mgr.get();
}
SupervisedUserManager* UserManagerImpl::GetSupervisedUserManager() {
return supervised_user_manager_.get();
}
const UserList& UserManagerImpl::GetUsers() const {
const_cast<UserManagerImpl*>(this)->EnsureUsersLoaded();
return users_;
}
UserList UserManagerImpl::GetUsersAdmittedForMultiProfile() const {
if (!UserManager::IsMultipleProfilesAllowed())
return UserList();
if (logged_in_users_.size() == 1 &&
GetPrimaryUser()->GetType() != User::USER_TYPE_REGULAR)
return UserList();
UserList result;
int num_users_allowed = 0;
const UserList& users = GetUsers();
for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
if ((*it)->GetType() == User::USER_TYPE_REGULAR && !(*it)->is_logged_in()) {
MultiProfileUserController::UserAllowedInSessionResult check =
multi_profile_user_controller_->
IsUserAllowedInSession((*it)->email());
if (check == MultiProfileUserController::
NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS) {
return UserList();
}
if (check == MultiProfileUserController::ALLOWED ||
check == MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS) {
result.push_back(*it);
if (check == MultiProfileUserController::ALLOWED)
num_users_allowed++;
}
}
}
if (!num_users_allowed)
result.clear();
return result;
}
const UserList& UserManagerImpl::GetLoggedInUsers() const {
return logged_in_users_;
}
const UserList& UserManagerImpl::GetLRULoggedInUsers() {
if (lru_logged_in_users_.empty() && active_user_) {
temp_single_logged_in_users_.clear();
temp_single_logged_in_users_.insert(temp_single_logged_in_users_.begin(),
active_user_);
return temp_single_logged_in_users_;
}
return lru_logged_in_users_;
}
UserList UserManagerImpl::GetUnlockUsers() const {
const UserList& logged_in_users = GetLoggedInUsers();
if (logged_in_users.empty())
return UserList();
UserList unlock_users;
Profile* profile = GetProfileByUser(primary_user_);
std::string primary_behavior =
profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior);
if (logged_in_users.size() == 1 ||
primary_behavior == MultiProfileUserController::kBehaviorPrimaryOnly) {
if (primary_user_->can_lock())
unlock_users.push_back(primary_user_);
} else {
for (UserList::const_iterator it = logged_in_users.begin();
it != logged_in_users.end(); ++it) {
User* user = (*it);
Profile* profile = GetProfileByUser(user);
const std::string behavior =
profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior);
if (behavior == MultiProfileUserController::kBehaviorUnrestricted &&
user->can_lock()) {
unlock_users.push_back(user);
} else if (behavior == MultiProfileUserController::kBehaviorPrimaryOnly) {
NOTREACHED()
<< "Spotted primary-only multi-profile policy for non-primary user";
}
}
}
return unlock_users;
}
const std::string& UserManagerImpl::GetOwnerEmail() {
return owner_email_;
}
void UserManagerImpl::UserLoggedIn(const std::string& user_id,
const std::string& username_hash,
bool browser_restart) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
DCHECK(!IsUserLoggedIn());
User* user = FindUserInListAndModify(user_id);
if (active_user_ && user) {
user->set_is_logged_in(true);
user->set_username_hash(username_hash);
logged_in_users_.push_back(user);
lru_logged_in_users_.push_back(user);
is_current_user_new_ = false;
WallpaperManager::Get()->SetUserWallpaperNow(active_user_->email());
NotifyUserAddedToSession(user);
return;
}
policy::DeviceLocalAccount::Type device_local_account_type;
if (user_id == UserManager::kGuestUserName) {
GuestUserLoggedIn();
} else if (user_id == UserManager::kRetailModeUserName) {
RetailModeUserLoggedIn();
} else if (policy::IsDeviceLocalAccountUser(user_id,
&device_local_account_type) &&
device_local_account_type ==
policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
KioskAppLoggedIn(user_id);
} else if (DemoAppLauncher::IsDemoAppSession(user_id)) {
DemoAccountLoggedIn();
} else {
EnsureUsersLoaded();
if (user && user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
PublicAccountUserLoggedIn(user);
} else if ((user && user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
(!user && gaia::ExtractDomainName(user_id) ==
UserManager::kLocallyManagedUserDomain)) {
LocallyManagedUserLoggedIn(user_id);
} else if (browser_restart && user_id == g_browser_process->local_state()->
GetString(kPublicAccountPendingDataRemoval)) {
PublicAccountUserLoggedIn(User::CreatePublicAccountUser(user_id));
} else if (user_id != owner_email_ && !user &&
(AreEphemeralUsersEnabled() || browser_restart)) {
RegularUserLoggedInAsEphemeral(user_id);
} else {
RegularUserLoggedIn(user_id);
}
session_length_limiter_.reset(new SessionLengthLimiter(NULL,
browser_restart));
}
DCHECK(active_user_);
active_user_->set_is_logged_in(true);
active_user_->set_is_active(true);
active_user_->set_username_hash(username_hash);
logged_in_users_.insert(logged_in_users_.begin(), active_user_);
SetLRUUser(active_user_);
if (!primary_user_) {
primary_user_ = active_user_;
if (primary_user_->GetType() == User::USER_TYPE_REGULAR)
SendRegularUserLoginMetrics(user_id);
}
UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType",
active_user_->GetType(), User::NUM_USER_TYPES);
g_browser_process->local_state()->SetString(kLastLoggedInRegularUser,
(active_user_->GetType() == User::USER_TYPE_REGULAR) ? user_id : "");
NotifyOnLogin();
}
void UserManagerImpl::SwitchActiveUser(const std::string& user_id) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
return;
User* user = FindUserAndModify(user_id);
if (!user) {
NOTREACHED() << "Switching to a non-existing user";
return;
}
if (user == active_user_) {
NOTREACHED() << "Switching to a user who is already active";
return;
}
if (!user->is_logged_in()) {
NOTREACHED() << "Switching to a user that is not logged in";
return;
}
if (user->GetType() != User::USER_TYPE_REGULAR) {
NOTREACHED() << "Switching to a non-regular user";
return;
}
if (user->username_hash().empty()) {
NOTREACHED() << "Switching to a user that doesn't have username_hash set";
return;
}
DCHECK(active_user_);
active_user_->set_is_active(false);
user->set_is_active(true);
active_user_ = user;
SetLRUUser(active_user_);
NotifyActiveUserHashChanged(active_user_->username_hash());
NotifyActiveUserChanged(active_user_);
}
void UserManagerImpl::RestoreActiveSessions() {
DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
base::Bind(&UserManagerImpl::OnRestoreActiveSessions,
base::Unretained(this)));
}
void UserManagerImpl::SessionStarted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
session_started_ = true;
UpdateLoginState();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_SESSION_STARTED,
content::Source<UserManager>(this),
content::Details<const User>(active_user_));
if (is_current_user_new_) {
g_browser_process->local_state()->CommitPendingWrite();
}
}
void UserManagerImpl::RemoveUser(const std::string& user_id,
RemoveUserDelegate* delegate) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const User* user = FindUser(user_id);
if (!user || (user->GetType() != User::USER_TYPE_REGULAR &&
user->GetType() != User::USER_TYPE_LOCALLY_MANAGED))
return;
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()
->browser_policy_connector_chromeos();
if (users_.size() < 2 && !connector->IsEnterpriseManaged())
return;
for (UserList::const_iterator it = logged_in_users_.begin();
it != logged_in_users_.end(); ++it) {
if ((*it)->email() == user_id)
return;
}
RemoveUserInternal(user_id, delegate);
}
void UserManagerImpl::RemoveUserInternal(const std::string& user_email,
RemoveUserDelegate* delegate) {
CrosSettings* cros_settings = CrosSettings::Get();
if (CrosSettingsProvider::TRUSTED != cros_settings->PrepareTrustedValues(
base::Bind(&UserManagerImpl::RemoveUserInternal,
base::Unretained(this),
user_email, delegate))) {
return;
}
std::string owner;
cros_settings->GetString(kDeviceOwner, &owner);
if (user_email == owner) {
return;
}
RemoveNonOwnerUserInternal(user_email, delegate);
}
void UserManagerImpl::RemoveNonOwnerUserInternal(const std::string& user_email,
RemoveUserDelegate* delegate) {
if (delegate)
delegate->OnBeforeUserRemoved(user_email);
RemoveUserFromList(user_email);
cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
user_email, base::Bind(&OnRemoveUserComplete, user_email));
if (delegate)
delegate->OnUserRemoved(user_email);
}
void UserManagerImpl::RemoveUserFromList(const std::string& user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RemoveNonCryptohomeData(user_id);
if (user_loading_stage_ == STAGE_LOADED) {
DeleteUser(RemoveRegularOrLocallyManagedUserFromList(user_id));
} else if (user_loading_stage_ == STAGE_LOADING) {
DCHECK(gaia::ExtractDomainName(user_id) ==
UserManager::kLocallyManagedUserDomain);
ListPrefUpdate users_update(g_browser_process->local_state(),
kRegularUsers);
users_update->Remove(base::StringValue(user_id), NULL);
} else {
NOTREACHED() << "Users are not loaded yet.";
return;
}
g_browser_process->local_state()->CommitPendingWrite();
}
bool UserManagerImpl::IsKnownUser(const std::string& user_id) const {
return FindUser(user_id) != NULL;
}
const User* UserManagerImpl::FindUser(const std::string& user_id) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (active_user_ && active_user_->email() == user_id)
return active_user_;
return FindUserInList(user_id);
}
User* UserManagerImpl::FindUserAndModify(const std::string& user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (active_user_ && active_user_->email() == user_id)
return active_user_;
return FindUserInListAndModify(user_id);
}
const User* UserManagerImpl::GetLoggedInUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return active_user_;
}
User* UserManagerImpl::GetLoggedInUser() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return active_user_;
}
const User* UserManagerImpl::GetActiveUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return active_user_;
}
User* UserManagerImpl::GetActiveUser() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return active_user_;
}
const User* UserManagerImpl::GetPrimaryUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return primary_user_;
}
User* UserManagerImpl::GetUserByProfile(Profile* profile) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (ProfileHelper::IsSigninProfile(profile))
return NULL;
if (IsMultipleProfilesAllowed()) {
const std::string username_hash =
ProfileHelper::GetUserIdHashFromProfile(profile);
const UserList& users = GetUsers();
const UserList::const_iterator pos = std::find_if(
users.begin(), users.end(), UserHashMatcher(username_hash));
if (pos != users.end())
return *pos;
return active_user_ &&
ProfileHelper::GetProfilePathByUserIdHash(
active_user_->username_hash()) == profile->GetPath()
? active_user_
: NULL;
}
return active_user_;
}
Profile* UserManagerImpl::GetProfileByUser(const User* user) const {
Profile* profile = NULL;
if (IsMultipleProfilesAllowed() && user->is_profile_created())
profile = ProfileHelper::GetProfileByUserIdHash(user->username_hash());
else
profile = ProfileManager::GetActiveUserProfile();
if (profile && IsLoggedInAsGuest())
profile = profile->GetOffTheRecordProfile();
return profile;
}
void UserManagerImpl::SaveUserOAuthStatus(
const std::string& user_id,
User::OAuthTokenStatus oauth_token_status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(1) << "Saving user OAuth token status in Local State";
User* user = FindUserAndModify(user_id);
if (user)
user->set_oauth_token_status(oauth_token_status);
GetUserFlow(user_id)->HandleOAuthTokenStatusChange(oauth_token_status);
if (IsUserNonCryptohomeDataEphemeral(user_id))
return;
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate oauth_status_update(local_state, kUserOAuthTokenStatus);
oauth_status_update->SetWithoutPathExpansion(user_id,
new base::FundamentalValue(static_cast<int>(oauth_token_status)));
}
void UserManagerImpl::SaveForceOnlineSignin(const std::string& user_id,
bool force_online_signin) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsUserNonCryptohomeDataEphemeral(user_id))
return;
DictionaryPrefUpdate force_online_update(g_browser_process->local_state(),
kUserForceOnlineSignin);
force_online_update->SetBooleanWithoutPathExpansion(user_id,
force_online_signin);
}
void UserManagerImpl::SaveUserDisplayName(const std::string& user_id,
const base::string16& display_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (User* user = FindUserAndModify(user_id)) {
user->set_display_name(display_name);
if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate display_name_update(local_state, kUserDisplayName);
display_name_update->SetWithoutPathExpansion(
user_id,
new base::StringValue(display_name));
supervised_user_manager_->UpdateManagerName(user_id, display_name);
}
}
}
base::string16 UserManagerImpl::GetUserDisplayName(
const std::string& user_id) const {
const User* user = FindUser(user_id);
return user ? user->display_name() : base::string16();
}
void UserManagerImpl::SaveUserDisplayEmail(const std::string& user_id,
const std::string& display_email) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
User* user = FindUserAndModify(user_id);
if (!user)
return;
user->set_display_email(display_email);
if (IsUserNonCryptohomeDataEphemeral(user_id))
return;
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate display_email_update(local_state, kUserDisplayEmail);
display_email_update->SetWithoutPathExpansion(
user_id,
new base::StringValue(display_email));
}
std::string UserManagerImpl::GetUserDisplayEmail(
const std::string& user_id) const {
const User* user = FindUser(user_id);
return user ? user->display_email() : user_id;
}
void UserManagerImpl::UpdateUserAccountData(
const std::string& user_id,
const UserAccountData& account_data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
SaveUserDisplayName(user_id, account_data.display_name());
if (User* user = FindUserAndModify(user_id)) {
base::string16 given_name = account_data.given_name();
user->set_given_name(given_name);
if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
PrefService* local_state = g_browser_process->local_state();
DictionaryPrefUpdate given_name_update(local_state, kUserGivenName);
given_name_update->SetWithoutPathExpansion(
user_id,
new base::StringValue(given_name));
}
}
UpdateUserAccountLocale(user_id, account_data.locale());
}
bool UserManagerImpl::RespectLocalePreference(
Profile* profile,
const User* user,
scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
if (g_browser_process == NULL)
return false;
if ((user == NULL) || (user != GetPrimaryUser()) ||
(!user->is_profile_created()))
return false;
if (GetLoggedInUsers().size() != 1)
return false;
const PrefService* prefs = profile->GetPrefs();
if (prefs == NULL)
return false;
std::string pref_locale;
const std::string pref_app_locale =
prefs->GetString(prefs::kApplicationLocale);
const std::string pref_bkup_locale =
prefs->GetString(prefs::kApplicationLocaleBackup);
pref_locale = pref_app_locale;
if (pref_locale.empty())
pref_locale = pref_bkup_locale;
const std::string* account_locale = NULL;
if (pref_locale.empty() && user->has_gaia_account()) {
if (user->GetAccountLocale() == NULL)
return false;
account_locale = user->GetAccountLocale();
pref_locale = *account_locale;
}
const std::string global_app_locale =
g_browser_process->GetApplicationLocale();
if (pref_locale.empty())
pref_locale = global_app_locale;
DCHECK(!pref_locale.empty());
LOG(WARNING) << "RespectLocalePreference: "
<< "app_locale='" << pref_app_locale << "', "
<< "bkup_locale='" << pref_bkup_locale << "', "
<< (account_locale != NULL
? (std::string("account_locale='") + (*account_locale) +
"'. ")
: (std::string("account_locale - unused. ")))
<< " Selected '" << pref_locale << "'";
profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
const bool enable_layouts = UserManager::Get()->IsLoggedInAsGuest();
locale_util::SwitchLanguage(pref_locale,
enable_layouts,
false ,
callback.Pass());
return true;
}
void UserManagerImpl::StopPolicyObserverForTesting() {
avatar_policy_observer_.reset();
wallpaper_policy_observer_.reset();
}
void UserManagerImpl::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED:
if (!device_local_account_policy_service_) {
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()
->browser_policy_connector_chromeos();
device_local_account_policy_service_ =
connector->GetDeviceLocalAccountPolicyService();
if (device_local_account_policy_service_)
device_local_account_policy_service_->AddObserver(this);
}
RetrieveTrustedDevicePolicies();
UpdateOwnership();
break;
case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED: {
Profile* profile = content::Details<Profile>(details).ptr();
if (IsUserLoggedIn() &&
!IsLoggedInAsGuest() &&
!IsLoggedInAsKioskApp()) {
if (IsLoggedInAsLocallyManagedUser())
ManagedUserPasswordServiceFactory::GetForProfile(profile);
if (IsLoggedInAsRegularUser())
ManagerPasswordServiceFactory::GetForProfile(profile);
if (!profile->IsOffTheRecord()) {
AuthSyncObserver* sync_observer =
AuthSyncObserverFactory::GetInstance()->GetForProfile(profile);
sync_observer->StartObserving();
multi_profile_user_controller_->StartObserving(profile);
multi_profile_first_run_notification_->UserProfilePrepared(profile);
}
}
if (IsUserLoggedIn() &&
GetPrimaryUser() &&
profile == GetProfileByUser(GetPrimaryUser()) &&
CertLoader::IsInitialized() &&
base::SysInfo::IsRunningOnChromeOS()) {
GetNSSCertDatabaseForProfile(profile,
base::Bind(&OnGetNSSCertDatabaseForUser));
}
break;
}
case chrome::NOTIFICATION_PROFILE_CREATED: {
Profile* profile = content::Source<Profile>(source).ptr();
User* user = GetUserByProfile(profile);
if (user != NULL)
user->set_profile_is_created();
break;
}
default:
NOTREACHED();
}
}
void UserManagerImpl::OnExternalDataSet(const std::string& policy,
const std::string& user_id) {
if (policy == policy::key::kUserAvatarImage)
GetUserImageManager(user_id)->OnExternalDataSet(policy);
else if (policy == policy::key::kWallpaperImage)
WallpaperManager::Get()->OnPolicySet(policy, user_id);
else
NOTREACHED();
}
void UserManagerImpl::OnExternalDataCleared(const std::string& policy,
const std::string& user_id) {
if (policy == policy::key::kUserAvatarImage)
GetUserImageManager(user_id)->OnExternalDataCleared(policy);
else if (policy == policy::key::kWallpaperImage)
WallpaperManager::Get()->OnPolicyCleared(policy, user_id);
else
NOTREACHED();
}
void UserManagerImpl::OnExternalDataFetched(const std::string& policy,
const std::string& user_id,
scoped_ptr<std::string> data) {
if (policy == policy::key::kUserAvatarImage)
GetUserImageManager(user_id)->OnExternalDataFetched(policy, data.Pass());
else if (policy == policy::key::kWallpaperImage)
WallpaperManager::Get()->OnPolicyFetched(policy, user_id, data.Pass());
else
NOTREACHED();
}
void UserManagerImpl::OnPolicyUpdated(const std::string& user_id) {
UpdatePublicAccountDisplayName(user_id);
NotifyUserListChanged();
}
void UserManagerImpl::OnDeviceLocalAccountsChanged() {
}
bool UserManagerImpl::IsCurrentUserOwner() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::AutoLock lk(is_current_user_owner_lock_);
return is_current_user_owner_;
}
void UserManagerImpl::SetCurrentUserIsOwner(bool is_current_user_owner) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
{
base::AutoLock lk(is_current_user_owner_lock_);
is_current_user_owner_ = is_current_user_owner;
}
UpdateLoginState();
}
bool UserManagerImpl::IsCurrentUserNew() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return is_current_user_new_;
}
bool UserManagerImpl::IsCurrentUserNonCryptohomeDataEphemeral() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
IsUserNonCryptohomeDataEphemeral(GetLoggedInUser()->email());
}
bool UserManagerImpl::CanCurrentUserLock() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() && active_user_->can_lock() &&
GetCurrentUserFlow()->CanLockScreen();
}
bool UserManagerImpl::IsUserLoggedIn() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return active_user_;
}
bool UserManagerImpl::IsLoggedInAsRegularUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_REGULAR;
}
bool UserManagerImpl::IsLoggedInAsDemoUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_RETAIL_MODE;
}
bool UserManagerImpl::IsLoggedInAsPublicAccount() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
}
bool UserManagerImpl::IsLoggedInAsGuest() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_GUEST;
}
bool UserManagerImpl::IsLoggedInAsLocallyManagedUser() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
}
bool UserManagerImpl::IsLoggedInAsKioskApp() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() &&
active_user_->GetType() == User::USER_TYPE_KIOSK_APP;
}
bool UserManagerImpl::IsLoggedInAsStub() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return IsUserLoggedIn() && active_user_->email() == kStubUser;
}
bool UserManagerImpl::IsSessionStarted() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return session_started_;
}
bool UserManagerImpl::UserSessionsRestored() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return user_sessions_restored_;
}
bool UserManagerImpl::HasBrowserRestarted() const {
CommandLine* command_line = CommandLine::ForCurrentProcess();
return base::SysInfo::IsRunningOnChromeOS() &&
command_line->HasSwitch(switches::kLoginUser) &&
!command_line->HasSwitch(switches::kLoginPassword);
}
bool UserManagerImpl::IsUserNonCryptohomeDataEphemeral(
const std::string& user_id) const {
if (user_id == UserManager::kGuestUserName ||
user_id == UserManager::kRetailModeUserName ||
user_id == kStubUser) {
return true;
}
if (user_id == owner_email_ || UserExistsInList(user_id) ||
user_id == g_browser_process->local_state()->
GetString(kPublicAccountPendingDataRemoval)) {
return false;
}
if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) &&
(is_current_user_ephemeral_regular_user_ || !IsLoggedInAsRegularUser())) {
return true;
}
return AreEphemeralUsersEnabled() || HasBrowserRestarted();
}
void UserManagerImpl::AddObserver(UserManager::Observer* obs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
observer_list_.AddObserver(obs);
}
void UserManagerImpl::RemoveObserver(UserManager::Observer* obs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
observer_list_.RemoveObserver(obs);
}
void UserManagerImpl::AddSessionStateObserver(
UserManager::UserSessionStateObserver* obs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
session_state_observer_list_.AddObserver(obs);
}
void UserManagerImpl::RemoveSessionStateObserver(
UserManager::UserSessionStateObserver* obs) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
session_state_observer_list_.RemoveObserver(obs);
}
void UserManagerImpl::NotifyLocalStateChanged() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FOR_EACH_OBSERVER(UserManager::Observer, observer_list_,
LocalStateChanged(this));
}
void UserManagerImpl::OnProfilePrepared(Profile* profile) {
LoginUtils::Get()->DoBrowserLaunch(profile,
NULL);
if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestName)) {
LoginUtils::Get()->RestoreAuthenticationSession(profile);
}
RestorePendingUserSessions();
}
void UserManagerImpl::EnsureUsersLoaded() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!g_browser_process || !g_browser_process->local_state())
return;
if (user_loading_stage_ != STAGE_NOT_LOADED)
return;
user_loading_stage_ = STAGE_LOADING;
if (supervised_user_manager_->HasFailedUserCreationTransaction())
supervised_user_manager_->RollbackUserCreationTransaction();
PrefService* local_state = g_browser_process->local_state();
const base::ListValue* prefs_regular_users =
local_state->GetList(kRegularUsers);
const base::ListValue* prefs_public_sessions =
local_state->GetList(kPublicAccounts);
const base::DictionaryValue* prefs_display_names =
local_state->GetDictionary(kUserDisplayName);
const base::DictionaryValue* prefs_given_names =
local_state->GetDictionary(kUserGivenName);
const base::DictionaryValue* prefs_display_emails =
local_state->GetDictionary(kUserDisplayEmail);
std::vector<std::string> public_sessions;
std::set<std::string> public_sessions_set;
ParseUserList(*prefs_public_sessions, std::set<std::string>(),
&public_sessions, &public_sessions_set);
for (std::vector<std::string>::const_iterator it = public_sessions.begin();
it != public_sessions.end(); ++it) {
users_.push_back(User::CreatePublicAccountUser(*it));
UpdatePublicAccountDisplayName(*it);
}
std::vector<std::string> regular_users;
std::set<std::string> regular_users_set;
ParseUserList(*prefs_regular_users, public_sessions_set,
®ular_users, ®ular_users_set);
for (std::vector<std::string>::const_iterator it = regular_users.begin();
it != regular_users.end(); ++it) {
User* user = NULL;
const std::string domain = gaia::ExtractDomainName(*it);
if (domain == UserManager::kLocallyManagedUserDomain)
user = User::CreateLocallyManagedUser(*it);
else
user = User::CreateRegularUser(*it);
user->set_oauth_token_status(LoadUserOAuthStatus(*it));
user->set_force_online_signin(LoadForceOnlineSignin(*it));
users_.push_back(user);
base::string16 display_name;
if (prefs_display_names->GetStringWithoutPathExpansion(*it,
&display_name)) {
user->set_display_name(display_name);
}
base::string16 given_name;
if (prefs_given_names->GetStringWithoutPathExpansion(*it, &given_name)) {
user->set_given_name(given_name);
}
std::string display_email;
if (prefs_display_emails->GetStringWithoutPathExpansion(*it,
&display_email)) {
user->set_display_email(display_email);
}
}
user_loading_stage_ = STAGE_LOADED;
for (UserList::iterator ui = users_.begin(), ue = users_.end();
ui != ue; ++ui) {
GetUserImageManager((*ui)->email())->LoadUserImage();
}
}
void UserManagerImpl::RetrieveTrustedDevicePolicies() {
ephemeral_users_enabled_ = false;
owner_email_ = "";
if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
base::Unretained(this)))) {
return;
}
cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled,
&ephemeral_users_enabled_);
cros_settings_->GetString(kDeviceOwner, &owner_email_);
EnsureUsersLoaded();
bool changed = UpdateAndCleanUpPublicAccounts(
policy::GetDeviceLocalAccounts(cros_settings_));
if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
kRegularUsers);
prefs_users_update->Clear();
for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
const std::string user_email = (*it)->email();
if ((*it)->GetType() == User::USER_TYPE_REGULAR &&
user_email != owner_email_) {
RemoveNonCryptohomeData(user_email);
DeleteUser(*it);
it = users_.erase(it);
changed = true;
} else {
if ((*it)->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
prefs_users_update->Append(new base::StringValue(user_email));
++it;
}
}
}
if (changed)
NotifyUserListChanged();
}
bool UserManagerImpl::AreEphemeralUsersEnabled() const {
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
return ephemeral_users_enabled_ &&
(connector->IsEnterpriseManaged() || !owner_email_.empty());
}
UserList& UserManagerImpl::GetUsersAndModify() {
EnsureUsersLoaded();
return users_;
}
const User* UserManagerImpl::FindUserInList(const std::string& user_id) const {
const UserList& users = GetUsers();
for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
if ((*it)->email() == user_id)
return *it;
}
return NULL;
}
const bool UserManagerImpl::UserExistsInList(const std::string& user_id) const {
PrefService* local_state = g_browser_process->local_state();
const base::ListValue* user_list = local_state->GetList(kRegularUsers);
for (size_t i = 0; i < user_list->GetSize(); ++i) {
std::string email;
if (user_list->GetString(i, &email) && (user_id == email))
return true;
}
return false;
}
User* UserManagerImpl::FindUserInListAndModify(const std::string& user_id) {
UserList& users = GetUsersAndModify();
for (UserList::iterator it = users.begin(); it != users.end(); ++it) {
if ((*it)->email() == user_id)
return *it;
}
return NULL;
}
void UserManagerImpl::GuestUserLoggedIn() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
active_user_ = User::CreateGuestUser();
active_user_->SetStubImage(User::kInvalidImageIndex, false);
WallpaperManager::Get()->SetUserWallpaperNow(UserManager::kGuestUserName);
}
void UserManagerImpl::AddUserRecord(User* user) {
ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
kRegularUsers);
prefs_users_update->Insert(0, new base::StringValue(user->email()));
users_.insert(users_.begin(), user);
}
void UserManagerImpl::RegularUserLoggedIn(const std::string& user_id) {
active_user_ = RemoveRegularOrLocallyManagedUserFromList(user_id);
is_current_user_new_ = !active_user_;
if (!active_user_) {
active_user_ = User::CreateRegularUser(user_id);
active_user_->set_oauth_token_status(LoadUserOAuthStatus(user_id));
SaveUserDisplayName(active_user_->email(),
base::UTF8ToUTF16(active_user_->GetAccountName(true)));
WallpaperManager::Get()->SetUserWallpaperNow(user_id);
}
AddUserRecord(active_user_);
GetUserImageManager(user_id)->UserLoggedIn(is_current_user_new_, false);
WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
g_browser_process->local_state()->CommitPendingWrite();
}
void UserManagerImpl::RegularUserLoggedInAsEphemeral(
const std::string& user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
is_current_user_new_ = true;
is_current_user_ephemeral_regular_user_ = true;
active_user_ = User::CreateRegularUser(user_id);
GetUserImageManager(user_id)->UserLoggedIn(is_current_user_new_, false);
WallpaperManager::Get()->SetUserWallpaperNow(user_id);
}
void UserManagerImpl::LocallyManagedUserLoggedIn(
const std::string& user_id) {
active_user_ = RemoveRegularOrLocallyManagedUserFromList(user_id);
if (!active_user_) {
is_current_user_new_ = true;
active_user_ = User::CreateLocallyManagedUser(user_id);
WallpaperManager::Get()->SetUserWallpaperNow(user_id);
} else {
if (supervised_user_manager_->CheckForFirstRun(user_id)) {
is_current_user_new_ = true;
WallpaperManager::Get()->SetUserWallpaperNow(user_id);
} else {
is_current_user_new_ = false;
}
}
ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
kRegularUsers);
prefs_users_update->Insert(0, new base::StringValue(user_id));
users_.insert(users_.begin(), active_user_);
if (is_current_user_new_) {
SaveUserDisplayName(active_user_->email(),
active_user_->GetDisplayName());
}
GetUserImageManager(user_id)->UserLoggedIn(is_current_user_new_, true);
WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
g_browser_process->local_state()->CommitPendingWrite();
}
void UserManagerImpl::PublicAccountUserLoggedIn(User* user) {
is_current_user_new_ = true;
active_user_ = user;
GetUserImageManager(user->email())->UserLoggedIn(false, true);
WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
}
void UserManagerImpl::KioskAppLoggedIn(const std::string& app_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
policy::DeviceLocalAccount::Type device_local_account_type;
DCHECK(policy::IsDeviceLocalAccountUser(app_id,
&device_local_account_type));
DCHECK_EQ(policy::DeviceLocalAccount::TYPE_KIOSK_APP,
device_local_account_type);
active_user_ = User::CreateKioskAppUser(app_id);
active_user_->SetStubImage(User::kInvalidImageIndex, false);
WallpaperManager::Get()->SetUserWallpaperNow(app_id);
const std::vector<policy::DeviceLocalAccount> device_local_accounts =
policy::GetDeviceLocalAccounts(cros_settings_);
const policy::DeviceLocalAccount* account = NULL;
for (std::vector<policy::DeviceLocalAccount>::const_iterator
it = device_local_accounts.begin();
it != device_local_accounts.end(); ++it) {
if (it->user_id == app_id) {
account = &*it;
break;
}
}
std::string kiosk_app_id;
if (account) {
kiosk_app_id = account->kiosk_app_id;
} else {
LOG(ERROR) << "Logged into nonexistent kiosk-app account: " << app_id;
NOTREACHED();
}
CommandLine* command_line = CommandLine::ForCurrentProcess();
command_line->AppendSwitch(::switches::kForceAppMode);
command_line->AppendSwitchASCII(::switches::kAppId, kiosk_app_id);
command_line->AppendSwitch(
wm::switches::kWindowAnimationsDisabled);
}
void UserManagerImpl::DemoAccountLoggedIn() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
active_user_ = User::CreateKioskAppUser(DemoAppLauncher::kDemoUserName);
active_user_->SetStubImage(User::kInvalidImageIndex, false);
WallpaperManager::Get()->SetUserWallpaperNow(DemoAppLauncher::kDemoUserName);
CommandLine::ForCurrentProcess()->AppendSwitch(
wm::switches::kWindowAnimationsDisabled);
}
void UserManagerImpl::RetailModeUserLoggedIn() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
is_current_user_new_ = true;
active_user_ = User::CreateRetailModeUser();
GetUserImageManager(UserManager::kRetailModeUserName)->UserLoggedIn(
is_current_user_new_,
true);
WallpaperManager::Get()->SetUserWallpaperNow(
UserManager::kRetailModeUserName);
}
void UserManagerImpl::NotifyOnLogin() {
UpdateNumberOfUsers();
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NotifyActiveUserHashChanged(active_user_->username_hash());
NotifyActiveUserChanged(active_user_);
UpdateLoginState();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::Source<UserManager>(this),
content::Details<const User>(active_user_));
if (GetLoggedInUsers().size() == 1) {
DeviceSettingsService::Get()->SetUsername(active_user_->email());
}
}
User::OAuthTokenStatus UserManagerImpl::LoadUserOAuthStatus(
const std::string& user_id) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
PrefService* local_state = g_browser_process->local_state();
const base::DictionaryValue* prefs_oauth_status =
local_state->GetDictionary(kUserOAuthTokenStatus);
int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
if (prefs_oauth_status &&
prefs_oauth_status->GetIntegerWithoutPathExpansion(
user_id, &oauth_token_status)) {
User::OAuthTokenStatus result =
static_cast<User::OAuthTokenStatus>(oauth_token_status);
if (result == User::OAUTH2_TOKEN_STATUS_INVALID)
GetUserFlow(user_id)->HandleOAuthTokenStatusChange(result);
return result;
}
return User::OAUTH_TOKEN_STATUS_UNKNOWN;
}
bool UserManagerImpl::LoadForceOnlineSignin(const std::string& user_id) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
PrefService* local_state = g_browser_process->local_state();
const base::DictionaryValue* prefs_force_online =
local_state->GetDictionary(kUserForceOnlineSignin);
bool force_online_signin = false;
if (prefs_force_online) {
prefs_force_online->GetBooleanWithoutPathExpansion(user_id,
&force_online_signin);
}
return force_online_signin;
}
void UserManagerImpl::UpdateOwnership() {
bool is_owner = DeviceSettingsService::Get()->HasPrivateOwnerKey();
VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner");
SetCurrentUserIsOwner(is_owner);
}
void UserManagerImpl::RemoveNonCryptohomeData(const std::string& user_id) {
WallpaperManager::Get()->RemoveUserWallpaperInfo(user_id);
GetUserImageManager(user_id)->DeleteUserImage();
PrefService* prefs = g_browser_process->local_state();
DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName);
prefs_display_name_update->RemoveWithoutPathExpansion(user_id, NULL);
DictionaryPrefUpdate prefs_given_name_update(prefs, kUserGivenName);
prefs_given_name_update->RemoveWithoutPathExpansion(user_id, NULL);
DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
prefs_display_email_update->RemoveWithoutPathExpansion(user_id, NULL);
DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
prefs_oauth_update->RemoveWithoutPathExpansion(user_id, NULL);
DictionaryPrefUpdate prefs_force_online_update(prefs, kUserForceOnlineSignin);
prefs_force_online_update->RemoveWithoutPathExpansion(user_id, NULL);
supervised_user_manager_->RemoveNonCryptohomeData(user_id);
multi_profile_user_controller_->RemoveCachedValues(user_id);
}
User* UserManagerImpl::RemoveRegularOrLocallyManagedUserFromList(
const std::string& user_id) {
ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
kRegularUsers);
prefs_users_update->Clear();
User* user = NULL;
for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
const std::string user_email = (*it)->email();
if (user_email == user_id) {
user = *it;
it = users_.erase(it);
} else {
if ((*it)->GetType() == User::USER_TYPE_REGULAR ||
(*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) {
prefs_users_update->Append(new base::StringValue(user_email));
}
++it;
}
}
return user;
}
void UserManagerImpl::CleanUpPublicAccountNonCryptohomeDataPendingRemoval() {
PrefService* local_state = g_browser_process->local_state();
const std::string public_account_pending_data_removal =
local_state->GetString(kPublicAccountPendingDataRemoval);
if (public_account_pending_data_removal.empty() ||
(IsUserLoggedIn() &&
public_account_pending_data_removal == GetActiveUser()->email())) {
return;
}
RemoveNonCryptohomeData(public_account_pending_data_removal);
local_state->ClearPref(kPublicAccountPendingDataRemoval);
}
void UserManagerImpl::CleanUpPublicAccountNonCryptohomeData(
const std::vector<std::string>& old_public_accounts) {
std::set<std::string> users;
for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it)
users.insert((*it)->email());
if (IsLoggedInAsPublicAccount()) {
const std::string active_user_id = GetActiveUser()->email();
if (users.find(active_user_id) == users.end()) {
g_browser_process->local_state()->SetString(
kPublicAccountPendingDataRemoval, active_user_id);
users.insert(active_user_id);
}
}
for (std::vector<std::string>::const_iterator
it = old_public_accounts.begin();
it != old_public_accounts.end(); ++it) {
if (users.find(*it) == users.end())
RemoveNonCryptohomeData(*it);
}
}
bool UserManagerImpl::UpdateAndCleanUpPublicAccounts(
const std::vector<policy::DeviceLocalAccount>& device_local_accounts) {
CleanUpPublicAccountNonCryptohomeDataPendingRemoval();
std::vector<std::string> old_public_accounts;
for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) {
if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT)
old_public_accounts.push_back((*it)->email());
}
std::vector<std::string> new_public_accounts;
for (std::vector<policy::DeviceLocalAccount>::const_iterator it =
device_local_accounts.begin();
it != device_local_accounts.end(); ++it) {
if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
new_public_accounts.push_back(it->user_id);
}
if (new_public_accounts.size() == old_public_accounts.size()) {
bool changed = false;
for (size_t i = 0; i < new_public_accounts.size(); ++i) {
if (new_public_accounts[i] != old_public_accounts[i]) {
changed = true;
break;
}
}
if (!changed)
return false;
}
ListPrefUpdate prefs_public_accounts_update(g_browser_process->local_state(),
kPublicAccounts);
prefs_public_accounts_update->Clear();
for (std::vector<std::string>::const_iterator it =
new_public_accounts.begin();
it != new_public_accounts.end(); ++it) {
prefs_public_accounts_update->AppendString(*it);
}
for (UserList::iterator it = users_.begin(); it != users_.end();) {
if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
if (*it != GetLoggedInUser())
DeleteUser(*it);
it = users_.erase(it);
} else {
++it;
}
}
for (std::vector<std::string>::const_reverse_iterator it =
new_public_accounts.rbegin();
it != new_public_accounts.rend(); ++it) {
if (IsLoggedInAsPublicAccount() && *it == GetActiveUser()->email())
users_.insert(users_.begin(), GetLoggedInUser());
else
users_.insert(users_.begin(), User::CreatePublicAccountUser(*it));
UpdatePublicAccountDisplayName(*it);
}
for (UserList::iterator ui = users_.begin(),
ue = users_.begin() + new_public_accounts.size();
ui != ue; ++ui) {
GetUserImageManager((*ui)->email())->LoadUserImage();
}
CleanUpPublicAccountNonCryptohomeData(old_public_accounts);
return true;
}
void UserManagerImpl::UpdatePublicAccountDisplayName(
const std::string& user_id) {
std::string display_name;
if (device_local_account_policy_service_) {
policy::DeviceLocalAccountPolicyBroker* broker =
device_local_account_policy_service_->GetBrokerForUser(user_id);
if (broker)
display_name = broker->GetDisplayName();
}
SaveUserDisplayName(user_id, base::UTF8ToUTF16(display_name));
}
UserFlow* UserManagerImpl::GetCurrentUserFlow() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!IsUserLoggedIn())
return GetDefaultUserFlow();
return GetUserFlow(GetLoggedInUser()->email());
}
UserFlow* UserManagerImpl::GetUserFlow(const std::string& user_id) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FlowMap::const_iterator it = specific_flows_.find(user_id);
if (it != specific_flows_.end())
return it->second;
return GetDefaultUserFlow();
}
void UserManagerImpl::SetUserFlow(const std::string& user_id, UserFlow* flow) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ResetUserFlow(user_id);
specific_flows_[user_id] = flow;
}
void UserManagerImpl::ResetUserFlow(const std::string& user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FlowMap::iterator it = specific_flows_.find(user_id);
if (it != specific_flows_.end()) {
delete it->second;
specific_flows_.erase(it);
}
}
bool UserManagerImpl::GetAppModeChromeClientOAuthInfo(
std::string* chrome_client_id, std::string* chrome_client_secret) {
if (!chrome::IsRunningInForcedAppMode() ||
chrome_client_id_.empty() ||
chrome_client_secret_.empty()) {
return false;
}
*chrome_client_id = chrome_client_id_;
*chrome_client_secret = chrome_client_secret_;
return true;
}
void UserManagerImpl::SetAppModeChromeClientOAuthInfo(
const std::string& chrome_client_id,
const std::string& chrome_client_secret) {
if (!chrome::IsRunningInForcedAppMode())
return;
chrome_client_id_ = chrome_client_id;
chrome_client_secret_ = chrome_client_secret;
}
bool UserManagerImpl::AreLocallyManagedUsersAllowed() const {
bool locally_managed_users_allowed = false;
cros_settings_->GetBoolean(kAccountsPrefSupervisedUsersEnabled,
&locally_managed_users_allowed);
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
return locally_managed_users_allowed || !connector->IsEnterpriseManaged();
}
base::FilePath UserManagerImpl::GetUserProfileDir(
const std::string& user_id) const {
base::FilePath profile_dir;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(::switches::kMultiProfiles)) {
const User* user = FindUser(user_id);
if (user && !user->username_hash().empty())
profile_dir = ProfileHelper::GetUserProfileDir(user->username_hash());
} else if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
profile_dir = ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
} else {
NOTREACHED();
profile_dir = base::FilePath();
}
ProfileManager* profile_manager = g_browser_process->profile_manager();
profile_dir = profile_manager->user_data_dir().Append(profile_dir);
return profile_dir;
}
UserFlow* UserManagerImpl::GetDefaultUserFlow() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!default_flow_.get())
default_flow_.reset(new DefaultUserFlow());
return default_flow_.get();
}
void UserManagerImpl::NotifyUserListChanged() {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_USER_LIST_CHANGED,
content::Source<UserManager>(this),
content::NotificationService::NoDetails());
}
void UserManagerImpl::NotifyActiveUserChanged(const User* active_user) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
session_state_observer_list_,
ActiveUserChanged(active_user));
}
void UserManagerImpl::NotifyUserAddedToSession(const User* added_user) {
UpdateNumberOfUsers();
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
session_state_observer_list_,
UserAddedToSession(added_user));
}
void UserManagerImpl::NotifyActiveUserHashChanged(const std::string& hash) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
session_state_observer_list_,
ActiveUserHashChanged(hash));
}
void UserManagerImpl::NotifyPendingUserSessionsRestoreFinished() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
user_sessions_restored_ = true;
FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
session_state_observer_list_,
PendingUserSessionsRestoreFinished());
}
void UserManagerImpl::UpdateLoginState() {
if (!LoginState::IsInitialized())
return;
LoginState::LoggedInState logged_in_state;
logged_in_state = active_user_ ? LoginState::LOGGED_IN_ACTIVE
: LoginState::LOGGED_IN_NONE;
LoginState::LoggedInUserType login_user_type;
if (logged_in_state == LoginState::LOGGED_IN_NONE)
login_user_type = LoginState::LOGGED_IN_USER_NONE;
else if (is_current_user_owner_)
login_user_type = LoginState::LOGGED_IN_USER_OWNER;
else if (active_user_->GetType() == User::USER_TYPE_GUEST)
login_user_type = LoginState::LOGGED_IN_USER_GUEST;
else if (active_user_->GetType() == User::USER_TYPE_RETAIL_MODE)
login_user_type = LoginState::LOGGED_IN_USER_RETAIL_MODE;
else if (active_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT)
login_user_type = LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT;
else if (active_user_->GetType() == User::USER_TYPE_LOCALLY_MANAGED)
login_user_type = LoginState::LOGGED_IN_USER_LOCALLY_MANAGED;
else if (active_user_->GetType() == User::USER_TYPE_KIOSK_APP)
login_user_type = LoginState::LOGGED_IN_USER_KIOSK_APP;
else
login_user_type = LoginState::LOGGED_IN_USER_REGULAR;
LoginState::Get()->SetLoggedInState(logged_in_state, login_user_type);
}
void UserManagerImpl::SetLRUUser(User* user) {
UserList::iterator it = std::find(lru_logged_in_users_.begin(),
lru_logged_in_users_.end(),
user);
if (it != lru_logged_in_users_.end())
lru_logged_in_users_.erase(it);
lru_logged_in_users_.insert(lru_logged_in_users_.begin(), user);
}
void UserManagerImpl::OnRestoreActiveSessions(
const SessionManagerClient::ActiveSessionsMap& sessions,
bool success) {
if (!success) {
LOG(ERROR) << "Could not get list of active user sessions after crash.";
DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
return;
}
DCHECK(GetLoggedInUsers().size() == 1);
DCHECK(GetActiveUser());
std::string active_user_id = GetActiveUser()->email();
SessionManagerClient::ActiveSessionsMap::const_iterator it;
for (it = sessions.begin(); it != sessions.end(); ++it) {
if (active_user_id == it->first)
continue;
pending_user_sessions_[it->first] = it->second;
}
RestorePendingUserSessions();
}
void UserManagerImpl::RestorePendingUserSessions() {
if (pending_user_sessions_.empty()) {
NotifyPendingUserSessionsRestoreFinished();
return;
}
SessionManagerClient::ActiveSessionsMap::const_iterator it =
pending_user_sessions_.begin();
std::string user_id = it->first;
std::string user_id_hash = it->second;
DCHECK(!user_id.empty());
DCHECK(!user_id_hash.empty());
pending_user_sessions_.erase(user_id);
UserList logged_in_users = GetLoggedInUsers();
bool user_already_logged_in = false;
for (UserList::const_iterator it = logged_in_users.begin();
it != logged_in_users.end(); ++it) {
const User* user = (*it);
if (user->email() == user_id) {
user_already_logged_in = true;
break;
}
}
DCHECK(!user_already_logged_in);
if (!user_already_logged_in) {
LoginUtils::Get()->PrepareProfile(
UserContext(user_id,
std::string(),
std::string(),
user_id_hash,
false,
UserContext::AUTH_FLOW_OFFLINE),
std::string(),
false,
true,
this);
} else {
RestorePendingUserSessions();
}
}
void UserManagerImpl::SendRegularUserLoginMetrics(const std::string& user_id) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kFirstExecAfterBoot)) {
const std::string last_email =
g_browser_process->local_state()->GetString(kLastLoggedInRegularUser);
const base::TimeDelta time_to_login =
base::TimeTicks::Now() - manager_creation_time_;
if (!last_email.empty() && user_id != last_email &&
time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
time_to_login.InSeconds(), 0, kLogoutToLoginDelayMaxSec, 50);
}
}
}
void UserManagerImpl::OnUserNotAllowed(const std::string& user_email) {
LOG(ERROR) << "Shutdown session because a user is not allowed to be in the "
"current session";
chromeos::ShowMultiprofilesSessionAbortedDialog(user_email);
}
void UserManagerImpl::UpdateUserAccountLocale(const std::string& user_id,
const std::string& locale) {
if (!locale.empty() &&
locale != g_browser_process->GetApplicationLocale()) {
BrowserThread::PostBlockingPoolTask(
FROM_HERE,
base::Bind(ResolveLocale, locale,
base::Bind(&UserManagerImpl::DoUpdateAccountLocale,
base::Unretained(this),
user_id)));
} else {
DoUpdateAccountLocale(user_id, locale);
}
}
void UserManagerImpl::DoUpdateAccountLocale(
const std::string& user_id,
const std::string& resolved_locale) {
if (User* user = FindUserAndModify(user_id))
user->SetAccountLocale(resolved_locale);
}
void UserManagerImpl::UpdateNumberOfUsers() {
size_t users = GetLoggedInUsers().size();
if (users) {
if ((users + GetUsersAdmittedForMultiProfile().size()) > 1)
ash::MultiProfileUMA::RecordUserCount(users);
}
base::debug::SetCrashKeyValue(crash_keys::kNumberOfUsers,
base::StringPrintf("%" PRIuS, GetLoggedInUsers().size()));
}
void UserManagerImpl::DeleteUser(User* user) {
const bool is_active_user = (user == active_user_);
delete user;
if (is_active_user)
active_user_ = NULL;
}
}