diff --git a/chrome/browser/chromeos/accessibility/magnification_manager_browsertest.cc b/chrome/browser/chromeos/accessibility/magnification_manager_browsertest.cc index 99921d94a0c2..8b387e114537 100644 --- a/chrome/browser/chromeos/accessibility/magnification_manager_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/magnification_manager_browsertest.cc @@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/users/user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 4365803f0716..e4083e318bc9 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc @@ -34,11 +34,9 @@ #include "chrome/browser/chromeos/login/users/user_manager.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/component_updater/component_updater_service.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/google/google_brand_chromeos.h" #include "chrome/browser/lifetime/application_lifetime.h" -#include "chrome/browser/net/crl_set_fetcher.h" #include "chrome/browser/net/nss_context.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" @@ -286,6 +284,12 @@ void UserSessionManager::InitRlz(Profile* profile) { #endif } +bool UserSessionManager::HasBrowserRestarted() const { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + return base::SysInfo::IsRunningOnChromeOS() && + command_line->HasSwitch(switches::kLoginUser); +} + OAuth2LoginManager::SessionRestoreStrategy UserSessionManager::GetSigninSessionRestoreStrategy() { return session_restore_strategy_; @@ -670,10 +674,11 @@ void UserSessionManager::FinalizePrepareProfile(Profile* profile) { CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient(); btl->AddLoginTimeMarker("TPMOwn-Start", false); if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) { - if (cryptohome_util::TpmIsOwned()) + if (cryptohome_util::TpmIsOwned()) { client->CallTpmClearStoredPasswordAndBlock(); - else + } else { client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback()); + } } btl->AddLoginTimeMarker("TPMOwn-End", false); @@ -697,16 +702,15 @@ void UserSessionManager::FinalizePrepareProfile(Profile* profile) { content::NotificationService::AllSources(), content::Details(profile)); - // Initialize various services only for primary user. + InitializeCertsForPrimaryUser(profile); + + // Initialize RLZ only for primary user. const user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile); - if (user_manager->GetPrimaryUser() == user) { + if (user_manager->GetPrimaryUser() == user) InitRlz(profile); - InitializeCerts(profile); - InitializeCRLSetFetcher(user); - } - // TODO(nkostylev): This pointer should probably never be NULL, but it looks + // TODO(altimofeev): This pointer should probably never be NULL, but it looks // like LoginUtilsImpl::OnProfileCreated() may be getting called before // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is // killed during shutdown in tests -- see http://crosbug.com/18269. Replace @@ -808,29 +812,21 @@ void UserSessionManager::InitRlzImpl(Profile* profile, bool disabled) { #endif } -void UserSessionManager::InitializeCerts(Profile* profile) { +void UserSessionManager::InitializeCertsForPrimaryUser(Profile* profile) { // Now that the user profile has been initialized // |GetNSSCertDatabaseForProfile| is safe to be used. - if (CertLoader::IsInitialized() && base::SysInfo::IsRunningOnChromeOS()) { + UserManager* user_manager = UserManager::Get(); + const user_manager::User* primary_user = user_manager->GetPrimaryUser(); + if (user_manager->IsUserLoggedIn() && + primary_user && + profile == ProfileHelper::Get()->GetProfileByUser(primary_user) && + CertLoader::IsInitialized() && + base::SysInfo::IsRunningOnChromeOS()) { GetNSSCertDatabaseForProfile(profile, base::Bind(&OnGetNSSCertDatabaseForUser)); } } -void UserSessionManager::InitializeCRLSetFetcher( - const user_manager::User* user) { - const std::string username_hash = user->username_hash(); - if (!username_hash.empty()) { - base::FilePath path; - path = ProfileHelper::GetProfilePathByUserIdHash(username_hash); - component_updater::ComponentUpdateService* cus = - g_browser_process->component_updater(); - CRLSetFetcher* crl_set = g_browser_process->crl_set_fetcher(); - if (crl_set && cus) - crl_set->StartInitialLoad(cus, path); - } -} - void UserSessionManager::OnRestoreActiveSessions( const SessionManagerClient::ActiveSessionsMap& sessions, bool success) { diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h index de6a512252b7..9344cb83a154 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.h +++ b/chrome/browser/chromeos/login/session/user_session_manager.h @@ -98,6 +98,10 @@ class UserSessionManager // Initialize RLZ. void InitRlz(Profile* profile); + // Returns true when the browser has crashed and restarted during the current + // user's session. + bool HasBrowserRestarted() const; + // TODO(nkostylev): Drop these methods once LoginUtilsImpl::AttemptRestart() // is migrated. OAuth2LoginManager::SessionRestoreStrategy GetSigninSessionRestoreStrategy(); @@ -194,12 +198,9 @@ class UserSessionManager // Initializes RLZ. If |disabled| is true, RLZ pings are disabled. void InitRlzImpl(Profile* profile, bool disabled); - // Get the NSS cert database for the user represented with |profile| - // and start certificate loader with it. - void InitializeCerts(Profile* profile); - - // Starts loading CRL set. - void InitializeCRLSetFetcher(const user_manager::User* user); + // Get the NSS cert database for the primary user and start certificate + // loader with it. + void InitializeCertsForPrimaryUser(Profile* profile); // Callback to process RetrieveActiveSessions() request results. void OnRestoreActiveSessions( diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager.cc b/chrome/browser/chromeos/login/users/chrome_user_manager.cc deleted file mode 100644 index 24c2ad8111b4..000000000000 --- a/chrome/browser/chromeos/login/users/chrome_user_manager.cc +++ /dev/null @@ -1,1003 +0,0 @@ -// Copyright 2014 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 "chrome/browser/chromeos/login/users/chrome_user_manager.h" - -#include -#include - -#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/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/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" -#include "chrome/browser/chromeos/login/session/user_session_manager.h" -#include "chrome/browser/chromeos/login/signin/auth_sync_observer.h" -#include "chrome/browser/chromeos/login/signin/auth_sync_observer_factory.h" -#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h" -#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" -#include "chrome/browser/chromeos/login/users/remove_user_delegate.h" -#include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.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/profiles/profile.h" -#include "chrome/browser/supervised_user/chromeos/manager_password_service_factory.h" -#include "chrome/browser/supervised_user/chromeos/supervised_user_password_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/chromeos_switches.h" -#include "chromeos/login/user_names.h" -#include "chromeos/settings/cros_settings_names.h" -#include "components/session_manager/core/session_manager.h" -#include "components/user_manager/user_image/user_image.h" -#include "components/user_manager/user_type.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" -#include "grit/theme_resources.h" -#include "policy/policy_constants.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/wm/core/wm_core_switches.h" - -using content::BrowserThread; - -namespace chromeos { -namespace { - -// A vector pref of the the regular users known on this device, arranged in LRU -// order. -const char kRegularUsers[] = "LoggedInUsers"; - -// A vector pref of the public accounts defined on this device. -const char kPublicAccounts[] = "PublicAccounts"; - -// A string pref that gets set when a public account is removed but a user is -// currently logged into that account, requiring the account's data to be -// removed after logout. -const char kPublicAccountPendingDataRemoval[] = - "PublicAccountPendingDataRemoval"; - -} // namespace - -// static -void UserManager::RegisterPrefs(PrefRegistrySimple* registry) { - UserManagerBase::RegisterPrefs(registry); - - registry->RegisterListPref(kPublicAccounts); - registry->RegisterStringPref(kPublicAccountPendingDataRemoval, std::string()); - SupervisedUserManager::RegisterPrefs(registry); - SessionLengthLimiter::RegisterPrefs(registry); -} - -ChromeUserManager::ChromeUserManager() - : cros_settings_(CrosSettings::Get()), - device_local_account_policy_service_(NULL), - supervised_user_manager_(new SupervisedUserManagerImpl(this)) { - UpdateNumberOfUsers(); - - // UserManager instance should be used only on UI thread. - 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(&ChromeUserManager::RetrieveTrustedDevicePolicies, - base::Unretained(this))); - multi_profile_user_controller_.reset( - new MultiProfileUserController(this, GetLocalState())); - - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); - avatar_policy_observer_.reset(new policy::CloudExternalDataPolicyObserver( - cros_settings_, - connector->GetDeviceLocalAccountPolicyService(), - policy::key::kUserAvatarImage, - this)); - avatar_policy_observer_->Init(); - - wallpaper_policy_observer_.reset(new policy::CloudExternalDataPolicyObserver( - cros_settings_, - connector->GetDeviceLocalAccountPolicyService(), - policy::key::kWallpaperImage, - this)); - wallpaper_policy_observer_->Init(); -} - -ChromeUserManager::~ChromeUserManager() { -} - -void ChromeUserManager::Shutdown() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::Shutdown(); - - local_accounts_subscription_.reset(); - - // Stop the session length limiter. - 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(); - registrar_.RemoveAll(); -} - -MultiProfileUserController* ChromeUserManager::GetMultiProfileUserController() { - return multi_profile_user_controller_.get(); -} - -UserImageManager* ChromeUserManager::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 mgr(new UserImageManagerImpl(user_id, this)); - user_image_managers_[user_id] = mgr; - return mgr.get(); -} - -SupervisedUserManager* ChromeUserManager::GetSupervisedUserManager() { - return supervised_user_manager_.get(); -} - -user_manager::UserList ChromeUserManager::GetUsersAdmittedForMultiProfile() - const { - // Supervised users are not allowed to use multi-profiles. - if (GetLoggedInUsers().size() == 1 && - GetPrimaryUser()->GetType() != user_manager::USER_TYPE_REGULAR) { - return user_manager::UserList(); - } - - user_manager::UserList result; - const user_manager::UserList& users = GetUsers(); - for (user_manager::UserList::const_iterator it = users.begin(); - it != users.end(); - ++it) { - if ((*it)->GetType() == user_manager::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 user_manager::UserList(); - } - - // Users with a policy that prevents them being added to a session will be - // shown in login UI but will be grayed out. - // Same applies to owner account (see http://crbug.com/385034). - if (check == MultiProfileUserController::ALLOWED || - check == MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS || - check == MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY) { - result.push_back(*it); - } - } - } - - return result; -} - -user_manager::UserList ChromeUserManager::GetUnlockUsers() const { - const user_manager::UserList& logged_in_users = GetLoggedInUsers(); - if (logged_in_users.empty()) - return user_manager::UserList(); - - user_manager::UserList unlock_users; - Profile* profile = ProfileHelper::Get()->GetProfileByUser(GetPrimaryUser()); - std::string primary_behavior = - profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior); - - // Specific case: only one logged in user or - // primary user has primary-only multi-profile policy. - if (logged_in_users.size() == 1 || - primary_behavior == MultiProfileUserController::kBehaviorPrimaryOnly) { - if (GetPrimaryUser()->can_lock()) - unlock_users.push_back(primary_user_); - } else { - // Fill list of potential unlock users based on multi-profile policy state. - for (user_manager::UserList::const_iterator it = logged_in_users.begin(); - it != logged_in_users.end(); - ++it) { - user_manager::User* user = (*it); - Profile* profile = ProfileHelper::Get()->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; -} - -void ChromeUserManager::SessionStarted() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::SessionStarted(); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SESSION_STARTED, - content::Source(this), - content::Details(GetActiveUser())); -} - -void ChromeUserManager::RemoveUserInternal(const std::string& user_email, - RemoveUserDelegate* delegate) { - CrosSettings* cros_settings = CrosSettings::Get(); - - const base::Closure& callback = - base::Bind(&ChromeUserManager::RemoveUserInternal, - base::Unretained(this), - user_email, - delegate); - - // Ensure the value of owner email has been fetched. - if (CrosSettingsProvider::TRUSTED != - cros_settings->PrepareTrustedValues(callback)) { - // Value of owner email is not fetched yet. RemoveUserInternal will be - // called again after fetch completion. - return; - } - std::string owner; - cros_settings->GetString(kDeviceOwner, &owner); - if (user_email == owner) { - // Owner is not allowed to be removed from the device. - return; - } - RemoveNonOwnerUserInternal(user_email, delegate); -} - -void ChromeUserManager::SaveUserOAuthStatus( - const std::string& user_id, - user_manager::User::OAuthTokenStatus oauth_token_status) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::SaveUserOAuthStatus(user_id, oauth_token_status); - - GetUserFlow(user_id)->HandleOAuthTokenStatusChange(oauth_token_status); -} - -void ChromeUserManager::SaveUserDisplayName( - const std::string& user_id, - const base::string16& display_name) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::SaveUserDisplayName(user_id, display_name); - - // Do not update local state if data stored or cached outside the user's - // cryptohome is to be treated as ephemeral. - if (!IsUserNonCryptohomeDataEphemeral(user_id)) - supervised_user_manager_->UpdateManagerName(user_id, display_name); -} - -void ChromeUserManager::StopPolicyObserverForTesting() { - avatar_policy_observer_.reset(); - wallpaper_policy_observer_.reset(); -} - -void ChromeUserManager::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(details).ptr(); - if (IsUserLoggedIn() && !IsLoggedInAsGuest() && !IsLoggedInAsKioskApp()) { - if (IsLoggedInAsSupervisedUser()) - SupervisedUserPasswordServiceFactory::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); - } - } - break; - } - case chrome::NOTIFICATION_PROFILE_CREATED: { - Profile* profile = content::Source(source).ptr(); - user_manager::User* user = - ProfileHelper::Get()->GetUserByProfile(profile); - if (user != NULL) - user->set_profile_is_created(); - - // If there is pending user switch, do it now. - if (!GetPendingUserSwitchID().empty()) { - // Call SwitchActiveUser async because otherwise it may cause - // ProfileManager::GetProfile before the profile gets registered - // in ProfileManager. It happens in case of sync profile load when - // NOTIFICATION_PROFILE_CREATED is called synchronously. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&ChromeUserManager::SwitchActiveUser, - base::Unretained(this), - GetPendingUserSwitchID())); - SetPendingUserSwitchID(std::string()); - } - break; - } - default: - NOTREACHED(); - } -} - -void ChromeUserManager::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 ChromeUserManager::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 ChromeUserManager::OnExternalDataFetched(const std::string& policy, - const std::string& user_id, - scoped_ptr 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 ChromeUserManager::OnPolicyUpdated(const std::string& user_id) { - const user_manager::User* user = FindUser(user_id); - if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) - return; - UpdatePublicAccountDisplayName(user_id); - NotifyUserListChanged(); -} - -void ChromeUserManager::OnDeviceLocalAccountsChanged() { - // No action needed here, changes to the list of device-local accounts get - // handled via the kAccountsPrefDeviceLocalAccounts device setting observer. -} - -bool ChromeUserManager::CanCurrentUserLock() const { - return UserManagerBase::CanCurrentUserLock() && - GetCurrentUserFlow()->CanLockScreen(); -} - -bool ChromeUserManager::IsUserNonCryptohomeDataEphemeral( - const std::string& user_id) const { - // Data belonging to the obsolete public accounts whose data has not been - // removed yet is not ephemeral. - bool is_obsolete_public_account = IsPublicAccountMarkedForRemoval(user_id); - - return !is_obsolete_public_account && - UserManagerBase::IsUserNonCryptohomeDataEphemeral(user_id); -} - -bool ChromeUserManager::AreEphemeralUsersEnabled() const { - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); - return GetEphemeralUsersEnabled() && - (connector->IsEnterpriseManaged() || !GetOwnerEmail().empty()); -} - -const std::string& ChromeUserManager::GetApplicationLocale() const { - return g_browser_process->GetApplicationLocale(); -} - -PrefService* ChromeUserManager::GetLocalState() const { - return g_browser_process ? g_browser_process->local_state() : NULL; -} - -bool ChromeUserManager::IsEnterpriseManaged() const { - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); - return connector->IsEnterpriseManaged(); -} - -void ChromeUserManager::LoadPublicAccounts( - std::set* public_sessions_set) { - const base::ListValue* prefs_public_sessions = - GetLocalState()->GetList(kPublicAccounts); - std::vector public_sessions; - ParseUserList(*prefs_public_sessions, - std::set(), - &public_sessions, - public_sessions_set); - for (std::vector::const_iterator it = public_sessions.begin(); - it != public_sessions.end(); - ++it) { - users_.push_back(user_manager::User::CreatePublicAccountUser(*it)); - UpdatePublicAccountDisplayName(*it); - } -} - -void ChromeUserManager::PerformPreUserListLoadingActions() { - // Clean up user list first. All code down the path should be synchronous, - // so that local state after transaction rollback is in consistent state. - // This process also should not trigger EnsureUsersLoaded again. - if (supervised_user_manager_->HasFailedUserCreationTransaction()) - supervised_user_manager_->RollbackUserCreationTransaction(); -} - -void ChromeUserManager::PerformPostUserListLoadingActions() { - for (user_manager::UserList::iterator ui = users_.begin(), ue = users_.end(); - ui != ue; - ++ui) { - GetUserImageManager((*ui)->email())->LoadUserImage(); - } -} - -void ChromeUserManager::PerformPostUserLoggedInActions(bool browser_restart) { - // Initialize the session length limiter and start it only if - // session limit is defined by the policy. - session_length_limiter_.reset( - new SessionLengthLimiter(NULL, browser_restart)); -} - -bool ChromeUserManager::IsDemoApp(const std::string& user_id) const { - return DemoAppLauncher::IsDemoAppSession(user_id); -} - -bool ChromeUserManager::IsKioskApp(const std::string& user_id) const { - policy::DeviceLocalAccount::Type device_local_account_type; - return policy::IsDeviceLocalAccountUser(user_id, - &device_local_account_type) && - device_local_account_type == - policy::DeviceLocalAccount::TYPE_KIOSK_APP; -} - -bool ChromeUserManager::IsPublicAccountMarkedForRemoval( - const std::string& user_id) const { - return user_id == - GetLocalState()->GetString(kPublicAccountPendingDataRemoval); -} - -void ChromeUserManager::RetrieveTrustedDevicePolicies() { - SetEphemeralUsersEnabled(false); - SetOwnerEmail(std::string()); - - // Schedule a callback if device policy has not yet been verified. - if (CrosSettingsProvider::TRUSTED != - cros_settings_->PrepareTrustedValues( - base::Bind(&ChromeUserManager::RetrieveTrustedDevicePolicies, - base::Unretained(this)))) { - return; - } - - bool ephemeral_users_enabled; - cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled, - &ephemeral_users_enabled); - SetEphemeralUsersEnabled(ephemeral_users_enabled); - - std::string owner_email; - cros_settings_->GetString(kDeviceOwner, &owner_email); - SetOwnerEmail(owner_email); - - EnsureUsersLoaded(); - - bool changed = UpdateAndCleanUpPublicAccounts( - policy::GetDeviceLocalAccounts(cros_settings_)); - - // If ephemeral users are enabled and we are on the login screen, take this - // opportunity to clean up by removing all regular users except the owner. - if (GetEphemeralUsersEnabled() && !IsUserLoggedIn()) { - ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers); - prefs_users_update->Clear(); - for (user_manager::UserList::iterator it = users_.begin(); - it != users_.end();) { - const std::string user_email = (*it)->email(); - if ((*it)->GetType() == user_manager::USER_TYPE_REGULAR && - user_email != GetOwnerEmail()) { - RemoveNonCryptohomeData(user_email); - DeleteUser(*it); - it = users_.erase(it); - changed = true; - } else { - if ((*it)->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) - prefs_users_update->Append(new base::StringValue(user_email)); - ++it; - } - } - } - - if (changed) - NotifyUserListChanged(); -} - -void ChromeUserManager::GuestUserLoggedIn() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::GuestUserLoggedIn(); - - // TODO(nkostylev): Add support for passing guest session cryptohome - // mount point. Legacy (--login-profile) value will be used for now. - // http://crosbug.com/230859 - active_user_->SetStubImage( - user_manager::UserImage( - *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - IDR_PROFILE_PICTURE_LOADING)), - user_manager::User::USER_IMAGE_INVALID, - false); - - // Initializes wallpaper after active_user_ is set. - WallpaperManager::Get()->SetUserWallpaperNow(chromeos::login::kGuestUserName); -} - -void ChromeUserManager::RegularUserLoggedIn(const std::string& user_id) { - UserManagerBase::RegularUserLoggedIn(user_id); - - if (IsCurrentUserNew()) - WallpaperManager::Get()->SetUserWallpaperNow(user_id); - - GetUserImageManager(user_id)->UserLoggedIn(IsCurrentUserNew(), false); - - WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); - - // Make sure that new data is persisted to Local State. - GetLocalState()->CommitPendingWrite(); -} - -void ChromeUserManager::RegularUserLoggedInAsEphemeral( - const std::string& user_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UserManagerBase::RegularUserLoggedInAsEphemeral(user_id); - - GetUserImageManager(user_id)->UserLoggedIn(IsCurrentUserNew(), false); - WallpaperManager::Get()->SetUserWallpaperNow(user_id); -} - -void ChromeUserManager::SupervisedUserLoggedIn(const std::string& user_id) { - // TODO(nkostylev): Refactor, share code with RegularUserLoggedIn(). - - // Remove the user from the user list. - active_user_ = RemoveRegularOrSupervisedUserFromList(user_id); - - // If the user was not found on the user list, create a new user. - if (!GetActiveUser()) { - SetIsCurrentUserNew(true); - active_user_ = user_manager::User::CreateSupervisedUser(user_id); - // Leaving OAuth token status at the default state = unknown. - WallpaperManager::Get()->SetUserWallpaperNow(user_id); - } else { - if (supervised_user_manager_->CheckForFirstRun(user_id)) { - SetIsCurrentUserNew(true); - WallpaperManager::Get()->SetUserWallpaperNow(user_id); - } else { - SetIsCurrentUserNew(true); - } - } - - // Add the user to the front of the user list. - ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers); - prefs_users_update->Insert(0, new base::StringValue(user_id)); - users_.insert(users_.begin(), active_user_); - - // Now that user is in the list, save display name. - if (IsCurrentUserNew()) { - SaveUserDisplayName(GetActiveUser()->email(), - GetActiveUser()->GetDisplayName()); - } - - GetUserImageManager(user_id)->UserLoggedIn(IsCurrentUserNew(), true); - WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); - - // Make sure that new data is persisted to Local State. - GetLocalState()->CommitPendingWrite(); -} - -void ChromeUserManager::PublicAccountUserLoggedIn(user_manager::User* user) { - SetIsCurrentUserNew(true); - active_user_ = user; - - // The UserImageManager chooses a random avatar picture when a user logs in - // for the first time. Tell the UserImageManager that this user is not new to - // prevent the avatar from getting changed. - GetUserImageManager(user->email())->UserLoggedIn(false, true); - WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); -} - -void ChromeUserManager::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_manager::User::CreateKioskAppUser(app_id); - active_user_->SetStubImage( - user_manager::UserImage( - *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - IDR_PROFILE_PICTURE_LOADING)), - user_manager::User::USER_IMAGE_INVALID, - false); - - WallpaperManager::Get()->SetUserWallpaperNow(app_id); - - // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like - // the kiosk_app_id in these objects, removing the need to re-parse the - // device-local account list here to extract the kiosk_app_id. - const std::vector device_local_accounts = - policy::GetDeviceLocalAccounts(cros_settings_); - const policy::DeviceLocalAccount* account = NULL; - for (std::vector::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); - - // Disable window animation since kiosk app runs in a single full screen - // window and window animation causes start-up janks. - command_line->AppendSwitch(wm::switches::kWindowAnimationsDisabled); -} - -void ChromeUserManager::DemoAccountLoggedIn() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - active_user_ = - user_manager::User::CreateKioskAppUser(DemoAppLauncher::kDemoUserName); - active_user_->SetStubImage( - user_manager::UserImage( - *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - IDR_PROFILE_PICTURE_LOADING)), - user_manager::User::USER_IMAGE_INVALID, - false); - WallpaperManager::Get()->SetUserWallpaperNow(DemoAppLauncher::kDemoUserName); - - CommandLine* command_line = CommandLine::ForCurrentProcess(); - command_line->AppendSwitch(::switches::kForceAppMode); - command_line->AppendSwitchASCII(::switches::kAppId, - DemoAppLauncher::kDemoAppId); - - // Disable window animation since the demo app runs in a single full screen - // window and window animation causes start-up janks. - CommandLine::ForCurrentProcess()->AppendSwitch( - wm::switches::kWindowAnimationsDisabled); -} - -void ChromeUserManager::RetailModeUserLoggedIn() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - SetIsCurrentUserNew(true); - active_user_ = user_manager::User::CreateRetailModeUser(); - GetUserImageManager(chromeos::login::kRetailModeUserName) - ->UserLoggedIn(IsCurrentUserNew(), true); - WallpaperManager::Get()->SetUserWallpaperNow( - chromeos::login::kRetailModeUserName); -} - -void ChromeUserManager::NotifyOnLogin() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - UserSessionManager::OverrideHomedir(); - UpdateNumberOfUsers(); - - UserManagerBase::NotifyOnLogin(); - - // TODO(nkostylev): Deprecate this notification in favor of - // ActiveUserChanged() observer call. - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_LOGIN_USER_CHANGED, - content::Source(this), - content::Details(GetActiveUser())); - - UserSessionManager::GetInstance()->PerformPostUserLoggedInActions(); -} - -void ChromeUserManager::UpdateOwnership() { - bool is_owner = DeviceSettingsService::Get()->HasPrivateOwnerKey(); - VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner"); - - SetCurrentUserIsOwner(is_owner); -} - -void ChromeUserManager::RemoveNonCryptohomeData(const std::string& user_id) { - UserManagerBase::RemoveNonCryptohomeData(user_id); - - WallpaperManager::Get()->RemoveUserWallpaperInfo(user_id); - GetUserImageManager(user_id)->DeleteUserImage(); - - supervised_user_manager_->RemoveNonCryptohomeData(user_id); - - multi_profile_user_controller_->RemoveCachedValues(user_id); -} - -void ChromeUserManager::CleanUpPublicAccountNonCryptohomeDataPendingRemoval() { - PrefService* local_state = GetLocalState(); - 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 ChromeUserManager::CleanUpPublicAccountNonCryptohomeData( - const std::vector& old_public_accounts) { - std::set users; - for (user_manager::UserList::const_iterator it = users_.begin(); - it != users_.end(); - ++it) - users.insert((*it)->email()); - - // If the user is logged into a public account that has been removed from the - // user list, mark the account's data as pending removal after logout. - if (IsLoggedInAsPublicAccount()) { - const std::string active_user_id = GetActiveUser()->email(); - if (users.find(active_user_id) == users.end()) { - GetLocalState()->SetString(kPublicAccountPendingDataRemoval, - active_user_id); - users.insert(active_user_id); - } - } - - // Remove the data belonging to any other public accounts that are no longer - // found on the user list. - for (std::vector::const_iterator it = - old_public_accounts.begin(); - it != old_public_accounts.end(); - ++it) { - if (users.find(*it) == users.end()) - RemoveNonCryptohomeData(*it); - } -} - -bool ChromeUserManager::UpdateAndCleanUpPublicAccounts( - const std::vector& device_local_accounts) { - // Try to remove any public account data marked as pending removal. - CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); - - // Get the current list of public accounts. - std::vector old_public_accounts; - for (user_manager::UserList::const_iterator it = users_.begin(); - it != users_.end(); - ++it) { - if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) - old_public_accounts.push_back((*it)->email()); - } - - // Get the new list of public accounts from policy. - std::vector new_public_accounts; - for (std::vector::const_iterator it = - device_local_accounts.begin(); - it != device_local_accounts.end(); - ++it) { - // TODO(mnissler, nkostylev, bartfab): Process Kiosk Apps within the - // standard login framework: http://crbug.com/234694 - if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION) - new_public_accounts.push_back(it->user_id); - } - - // If the list of public accounts has not changed, return. - 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; - } - - // Persist the new list of public accounts in a pref. - ListPrefUpdate prefs_public_accounts_update(GetLocalState(), kPublicAccounts); - prefs_public_accounts_update->Clear(); - for (std::vector::const_iterator it = - new_public_accounts.begin(); - it != new_public_accounts.end(); - ++it) { - prefs_public_accounts_update->AppendString(*it); - } - - // Remove the old public accounts from the user list. - for (user_manager::UserList::iterator it = users_.begin(); - it != users_.end();) { - if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) { - if (*it != GetLoggedInUser()) - DeleteUser(*it); - it = users_.erase(it); - } else { - ++it; - } - } - - // Add the new public accounts to the front of the user list. - for (std::vector::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_manager::User::CreatePublicAccountUser(*it)); - UpdatePublicAccountDisplayName(*it); - } - - for (user_manager::UserList::iterator - ui = users_.begin(), - ue = users_.begin() + new_public_accounts.size(); - ui != ue; - ++ui) { - GetUserImageManager((*ui)->email())->LoadUserImage(); - } - - // Remove data belonging to public accounts that are no longer found on the - // user list. - CleanUpPublicAccountNonCryptohomeData(old_public_accounts); - - return true; -} - -void ChromeUserManager::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(); - } - - // Set or clear the display name. - SaveUserDisplayName(user_id, base::UTF8ToUTF16(display_name)); -} - -UserFlow* ChromeUserManager::GetCurrentUserFlow() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!IsUserLoggedIn()) - return GetDefaultUserFlow(); - return GetUserFlow(GetLoggedInUser()->email()); -} - -UserFlow* ChromeUserManager::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 ChromeUserManager::SetUserFlow(const std::string& user_id, - UserFlow* flow) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - ResetUserFlow(user_id); - specific_flows_[user_id] = flow; -} - -void ChromeUserManager::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 ChromeUserManager::AreSupervisedUsersAllowed() const { - bool supervised_users_allowed = false; - cros_settings_->GetBoolean(kAccountsPrefSupervisedUsersEnabled, - &supervised_users_allowed); - return supervised_users_allowed; -} - -UserFlow* ChromeUserManager::GetDefaultUserFlow() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!default_flow_.get()) - default_flow_.reset(new DefaultUserFlow()); - return default_flow_.get(); -} - -void ChromeUserManager::NotifyUserListChanged() { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_USER_LIST_CHANGED, - content::Source(this), - content::NotificationService::NoDetails()); -} - -void ChromeUserManager::NotifyUserAddedToSession( - const user_manager::User* added_user, - bool user_switch_pending) { - if (user_switch_pending) - SetPendingUserSwitchID(added_user->email()); - - UpdateNumberOfUsers(); - UserManagerBase::NotifyUserAddedToSession(added_user, user_switch_pending); -} - -void ChromeUserManager::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 ChromeUserManager::UpdateNumberOfUsers() { - size_t users = GetLoggedInUsers().size(); - if (users) { - // Write the user number as UMA stat when a multi user session is possible. - if ((users + GetUsersAdmittedForMultiProfile().size()) > 1) - ash::MultiProfileUMA::RecordUserCount(users); - } - - base::debug::SetCrashKeyValue( - crash_keys::kNumberOfUsers, - base::StringPrintf("%" PRIuS, GetLoggedInUsers().size())); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager.h b/chrome/browser/chromeos/login/users/chrome_user_manager.h deleted file mode 100644 index 4f3b25ebad15..000000000000 --- a/chrome/browser/chromeos/login/users/chrome_user_manager.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USERS_CHROME_USER_MANAGER_H_ -#define CHROME_BROWSER_CHROMEOS_LOGIN_USERS_CHROME_USER_MANAGER_H_ - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/memory/linked_ptr.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" -#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h" -#include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h" -#include "chrome/browser/chromeos/login/users/user_manager_base.h" -#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" -#include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer.h" -#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/device_settings_service.h" -#include "components/user_manager/user.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -class PrefService; -class ProfileSyncService; - -namespace policy { -struct DeviceLocalAccount; -} - -namespace chromeos { - -class MultiProfileUserController; -class RemoveUserDelegate; -class SupervisedUserManagerImpl; -class SessionLengthLimiter; - -// Chrome specific implementation of the UserManager. -class ChromeUserManager - : public UserManagerBase, - public content::NotificationObserver, - public policy::CloudExternalDataPolicyObserver::Delegate, - public policy::DeviceLocalAccountPolicyService::Observer, - public MultiProfileUserControllerDelegate { - public: - virtual ~ChromeUserManager(); - - // UserManager implementation: - virtual void Shutdown() OVERRIDE; - virtual MultiProfileUserController* GetMultiProfileUserController() OVERRIDE; - virtual UserImageManager* GetUserImageManager( - const std::string& user_id) OVERRIDE; - virtual SupervisedUserManager* GetSupervisedUserManager() OVERRIDE; - virtual user_manager::UserList GetUsersAdmittedForMultiProfile() - const OVERRIDE; - virtual user_manager::UserList GetUnlockUsers() const OVERRIDE; - virtual void SessionStarted() OVERRIDE; - virtual void SaveUserOAuthStatus( - const std::string& user_id, - user_manager::User::OAuthTokenStatus oauth_token_status) OVERRIDE; - virtual void SaveUserDisplayName(const std::string& user_id, - const base::string16& display_name) OVERRIDE; - virtual bool CanCurrentUserLock() const OVERRIDE; - virtual bool IsUserNonCryptohomeDataEphemeral( - const std::string& user_id) const OVERRIDE; - - virtual UserFlow* GetCurrentUserFlow() const OVERRIDE; - virtual UserFlow* GetUserFlow(const std::string& user_id) const OVERRIDE; - virtual void SetUserFlow(const std::string& user_id, UserFlow* flow) OVERRIDE; - virtual void ResetUserFlow(const std::string& user_id) OVERRIDE; - virtual bool AreSupervisedUsersAllowed() const OVERRIDE; - - // content::NotificationObserver implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - - // policy::CloudExternalDataPolicyObserver::Delegate: - virtual void OnExternalDataSet(const std::string& policy, - const std::string& user_id) OVERRIDE; - virtual void OnExternalDataCleared(const std::string& policy, - const std::string& user_id) OVERRIDE; - virtual void OnExternalDataFetched(const std::string& policy, - const std::string& user_id, - scoped_ptr data) OVERRIDE; - - // policy::DeviceLocalAccountPolicyService::Observer implementation. - virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; - virtual void OnDeviceLocalAccountsChanged() OVERRIDE; - - void StopPolicyObserverForTesting(); - - protected: - // UserManagerBase implementation: - virtual bool AreEphemeralUsersEnabled() const OVERRIDE; - virtual const std::string& GetApplicationLocale() const OVERRIDE; - virtual PrefService* GetLocalState() const OVERRIDE; - virtual bool IsEnterpriseManaged() const OVERRIDE; - virtual void LoadPublicAccounts(std::set* users_set) OVERRIDE; - virtual void NotifyOnLogin() OVERRIDE; - virtual void NotifyUserAddedToSession(const user_manager::User* added_user, - bool user_switch_pending) OVERRIDE; - virtual void PerformPreUserListLoadingActions() OVERRIDE; - virtual void PerformPostUserListLoadingActions() OVERRIDE; - virtual void PerformPostUserLoggedInActions(bool browser_restart) OVERRIDE; - virtual void RemoveNonCryptohomeData(const std::string& user_id) OVERRIDE; - virtual void RemoveUserInternal(const std::string& user_email, - RemoveUserDelegate* delegate) OVERRIDE; - virtual bool IsDemoApp(const std::string& user_id) const OVERRIDE; - virtual bool IsKioskApp(const std::string& user_id) const OVERRIDE; - virtual bool IsPublicAccountMarkedForRemoval( - const std::string& user_id) const OVERRIDE; - virtual void DemoAccountLoggedIn() OVERRIDE; - virtual void GuestUserLoggedIn() OVERRIDE; - virtual void KioskAppLoggedIn(const std::string& app_id) OVERRIDE; - virtual void PublicAccountUserLoggedIn(user_manager::User* user) OVERRIDE; - virtual void RegularUserLoggedIn(const std::string& user_id) OVERRIDE; - virtual void RegularUserLoggedInAsEphemeral( - const std::string& user_id) OVERRIDE; - virtual void RetailModeUserLoggedIn() OVERRIDE; - virtual void SupervisedUserLoggedIn(const std::string& user_id) OVERRIDE; - - private: - friend class SupervisedUserManagerImpl; - friend class UserManager; - friend class UserManagerTest; - friend class WallpaperManager; - friend class WallpaperManagerTest; - - typedef base::hash_map > - UserImageManagerMap; - - ChromeUserManager(); - - // Retrieves trusted device policies and removes users from the persistent - // list if ephemeral users are enabled. Schedules a callback to itself if - // trusted device policies are not yet available. - void RetrieveTrustedDevicePolicies(); - - // Updates current user ownership on UI thread. - void UpdateOwnership(); - - // If data for a public account is marked as pending removal and the user is - // no longer logged into that account, removes the data. - void CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); - - // Removes data belonging to public accounts that are no longer found on the - // user list. If the user is currently logged into one of these accounts, the - // data for that account is not removed immediately but marked as pending - // removal after logout. - void CleanUpPublicAccountNonCryptohomeData( - const std::vector& old_public_accounts); - - // Replaces the list of public accounts with those found in - // |device_local_accounts|. Ensures that data belonging to accounts no longer - // on the list is removed. Returns |true| if the list has changed. - // Public accounts are defined by policy. This method is called whenever an - // updated list of public accounts is received from policy. - bool UpdateAndCleanUpPublicAccounts( - const std::vector& device_local_accounts); - - // Updates the display name for public account |username| from policy settings - // associated with that username. - void UpdatePublicAccountDisplayName(const std::string& user_id); - - // Notifies the UI about a change to the user list. - void NotifyUserListChanged(); - - // Lazily creates default user flow. - UserFlow* GetDefaultUserFlow() const; - - // MultiProfileUserControllerDelegate implementation: - virtual void OnUserNotAllowed(const std::string& user_email) OVERRIDE; - - // Update the number of users. - void UpdateNumberOfUsers(); - - // Interface to the signed settings store. - CrosSettings* cros_settings_; - - // Interface to device-local account definitions and associated policy. - policy::DeviceLocalAccountPolicyService* device_local_account_policy_service_; - - content::NotificationRegistrar registrar_; - - // User avatar managers. - UserImageManagerMap user_image_managers_; - - // Supervised user manager. - scoped_ptr supervised_user_manager_; - - // Session length limiter. - scoped_ptr session_length_limiter_; - - typedef std::map FlowMap; - - // Lazy-initialized default flow. - mutable scoped_ptr default_flow_; - - // Specific flows by user e-mail. Keys should be canonicalized before - // access. - FlowMap specific_flows_; - - scoped_ptr local_accounts_subscription_; - - scoped_ptr multi_profile_user_controller_; - - // Observer for the policy that can be used to manage user images. - scoped_ptr avatar_policy_observer_; - - // Observer for the policy that can be used to manage wallpapers. - scoped_ptr - wallpaper_policy_observer_; - - DISALLOW_COPY_AND_ASSIGN(ChromeUserManager); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_LOGIN_USERS_CHROME_USER_MANAGER_H_ diff --git a/chrome/browser/chromeos/login/users/fake_user_manager.cc b/chrome/browser/chromeos/login/users/fake_user_manager.cc index 93801bdc2101..56326a68e3e4 100644 --- a/chrome/browser/chromeos/login/users/fake_user_manager.cc +++ b/chrome/browser/chromeos/login/users/fake_user_manager.cc @@ -177,7 +177,7 @@ UserImageManager* FakeUserManager::GetUserImageManager( return NULL; } -const user_manager::UserList& FakeUserManager::GetLRULoggedInUsers() const { +const user_manager::UserList& FakeUserManager::GetLRULoggedInUsers() { return user_list_; } @@ -185,7 +185,7 @@ user_manager::UserList FakeUserManager::GetUnlockUsers() const { return user_list_; } -const std::string& FakeUserManager::GetOwnerEmail() const { +const std::string& FakeUserManager::GetOwnerEmail() { return owner_email_; } diff --git a/chrome/browser/chromeos/login/users/fake_user_manager.h b/chrome/browser/chromeos/login/users/fake_user_manager.h index 8ade4ec8b6a4..f216c38fb027 100644 --- a/chrome/browser/chromeos/login/users/fake_user_manager.h +++ b/chrome/browser/chromeos/login/users/fake_user_manager.h @@ -63,9 +63,9 @@ class FakeUserManager : public UserManager { virtual UserImageManager* GetUserImageManager( const std::string& user_id) OVERRIDE; virtual SupervisedUserManager* GetSupervisedUserManager() OVERRIDE; - virtual const user_manager::UserList& GetLRULoggedInUsers() const OVERRIDE; + virtual const user_manager::UserList& GetLRULoggedInUsers() OVERRIDE; virtual user_manager::UserList GetUnlockUsers() const OVERRIDE; - virtual const std::string& GetOwnerEmail() const OVERRIDE; + virtual const std::string& GetOwnerEmail() OVERRIDE; virtual void SessionStarted() OVERRIDE {} virtual void RemoveUser(const std::string& email, RemoveUserDelegate* delegate) OVERRIDE {} diff --git a/chrome/browser/chromeos/login/users/mock_user_manager.cc b/chrome/browser/chromeos/login/users/mock_user_manager.cc index a283a6769033..ac80b9488902 100644 --- a/chrome/browser/chromeos/login/users/mock_user_manager.cc +++ b/chrome/browser/chromeos/login/users/mock_user_manager.cc @@ -36,7 +36,7 @@ user_manager::UserList MockUserManager::GetUnlockUsers() const { return user_list_; } -const std::string& MockUserManager::GetOwnerEmail() const { +const std::string& MockUserManager::GetOwnerEmail() { return GetLoggedInUser()->email(); } diff --git a/chrome/browser/chromeos/login/users/mock_user_manager.h b/chrome/browser/chromeos/login/users/mock_user_manager.h index a5ad8de04191..26aa3e6014c1 100644 --- a/chrome/browser/chromeos/login/users/mock_user_manager.h +++ b/chrome/browser/chromeos/login/users/mock_user_manager.h @@ -29,7 +29,7 @@ class MockUserManager : public UserManager { MOCK_CONST_METHOD0(GetUsersAdmittedForMultiProfile, user_manager::UserList(void)); MOCK_CONST_METHOD0(GetLoggedInUsers, const user_manager::UserList&(void)); - MOCK_CONST_METHOD0(GetLRULoggedInUsers, const user_manager::UserList&(void)); + MOCK_METHOD0(GetLRULoggedInUsers, const user_manager::UserList&(void)); MOCK_METHOD3(UserLoggedIn, void( const std::string&, const std::string&, bool)); MOCK_METHOD1(SwitchActiveUser, void(const std::string& email)); @@ -78,11 +78,11 @@ class MockUserManager : public UserManager { MOCK_CONST_METHOD0(AreSupervisedUsersAllowed, bool(void)); // You can't mock these functions easily because nobody can create - // User objects but the ChromeUserManager and us. + // User objects but the UserManagerImpl and us. virtual const user_manager::UserList& GetUsers() const OVERRIDE; virtual const user_manager::User* GetLoggedInUser() const OVERRIDE; virtual user_manager::UserList GetUnlockUsers() const OVERRIDE; - virtual const std::string& GetOwnerEmail() const OVERRIDE; + virtual const std::string& GetOwnerEmail() OVERRIDE; virtual user_manager::User* GetLoggedInUser() OVERRIDE; virtual const user_manager::User* GetActiveUser() const OVERRIDE; virtual user_manager::User* GetActiveUser() OVERRIDE; diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc index 7335a0a69ee6..0c2e1b249194 100644 --- a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc @@ -17,7 +17,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h" #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h" -#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" @@ -129,8 +129,9 @@ void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey); } -SupervisedUserManagerImpl::SupervisedUserManagerImpl(ChromeUserManager* owner) - : owner_(owner), cros_settings_(CrosSettings::Get()) { +SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl* owner) + : owner_(owner), + cros_settings_(CrosSettings::Get()) { // SupervisedUserManager instance should be used only on UI thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); authentication_.reset(new SupervisedUserAuthentication(this)); diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h index 05e45d46727c..3daa00e42d7b 100644 --- a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h +++ b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.h @@ -14,8 +14,8 @@ namespace chromeos { -class ChromeUserManager; class CrosSettings; +class UserManagerImpl; // Implementation of the UserManager. class SupervisedUserManagerImpl @@ -60,10 +60,10 @@ class SupervisedUserManagerImpl const std::string& token) OVERRIDE; private: - friend class ChromeUserManager; friend class UserManager; + friend class UserManagerImpl; - explicit SupervisedUserManagerImpl(ChromeUserManager* owner); + explicit SupervisedUserManagerImpl(UserManagerImpl* owner); // Returns true if there is non-committed user creation transaction. bool HasFailedUserCreationTransaction(); @@ -106,7 +106,7 @@ class SupervisedUserManagerImpl void CleanPref(const std::string& user_id, const char* key); - ChromeUserManager* owner_; + UserManagerImpl* owner_; // Interface to the signed settings store. CrosSettings* cros_settings_; diff --git a/chrome/browser/chromeos/login/users/user_manager.cc b/chrome/browser/chromeos/login/users/user_manager.cc index 1adceeb6e36c..842cf85392f8 100644 --- a/chrome/browser/chromeos/login/users/user_manager.cc +++ b/chrome/browser/chromeos/login/users/user_manager.cc @@ -7,7 +7,7 @@ #include "base/command_line.h" #include "base/prefs/pref_registry_simple.h" #include "chrome/browser/browser_process_platform_part_chromeos.h" -#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/common/chrome_switches.h" @@ -50,7 +50,7 @@ UserManager::UserAccountData::~UserAccountData() {} // static void UserManager::Initialize() { CHECK(!g_user_manager); - g_user_manager = new ChromeUserManager(); + g_user_manager = new UserManagerImpl(); } // static diff --git a/chrome/browser/chromeos/login/users/user_manager.h b/chrome/browser/chromeos/login/users/user_manager.h index 8b2d961664c0..fe42e311ab0b 100644 --- a/chrome/browser/chromeos/login/users/user_manager.h +++ b/chrome/browser/chromeos/login/users/user_manager.h @@ -19,7 +19,7 @@ class RemoveUserDelegate; class UserImageManager; class SupervisedUserManager; -// Interface for UserManagerBase - provides a mechanism for discovering users +// Base class for UserManagerImpl - provides a mechanism for discovering users // who have logged into this Chrome OS device before and updating that list. class UserManager { public: @@ -122,7 +122,7 @@ class UserManager { // Returns a list of users who are currently logged in in the LRU order - // so the active user is the first one in the list. If there is no user logged // in, the current user will be returned. - virtual const user_manager::UserList& GetLRULoggedInUsers() const = 0; + virtual const user_manager::UserList& GetLRULoggedInUsers() = 0; // Returns a list of users who can unlock the device. // This list is based on policy and whether user is able to do unlock. @@ -134,7 +134,7 @@ class UserManager { // Returns the email of the owner user. Returns an empty string if there is // no owner for the device. - virtual const std::string& GetOwnerEmail() const = 0; + virtual const std::string& GetOwnerEmail() = 0; // Indicates that a user with the given |user_id| has just logged in. The // persistent list is updated accordingly if the user is not ephemeral. diff --git a/chrome/browser/chromeos/login/users/user_manager_base.cc b/chrome/browser/chromeos/login/users/user_manager_base.cc deleted file mode 100644 index febb6f08eef0..000000000000 --- a/chrome/browser/chromeos/login/users/user_manager_base.cc +++ /dev/null @@ -1,1042 +0,0 @@ -// Copyright 2014 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 "chrome/browser/chromeos/login/users/user_manager_base.h" - -#include -#include - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/compiler_specific.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/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/chromeos/login/users/remove_user_delegate.h" -#include "chromeos/chromeos_switches.h" -#include "chromeos/cryptohome/async_method_caller.h" -#include "chromeos/login/login_state.h" -#include "chromeos/login/user_names.h" -#include "components/session_manager/core/session_manager.h" -#include "components/user_manager/user_type.h" -#include "content/public/browser/browser_thread.h" -#include "google_apis/gaia/gaia_auth_util.h" -#include "ui/base/l10n/l10n_util.h" - -using content::BrowserThread; - -namespace chromeos { -namespace { - -// A vector pref of the the regular users known on this device, arranged in LRU -// order. -const char kRegularUsers[] = "LoggedInUsers"; - -// A dictionary that maps user IDs to the displayed name. -const char kUserDisplayName[] = "UserDisplayName"; - -// A dictionary that maps user IDs to the user's given name. -const char kUserGivenName[] = "UserGivenName"; - -// A dictionary that maps user IDs to the displayed (non-canonical) emails. -const char kUserDisplayEmail[] = "UserDisplayEmail"; - -// A dictionary that maps user IDs to OAuth token presence flag. -const char kUserOAuthTokenStatus[] = "OAuthTokenStatus"; - -// A dictionary that maps user IDs to a flag indicating whether online -// authentication against GAIA should be enforced during the next sign-in. -const char kUserForceOnlineSignin[] = "UserForceOnlineSignin"; - -// A string pref containing the ID of the last user who logged in if it was -// a regular user or an empty string if it was another type of user (guest, -// kiosk, public account, etc.). -const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser"; - -// Upper bound for a histogram metric reporting the amount of time between -// one regular user logging out and a different regular user logging in. -const int kLogoutToLoginDelayMaxSec = 1800; - -// Callback that is called after user removal is complete. -void OnRemoveUserComplete(const std::string& user_email, - bool success, - cryptohome::MountError return_code) { - // Log the error, but there's not much we can do. - if (!success) { - LOG(ERROR) << "Removal of cryptohome for " << user_email - << " failed, return code: " << return_code; - } -} - -// Runs on SequencedWorkerPool thread. Passes resolved locale to -// |on_resolve_callback| on UI thread. -void ResolveLocale( - const std::string& raw_locale, - base::Callback on_resolve_callback) { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::string resolved_locale; - // Ignore result - l10n_util::CheckAndResolveLocale(raw_locale, &resolved_locale); - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, - base::Bind(on_resolve_callback, resolved_locale)); -} - -} // namespace - -// static -void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterListPref(kRegularUsers); - registry->RegisterStringPref(kLastLoggedInRegularUser, std::string()); - registry->RegisterDictionaryPref(kUserDisplayName); - registry->RegisterDictionaryPref(kUserGivenName); - registry->RegisterDictionaryPref(kUserDisplayEmail); - registry->RegisterDictionaryPref(kUserOAuthTokenStatus); - registry->RegisterDictionaryPref(kUserForceOnlineSignin); -} - -UserManagerBase::UserManagerBase() - : active_user_(NULL), - primary_user_(NULL), - user_loading_stage_(STAGE_NOT_LOADED), - session_started_(false), - is_current_user_owner_(false), - is_current_user_new_(false), - is_current_user_ephemeral_regular_user_(false), - ephemeral_users_enabled_(false), - manager_creation_time_(base::TimeTicks::Now()) { - // UserManager instance should be used only on UI thread. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - UpdateLoginState(); -} - -UserManagerBase::~UserManagerBase() { - // Can't use STLDeleteElements because of the private destructor of User. - for (user_manager::UserList::iterator it = users_.begin(); it != users_.end(); - it = users_.erase(it)) { - DeleteUser(*it); - } - // These are pointers to the same User instances that were in users_ list. - logged_in_users_.clear(); - lru_logged_in_users_.clear(); - - DeleteUser(active_user_); -} - -void UserManagerBase::Shutdown() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); -} - -const user_manager::UserList& UserManagerBase::GetUsers() const { - const_cast(this)->EnsureUsersLoaded(); - return users_; -} - -const user_manager::UserList& UserManagerBase::GetLoggedInUsers() const { - return logged_in_users_; -} - -const user_manager::UserList& UserManagerBase::GetLRULoggedInUsers() const { - return lru_logged_in_users_; -} - -const std::string& UserManagerBase::GetOwnerEmail() const { - return owner_email_; -} - -void UserManagerBase::UserLoggedIn(const std::string& user_id, - const std::string& username_hash, - bool browser_restart) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - user_manager::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); - - // Reset the new user flag if the user already exists. - SetIsCurrentUserNew(false); - NotifyUserAddedToSession(user, true /* user switch pending */); - - return; - } - - if (user_id == chromeos::login::kGuestUserName) { - GuestUserLoggedIn(); - } else if (user_id == chromeos::login::kRetailModeUserName) { - RetailModeUserLoggedIn(); - } else if (IsKioskApp(user_id)) { - KioskAppLoggedIn(user_id); - } else if (IsDemoApp(user_id)) { - DemoAccountLoggedIn(); - } else { - EnsureUsersLoaded(); - - if (user && user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) { - PublicAccountUserLoggedIn(user); - } else if ((user && - user->GetType() == user_manager::USER_TYPE_SUPERVISED) || - (!user && - gaia::ExtractDomainName(user_id) == - chromeos::login::kSupervisedUserDomain)) { - SupervisedUserLoggedIn(user_id); - } else if (browser_restart && IsPublicAccountMarkedForRemoval(user_id)) { - PublicAccountUserLoggedIn( - user_manager::User::CreatePublicAccountUser(user_id)); - } else if (user_id != GetOwnerEmail() && !user && - (AreEphemeralUsersEnabled() || browser_restart)) { - RegularUserLoggedInAsEphemeral(user_id); - } else { - RegularUserLoggedIn(user_id); - } - } - - DCHECK(active_user_); - active_user_->set_is_logged_in(true); - active_user_->set_is_active(true); - active_user_->set_username_hash(username_hash); - - // Place user who just signed in to the top of the logged in users. - 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_manager::USER_TYPE_REGULAR) - SendRegularUserLoginMetrics(user_id); - } - - UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType", - active_user_->GetType(), - user_manager::NUM_USER_TYPES); - - GetLocalState()->SetString( - kLastLoggedInRegularUser, - (active_user_->GetType() == user_manager::USER_TYPE_REGULAR) ? user_id - : ""); - - NotifyOnLogin(); - PerformPostUserLoggedInActions(browser_restart); -} - -void UserManagerBase::SwitchActiveUser(const std::string& user_id) { - user_manager::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_manager::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; - - // Move the user to the front. - SetLRUUser(active_user_); - - NotifyActiveUserHashChanged(active_user_->username_hash()); - NotifyActiveUserChanged(active_user_); -} - -void UserManagerBase::SessionStarted() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - session_started_ = true; - - UpdateLoginState(); - session_manager::SessionManager::Get()->SetSessionState( - session_manager::SESSION_STATE_ACTIVE); - - if (IsCurrentUserNew()) { - // Make sure that the new user's data is persisted to Local State. - GetLocalState()->CommitPendingWrite(); - } -} - -void UserManagerBase::RemoveUser(const std::string& user_id, - RemoveUserDelegate* delegate) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!CanUserBeRemoved(FindUser(user_id))) - return; - - RemoveUserInternal(user_id, delegate); -} - -void UserManagerBase::RemoveUserInternal(const std::string& user_email, - RemoveUserDelegate* delegate) { - RemoveNonOwnerUserInternal(user_email, delegate); -} - -void UserManagerBase::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 UserManagerBase::RemoveUserFromList(const std::string& user_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - RemoveNonCryptohomeData(user_id); - if (user_loading_stage_ == STAGE_LOADED) { - DeleteUser(RemoveRegularOrSupervisedUserFromList(user_id)); - } else if (user_loading_stage_ == STAGE_LOADING) { - DCHECK(gaia::ExtractDomainName(user_id) == - chromeos::login::kSupervisedUserDomain); - // Special case, removing partially-constructed supervised user during user - // list loading. - ListPrefUpdate users_update(GetLocalState(), kRegularUsers); - users_update->Remove(base::StringValue(user_id), NULL); - } else { - NOTREACHED() << "Users are not loaded yet."; - return; - } - - // Make sure that new data is persisted to Local State. - GetLocalState()->CommitPendingWrite(); -} - -bool UserManagerBase::IsKnownUser(const std::string& user_id) const { - return FindUser(user_id) != NULL; -} - -const user_manager::User* UserManagerBase::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_manager::User* UserManagerBase::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_manager::User* UserManagerBase::GetLoggedInUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return active_user_; -} - -user_manager::User* UserManagerBase::GetLoggedInUser() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return active_user_; -} - -const user_manager::User* UserManagerBase::GetActiveUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return active_user_; -} - -user_manager::User* UserManagerBase::GetActiveUser() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return active_user_; -} - -const user_manager::User* UserManagerBase::GetPrimaryUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return primary_user_; -} - -void UserManagerBase::SaveUserOAuthStatus( - const std::string& user_id, - user_manager::User::OAuthTokenStatus oauth_token_status) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - DVLOG(1) << "Saving user OAuth token status in Local State"; - user_manager::User* user = FindUserAndModify(user_id); - if (user) - user->set_oauth_token_status(oauth_token_status); - - // Do not update local state if data stored or cached outside the user's - // cryptohome is to be treated as ephemeral. - if (IsUserNonCryptohomeDataEphemeral(user_id)) - return; - - DictionaryPrefUpdate oauth_status_update(GetLocalState(), - kUserOAuthTokenStatus); - oauth_status_update->SetWithoutPathExpansion( - user_id, - new base::FundamentalValue(static_cast(oauth_token_status))); -} - -void UserManagerBase::SaveForceOnlineSignin(const std::string& user_id, - bool force_online_signin) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - // Do not update local state if data stored or cached outside the user's - // cryptohome is to be treated as ephemeral. - if (IsUserNonCryptohomeDataEphemeral(user_id)) - return; - - DictionaryPrefUpdate force_online_update(GetLocalState(), - kUserForceOnlineSignin); - force_online_update->SetBooleanWithoutPathExpansion(user_id, - force_online_signin); -} - -void UserManagerBase::SaveUserDisplayName(const std::string& user_id, - const base::string16& display_name) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (user_manager::User* user = FindUserAndModify(user_id)) { - user->set_display_name(display_name); - - // Do not update local state if data stored or cached outside the user's - // cryptohome is to be treated as ephemeral. - if (!IsUserNonCryptohomeDataEphemeral(user_id)) { - DictionaryPrefUpdate display_name_update(GetLocalState(), - kUserDisplayName); - display_name_update->SetWithoutPathExpansion( - user_id, new base::StringValue(display_name)); - } - } -} - -base::string16 UserManagerBase::GetUserDisplayName( - const std::string& user_id) const { - const user_manager::User* user = FindUser(user_id); - return user ? user->display_name() : base::string16(); -} - -void UserManagerBase::SaveUserDisplayEmail(const std::string& user_id, - const std::string& display_email) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - user_manager::User* user = FindUserAndModify(user_id); - if (!user) - return; // Ignore if there is no such user. - - user->set_display_email(display_email); - - // Do not update local state if data stored or cached outside the user's - // cryptohome is to be treated as ephemeral. - if (IsUserNonCryptohomeDataEphemeral(user_id)) - return; - - DictionaryPrefUpdate display_email_update(GetLocalState(), kUserDisplayEmail); - display_email_update->SetWithoutPathExpansion( - user_id, new base::StringValue(display_email)); -} - -std::string UserManagerBase::GetUserDisplayEmail( - const std::string& user_id) const { - const user_manager::User* user = FindUser(user_id); - return user ? user->display_email() : user_id; -} - -void UserManagerBase::UpdateUserAccountData( - const std::string& user_id, - const UserAccountData& account_data) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - SaveUserDisplayName(user_id, account_data.display_name()); - - if (user_manager::User* user = FindUserAndModify(user_id)) { - base::string16 given_name = account_data.given_name(); - user->set_given_name(given_name); - if (!IsUserNonCryptohomeDataEphemeral(user_id)) { - DictionaryPrefUpdate given_name_update(GetLocalState(), kUserGivenName); - given_name_update->SetWithoutPathExpansion( - user_id, new base::StringValue(given_name)); - } - } - - UpdateUserAccountLocale(user_id, account_data.locale()); -} - -// static -void UserManagerBase::ParseUserList(const base::ListValue& users_list, - const std::set& existing_users, - std::vector* users_vector, - std::set* 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); - } -} - -bool UserManagerBase::IsCurrentUserOwner() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::AutoLock lk(is_current_user_owner_lock_); - return is_current_user_owner_; -} - -void UserManagerBase::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 UserManagerBase::IsCurrentUserNew() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return is_current_user_new_; -} - -bool UserManagerBase::IsCurrentUserNonCryptohomeDataEphemeral() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - IsUserNonCryptohomeDataEphemeral(GetLoggedInUser()->email()); -} - -bool UserManagerBase::CanCurrentUserLock() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && active_user_->can_lock(); -} - -bool UserManagerBase::IsUserLoggedIn() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return active_user_; -} - -bool UserManagerBase::IsLoggedInAsRegularUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_REGULAR; -} - -bool UserManagerBase::IsLoggedInAsDemoUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_RETAIL_MODE; -} - -bool UserManagerBase::IsLoggedInAsPublicAccount() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT; -} - -bool UserManagerBase::IsLoggedInAsGuest() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_GUEST; -} - -bool UserManagerBase::IsLoggedInAsSupervisedUser() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_SUPERVISED; -} - -bool UserManagerBase::IsLoggedInAsKioskApp() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && - active_user_->GetType() == user_manager::USER_TYPE_KIOSK_APP; -} - -bool UserManagerBase::IsLoggedInAsStub() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return IsUserLoggedIn() && active_user_->email() == login::kStubUser; -} - -bool UserManagerBase::IsSessionStarted() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return session_started_; -} - -bool UserManagerBase::IsUserNonCryptohomeDataEphemeral( - const std::string& user_id) const { - // Data belonging to the guest, retail mode and stub users is always - // ephemeral. - if (user_id == login::kGuestUserName || - user_id == login::kRetailModeUserName || user_id == login::kStubUser) { - return true; - } - - // Data belonging to the owner, anyone found on the user list and obsolete - // public accounts whose data has not been removed yet is not ephemeral. - if (user_id == GetOwnerEmail() || UserExistsInList(user_id) || - IsPublicAccountMarkedForRemoval(user_id)) { - return false; - } - - // Data belonging to the currently logged-in user is ephemeral when: - // a) The user logged into a regular account while the ephemeral users policy - // was enabled. - // - or - - // b) The user logged into any other account type. - if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) && - (is_current_user_ephemeral_regular_user_ || !IsLoggedInAsRegularUser())) { - return true; - } - - // Data belonging to any other user is ephemeral when: - // a) Going through the regular login flow and the ephemeral users policy is - // enabled. - // - or - - // b) The browser is restarting after a crash. - return AreEphemeralUsersEnabled() || - session_manager::SessionManager::HasBrowserRestarted(); -} - -void UserManagerBase::AddObserver(UserManager::Observer* obs) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - observer_list_.AddObserver(obs); -} - -void UserManagerBase::RemoveObserver(UserManager::Observer* obs) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - observer_list_.RemoveObserver(obs); -} - -void UserManagerBase::AddSessionStateObserver( - UserManager::UserSessionStateObserver* obs) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - session_state_observer_list_.AddObserver(obs); -} - -void UserManagerBase::RemoveSessionStateObserver( - UserManager::UserSessionStateObserver* obs) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - session_state_observer_list_.RemoveObserver(obs); -} - -void UserManagerBase::NotifyLocalStateChanged() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - FOR_EACH_OBSERVER( - UserManager::Observer, observer_list_, LocalStateChanged(this)); -} - -bool UserManagerBase::CanUserBeRemoved(const user_manager::User* user) const { - // Only regular and supervised users are allowed to be manually removed. - if (!user || (user->GetType() != user_manager::USER_TYPE_REGULAR && - user->GetType() != user_manager::USER_TYPE_SUPERVISED)) { - return false; - } - - // Sanity check: we must not remove single user unless it's an enterprise - // device. This check may seem redundant at a first sight because - // this single user must be an owner and we perform special check later - // in order not to remove an owner. However due to non-instant nature of - // ownership assignment this later check may sometimes fail. - // See http://crosbug.com/12723 - if (users_.size() < 2 && !IsEnterpriseManaged()) - return false; - - // Sanity check: do not allow any of the the logged in users to be removed. - for (user_manager::UserList::const_iterator it = logged_in_users_.begin(); - it != logged_in_users_.end(); - ++it) { - if ((*it)->email() == user->email()) - return false; - } - - return true; -} - -bool UserManagerBase::GetEphemeralUsersEnabled() const { - return ephemeral_users_enabled_; -} - -void UserManagerBase::SetEphemeralUsersEnabled(bool enabled) { - ephemeral_users_enabled_ = enabled; -} - -void UserManagerBase::SetIsCurrentUserNew(bool is_new) { - is_current_user_new_ = is_new; -} - -void UserManagerBase::SetOwnerEmail(std::string owner_user_id) { - owner_email_ = owner_user_id; -} - -const std::string& UserManagerBase::GetPendingUserSwitchID() const { - return pending_user_switch_; -} - -void UserManagerBase::SetPendingUserSwitchID(std::string user_id) { - pending_user_switch_ = user_id; -} - -void UserManagerBase::EnsureUsersLoaded() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!GetLocalState()) - return; - - if (user_loading_stage_ != STAGE_NOT_LOADED) - return; - user_loading_stage_ = STAGE_LOADING; - - PerformPreUserListLoadingActions(); - - PrefService* local_state = GetLocalState(); - const base::ListValue* prefs_regular_users = - local_state->GetList(kRegularUsers); - - 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); - - // Load public sessions first. - std::set public_sessions_set; - LoadPublicAccounts(&public_sessions_set); - - // Load regular users and supervised users. - std::vector regular_users; - std::set regular_users_set; - ParseUserList(*prefs_regular_users, - public_sessions_set, - ®ular_users, - ®ular_users_set); - for (std::vector::const_iterator it = regular_users.begin(); - it != regular_users.end(); - ++it) { - user_manager::User* user = NULL; - const std::string domain = gaia::ExtractDomainName(*it); - if (domain == chromeos::login::kSupervisedUserDomain) - user = user_manager::User::CreateSupervisedUser(*it); - else - user = user_manager::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; - - PerformPostUserListLoadingActions(); -} - -user_manager::UserList& UserManagerBase::GetUsersAndModify() { - EnsureUsersLoaded(); - return users_; -} - -const user_manager::User* UserManagerBase::FindUserInList( - const std::string& user_id) const { - const user_manager::UserList& users = GetUsers(); - for (user_manager::UserList::const_iterator it = users.begin(); - it != users.end(); - ++it) { - if ((*it)->email() == user_id) - return *it; - } - return NULL; -} - -const bool UserManagerBase::UserExistsInList(const std::string& user_id) const { - const base::ListValue* user_list = GetLocalState()->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_manager::User* UserManagerBase::FindUserInListAndModify( - const std::string& user_id) { - user_manager::UserList& users = GetUsersAndModify(); - for (user_manager::UserList::iterator it = users.begin(); it != users.end(); - ++it) { - if ((*it)->email() == user_id) - return *it; - } - return NULL; -} - -void UserManagerBase::GuestUserLoggedIn() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - active_user_ = user_manager::User::CreateGuestUser(); -} - -void UserManagerBase::AddUserRecord(user_manager::User* user) { - // Add the user to the front of the user list. - ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers); - prefs_users_update->Insert(0, new base::StringValue(user->email())); - users_.insert(users_.begin(), user); -} - -void UserManagerBase::RegularUserLoggedIn(const std::string& user_id) { - // Remove the user from the user list. - active_user_ = RemoveRegularOrSupervisedUserFromList(user_id); - - // If the user was not found on the user list, create a new user. - SetIsCurrentUserNew(!active_user_); - if (IsCurrentUserNew()) { - active_user_ = user_manager::User::CreateRegularUser(user_id); - active_user_->set_oauth_token_status(LoadUserOAuthStatus(user_id)); - SaveUserDisplayName(active_user_->email(), - base::UTF8ToUTF16(active_user_->GetAccountName(true))); - } - - AddUserRecord(active_user_); - - // Make sure that new data is persisted to Local State. - GetLocalState()->CommitPendingWrite(); -} - -void UserManagerBase::RegularUserLoggedInAsEphemeral( - const std::string& user_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - SetIsCurrentUserNew(true); - is_current_user_ephemeral_regular_user_ = true; - active_user_ = user_manager::User::CreateRegularUser(user_id); -} - -void UserManagerBase::NotifyOnLogin() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - NotifyActiveUserHashChanged(active_user_->username_hash()); - NotifyActiveUserChanged(active_user_); - UpdateLoginState(); -} - -user_manager::User::OAuthTokenStatus UserManagerBase::LoadUserOAuthStatus( - const std::string& user_id) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - const base::DictionaryValue* prefs_oauth_status = - GetLocalState()->GetDictionary(kUserOAuthTokenStatus); - int oauth_token_status = user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN; - if (prefs_oauth_status && - prefs_oauth_status->GetIntegerWithoutPathExpansion(user_id, - &oauth_token_status)) { - user_manager::User::OAuthTokenStatus result = - static_cast(oauth_token_status); - if (result == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) - GetUserFlow(user_id)->HandleOAuthTokenStatusChange(result); - return result; - } - return user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN; -} - -bool UserManagerBase::LoadForceOnlineSignin(const std::string& user_id) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - const base::DictionaryValue* prefs_force_online = - GetLocalState()->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 UserManagerBase::RemoveNonCryptohomeData(const std::string& user_id) { - PrefService* prefs = GetLocalState(); - 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); -} - -user_manager::User* UserManagerBase::RemoveRegularOrSupervisedUserFromList( - const std::string& user_id) { - ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers); - prefs_users_update->Clear(); - user_manager::User* user = NULL; - for (user_manager::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_manager::USER_TYPE_REGULAR || - (*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) { - prefs_users_update->Append(new base::StringValue(user_email)); - } - ++it; - } - } - return user; -} - -void UserManagerBase::NotifyActiveUserChanged( - const user_manager::User* active_user) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver, - session_state_observer_list_, - ActiveUserChanged(active_user)); -} - -void UserManagerBase::NotifyUserAddedToSession( - const user_manager::User* added_user, - bool user_switch_pending) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver, - session_state_observer_list_, - UserAddedToSession(added_user)); -} - -void UserManagerBase::NotifyActiveUserHashChanged(const std::string& hash) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver, - session_state_observer_list_, - ActiveUserHashChanged(hash)); -} - -void UserManagerBase::UpdateLoginState() { - if (!LoginState::IsInitialized()) - return; // LoginState may not be intialized in tests. - - 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_manager::USER_TYPE_GUEST) - login_user_type = LoginState::LOGGED_IN_USER_GUEST; - else if (active_user_->GetType() == user_manager::USER_TYPE_RETAIL_MODE) - login_user_type = LoginState::LOGGED_IN_USER_RETAIL_MODE; - else if (active_user_->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) - login_user_type = LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT; - else if (active_user_->GetType() == user_manager::USER_TYPE_SUPERVISED) - login_user_type = LoginState::LOGGED_IN_USER_SUPERVISED; - else if (active_user_->GetType() == user_manager::USER_TYPE_KIOSK_APP) - login_user_type = LoginState::LOGGED_IN_USER_KIOSK_APP; - else - login_user_type = LoginState::LOGGED_IN_USER_REGULAR; - - if (primary_user_) { - LoginState::Get()->SetLoggedInStateAndPrimaryUser( - logged_in_state, login_user_type, primary_user_->username_hash()); - } else { - LoginState::Get()->SetLoggedInState(logged_in_state, login_user_type); - } -} - -void UserManagerBase::SetLRUUser(user_manager::User* user) { - user_manager::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 UserManagerBase::SendRegularUserLoginMetrics(const std::string& user_id) { - // If this isn't the first time Chrome was run after the system booted, - // assume that Chrome was restarted because a previous session ended. - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kFirstExecAfterBoot)) { - const std::string last_email = - GetLocalState()->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 UserManagerBase::UpdateUserAccountLocale(const std::string& user_id, - const std::string& locale) { - if (!locale.empty() && locale != GetApplicationLocale()) { - base::Callback on_resolve_callback = - base::Bind(&UserManagerBase::DoUpdateAccountLocale, - base::Unretained(this), - user_id); - BrowserThread::PostBlockingPoolTask(FROM_HERE, - base::Bind(ResolveLocale, - locale, - on_resolve_callback)); - } else { - DoUpdateAccountLocale(user_id, locale); - } -} - -void UserManagerBase::DoUpdateAccountLocale( - const std::string& user_id, - const std::string& resolved_locale) { - if (user_manager::User* user = FindUserAndModify(user_id)) - user->SetAccountLocale(resolved_locale); -} - -void UserManagerBase::DeleteUser(user_manager::User* user) { - const bool is_active_user = (user == active_user_); - delete user; - if (is_active_user) - active_user_ = NULL; -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/login/users/user_manager_impl.cc b/chrome/browser/chromeos/login/users/user_manager_impl.cc new file mode 100644 index 000000000000..2a8d493b2fee --- /dev/null +++ b/chrome/browser/chromeos/login/users/user_manager_impl.cc @@ -0,0 +1,1839 @@ +// Copyright 2014 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 "chrome/browser/chromeos/login/users/user_manager_impl.h" + +#include +#include + +#include "ash/multi_profile_uma.h" +#include "base/base_paths.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/path_service.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/browser_process.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" +#include "chrome/browser/chromeos/login/session/user_session_manager.h" +#include "chrome/browser/chromeos/login/signin/auth_sync_observer.h" +#include "chrome/browser/chromeos/login/signin/auth_sync_observer_factory.h" +#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" +#include "chrome/browser/chromeos/login/users/remove_user_delegate.h" +#include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.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/net/crl_set_fetcher.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/supervised_user/chromeos/manager_password_service_factory.h" +#include "chrome/browser/supervised_user/chromeos/supervised_user_password_service_factory.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/crash_keys.h" +#include "chrome/common/pref_names.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/login/auth/user_context.h" +#include "chromeos/login/login_state.h" +#include "chromeos/login/user_names.h" +#include "chromeos/settings/cros_settings_names.h" +#include "components/session_manager/core/session_manager.h" +#include "components/user_manager/user_image/user_image.h" +#include "components/user_manager/user_type.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 "grit/theme_resources.h" +#include "policy/policy_constants.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/wm/core/wm_core_switches.h" + +using content::BrowserThread; + +namespace chromeos { +namespace { + +// A vector pref of the the regular users known on this device, arranged in LRU +// order. +const char kRegularUsers[] = "LoggedInUsers"; + +// A vector pref of the public accounts defined on this device. +const char kPublicAccounts[] = "PublicAccounts"; + +// A string pref that gets set when a public account is removed but a user is +// currently logged into that account, requiring the account's data to be +// removed after logout. +const char kPublicAccountPendingDataRemoval[] = + "PublicAccountPendingDataRemoval"; + +// A dictionary that maps user IDs to the displayed name. +const char kUserDisplayName[] = "UserDisplayName"; + +// A dictionary that maps user IDs to the user's given name. +const char kUserGivenName[] = "UserGivenName"; + +// A dictionary that maps user IDs to the displayed (non-canonical) emails. +const char kUserDisplayEmail[] = "UserDisplayEmail"; + +// A dictionary that maps user IDs to OAuth token presence flag. +const char kUserOAuthTokenStatus[] = "OAuthTokenStatus"; + +// A dictionary that maps user IDs to a flag indicating whether online +// authentication against GAIA should be enforced during the next sign-in. +const char kUserForceOnlineSignin[] = "UserForceOnlineSignin"; + +// A string pref containing the ID of the last user who logged in if it was +// a regular user or an empty string if it was another type of user (guest, +// kiosk, public account, etc.). +const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser"; + +// Upper bound for a histogram metric reporting the amount of time between +// one regular user logging out and a different regular user logging in. +const int kLogoutToLoginDelayMaxSec = 1800; + +// Callback that is called after user removal is complete. +void OnRemoveUserComplete(const std::string& user_email, + bool success, + cryptohome::MountError return_code) { + // Log the error, but there's not much we can do. + if (!success) { + LOG(ERROR) << "Removal of cryptohome for " << user_email + << " failed, return code: " << return_code; + } +} + +// Helper function that copies users from |users_list| to |users_vector| and +// |users_set|. Duplicates and users already present in |existing_users| are +// skipped. +void ParseUserList(const base::ListValue& users_list, + const std::set& existing_users, + std::vector* users_vector, + std::set* 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); + } +} + +// Runs on SequencedWorkerPool thread. Passes resolved locale to +// |on_resolve_callback| on UI thread. +void ResolveLocale( + const std::string& raw_locale, + base::Callback on_resolve_callback) { + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::string resolved_locale; + // Ignore result + l10n_util::CheckAndResolveLocale(raw_locale, &resolved_locale); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(on_resolve_callback, resolved_locale)); +} + +} // namespace + +// static +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), + 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()) { + UpdateNumberOfUsers(); + // UserManager instance should be used only on UI thread. + 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))); + 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_, + connector->GetDeviceLocalAccountPolicyService(), + policy::key::kUserAvatarImage, + this)); + avatar_policy_observer_->Init(); + + wallpaper_policy_observer_.reset(new policy::CloudExternalDataPolicyObserver( + cros_settings_, + connector->GetDeviceLocalAccountPolicyService(), + policy::key::kWallpaperImage, + this)); + wallpaper_policy_observer_->Init(); + + UpdateLoginState(); +} + +UserManagerImpl::~UserManagerImpl() { + // Can't use STLDeleteElements because of the private destructor of User. + for (user_manager::UserList::iterator it = users_.begin(); it != users_.end(); + it = users_.erase(it)) { + DeleteUser(*it); + } + // These are pointers to the same User instances that were in users_ list. + logged_in_users_.clear(); + lru_logged_in_users_.clear(); + + DeleteUser(active_user_); +} + +void UserManagerImpl::Shutdown() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + local_accounts_subscription_.reset(); + // Stop the session length limiter. + 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(); + registrar_.RemoveAll(); +} + +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 mgr(new UserImageManagerImpl(user_id, this)); + user_image_managers_[user_id] = mgr; + return mgr.get(); +} + +SupervisedUserManager* UserManagerImpl::GetSupervisedUserManager() { + return supervised_user_manager_.get(); +} + +const user_manager::UserList& UserManagerImpl::GetUsers() const { + const_cast(this)->EnsureUsersLoaded(); + return users_; +} + +user_manager::UserList UserManagerImpl::GetUsersAdmittedForMultiProfile() + const { + // Supervised users are not allowed to use multi-profiles. + if (logged_in_users_.size() == 1 && + GetPrimaryUser()->GetType() != user_manager::USER_TYPE_REGULAR) { + return user_manager::UserList(); + } + + user_manager::UserList result; + const user_manager::UserList& users = GetUsers(); + for (user_manager::UserList::const_iterator it = users.begin(); + it != users.end(); + ++it) { + if ((*it)->GetType() == user_manager::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 user_manager::UserList(); + } + + // Users with a policy that prevents them being added to a session will be + // shown in login UI but will be grayed out. + // Same applies to owner account (see http://crbug.com/385034). + if (check == MultiProfileUserController::ALLOWED || + check == MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS || + check == MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY) { + result.push_back(*it); + } + } + } + + return result; +} + +const user_manager::UserList& UserManagerImpl::GetLoggedInUsers() const { + return logged_in_users_; +} + +const user_manager::UserList& UserManagerImpl::GetLRULoggedInUsers() { + // If there is no user logged in, we return the active user as the only one. + 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_; +} + +user_manager::UserList UserManagerImpl::GetUnlockUsers() const { + const user_manager::UserList& logged_in_users = GetLoggedInUsers(); + if (logged_in_users.empty()) + return user_manager::UserList(); + + user_manager::UserList unlock_users; + Profile* profile = ProfileHelper::Get()->GetProfileByUser(primary_user_); + std::string primary_behavior = + profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior); + + // Specific case: only one logged in user or + // primary user has primary-only multi-profile policy. + if (logged_in_users.size() == 1 || + primary_behavior == MultiProfileUserController::kBehaviorPrimaryOnly) { + if (primary_user_->can_lock()) + unlock_users.push_back(primary_user_); + } else { + // Fill list of potential unlock users based on multi-profile policy state. + for (user_manager::UserList::const_iterator it = logged_in_users.begin(); + it != logged_in_users.end(); + ++it) { + user_manager::User* user = (*it); + Profile* profile = ProfileHelper::Get()->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)); + + user_manager::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); + // Reset the new user flag if the user already exists. + is_current_user_new_ = false; + NotifyUserAddedToSession(user); + // Remember that we need to switch to this user as soon as profile ready. + pending_user_switch_ = user_id; + return; + } + + policy::DeviceLocalAccount::Type device_local_account_type; + if (user_id == chromeos::login::kGuestUserName) { + GuestUserLoggedIn(); + } else if (user_id == chromeos::login::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_manager::USER_TYPE_PUBLIC_ACCOUNT) { + PublicAccountUserLoggedIn(user); + } else if ((user && + user->GetType() == user_manager::USER_TYPE_SUPERVISED) || + (!user && + gaia::ExtractDomainName(user_id) == + chromeos::login::kSupervisedUserDomain)) { + SupervisedUserLoggedIn(user_id); + } else if (browser_restart && user_id == g_browser_process->local_state()-> + GetString(kPublicAccountPendingDataRemoval)) { + PublicAccountUserLoggedIn( + user_manager::User::CreatePublicAccountUser(user_id)); + } else if (user_id != owner_email_ && !user && + (AreEphemeralUsersEnabled() || browser_restart)) { + RegularUserLoggedInAsEphemeral(user_id); + } else { + RegularUserLoggedIn(user_id); + } + + // Initialize the session length limiter and start it only if + // session limit is defined by the policy. + 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); + + // Place user who just signed in to the top of the logged in users. + logged_in_users_.insert(logged_in_users_.begin(), active_user_); + SetLRUUser(active_user_); + + if (!primary_user_) { + // Register CRLSet now that the home dir is mounted. + if (!username_hash.empty()) { + base::FilePath path; + path = + chromeos::ProfileHelper::GetProfilePathByUserIdHash(username_hash); + component_updater::ComponentUpdateService* cus = + g_browser_process->component_updater(); + CRLSetFetcher* crl_set = g_browser_process->crl_set_fetcher(); + if (crl_set && cus) + crl_set->StartInitialLoad(cus, path); + } + primary_user_ = active_user_; + if (primary_user_->GetType() == user_manager::USER_TYPE_REGULAR) + SendRegularUserLoginMetrics(user_id); + } + + UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType", + active_user_->GetType(), + user_manager::NUM_USER_TYPES); + + g_browser_process->local_state()->SetString( + kLastLoggedInRegularUser, + (active_user_->GetType() == user_manager::USER_TYPE_REGULAR) ? user_id + : ""); + + NotifyOnLogin(); +} + +void UserManagerImpl::SwitchActiveUser(const std::string& user_id) { + user_manager::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_manager::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; + + // Move the user to the front. + SetLRUUser(active_user_); + + NotifyActiveUserHashChanged(active_user_->username_hash()); + NotifyActiveUserChanged(active_user_); +} + +void UserManagerImpl::SessionStarted() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + session_started_ = true; + + UpdateLoginState(); + g_browser_process->platform_part()->SessionManager()->SetSessionState( + session_manager::SESSION_STATE_ACTIVE); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_SESSION_STARTED, + content::Source(this), + content::Details(active_user_)); + if (is_current_user_new_) { + // Make sure that the new user's data is persisted to Local State. + g_browser_process->local_state()->CommitPendingWrite(); + } +} + +void UserManagerImpl::RemoveUser(const std::string& user_id, + RemoveUserDelegate* delegate) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + const user_manager::User* user = FindUser(user_id); + if (!user || (user->GetType() != user_manager::USER_TYPE_REGULAR && + user->GetType() != user_manager::USER_TYPE_SUPERVISED)) + return; + + // Sanity check: we must not remove single user unless it's an enterprise + // device. This check may seem redundant at a first sight because + // this single user must be an owner and we perform special check later + // in order not to remove an owner. However due to non-instant nature of + // ownership assignment this later check may sometimes fail. + // See http://crosbug.com/12723 + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part() + ->browser_policy_connector_chromeos(); + if (users_.size() < 2 && !connector->IsEnterpriseManaged()) + return; + + // Sanity check: do not allow any of the the logged in users to be removed. + for (user_manager::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(); + + // Ensure the value of owner email has been fetched. + if (CrosSettingsProvider::TRUSTED != cros_settings->PrepareTrustedValues( + base::Bind(&UserManagerImpl::RemoveUserInternal, + base::Unretained(this), + user_email, delegate))) { + // Value of owner email is not fetched yet. RemoveUserInternal will be + // called again after fetch completion. + return; + } + std::string owner; + cros_settings->GetString(kDeviceOwner, &owner); + if (user_email == owner) { + // Owner is not allowed to be removed from the device. + 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(RemoveRegularOrSupervisedUserFromList(user_id)); + } else if (user_loading_stage_ == STAGE_LOADING) { + DCHECK(gaia::ExtractDomainName(user_id) == + chromeos::login::kSupervisedUserDomain); + // Special case, removing partially-constructed supervised user during user + // list loading. + 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; + } + // Make sure that new data is persisted to Local State. + g_browser_process->local_state()->CommitPendingWrite(); +} + +bool UserManagerImpl::IsKnownUser(const std::string& user_id) const { + return FindUser(user_id) != NULL; +} + +const user_manager::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_manager::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_manager::User* UserManagerImpl::GetLoggedInUser() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return active_user_; +} + +user_manager::User* UserManagerImpl::GetLoggedInUser() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return active_user_; +} + +const user_manager::User* UserManagerImpl::GetActiveUser() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return active_user_; +} + +user_manager::User* UserManagerImpl::GetActiveUser() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return active_user_; +} + +const user_manager::User* UserManagerImpl::GetPrimaryUser() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return primary_user_; +} + +void UserManagerImpl::SaveUserOAuthStatus( + const std::string& user_id, + user_manager::User::OAuthTokenStatus oauth_token_status) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + DVLOG(1) << "Saving user OAuth token status in Local State"; + user_manager::User* user = FindUserAndModify(user_id); + if (user) + user->set_oauth_token_status(oauth_token_status); + + GetUserFlow(user_id)->HandleOAuthTokenStatusChange(oauth_token_status); + + // Do not update local state if data stored or cached outside the user's + // cryptohome is to be treated as ephemeral. + 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(oauth_token_status))); +} + +void UserManagerImpl::SaveForceOnlineSignin(const std::string& user_id, + bool force_online_signin) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // Do not update local state if data stored or cached outside the user's + // cryptohome is to be treated as ephemeral. + 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_manager::User* user = FindUserAndModify(user_id)) { + user->set_display_name(display_name); + + // Do not update local state if data stored or cached outside the user's + // cryptohome is to be treated as ephemeral. + 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_manager::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_manager::User* user = FindUserAndModify(user_id); + if (!user) + return; // Ignore if there is no such user. + + user->set_display_email(display_email); + + // Do not update local state if data stored or cached outside the user's + // cryptohome is to be treated as ephemeral. + 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_manager::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_manager::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()); +} + +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(details).ptr(); + if (IsUserLoggedIn() && + !IsLoggedInAsGuest() && + !IsLoggedInAsKioskApp()) { + if (IsLoggedInAsSupervisedUser()) + SupervisedUserPasswordServiceFactory::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); + } + } + break; + } + case chrome::NOTIFICATION_PROFILE_CREATED: { + Profile* profile = content::Source(source).ptr(); + user_manager::User* user = + ProfileHelper::Get()->GetUserByProfile(profile); + if (user != NULL) + user->set_profile_is_created(); + // If there is pending user switch, do it now. + if (!pending_user_switch_.empty()) { + // Call SwitchActiveUser async because otherwise it may cause + // ProfileManager::GetProfile before the profile gets registered + // in ProfileManager. It happens in case of sync profile load when + // NOTIFICATION_PROFILE_CREATED is called synchronously. + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&UserManagerImpl::SwitchActiveUser, + base::Unretained(this), + pending_user_switch_)); + pending_user_switch_.clear(); + } + 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 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) { + const user_manager::User* user = FindUserInList(user_id); + if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) + return; + UpdatePublicAccountDisplayName(user_id); + NotifyUserListChanged(); +} + +void UserManagerImpl::OnDeviceLocalAccountsChanged() { + // No action needed here, changes to the list of device-local accounts get + // handled via the kAccountsPrefDeviceLocalAccounts device setting observer. +} + +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_manager::USER_TYPE_REGULAR; +} + +bool UserManagerImpl::IsLoggedInAsDemoUser() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && + active_user_->GetType() == user_manager::USER_TYPE_RETAIL_MODE; +} + +bool UserManagerImpl::IsLoggedInAsPublicAccount() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && + active_user_->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT; +} + +bool UserManagerImpl::IsLoggedInAsGuest() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && + active_user_->GetType() == user_manager::USER_TYPE_GUEST; +} + +bool UserManagerImpl::IsLoggedInAsSupervisedUser() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && + active_user_->GetType() == user_manager::USER_TYPE_SUPERVISED; +} + +bool UserManagerImpl::IsLoggedInAsKioskApp() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && + active_user_->GetType() == user_manager::USER_TYPE_KIOSK_APP; +} + +bool UserManagerImpl::IsLoggedInAsStub() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return IsUserLoggedIn() && active_user_->email() == login::kStubUser; +} + +bool UserManagerImpl::IsSessionStarted() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return session_started_; +} + +bool UserManagerImpl::IsUserNonCryptohomeDataEphemeral( + const std::string& user_id) const { + // Data belonging to the guest, retail mode and stub users is always + // ephemeral. + if (user_id == login::kGuestUserName || + user_id == login::kRetailModeUserName || user_id == login::kStubUser) { + return true; + } + + // Data belonging to the owner, anyone found on the user list and obsolete + // public accounts whose data has not been removed yet is not ephemeral. + if (user_id == owner_email_ || UserExistsInList(user_id) || + user_id == g_browser_process->local_state()-> + GetString(kPublicAccountPendingDataRemoval)) { + return false; + } + + // Data belonging to the currently logged-in user is ephemeral when: + // a) The user logged into a regular account while the ephemeral users policy + // was enabled. + // - or - + // b) The user logged into any other account type. + if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) && + (is_current_user_ephemeral_regular_user_ || !IsLoggedInAsRegularUser())) { + return true; + } + + // Data belonging to any other user is ephemeral when: + // a) Going through the regular login flow and the ephemeral users policy is + // enabled. + // - or - + // b) The browser is restarting after a crash. + return AreEphemeralUsersEnabled() || + UserSessionManager::GetInstance()->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::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; + // Clean up user list first. All code down the path should be synchronous, + // so that local state after transaction rollback is in consistent state. + // This process also should not trigger EnsureUsersLoaded again. + 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); + + // Load public sessions first. + std::vector public_sessions; + std::set public_sessions_set; + ParseUserList(*prefs_public_sessions, std::set(), + &public_sessions, &public_sessions_set); + for (std::vector::const_iterator it = public_sessions.begin(); + it != public_sessions.end(); ++it) { + users_.push_back(user_manager::User::CreatePublicAccountUser(*it)); + UpdatePublicAccountDisplayName(*it); + } + + // Load regular users and supervised users. + std::vector regular_users; + std::set regular_users_set; + ParseUserList(*prefs_regular_users, public_sessions_set, + ®ular_users, ®ular_users_set); + for (std::vector::const_iterator it = regular_users.begin(); + it != regular_users.end(); ++it) { + user_manager::User* user = NULL; + const std::string domain = gaia::ExtractDomainName(*it); + if (domain == chromeos::login::kSupervisedUserDomain) + user = user_manager::User::CreateSupervisedUser(*it); + else + user = user_manager::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 (user_manager::UserList::iterator ui = users_.begin(), ue = users_.end(); + ui != ue; + ++ui) { + GetUserImageManager((*ui)->email())->LoadUserImage(); + } +} + +void UserManagerImpl::RetrieveTrustedDevicePolicies() { + ephemeral_users_enabled_ = false; + owner_email_.clear(); + + // Schedule a callback if device policy has not yet been verified. + 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 are enabled and we are on the login screen, take this + // opportunity to clean up by removing all regular users except the owner. + if (ephemeral_users_enabled_ && !IsUserLoggedIn()) { + ListPrefUpdate prefs_users_update(g_browser_process->local_state(), + kRegularUsers); + prefs_users_update->Clear(); + for (user_manager::UserList::iterator it = users_.begin(); + it != users_.end();) { + const std::string user_email = (*it)->email(); + if ((*it)->GetType() == user_manager::USER_TYPE_REGULAR && + user_email != owner_email_) { + RemoveNonCryptohomeData(user_email); + DeleteUser(*it); + it = users_.erase(it); + changed = true; + } else { + if ((*it)->GetType() != user_manager::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()); +} + +user_manager::UserList& UserManagerImpl::GetUsersAndModify() { + EnsureUsersLoaded(); + return users_; +} + +const user_manager::User* UserManagerImpl::FindUserInList( + const std::string& user_id) const { + const user_manager::UserList& users = GetUsers(); + for (user_manager::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_manager::User* UserManagerImpl::FindUserInListAndModify( + const std::string& user_id) { + user_manager::UserList& users = GetUsersAndModify(); + for (user_manager::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_manager::User::CreateGuestUser(); + // TODO(nkostylev): Add support for passing guest session cryptohome + // mount point. Legacy (--login-profile) value will be used for now. + // http://crosbug.com/230859 + active_user_->SetStubImage( + user_manager::UserImage( + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_PROFILE_PICTURE_LOADING)), + user_manager::User::USER_IMAGE_INVALID, + false); + // Initializes wallpaper after active_user_ is set. + WallpaperManager::Get()->SetUserWallpaperNow(chromeos::login::kGuestUserName); +} + +void UserManagerImpl::AddUserRecord(user_manager::User* user) { + // Add the user to the front of the user list. + 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) { + // Remove the user from the user list. + active_user_ = RemoveRegularOrSupervisedUserFromList(user_id); + + // If the user was not found on the user list, create a new user. + is_current_user_new_ = !active_user_; + if (!active_user_) { + active_user_ = user_manager::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(); + + // Make sure that new data is persisted to Local State. + 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_manager::User::CreateRegularUser(user_id); + GetUserImageManager(user_id)->UserLoggedIn(is_current_user_new_, false); + WallpaperManager::Get()->SetUserWallpaperNow(user_id); +} + +void UserManagerImpl::SupervisedUserLoggedIn( + const std::string& user_id) { + // TODO(nkostylev): Refactor, share code with RegularUserLoggedIn(). + + // Remove the user from the user list. + active_user_ = RemoveRegularOrSupervisedUserFromList(user_id); + // If the user was not found on the user list, create a new user. + if (!active_user_) { + is_current_user_new_ = true; + active_user_ = user_manager::User::CreateSupervisedUser(user_id); + // Leaving OAuth token status at the default state = unknown. + 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; + } + } + + // Add the user to the front of the user list. + 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_); + + // Now that user is in the list, save display name. + if (is_current_user_new_) { + SaveUserDisplayName(active_user_->email(), + active_user_->GetDisplayName()); + } + + GetUserImageManager(user_id)->UserLoggedIn(is_current_user_new_, true); + WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); + + // Make sure that new data is persisted to Local State. + g_browser_process->local_state()->CommitPendingWrite(); +} + +void UserManagerImpl::PublicAccountUserLoggedIn(user_manager::User* user) { + is_current_user_new_ = true; + active_user_ = user; + // The UserImageManager chooses a random avatar picture when a user logs in + // for the first time. Tell the UserImageManager that this user is not new to + // prevent the avatar from getting changed. + 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_manager::User::CreateKioskAppUser(app_id); + active_user_->SetStubImage( + user_manager::UserImage( + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_PROFILE_PICTURE_LOADING)), + user_manager::User::USER_IMAGE_INVALID, + false); + + WallpaperManager::Get()->SetUserWallpaperNow(app_id); + + // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like + // the kiosk_app_id in these objects, removing the need to re-parse the + // device-local account list here to extract the kiosk_app_id. + const std::vector device_local_accounts = + policy::GetDeviceLocalAccounts(cros_settings_); + const policy::DeviceLocalAccount* account = NULL; + for (std::vector::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); + + // Disable window animation since kiosk app runs in a single full screen + // window and window animation causes start-up janks. + command_line->AppendSwitch( + wm::switches::kWindowAnimationsDisabled); +} + +void UserManagerImpl::DemoAccountLoggedIn() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + active_user_ = + user_manager::User::CreateKioskAppUser(DemoAppLauncher::kDemoUserName); + active_user_->SetStubImage( + user_manager::UserImage( + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + IDR_PROFILE_PICTURE_LOADING)), + user_manager::User::USER_IMAGE_INVALID, + false); + WallpaperManager::Get()->SetUserWallpaperNow(DemoAppLauncher::kDemoUserName); + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + command_line->AppendSwitch(::switches::kForceAppMode); + command_line->AppendSwitchASCII(::switches::kAppId, + DemoAppLauncher::kDemoAppId); + + // Disable window animation since the demo app runs in a single full screen + // window and window animation causes start-up janks. + CommandLine::ForCurrentProcess()->AppendSwitch( + wm::switches::kWindowAnimationsDisabled); +} + +void UserManagerImpl::RetailModeUserLoggedIn() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + is_current_user_new_ = true; + active_user_ = user_manager::User::CreateRetailModeUser(); + GetUserImageManager(chromeos::login::kRetailModeUserName) + ->UserLoggedIn(is_current_user_new_, true); + WallpaperManager::Get()->SetUserWallpaperNow( + chromeos::login::kRetailModeUserName); +} + +void UserManagerImpl::NotifyOnLogin() { + CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + UserSessionManager::OverrideHomedir(); + + UpdateNumberOfUsers(); + NotifyActiveUserHashChanged(active_user_->username_hash()); + NotifyActiveUserChanged(active_user_); + UpdateLoginState(); + + // TODO(nkostylev): Deprecate this notification in favor of + // ActiveUserChanged() observer call. + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_LOGIN_USER_CHANGED, + content::Source(this), + content::Details(active_user_)); + + UserSessionManager::GetInstance()->PerformPostUserLoggedInActions(); +} + +user_manager::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_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN; + if (prefs_oauth_status && + prefs_oauth_status->GetIntegerWithoutPathExpansion( + user_id, &oauth_token_status)) { + user_manager::User::OAuthTokenStatus result = + static_cast(oauth_token_status); + if (result == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) + GetUserFlow(user_id)->HandleOAuthTokenStatusChange(result); + return result; + } + return user_manager::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_manager::User* UserManagerImpl::RemoveRegularOrSupervisedUserFromList( + const std::string& user_id) { + ListPrefUpdate prefs_users_update(g_browser_process->local_state(), + kRegularUsers); + prefs_users_update->Clear(); + user_manager::User* user = NULL; + for (user_manager::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_manager::USER_TYPE_REGULAR || + (*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) { + 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& old_public_accounts) { + std::set users; + for (user_manager::UserList::const_iterator it = users_.begin(); + it != users_.end(); + ++it) + users.insert((*it)->email()); + + // If the user is logged into a public account that has been removed from the + // user list, mark the account's data as pending removal after logout. + 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); + } + } + + // Remove the data belonging to any other public accounts that are no longer + // found on the user list. + for (std::vector::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& device_local_accounts) { + // Try to remove any public account data marked as pending removal. + CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); + + // Get the current list of public accounts. + std::vector old_public_accounts; + for (user_manager::UserList::const_iterator it = users_.begin(); + it != users_.end(); + ++it) { + if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) + old_public_accounts.push_back((*it)->email()); + } + + // Get the new list of public accounts from policy. + std::vector new_public_accounts; + for (std::vector::const_iterator it = + device_local_accounts.begin(); + it != device_local_accounts.end(); ++it) { + // TODO(mnissler, nkostylev, bartfab): Process Kiosk Apps within the + // standard login framework: http://crbug.com/234694 + if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION) + new_public_accounts.push_back(it->user_id); + } + + // If the list of public accounts has not changed, return. + 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; + } + + // Persist the new list of public accounts in a pref. + ListPrefUpdate prefs_public_accounts_update(g_browser_process->local_state(), + kPublicAccounts); + prefs_public_accounts_update->Clear(); + for (std::vector::const_iterator it = + new_public_accounts.begin(); + it != new_public_accounts.end(); ++it) { + prefs_public_accounts_update->AppendString(*it); + } + + // Remove the old public accounts from the user list. + for (user_manager::UserList::iterator it = users_.begin(); + it != users_.end();) { + if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) { + if (*it != GetLoggedInUser()) + DeleteUser(*it); + it = users_.erase(it); + } else { + ++it; + } + } + + // Add the new public accounts to the front of the user list. + for (std::vector::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_manager::User::CreatePublicAccountUser(*it)); + UpdatePublicAccountDisplayName(*it); + } + + for (user_manager::UserList::iterator + ui = users_.begin(), + ue = users_.begin() + new_public_accounts.size(); + ui != ue; + ++ui) { + GetUserImageManager((*ui)->email())->LoadUserImage(); + } + + // Remove data belonging to public accounts that are no longer found on the + // user list. + 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(); + } + + // Set or clear the display name. + 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::AreSupervisedUsersAllowed() const { + bool supervised_users_allowed = false; + cros_settings_->GetBoolean(kAccountsPrefSupervisedUsersEnabled, + &supervised_users_allowed); + return supervised_users_allowed; +} + +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(this), + content::NotificationService::NoDetails()); +} + +void UserManagerImpl::NotifyActiveUserChanged( + const user_manager::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_manager::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::UpdateLoginState() { + if (!LoginState::IsInitialized()) + return; // LoginState may not be intialized in tests. + 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_manager::USER_TYPE_GUEST) + login_user_type = LoginState::LOGGED_IN_USER_GUEST; + else if (active_user_->GetType() == user_manager::USER_TYPE_RETAIL_MODE) + login_user_type = LoginState::LOGGED_IN_USER_RETAIL_MODE; + else if (active_user_->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) + login_user_type = LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT; + else if (active_user_->GetType() == user_manager::USER_TYPE_SUPERVISED) + login_user_type = LoginState::LOGGED_IN_USER_SUPERVISED; + else if (active_user_->GetType() == user_manager::USER_TYPE_KIOSK_APP) + login_user_type = LoginState::LOGGED_IN_USER_KIOSK_APP; + else + login_user_type = LoginState::LOGGED_IN_USER_REGULAR; + + if (primary_user_) { + LoginState::Get()->SetLoggedInStateAndPrimaryUser( + logged_in_state, login_user_type, primary_user_->username_hash()); + } else { + LoginState::Get()->SetLoggedInState(logged_in_state, login_user_type); + } +} + +void UserManagerImpl::SetLRUUser(user_manager::User* user) { + user_manager::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::SendRegularUserLoginMetrics(const std::string& user_id) { + // If this isn't the first time Chrome was run after the system booted, + // assume that Chrome was restarted because a previous session ended. + 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_manager::User* user = FindUserAndModify(user_id)) + user->SetAccountLocale(resolved_locale); +} + +void UserManagerImpl::UpdateNumberOfUsers() { + size_t users = GetLoggedInUsers().size(); + if (users) { + // Write the user number as UMA stat when a multi user session is possible. + if ((users + GetUsersAdmittedForMultiProfile().size()) > 1) + ash::MultiProfileUMA::RecordUserCount(users); + } + + base::debug::SetCrashKeyValue(crash_keys::kNumberOfUsers, + base::StringPrintf("%" PRIuS, GetLoggedInUsers().size())); +} + +void UserManagerImpl::DeleteUser(user_manager::User* user) { + const bool is_active_user = (user == active_user_); + delete user; + if (is_active_user) + active_user_ = NULL; +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/login/users/user_manager_base.h b/chrome/browser/chromeos/login/users/user_manager_impl.h similarity index 57% rename from chrome/browser/chromeos/login/users/user_manager_base.h rename to chrome/browser/chromeos/login/users/user_manager_impl.h index 5900419e10ca..46ed7c9d0141 100644 --- a/chrome/browser/chromeos/login/users/user_manager_base.h +++ b/chrome/browser/chromeos/login/users/user_manager_impl.h @@ -2,41 +2,69 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_BASE_H_ -#define CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_BASE_H_ +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_IMPL_H_ -#include +#include #include #include #include "base/basictypes.h" +#include "base/containers/hash_tables.h" +#include "base/memory/linked_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/synchronization/lock.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h" +#include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h" #include "chrome/browser/chromeos/login/users/user_manager.h" +#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" +#include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer.h" +#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "components/user_manager/user.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" class PrefService; -class PrefRegistrySimple; +class ProfileSyncService; + +namespace policy { +struct DeviceLocalAccount; +} namespace chromeos { +class MultiProfileUserController; class RemoveUserDelegate; - -// Base implementation of the UserManager interface. -class UserManagerBase : public UserManager { +class SupervisedUserManagerImpl; +class SessionLengthLimiter; + +// Implementation of the UserManager. +class UserManagerImpl + : public UserManager, + public content::NotificationObserver, + public policy::CloudExternalDataPolicyObserver::Delegate, + public policy::DeviceLocalAccountPolicyService::Observer, + public MultiProfileUserControllerDelegate { public: - virtual ~UserManagerBase(); - - // Registers UserManagerBase preferences. - static void RegisterPrefs(PrefRegistrySimple* registry); + virtual ~UserManagerImpl(); // UserManager implementation: virtual void Shutdown() OVERRIDE; + virtual MultiProfileUserController* GetMultiProfileUserController() OVERRIDE; + virtual UserImageManager* GetUserImageManager( + const std::string& user_id) OVERRIDE; + virtual SupervisedUserManager* GetSupervisedUserManager() OVERRIDE; virtual const user_manager::UserList& GetUsers() const OVERRIDE; + virtual user_manager::UserList GetUsersAdmittedForMultiProfile() + const OVERRIDE; virtual const user_manager::UserList& GetLoggedInUsers() const OVERRIDE; - virtual const user_manager::UserList& GetLRULoggedInUsers() const OVERRIDE; - virtual const std::string& GetOwnerEmail() const OVERRIDE; + virtual const user_manager::UserList& GetLRULoggedInUsers() OVERRIDE; + virtual user_manager::UserList GetUnlockUsers() const OVERRIDE; + virtual const std::string& GetOwnerEmail() OVERRIDE; virtual void UserLoggedIn(const std::string& user_id, const std::string& user_id_hash, bool browser_restart) OVERRIDE; @@ -94,190 +122,156 @@ class UserManagerBase : public UserManager { UserManager::UserSessionStateObserver* obs) OVERRIDE; virtual void NotifyLocalStateChanged() OVERRIDE; - // Helper function that copies users from |users_list| to |users_vector| and - // |users_set|. Duplicates and users already present in |existing_users| are - // skipped. - static void ParseUserList(const base::ListValue& users_list, - const std::set& existing_users, - std::vector* users_vector, - std::set* users_set); + virtual UserFlow* GetCurrentUserFlow() const OVERRIDE; + virtual UserFlow* GetUserFlow(const std::string& user_id) const OVERRIDE; + virtual void SetUserFlow(const std::string& user_id, UserFlow* flow) OVERRIDE; + virtual void ResetUserFlow(const std::string& user_id) OVERRIDE; + virtual bool AreSupervisedUsersAllowed() const OVERRIDE; - protected: - UserManagerBase(); + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; - // Adds |user| to users list, and adds it to front of LRU list. It is assumed - // that there is no user with same id. - virtual void AddUserRecord(user_manager::User* user); + // policy::CloudExternalDataPolicyObserver::Delegate: + virtual void OnExternalDataSet(const std::string& policy, + const std::string& user_id) OVERRIDE; + virtual void OnExternalDataCleared(const std::string& policy, + const std::string& user_id) OVERRIDE; + virtual void OnExternalDataFetched(const std::string& policy, + const std::string& user_id, + scoped_ptr data) OVERRIDE; - // Returns true if trusted device policies have successfully been retrieved - // and ephemeral users are enabled. - virtual bool AreEphemeralUsersEnabled() const = 0; + // policy::DeviceLocalAccountPolicyService::Observer implementation. + virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE; + virtual void OnDeviceLocalAccountsChanged() OVERRIDE; - // Returns true if user may be removed. - virtual bool CanUserBeRemoved(const user_manager::User* user) const; + void StopPolicyObserverForTesting(); - // A wrapper around C++ delete operator. Deletes |user|, and when |user| - // equals to active_user_, active_user_ is reset to NULL. - virtual void DeleteUser(user_manager::User* user); + private: + friend class SupervisedUserManagerImpl; + friend class UserManager; + friend class WallpaperManager; + friend class UserManagerTest; + friend class WallpaperManagerTest; - // Returns the locale used by the application. - virtual const std::string& GetApplicationLocale() const = 0; + typedef base::hash_map > UserImageManagerMap; - // Returns "Local State" PrefService instance. - virtual PrefService* GetLocalState() const = 0; + // Stages of loading user list from preferences. Some methods can have + // different behavior depending on stage. + enum UserLoadStage { + STAGE_NOT_LOADED = 0, + STAGE_LOADING, + STAGE_LOADED + }; + + UserManagerImpl(); // Loads |users_| from Local State if the list has not been loaded yet. // Subsequent calls have no effect. Must be called on the UI thread. void EnsureUsersLoaded(); - // Returns true if device is enterprise managed. - virtual bool IsEnterpriseManaged() const = 0; - - // Helper function that copies users from |users_list| to |users_vector| and - // |users_set|. Duplicates and users already present in |existing_users| are - // skipped. - // Loads public accounts from the Local state and fills in - // |public_sessions_set|. - virtual void LoadPublicAccounts( - std::set* public_sessions_set) = 0; - - // Notifies that user has logged in. - virtual void NotifyOnLogin(); - - // Notifies observers that another user was added to the session. - // If |user_switch_pending| is true this means that user has not been fully - // initialized yet like waiting for profile to be loaded. - virtual void NotifyUserAddedToSession(const user_manager::User* added_user, - bool user_switch_pending); - - // Performs any additional actions before user list is loaded. - virtual void PerformPreUserListLoadingActions() = 0; - - // Performs any additional actions after user list is loaded. - virtual void PerformPostUserListLoadingActions() = 0; - - // Performs any additional actions after UserLoggedIn() execution has been - // completed. - // |browser_restart| is true when reloading Chrome after crash to distinguish - // from normal sign in flow. - virtual void PerformPostUserLoggedInActions(bool browser_restart) = 0; - - // Implementation for RemoveUser method. It is synchronous. It is called from - // RemoveUserInternal after owner check. - virtual void RemoveNonOwnerUserInternal(const std::string& user_email, - RemoveUserDelegate* delegate); - - // Removes a regular or supervised user from the user list. - // Returns the user if found or NULL otherwise. - // Also removes the user from the persistent user list. - user_manager::User* RemoveRegularOrSupervisedUserFromList( - const std::string& user_id); - - // Implementation for RemoveUser method. This is an asynchronous part of the - // method, that verifies that owner will not get deleted, and calls - // |RemoveNonOwnerUserInternal|. - virtual void RemoveUserInternal(const std::string& user_email, - RemoveUserDelegate* delegate); - - // Removes data stored or cached outside the user's cryptohome (wallpaper, - // avatar, OAuth token status, display name, display email). - virtual void RemoveNonCryptohomeData(const std::string& user_id); - - // Check for a particular user type. + // Retrieves trusted device policies and removes users from the persistent + // list if ephemeral users are enabled. Schedules a callback to itself if + // trusted device policies are not yet available. + void RetrieveTrustedDevicePolicies(); - // Returns true if |user_id| represents demo app. - virtual bool IsDemoApp(const std::string& user_id) const = 0; + // Returns true if trusted device policies have successfully been retrieved + // and ephemeral users are enabled. + bool AreEphemeralUsersEnabled() const; - // Returns true if |user_id| represents kiosk app. - virtual bool IsKioskApp(const std::string& user_id) const = 0; + // Returns a list of users who have logged into this device previously. + // Same as GetUsers but used if you need to modify User from that list. + user_manager::UserList& GetUsersAndModify(); - // Returns true if |user_id| represents public account that has been marked - // for deletion. - virtual bool IsPublicAccountMarkedForRemoval( - const std::string& user_id) const = 0; + // Returns the user with the given email address if found in the persistent + // list. Returns |NULL| otherwise. + const user_manager::User* FindUserInList(const std::string& user_id) const; - // These methods are called when corresponding user type has signed in. + // Returns |true| if user with the given id is found in the persistent list. + // Returns |false| otherwise. Does not trigger user loading. + const bool UserExistsInList(const std::string& user_id) const; - // Indicates that the demo account has just logged in. - virtual void DemoAccountLoggedIn() = 0; + // Same as FindUserInList but returns non-const pointer to User object. + user_manager::User* FindUserInListAndModify(const std::string& user_id); // Indicates that a user just logged in as guest. - virtual void GuestUserLoggedIn(); - - // Indicates that a kiosk app robot just logged in. - virtual void KioskAppLoggedIn(const std::string& app_id) = 0; - - // Indicates that a user just logged into a public session. - virtual void PublicAccountUserLoggedIn(user_manager::User* user) = 0; + void GuestUserLoggedIn(); // Indicates that a regular user just logged in. - virtual void RegularUserLoggedIn(const std::string& user_id); + void RegularUserLoggedIn(const std::string& user_id); // Indicates that a regular user just logged in as ephemeral. - virtual void RegularUserLoggedInAsEphemeral(const std::string& user_id); - - // Indicates that a user just logged into a retail mode session. - virtual void RetailModeUserLoggedIn() = 0; + void RegularUserLoggedInAsEphemeral(const std::string& user_id); // Indicates that a supervised user just logged in. - virtual void SupervisedUserLoggedIn(const std::string& user_id) = 0; + void SupervisedUserLoggedIn(const std::string& user_id); - // Getters/setters for private members. + // Indicates that a user just logged into a public session. + void PublicAccountUserLoggedIn(user_manager::User* user); - virtual void SetCurrentUserIsOwner(bool is_current_user_owner); + // Indicates that a kiosk app robot just logged in. + void KioskAppLoggedIn(const std::string& app_id); - virtual bool GetEphemeralUsersEnabled() const; - virtual void SetEphemeralUsersEnabled(bool enabled); + // Indicates that the demo account has just logged in. + void DemoAccountLoggedIn(); - virtual void SetIsCurrentUserNew(bool is_new); + // Indicates that a user just logged into a retail mode session. + void RetailModeUserLoggedIn(); - virtual void SetOwnerEmail(std::string owner_user_id); + // Notifies that user has logged in. + // Sends NOTIFICATION_LOGIN_USER_CHANGED notification. + void NotifyOnLogin(); - virtual const std::string& GetPendingUserSwitchID() const; - virtual void SetPendingUserSwitchID(std::string user_id); + // Reads user's oauth token status from local state preferences. + user_manager::User::OAuthTokenStatus LoadUserOAuthStatus( + const std::string& user_id) const; - // The logged-in user that is currently active in current session. - // NULL until a user has logged in, then points to one - // of the User instances in |users_|, the |guest_user_| instance or an - // ephemeral user instance. - user_manager::User* active_user_; + // Read a flag indicating whether online authentication against GAIA should + // be enforced during the user's next sign-in from local state preferences. + bool LoadForceOnlineSignin(const std::string& user_id) const; - // The primary user of the current session. It is recorded for the first - // signed-in user and does not change thereafter. - user_manager::User* primary_user_; + void SetCurrentUserIsOwner(bool is_current_user_owner); - // List of all known users. User instances are owned by |this|. Regular users - // are removed by |RemoveUserFromList|, public accounts by - // |UpdateAndCleanUpPublicAccounts|. - user_manager::UserList users_; + // Updates current user ownership on UI thread. + void UpdateOwnership(); - private: - // Stages of loading user list from preferences. Some methods can have - // different behavior depending on stage. - enum UserLoadStage { STAGE_NOT_LOADED = 0, STAGE_LOADING, STAGE_LOADED }; + // Removes data stored or cached outside the user's cryptohome (wallpaper, + // avatar, OAuth token status, display name, display email). + void RemoveNonCryptohomeData(const std::string& user_id); - // Returns a list of users who have logged into this device previously. - // Same as GetUsers but used if you need to modify User from that list. - user_manager::UserList& GetUsersAndModify(); + // Removes a regular or supervised user from the user list. + // Returns the user if found or NULL otherwise. + // Also removes the user from the persistent user list. + user_manager::User* RemoveRegularOrSupervisedUserFromList( + const std::string& user_id); - // Returns the user with the given email address if found in the persistent - // list. Returns |NULL| otherwise. - const user_manager::User* FindUserInList(const std::string& user_id) const; + // If data for a public account is marked as pending removal and the user is + // no longer logged into that account, removes the data. + void CleanUpPublicAccountNonCryptohomeDataPendingRemoval(); - // Returns |true| if user with the given id is found in the persistent list. - // Returns |false| otherwise. Does not trigger user loading. - const bool UserExistsInList(const std::string& user_id) const; + // Removes data belonging to public accounts that are no longer found on the + // user list. If the user is currently logged into one of these accounts, the + // data for that account is not removed immediately but marked as pending + // removal after logout. + void CleanUpPublicAccountNonCryptohomeData( + const std::vector& old_public_accounts); - // Same as FindUserInList but returns non-const pointer to User object. - user_manager::User* FindUserInListAndModify(const std::string& user_id); + // Replaces the list of public accounts with those found in + // |device_local_accounts|. Ensures that data belonging to accounts no longer + // on the list is removed. Returns |true| if the list has changed. + // Public accounts are defined by policy. This method is called whenever an + // updated list of public accounts is received from policy. + bool UpdateAndCleanUpPublicAccounts( + const std::vector& device_local_accounts); - // Reads user's oauth token status from local state preferences. - user_manager::User::OAuthTokenStatus LoadUserOAuthStatus( - const std::string& user_id) const; + // Updates the display name for public account |username| from policy settings + // associated with that username. + void UpdatePublicAccountDisplayName(const std::string& user_id); - // Read a flag indicating whether online authentication against GAIA should - // be enforced during the user's next sign-in from local state preferences. - bool LoadForceOnlineSignin(const std::string& user_id) const; + // Notifies the UI about a change to the user list. + void NotifyUserListChanged(); // Notifies observers that merge session state had changed. void NotifyMergeSessionStateChanged(); @@ -285,18 +279,42 @@ class UserManagerBase : public UserManager { // Notifies observers that active user has changed. void NotifyActiveUserChanged(const user_manager::User* active_user); + // Notifies observers that another user was added to the session. + void NotifyUserAddedToSession(const user_manager::User* added_user); + // Notifies observers that active user_id hash has changed. void NotifyActiveUserHashChanged(const std::string& hash); + // Lazily creates default user flow. + UserFlow* GetDefaultUserFlow() const; + // Update the global LoginState. void UpdateLoginState(); // Insert |user| at the front of the LRU user list. void SetLRUUser(user_manager::User* user); + // Adds |user| to users list, and adds it to front of LRU list. It is assumed + // that there is no user with same id. + void AddUserRecord(user_manager::User* user); + // Sends metrics in response to a regular user logging in. void SendRegularUserLoginMetrics(const std::string& user_id); + // Implementation for RemoveUser method. This is an asynchronous part of the + // method, that verifies that owner will not get deleted, and calls + // |RemoveNonOwnerUserInternal|. + void RemoveUserInternal(const std::string& user_email, + RemoveUserDelegate* delegate); + + // Implementation for RemoveUser method. It is synchronous. It is called from + // RemoveUserInternal after owner check. + void RemoveNonOwnerUserInternal(const std::string& user_email, + RemoveUserDelegate* delegate); + + // MultiProfileUserControllerDelegate implementation: + virtual void OnUserNotAllowed(const std::string& user_email) OVERRIDE; + // Sets account locale for user with id |user_id|. virtual void UpdateUserAccountLocale(const std::string& user_id, const std::string& locale); @@ -305,9 +323,27 @@ class UserManagerBase : public UserManager { void DoUpdateAccountLocale(const std::string& user_id, const std::string& resolved_locale); + // Update the number of users. + void UpdateNumberOfUsers(); + + // A wrapper around C++ delete operator. Deletes |user|, and when |user| + // equals to active_user_, active_user_ is reset to NULL. + void DeleteUser(user_manager::User* user); + + // Interface to the signed settings store. + CrosSettings* cros_settings_; + + // Interface to device-local account definitions and associated policy. + policy::DeviceLocalAccountPolicyService* device_local_account_policy_service_; + // Indicates stage of loading user from prefs. UserLoadStage user_loading_stage_; + // List of all known users. User instances are owned by |this|. Regular users + // are removed by |RemoveUserFromList|, public accounts by + // |UpdateAndCleanUpPublicAccounts|. + user_manager::UserList users_; + // List of all users that are logged in current session. These point to User // instances in |users_|. Only one of them could be marked as active. user_manager::UserList logged_in_users_; @@ -317,6 +353,19 @@ class UserManagerBase : public UserManager { // the active user should always be the first one in the list. user_manager::UserList lru_logged_in_users_; + // The list which gets reported when the |lru_logged_in_users_| list is empty. + user_manager::UserList temp_single_logged_in_users_; + + // The logged-in user that is currently active in current session. + // NULL until a user has logged in, then points to one + // of the User instances in |users_|, the |guest_user_| instance or an + // ephemeral user instance. + user_manager::User* active_user_; + + // The primary user of the current session. It is recorded for the first + // signed-in user and does not change thereafter. + user_manager::User* primary_user_; + // True if SessionStarted() has been called. bool session_started_; @@ -345,22 +394,54 @@ class UserManagerBase : public UserManager { // been read from trusted device policy yet. std::string owner_email_; + content::NotificationRegistrar registrar_; + ObserverList observer_list_; // TODO(nkostylev): Merge with session state refactoring CL. ObserverList session_state_observer_list_; + // User avatar managers. + UserImageManagerMap user_image_managers_; + + // Supervised user manager. + scoped_ptr supervised_user_manager_; + + // Session length limiter. + scoped_ptr session_length_limiter_; + + typedef std::map FlowMap; + + // Lazy-initialized default flow. + mutable scoped_ptr default_flow_; + + // Specific flows by user e-mail. Keys should be canonicalized before + // access. + FlowMap specific_flows_; + // Time at which this object was created. base::TimeTicks manager_creation_time_; + scoped_ptr + local_accounts_subscription_; + + scoped_ptr multi_profile_user_controller_; + + // Observer for the policy that can be used to manage user images. + scoped_ptr avatar_policy_observer_; + + // Observer for the policy that can be used to manage wallpapers. + scoped_ptr + wallpaper_policy_observer_; + // ID of the user just added to the session that needs to be activated // as soon as user's profile is loaded. std::string pending_user_switch_; - DISALLOW_COPY_AND_ASSIGN(UserManagerBase); + DISALLOW_COPY_AND_ASSIGN(UserManagerImpl); }; } // namespace chromeos -#endif // CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_BASE_H_ +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_USERS_USER_MANAGER_IMPL_H_ diff --git a/chrome/browser/chromeos/login/users/user_manager_unittest.cc b/chrome/browser/chromeos/login/users/user_manager_unittest.cc index fb047de54814..ed16b5d15210 100644 --- a/chrome/browser/chromeos/login/users/user_manager_unittest.cc +++ b/chrome/browser/chromeos/login/users/user_manager_unittest.cc @@ -12,8 +12,8 @@ #include "base/run_loop.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" @@ -103,33 +103,32 @@ class UserManagerTest : public testing::Test { chromeos::DBusThreadManager::Shutdown(); } - ChromeUserManager* GetChromeUserManager() const { - return static_cast(UserManager::Get()); + UserManagerImpl* GetUserManagerImpl() const { + return static_cast(UserManager::Get()); } bool GetUserManagerEphemeralUsersEnabled() const { - return GetChromeUserManager()->GetEphemeralUsersEnabled(); + return GetUserManagerImpl()->ephemeral_users_enabled_; } void SetUserManagerEphemeralUsersEnabled(bool ephemeral_users_enabled) { - GetChromeUserManager()->SetEphemeralUsersEnabled(ephemeral_users_enabled); + GetUserManagerImpl()->ephemeral_users_enabled_ = ephemeral_users_enabled; } const std::string& GetUserManagerOwnerEmail() const { - return GetChromeUserManager()->GetOwnerEmail(); + return GetUserManagerImpl()-> owner_email_; } void SetUserManagerOwnerEmail(const std::string& owner_email) { - GetChromeUserManager()->SetOwnerEmail(owner_email); + GetUserManagerImpl()->owner_email_ = owner_email; } void ResetUserManager() { // Reset the UserManager singleton. user_manager_enabler_.reset(); - // Initialize the UserManager singleton to a fresh ChromeUserManager - // instance. + // Initialize the UserManager singleton to a fresh UserManagerImpl instance. user_manager_enabler_.reset( - new ScopedUserManagerEnabler(new ChromeUserManager)); + new ScopedUserManagerEnabler(new UserManagerImpl)); } void SetDeviceSettings(bool ephemeral_users_enabled, @@ -146,7 +145,7 @@ class UserManagerTest : public testing::Test { } void RetrieveTrustedDevicePolicies() { - GetChromeUserManager()->RetrieveTrustedDevicePolicies(); + GetUserManagerImpl()->RetrieveTrustedDevicePolicies(); } protected: diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_unittest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_unittest.cc index 3065c4c60c63..3adab57de986 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_unittest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_unittest.cc @@ -20,6 +20,7 @@ #include "base/prefs/testing_pref_service.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/users/fake_user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc index 14d1d9bb7282..1861cb92cade 100644 --- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc @@ -45,8 +45,8 @@ #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h" #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h" -#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/user_manager.h" +#include "chrome/browser/chromeos/login/users/user_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/cloud_external_data_manager_base_test_util.h" @@ -872,8 +872,8 @@ IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) { // verify that the underlying policy subsystem will start a fetch // without this request as well, the chromeos::UserManager must be // prevented from seeing the policy change. - reinterpret_cast(chromeos::UserManager::Get()) - ->StopPolicyObserverForTesting(); + reinterpret_cast(chromeos::UserManager::Get())-> + StopPolicyObserverForTesting(); UploadDeviceLocalAccountPolicy(); AddPublicSessionToDevicePolicy(kAccountId1); diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc index 8f48badf7940..7659f4910176 100644 --- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc +++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc @@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/login/login_utils.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/users/user_manager.h" +#include "chrome/browser/chromeos/login/users/user_manager_impl.h" #include "chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index ab12b0b5c7b4..d9a87662a744 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -723,8 +723,6 @@ 'browser/chromeos/login/users/avatar/user_image_manager_impl.h', 'browser/chromeos/login/users/avatar/user_image_sync_observer.cc', 'browser/chromeos/login/users/avatar/user_image_sync_observer.h', - 'browser/chromeos/login/users/chrome_user_manager.cc', - 'browser/chromeos/login/users/chrome_user_manager.h', 'browser/chromeos/login/users/multi_profile_user_controller.cc', 'browser/chromeos/login/users/multi_profile_user_controller.h', 'browser/chromeos/login/users/multi_profile_user_controller_delegate.h', @@ -734,8 +732,8 @@ 'browser/chromeos/login/users/supervised_user_manager_impl.h', 'browser/chromeos/login/users/user_manager.cc', 'browser/chromeos/login/users/user_manager.h', - 'browser/chromeos/login/users/user_manager_base.cc', - 'browser/chromeos/login/users/user_manager_base.h', + 'browser/chromeos/login/users/user_manager_impl.cc', + 'browser/chromeos/login/users/user_manager_impl.h', 'browser/chromeos/login/users/wallpaper/wallpaper_manager.cc', 'browser/chromeos/login/users/wallpaper/wallpaper_manager.h', 'browser/chromeos/login/version_info_updater.cc', diff --git a/components/OWNERS b/components/OWNERS index 2254d88fe597..e721131b6a81 100644 --- a/components/OWNERS +++ b/components/OWNERS @@ -152,12 +152,6 @@ per-file search_engines.gypi=stevet@chromium.org per-file search_provider_logos*=newt@chromium.org per-file search_provider_logos*=justincohen@chromium.org -per-file session_manager.gypi=antrim@chromium.org -per-file session_manager.gypi=dpolukhin@chromium.org -per-file session_manager.gypi=dzhioev@chromium.org -per-file session_manager.gypi=nkostylev@chromium.org -per-file session_manager.gypi=ygorshenin@chromium.org - per-file sessions.gypi=marja@chromium.org per-file sessions.gypi=sky@chromium.org diff --git a/components/session_manager.gypi b/components/session_manager.gypi index 592473d9ea60..d9c938d63c1f 100644 --- a/components/session_manager.gypi +++ b/components/session_manager.gypi @@ -21,13 +21,6 @@ 'session_manager/core/session_manager.cc', 'session_manager/session_manager_export.h', ], - 'conditions': [ - ['chromeos == 1', { - 'dependencies': [ - '<(DEPTH)/chromeos/chromeos.gyp:chromeos', - ], - }], - ], }, ], } diff --git a/components/session_manager/DEPS b/components/session_manager/DEPS index 85aa5db767e1..48e88750d4a4 100644 --- a/components/session_manager/DEPS +++ b/components/session_manager/DEPS @@ -1,3 +1,2 @@ include_rules = [ - '+chromeos/chromeos_switches.h', ] diff --git a/components/session_manager/core/session_manager.cc b/components/session_manager/core/session_manager.cc index f86de43b536d..3fff7484f57f 100644 --- a/components/session_manager/core/session_manager.cc +++ b/components/session_manager/core/session_manager.cc @@ -6,30 +6,12 @@ #include "base/logging.h" -#if defined(OS_CHROMEOS) -#include "base/command_line.h" -#include "base/sys_info.h" -#include "chromeos/chromeos_switches.h" -#endif - namespace session_manager { -// static -SessionManager* SessionManager::instance = NULL; - SessionManager::SessionManager() : session_state_(SESSION_STATE_UNKNOWN) { - DCHECK(!SessionManager::Get()); - SessionManager::SetInstance(this); } SessionManager::~SessionManager() { - DCHECK(instance == this); - SessionManager::SetInstance(NULL); -} - -// static -SessionManager* SessionManager::Get() { - return SessionManager::instance; } void SessionManager::SetSessionState(SessionState state) { @@ -49,26 +31,10 @@ void SessionManager::Initialize(SessionManagerDelegate* delegate) { delegate_->SetSessionManager(this); } -// static -void SessionManager::SetInstance(SessionManager* session_manager) { - SessionManager::instance = session_manager; -} - void SessionManager::Start() { delegate_->Start(); } -// static -bool SessionManager::HasBrowserRestarted() { -#if defined(OS_CHROMEOS) - CommandLine* command_line = CommandLine::ForCurrentProcess(); - return base::SysInfo::IsRunningOnChromeOS() && - command_line->HasSwitch(chromeos::switches::kLoginUser); -#else - return false; -#endif -} - SessionManagerDelegate::SessionManagerDelegate() : session_manager_(NULL) { } diff --git a/components/session_manager/core/session_manager.h b/components/session_manager/core/session_manager.h index d2e97043d4a5..e728e7fc93ce 100644 --- a/components/session_manager/core/session_manager.h +++ b/components/session_manager/core/session_manager.h @@ -45,10 +45,6 @@ class SESSION_EXPORT SessionManager { SessionManager(); virtual ~SessionManager(); - // Returns current SessionManager instance and NULL if it hasn't been - // initialized yet. - static SessionManager* Get(); - SessionState session_state() const { return session_state_; } virtual void SetSessionState(SessionState state); @@ -56,25 +52,11 @@ class SESSION_EXPORT SessionManager { // current session type / state. void Start(); - // Returns true when the browser has crashed and restarted during the current - // user's session. - static bool HasBrowserRestarted(); - protected: // Initializes SessionManager with delegate. void Initialize(SessionManagerDelegate* delegate); - // Sets SessionManager instance. - static void SetInstance(SessionManager* session_manager); - private: - // Pointer to the existing SessionManager instance (if any). - // Set in ctor, reset in dtor. Not owned since specific implementation of - // SessionManager should decide on its own appropriate owner of SessionManager - // instance. For src/chrome implementation such place is - // g_browser_process->platform_part(). - static SessionManager* instance; - SessionState session_state_; scoped_ptr delegate_; diff --git a/components/user_manager/user.h b/components/user_manager/user.h index ae09573ec45c..60ed45ac47b0 100644 --- a/components/user_manager/user.h +++ b/components/user_manager/user.h @@ -18,14 +18,13 @@ #include "ui/gfx/image/image_skia.h" namespace chromeos { -class ChromeUserManager; class FakeLoginUtils; class FakeUserManager; class MockUserManager; class SupervisedUserManagerImpl; class UserAddingScreenTest; class UserImageManagerImpl; -class UserManagerBase; +class UserManagerImpl; class UserSessionManager; } @@ -149,10 +148,9 @@ class USER_MANAGER_EXPORT User : public UserInfo { bool is_profile_created() const { return profile_is_created_; } protected: - friend class chromeos::ChromeUserManager; friend class chromeos::SupervisedUserManagerImpl; + friend class chromeos::UserManagerImpl; friend class chromeos::UserImageManagerImpl; - friend class chromeos::UserManagerBase; friend class chromeos::UserSessionManager; // For testing: