Index: chrome/browser/chromeos/login/user_manager_impl.cc |
=================================================================== |
--- chrome/browser/chromeos/login/user_manager_impl.cc (revision 170577) |
+++ chrome/browser/chromeos/login/user_manager_impl.cc (working copy) |
@@ -4,10 +4,6 @@ |
#include "chrome/browser/chromeos/login/user_manager_impl.h" |
-#include <cstddef> |
-#include <set> |
-#include <vector> |
- |
#include "ash/shell.h" |
#include "base/bind.h" |
#include "base/chromeos/chromeos_version.h" |
@@ -27,6 +23,7 @@ |
#include "chrome/browser/chromeos/login/remove_user_delegate.h" |
#include "chrome/browser/chromeos/login/user_image_manager_impl.h" |
#include "chrome/browser/chromeos/login/wizard_controller.h" |
+#include "chrome/browser/chromeos/settings/cros_settings.h" |
#include "chrome/browser/policy/browser_policy_connector.h" |
#include "chrome/browser/prefs/pref_service.h" |
#include "chrome/browser/prefs/scoped_user_pref_update.h" |
@@ -47,19 +44,9 @@ |
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 users who have logged into the device. |
+const char kLoggedInUsers[] = "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 usernames to the displayed name. |
const char kUserDisplayName[] = "UserDisplayName"; |
@@ -110,47 +97,11 @@ |
delegate->OnUserRemoved(user_email); |
} |
-// Helper function that copies users from |users_list| to |users_vector| and |
-// |users_set|. Duplicates and users already present in |existing_users| are |
-// skipped. The |logged_in_user| is also skipped and the return value |
-// indicates whether that user was found in |users_list|. |
-bool ParseUserList(const ListValue& users_list, |
- const std::set<std::string>& existing_users, |
- const std::string& logged_in_user, |
- std::vector<std::string>* users_vector, |
- std::set<std::string>* users_set) { |
- users_vector->clear(); |
- users_set->clear(); |
- bool logged_in_user_on_list = false; |
- 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; |
- } |
- if (email == logged_in_user) { |
- logged_in_user_on_list = true; |
- continue; |
- } |
- users_vector->push_back(email); |
- } |
- users_set->erase(logged_in_user); |
- return logged_in_user_on_list; |
-} |
- |
} // namespace |
// static |
void UserManager::RegisterPrefs(PrefService* local_state) { |
- local_state->RegisterListPref(kRegularUsers, PrefService::UNSYNCABLE_PREF); |
- local_state->RegisterListPref(kPublicAccounts, PrefService::UNSYNCABLE_PREF); |
- local_state->RegisterStringPref(kPublicAccountPendingDataRemoval, "", |
- PrefService::UNSYNCABLE_PREF); |
+ local_state->RegisterListPref(kLoggedInUsers, PrefService::UNSYNCABLE_PREF); |
local_state->RegisterDictionaryPref(kUserOAuthTokenStatus, |
PrefService::UNSYNCABLE_PREF); |
local_state->RegisterDictionaryPref(kUserDisplayName, |
@@ -160,9 +111,7 @@ |
} |
UserManagerImpl::UserManagerImpl() |
- : cros_settings_(CrosSettings::Get()), |
- users_loaded_(false), |
- logged_in_user_(NULL), |
+ : logged_in_user_(NULL), |
session_started_(false), |
is_current_user_owner_(false), |
is_current_user_new_(false), |
@@ -188,12 +137,6 @@ |
delete logged_in_user_; |
} |
-void UserManagerImpl::Shutdown() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- cros_settings_->RemoveSettingsObserver(kAccountsPrefDeviceLocalAccounts, |
- this); |
-} |
- |
UserImageManager* UserManagerImpl::GetUserImageManager() { |
return user_image_manager_.get(); |
} |
@@ -225,19 +168,35 @@ |
EnsureUsersLoaded(); |
- // Remove the user from the user list. |
- logged_in_user_ = RemoveRegularUserFromList(email); |
+ // Clear the prefs view of the users. |
+ PrefService* prefs = g_browser_process->local_state(); |
+ ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers); |
+ prefs_users_update->Clear(); |
- // Add the user to the front of the persistent user list. |
- ListPrefUpdate prefs_users_update(g_browser_process->local_state(), |
- kRegularUsers); |
- prefs_users_update->Insert(0, new base::StringValue(email)); |
+ // Make sure this user is first. |
+ prefs_users_update->Append(new base::StringValue(email)); |
+ UserList::iterator logged_in_user = users_.end(); |
+ for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) { |
+ std::string user_email = (*it)->email(); |
+ // Skip the most recent user. |
+ if (email != user_email) |
+ prefs_users_update->Append(new base::StringValue(user_email)); |
+ else |
+ logged_in_user = it; |
+ } |
- // If the user was not found on the user list, create a new user. |
- if (!logged_in_user_) { |
+ if (logged_in_user == users_.end()) { |
is_current_user_new_ = true; |
logged_in_user_ = User::CreateRegularUser(email); |
logged_in_user_->set_oauth_token_status(LoadUserOAuthStatus(email)); |
+ } else { |
+ logged_in_user_ = *logged_in_user; |
+ users_.erase(logged_in_user); |
+ } |
+ // This user must be in the front of the user list. |
+ users_.insert(users_.begin(), logged_in_user_); |
+ |
+ if (is_current_user_new_) { |
SaveUserDisplayName(logged_in_user_->email(), |
UTF8ToUTF16(logged_in_user_->GetAccountName(true))); |
WallpaperManager::Get()->SetInitialUserWallpaper(email, true); |
@@ -250,8 +209,8 @@ |
WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); |
} |
- // Make sure that new data is persisted to Local State. |
- g_browser_process->local_state()->CommitPendingWrite(); |
+ // Make sure we persist new user data to Local State. |
+ prefs->CommitPendingWrite(); |
NotifyOnLogin(); |
} |
@@ -294,7 +253,7 @@ |
content::NotificationService::AllSources(), |
content::NotificationService::NoDetails()); |
if (is_current_user_new_) { |
- // Make sure that the new user's data is persisted to Local State. |
+ // Make sure we persist new user data to Local State. |
g_browser_process->local_state()->CommitPendingWrite(); |
} |
} |
@@ -303,8 +262,7 @@ |
RemoveUserDelegate* delegate) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- const User* user = FindUser(email); |
- if (!user || user->GetType() != User::USER_TYPE_REGULAR) |
+ if (!IsKnownUser(email)) |
return; |
// Sanity check: we must not remove single user. This check may seem |
@@ -325,10 +283,7 @@ |
void UserManagerImpl::RemoveUserFromList(const std::string& email) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
EnsureUsersLoaded(); |
- RemoveNonCryptohomeData(email); |
- delete RemoveRegularUserFromList(email); |
- // Make sure that new data is persisted to Local State. |
- g_browser_process->local_state()->CommitPendingWrite(); |
+ RemoveUserFromListInternal(email); |
} |
bool UserManagerImpl::IsKnownUser(const std::string& email) const { |
@@ -474,18 +429,13 @@ |
} |
} |
break; |
- case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: |
- DCHECK_EQ(*content::Details<const std::string>(details).ptr(), |
- kAccountsPrefDeviceLocalAccounts); |
- RetrieveTrustedDevicePolicies(); |
- break; |
default: |
NOTREACHED(); |
} |
} |
void UserManagerImpl::OnStateChanged() { |
- DCHECK(IsLoggedInAsRegularUser()); |
+ DCHECK(IsUserLoggedIn() && !IsLoggedInAsGuest()); |
GoogleServiceAuthError::State state = |
observed_sync_service_->GetAuthError().state(); |
if (state != GoogleServiceAuthError::NONE && |
@@ -534,12 +484,6 @@ |
return logged_in_user_; |
} |
-bool UserManagerImpl::IsLoggedInAsRegularUser() const { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- return IsUserLoggedIn() && |
- logged_in_user_->GetType() == User::USER_TYPE_REGULAR; |
-} |
- |
bool UserManagerImpl::IsLoggedInAsDemoUser() const { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
return IsUserLoggedIn() && |
@@ -609,56 +553,46 @@ |
void UserManagerImpl::EnsureUsersLoaded() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!users_.empty()) |
+ return; |
if (!g_browser_process) |
return; |
- if (users_loaded_) |
- return; |
- users_loaded_ = true; |
- |
PrefService* local_state = g_browser_process->local_state(); |
- const ListValue* prefs_regular_users = local_state->GetList(kRegularUsers); |
- const ListValue* prefs_public_accounts = |
- local_state->GetList(kPublicAccounts); |
+ const ListValue* prefs_users = |
+ local_state->GetList(kLoggedInUsers); |
const DictionaryValue* prefs_display_names = |
local_state->GetDictionary(kUserDisplayName); |
const DictionaryValue* prefs_display_emails = |
local_state->GetDictionary(kUserDisplayEmail); |
- // Load regular users. |
- std::vector<std::string> regular_users; |
- std::set<std::string> regular_users_set; |
- ParseUserList(*prefs_regular_users, std::set<std::string>(), "", |
- ®ular_users, ®ular_users_set); |
- for (std::vector<std::string>::const_iterator it = regular_users.begin(); |
- it != regular_users.end(); ++it) { |
- User* user = User::CreateRegularUser(*it); |
- user->set_oauth_token_status(LoadUserOAuthStatus(*it)); |
- users_.push_back(user); |
+ if (!prefs_users) |
+ return; |
- string16 display_name; |
- if (prefs_display_names->GetStringWithoutPathExpansion(*it, |
- &display_name)) { |
- user->set_display_name(display_name); |
- } |
+ for (ListValue::const_iterator it = prefs_users->begin(); |
+ it != prefs_users->end(); ++it) { |
+ std::string email; |
+ if ((*it)->GetAsString(&email)) { |
+ User* user = User::CreateRegularUser(email); |
+ user->set_oauth_token_status(LoadUserOAuthStatus(email)); |
+ users_.push_back(user); |
- std::string display_email; |
- if (prefs_display_emails->GetStringWithoutPathExpansion(*it, |
- &display_email)) { |
- user->set_display_email(display_email); |
+ string16 display_name; |
+ if (prefs_display_names && |
+ prefs_display_names->GetStringWithoutPathExpansion( |
+ email, &display_name)) { |
+ user->set_display_name(display_name); |
+ } |
+ |
+ std::string display_email; |
+ if (prefs_display_emails && |
+ prefs_display_emails->GetStringWithoutPathExpansion( |
+ email, &display_email)) { |
+ user->set_display_email(display_email); |
+ } |
} |
} |
- // Load public accounts. |
- std::vector<std::string> public_accounts; |
- std::set<std::string> public_accounts_set; |
- ParseUserList(*prefs_public_accounts, regular_users_set, "", |
- &public_accounts, &public_accounts_set); |
- for (std::vector<std::string>::const_iterator it = public_accounts.begin(); |
- it != public_accounts.end(); ++it) { |
- users_.push_back(User::CreatePublicAccountUser(*it)); |
- } |
- |
user_image_manager_->LoadUserImages(users_); |
} |
@@ -666,53 +600,42 @@ |
ephemeral_users_enabled_ = false; |
owner_email_ = ""; |
+ CrosSettings* cros_settings = CrosSettings::Get(); |
// Schedule a callback if device policy has not yet been verified. |
- if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues( |
+ 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_); |
- const base::ListValue* public_accounts; |
- cros_settings_->GetList(kAccountsPrefDeviceLocalAccounts, &public_accounts); |
+ cros_settings->GetBoolean(kAccountsPrefEphemeralUsersEnabled, |
+ &ephemeral_users_enabled_); |
+ cros_settings->GetString(kDeviceOwner, &owner_email_); |
- EnsureUsersLoaded(); |
- |
- bool changed = UpdateAndCleanUpPublicAccounts(*public_accounts); |
- |
// 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. |
+ // opportunity to clean up by removing all users except the owner. |
if (ephemeral_users_enabled_ && !IsUserLoggedIn()) { |
- ListPrefUpdate prefs_users_update(g_browser_process->local_state(), |
- kRegularUsers); |
- prefs_users_update->Clear(); |
- for (UserList::iterator it = users_.begin(); it != users_.end(); ) { |
- const std::string user_email = (*it)->email(); |
- if ((*it)->GetType() == User::USER_TYPE_REGULAR && |
- user_email != owner_email_) { |
- RemoveNonCryptohomeData(user_email); |
- delete *it; |
- it = users_.erase(it); |
+ scoped_ptr<base::ListValue> users( |
+ g_browser_process->local_state()->GetList(kLoggedInUsers)->DeepCopy()); |
+ |
+ bool changed = false; |
+ for (base::ListValue::const_iterator user = users->begin(); |
+ user != users->end(); ++user) { |
+ std::string user_email; |
+ (*user)->GetAsString(&user_email); |
+ if (user_email != owner_email_) { |
+ RemoveUserFromListInternal(user_email); |
changed = true; |
- } else { |
- prefs_users_update->Append(new base::StringValue(user_email)); |
- ++it; |
} |
} |
- } |
- if (changed) { |
- content::NotificationService::current()->Notify( |
- chrome::NOTIFICATION_POLICY_USER_LIST_CHANGED, |
- content::Source<UserManager>(this), |
- content::NotificationService::NoDetails()); |
+ if (changed) { |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_POLICY_USER_LIST_CHANGED, |
+ content::Source<UserManager>(this), |
+ content::NotificationService::NoDetails()); |
+ } |
} |
- |
- cros_settings_->AddSettingsObserver(kAccountsPrefDeviceLocalAccounts, |
- this); |
} |
bool UserManagerImpl::AreEphemeralUsersEnabled() const { |
@@ -758,11 +681,24 @@ |
base::Unretained(this))); |
} |
-void UserManagerImpl::RemoveNonCryptohomeData(const std::string& email) { |
+void UserManagerImpl::RemoveUserFromListInternal(const std::string& email) { |
+ // Clear the prefs view of the users. |
+ PrefService* prefs = g_browser_process->local_state(); |
+ ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers); |
+ prefs_users_update->Clear(); |
+ |
+ UserList::iterator user_to_remove = users_.end(); |
+ for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) { |
+ std::string user_email = (*it)->email(); |
+ // Skip user that we would like to delete. |
+ if (email != user_email) |
+ prefs_users_update->Append(new base::StringValue(user_email)); |
+ else |
+ user_to_remove = it; |
+ } |
+ |
WallpaperManager::Get()->RemoveUserWallpaperInfo(email); |
- user_image_manager_->DeleteUserImage(email); |
- PrefService* prefs = g_browser_process->local_state(); |
DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus); |
int oauth_status; |
prefs_oauth_update->GetIntegerWithoutPathExpansion(email, &oauth_status); |
@@ -773,112 +709,11 @@ |
DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail); |
prefs_display_email_update->RemoveWithoutPathExpansion(email, NULL); |
-} |
-User *UserManagerImpl::RemoveRegularUserFromList(const std::string& email) { |
- ListPrefUpdate prefs_users_update(g_browser_process->local_state(), |
- kRegularUsers); |
- prefs_users_update->Clear(); |
- User* user = NULL; |
- for (UserList::iterator it = users_.begin(); it != users_.end(); ) { |
- const std::string user_email = (*it)->email(); |
- if (user_email == email) { |
- user = *it; |
- it = users_.erase(it); |
- } else { |
- if ((*it)->GetType() == User::USER_TYPE_REGULAR) |
- prefs_users_update->Append(new base::StringValue(user_email)); |
- ++it; |
- } |
+ if (user_to_remove != users_.end()) { |
+ delete *user_to_remove; |
+ users_.erase(user_to_remove); |
} |
- return user; |
} |
-bool UserManagerImpl::UpdateAndCleanUpPublicAccounts( |
- const base::ListValue& public_accounts) { |
- PrefService* local_state = g_browser_process->local_state(); |
- |
- // Determine the currently logged-in user's email. |
- std::string logged_in_user_email; |
- if (IsUserLoggedIn()) |
- logged_in_user_email = GetLoggedInUser()->email(); |
- |
- // If there is a public account whose data is pending removal and the user is |
- // not currently logged in with that account, take this opportunity to remove |
- // the data. |
- std::string public_account_pending_data_removal = |
- local_state->GetString(kPublicAccountPendingDataRemoval); |
- if (!public_account_pending_data_removal.empty() && |
- public_account_pending_data_removal != logged_in_user_email) { |
- RemoveNonCryptohomeData(public_account_pending_data_removal); |
- local_state->ClearPref(kPublicAccountPendingDataRemoval); |
- } |
- |
- // Split the current user list public accounts and regular users. |
- std::vector<std::string> old_public_accounts; |
- std::set<std::string> regular_users; |
- for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) { |
- if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) |
- old_public_accounts.push_back((*it)->email()); |
- else |
- regular_users.insert((*it)->email()); |
- } |
- |
- // Get the new list of public accounts from policy. |
- std::vector<std::string> new_public_accounts; |
- std::set<std::string> new_public_accounts_set; |
- if (!ParseUserList(public_accounts, regular_users, logged_in_user_email, |
- &new_public_accounts, &new_public_accounts_set) && |
- IsUserLoggedIn()) { |
- User* user = GetLoggedInUser(); |
- // If the user is currently logged into a public account that has been |
- // removed from the list, mark the account's data as pending removal after |
- // logout. |
- if (user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) { |
- local_state->SetString(kPublicAccountPendingDataRemoval, |
- logged_in_user_email); |
- } |
- } |
- |
- // Persist the new list of public accounts in a pref. |
- ListPrefUpdate prefs_public_accounts_update(local_state, kPublicAccounts); |
- scoped_ptr<base::ListValue> prefs_public_accounts(public_accounts.DeepCopy()); |
- prefs_public_accounts_update->Swap(prefs_public_accounts.get()); |
- |
- // 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; |
- } |
- |
- // Remove the old public accounts from the user list. |
- for (UserList::iterator it = users_.begin(); it != users_.end(); ) { |
- if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) { |
- delete *it; |
- it = users_.erase(it); |
- } else { |
- ++it; |
- } |
- } |
- |
- // Add the new public accounts to the front of the user list. |
- for (std::vector<std::string>::const_reverse_iterator |
- it = new_public_accounts.rbegin(); |
- it != new_public_accounts.rend(); ++it) { |
- users_.insert(users_.begin(), User::CreatePublicAccountUser(*it)); |
- } |
- |
- user_image_manager_->LoadUserImages( |
- UserList(users_.begin(), users_.begin() + new_public_accounts.size())); |
- |
- return true; |
-} |
- |
} // namespace chromeos |