Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: chrome/browser/chromeos/login/user_manager_impl.cc

Issue 11419184: Add public accounts to UserManager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Re-upload against the correct upstream commit. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/login/user_manager_impl.h" 5 #include "chrome/browser/chromeos/login/user_manager_impl.h"
6 6
7 #include <cstddef>
8
7 #include "ash/shell.h" 9 #include "ash/shell.h"
8 #include "base/bind.h" 10 #include "base/bind.h"
9 #include "base/chromeos/chromeos_version.h" 11 #include "base/chromeos/chromeos_version.h"
10 #include "base/command_line.h" 12 #include "base/command_line.h"
11 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
12 #include "base/file_path.h" 14 #include "base/file_path.h"
13 #include "base/file_util.h" 15 #include "base/file_util.h"
14 #include "base/logging.h" 16 #include "base/logging.h"
15 #include "base/rand_util.h" 17 #include "base/rand_util.h"
16 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
17 #include "base/values.h" 19 #include "base/values.h"
18 #include "chrome/browser/browser_process.h" 20 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chromeos/cros/cert_library.h" 21 #include "chrome/browser/chromeos/cros/cert_library.h"
20 #include "chrome/browser/chromeos/cros/cros_library.h" 22 #include "chrome/browser/chromeos/cros/cros_library.h"
21 #include "chrome/browser/chromeos/input_method/input_method_manager.h" 23 #include "chrome/browser/chromeos/input_method/input_method_manager.h"
22 #include "chrome/browser/chromeos/login/login_display.h" 24 #include "chrome/browser/chromeos/login/login_display.h"
23 #include "chrome/browser/chromeos/login/remove_user_delegate.h" 25 #include "chrome/browser/chromeos/login/remove_user_delegate.h"
24 #include "chrome/browser/chromeos/login/user_image_manager_impl.h" 26 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
25 #include "chrome/browser/chromeos/login/wizard_controller.h" 27 #include "chrome/browser/chromeos/login/wizard_controller.h"
26 #include "chrome/browser/chromeos/settings/cros_settings.h"
27 #include "chrome/browser/policy/browser_policy_connector.h" 28 #include "chrome/browser/policy/browser_policy_connector.h"
28 #include "chrome/browser/prefs/pref_service.h" 29 #include "chrome/browser/prefs/pref_service.h"
29 #include "chrome/browser/prefs/scoped_user_pref_update.h" 30 #include "chrome/browser/prefs/scoped_user_pref_update.h"
30 #include "chrome/browser/profiles/profile_manager.h" 31 #include "chrome/browser/profiles/profile_manager.h"
31 #include "chrome/browser/sync/profile_sync_service.h" 32 #include "chrome/browser/sync/profile_sync_service.h"
32 #include "chrome/browser/sync/profile_sync_service_factory.h" 33 #include "chrome/browser/sync/profile_sync_service_factory.h"
33 #include "chrome/common/chrome_notification_types.h" 34 #include "chrome/common/chrome_notification_types.h"
34 #include "chrome/common/chrome_switches.h" 35 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/pref_names.h" 36 #include "chrome/common/pref_names.h"
36 #include "chromeos/cryptohome/async_method_caller.h" 37 #include "chromeos/cryptohome/async_method_caller.h"
37 #include "content/public/browser/browser_thread.h" 38 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/notification_service.h" 39 #include "content/public/browser/notification_service.h"
39 #include "google_apis/gaia/google_service_auth_error.h" 40 #include "google_apis/gaia/google_service_auth_error.h"
40 41
41 using content::BrowserThread; 42 using content::BrowserThread;
42 43
43 namespace chromeos { 44 namespace chromeos {
44 45
45 namespace { 46 namespace {
46 47
47 // A vector pref of the users who have logged into the device. 48 // A vector pref of the regular users who have logged into this device.
48 const char kLoggedInUsers[] = "LoggedInUsers"; 49 const char kRegularUsers[] = "LoggedInUsers";
50
51 // A vector pref of the device-local users defined on this device.
52 const char kLocalUsers[] = "LocalUsers";
53
54 // A string pref that gets set when a device-local user is to be removed but is
55 // currently logged in, requiring the user's data to be removed after logout.
56 const char kUserPendingDataRemoval[] = "UserPendingDataRemoval";
49 57
50 // A dictionary that maps usernames to the displayed name. 58 // A dictionary that maps usernames to the displayed name.
51 const char kUserDisplayName[] = "UserDisplayName"; 59 const char kUserDisplayName[] = "UserDisplayName";
52 60
53 // A dictionary that maps usernames to the displayed (non-canonical) emails. 61 // A dictionary that maps usernames to the displayed (non-canonical) emails.
54 const char kUserDisplayEmail[] = "UserDisplayEmail"; 62 const char kUserDisplayEmail[] = "UserDisplayEmail";
55 63
56 // A dictionary that maps usernames to OAuth token presence flag. 64 // A dictionary that maps usernames to OAuth token presence flag.
57 const char kUserOAuthTokenStatus[] = "OAuthTokenStatus"; 65 const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
58 66
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 user_email, base::Bind(&OnRemoveUserComplete, user_email)); 102 user_email, base::Bind(&OnRemoveUserComplete, user_email));
95 103
96 if (delegate) 104 if (delegate)
97 delegate->OnUserRemoved(user_email); 105 delegate->OnUserRemoved(user_email);
98 } 106 }
99 107
100 } // namespace 108 } // namespace
101 109
102 // static 110 // static
103 void UserManager::RegisterPrefs(PrefService* local_state) { 111 void UserManager::RegisterPrefs(PrefService* local_state) {
104 local_state->RegisterListPref(kLoggedInUsers, PrefService::UNSYNCABLE_PREF); 112 local_state->RegisterListPref(kRegularUsers, PrefService::UNSYNCABLE_PREF);
113 local_state->RegisterListPref(kLocalUsers, PrefService::UNSYNCABLE_PREF);
114 local_state->RegisterStringPref(kUserPendingDataRemoval, "",
115 PrefService::UNSYNCABLE_PREF);
105 local_state->RegisterDictionaryPref(kUserOAuthTokenStatus, 116 local_state->RegisterDictionaryPref(kUserOAuthTokenStatus,
106 PrefService::UNSYNCABLE_PREF); 117 PrefService::UNSYNCABLE_PREF);
107 local_state->RegisterDictionaryPref(kUserDisplayName, 118 local_state->RegisterDictionaryPref(kUserDisplayName,
108 PrefService::UNSYNCABLE_PREF); 119 PrefService::UNSYNCABLE_PREF);
109 local_state->RegisterDictionaryPref(kUserDisplayEmail, 120 local_state->RegisterDictionaryPref(kUserDisplayEmail,
110 PrefService::UNSYNCABLE_PREF); 121 PrefService::UNSYNCABLE_PREF);
111 } 122 }
112 123
113 UserManagerImpl::UserManagerImpl() 124 UserManagerImpl::UserManagerImpl()
114 : logged_in_user_(NULL), 125 : cros_settings_(CrosSettings::Get()),
126 observing_cros_settings_(false),
127 users_loaded_(false),
128 logged_in_user_(NULL),
115 session_started_(false), 129 session_started_(false),
116 is_current_user_owner_(false), 130 is_current_user_owner_(false),
117 is_current_user_new_(false), 131 is_current_user_new_(false),
118 is_current_user_ephemeral_(false), 132 is_current_user_ephemeral_(false),
119 ephemeral_users_enabled_(false), 133 ephemeral_users_enabled_(false),
120 observed_sync_service_(NULL), 134 observed_sync_service_(NULL),
121 user_image_manager_(new UserImageManagerImpl) { 135 user_image_manager_(new UserImageManagerImpl),
136 weak_ptr_factory_(this) {
122 // UserManager instance should be used only on UI thread. 137 // UserManager instance should be used only on UI thread.
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
124 registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, 139 registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
125 content::NotificationService::AllSources()); 140 content::NotificationService::AllSources());
126 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, 141 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
127 content::NotificationService::AllSources()); 142 content::NotificationService::AllSources());
128 RetrieveTrustedDevicePolicies(); 143 RetrieveTrustedDevicePolicies();
129 } 144 }
130 145
131 UserManagerImpl::~UserManagerImpl() { 146 UserManagerImpl::~UserManagerImpl() {
(...skipping 29 matching lines...) Expand all
161 return; 176 return;
162 } 177 }
163 178
164 if (IsEphemeralUser(email)) { 179 if (IsEphemeralUser(email)) {
165 EphemeralUserLoggedIn(email); 180 EphemeralUserLoggedIn(email);
166 return; 181 return;
167 } 182 }
168 183
169 EnsureUsersLoaded(); 184 EnsureUsersLoaded();
170 185
171 // Clear the prefs view of the users. 186 // Move the user to the front of the user list (adding the user if necessary).
172 PrefService* prefs = g_browser_process->local_state(); 187 logged_in_user_ = UpdateRegularUsers(email, true);
173 ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
174 prefs_users_update->Clear();
175
176 // Make sure this user is first.
177 prefs_users_update->Append(new base::StringValue(email));
178 UserList::iterator logged_in_user = users_.end();
179 for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
180 std::string user_email = (*it)->email();
181 // Skip the most recent user.
182 if (email != user_email)
183 prefs_users_update->Append(new base::StringValue(user_email));
184 else
185 logged_in_user = it;
186 }
187
188 if (logged_in_user == users_.end()) {
189 is_current_user_new_ = true;
190 logged_in_user_ = User::CreateRegularUser(email);
191 logged_in_user_->set_oauth_token_status(LoadUserOAuthStatus(email));
192 } else {
193 logged_in_user_ = *logged_in_user;
194 users_.erase(logged_in_user);
195 }
196 // This user must be in the front of the user list.
197 users_.insert(users_.begin(), logged_in_user_);
198 188
199 if (is_current_user_new_) { 189 if (is_current_user_new_) {
200 SaveUserDisplayName(logged_in_user_->email(), 190 SaveUserDisplayName(logged_in_user_->email(),
201 UTF8ToUTF16(logged_in_user_->GetAccountName(true))); 191 UTF8ToUTF16(logged_in_user_->GetAccountName(true)));
202 WallpaperManager::Get()->SetInitialUserWallpaper(email, true); 192 WallpaperManager::Get()->SetInitialUserWallpaper(email, true);
203 } 193 }
204 194
205 user_image_manager_->UserLoggedIn(email, is_current_user_new_); 195 user_image_manager_->UserLoggedIn(email, is_current_user_new_);
206 196
207 if (!browser_restart) { 197 if (!browser_restart) {
208 // For GAIA login flow, logged in user wallpaper may not be loaded. 198 // For GAIA login flow, logged in user wallpaper may not be loaded.
209 WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); 199 WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
210 } 200 }
211 201
212 // Make sure we persist new user data to Local State. 202 // Make sure the modified data is persisted to Local State.
213 prefs->CommitPendingWrite(); 203 g_browser_process->local_state()->CommitPendingWrite();
214 204
215 NotifyOnLogin(); 205 NotifyOnLogin();
216 } 206 }
217 207
218 void UserManagerImpl::RetailModeUserLoggedIn() { 208 void UserManagerImpl::RetailModeUserLoggedIn() {
219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
220 is_current_user_new_ = true; 210 is_current_user_new_ = true;
221 is_current_user_ephemeral_ = true; 211 is_current_user_ephemeral_ = true;
222 logged_in_user_ = User::CreateRetailModeUser(); 212 logged_in_user_ = User::CreateRetailModeUser();
223 user_image_manager_->UserLoggedIn(kRetailModeUserEMail, 213 user_image_manager_->UserLoggedIn(kRetailModeUserEMail,
(...skipping 22 matching lines...) Expand all
246 } 236 }
247 237
248 void UserManagerImpl::SessionStarted() { 238 void UserManagerImpl::SessionStarted() {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250 session_started_ = true; 240 session_started_ = true;
251 content::NotificationService::current()->Notify( 241 content::NotificationService::current()->Notify(
252 chrome::NOTIFICATION_SESSION_STARTED, 242 chrome::NOTIFICATION_SESSION_STARTED,
253 content::NotificationService::AllSources(), 243 content::NotificationService::AllSources(),
254 content::NotificationService::NoDetails()); 244 content::NotificationService::NoDetails());
255 if (is_current_user_new_) { 245 if (is_current_user_new_) {
256 // Make sure we persist new user data to Local State. 246 // Make sure the modified data is persisted to Local State.
pastarmovj 2012/11/28 09:57:16 I am not convinced we need all those CommitPending
bartfab (slow) 2012/11/28 12:30:17 I removed the CommitPendingWrite() calls. I agree
257 g_browser_process->local_state()->CommitPendingWrite(); 247 g_browser_process->local_state()->CommitPendingWrite();
258 } 248 }
259 } 249 }
260 250
261 void UserManagerImpl::RemoveUser(const std::string& email, 251 void UserManagerImpl::RemoveUser(const std::string& email,
262 RemoveUserDelegate* delegate) { 252 RemoveUserDelegate* delegate) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264 254
265 if (!IsKnownUser(email)) 255 const User* user = FindUser(email);
256 if (!user || user->GetType() != User::USER_TYPE_REGULAR)
266 return; 257 return;
267 258
268 // Sanity check: we must not remove single user. This check may seem 259 // Sanity check: we must not remove single user. This check may seem
269 // redundant at a first sight because this single user must be an owner and 260 // redundant at a first sight because this single user must be an owner and
270 // we perform special check later in order not to remove an owner. However 261 // we perform special check later in order not to remove an owner. However
271 // due to non-instant nature of ownership assignment this later check may 262 // due to non-instant nature of ownership assignment this later check may
272 // sometimes fail. See http://crosbug.com/12723 263 // sometimes fail. See http://crosbug.com/12723
273 if (users_.size() < 2) 264 if (users_.size() < 2)
274 return; 265 return;
275 266
276 // Sanity check: do not allow the logged-in user to remove himself. 267 // Sanity check: do not allow the logged-in user to remove himself.
277 if (logged_in_user_ && logged_in_user_->email() == email) 268 if (logged_in_user_ && logged_in_user_->email() == email)
278 return; 269 return;
279 270
280 RemoveUserInternal(email, delegate); 271 RemoveUserInternal(email, delegate);
281 } 272 }
282 273
283 void UserManagerImpl::RemoveUserFromList(const std::string& email) { 274 void UserManagerImpl::RemoveUserFromList(const std::string& email) {
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285 EnsureUsersLoaded(); 276 EnsureUsersLoaded();
286 RemoveUserFromListInternal(email); 277 RemoveNonCryptohomeData(email);
278 UpdateRegularUsers(email, false);
pastarmovj 2012/11/28 09:57:16 I have a proposal about the second parameter of th
bartfab (slow) 2012/11/28 12:30:17 I refactored the code. There is now a |RemoveUserF
279 // Make sure the modified data is persisted to Local State.
280 g_browser_process->local_state()->CommitPendingWrite();
287 } 281 }
288 282
289 bool UserManagerImpl::IsKnownUser(const std::string& email) const { 283 bool UserManagerImpl::IsKnownUser(const std::string& email) const {
290 return FindUser(email) != NULL; 284 return FindUser(email) != NULL;
291 } 285 }
292 286
293 const User* UserManagerImpl::FindUser(const std::string& email) const { 287 const User* UserManagerImpl::FindUser(const std::string& email) const {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295 if (logged_in_user_ && logged_in_user_->email() == email) 289 if (logged_in_user_ && logged_in_user_->email() == email)
296 return logged_in_user_; 290 return logged_in_user_;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 if (!profile->IsOffTheRecord() && 416 if (!profile->IsOffTheRecord() &&
423 profile == ProfileManager::GetDefaultProfile()) { 417 profile == ProfileManager::GetDefaultProfile()) {
424 DCHECK(NULL == observed_sync_service_); 418 DCHECK(NULL == observed_sync_service_);
425 observed_sync_service_ = 419 observed_sync_service_ =
426 ProfileSyncServiceFactory::GetForProfile(profile); 420 ProfileSyncServiceFactory::GetForProfile(profile);
427 if (observed_sync_service_) 421 if (observed_sync_service_)
428 observed_sync_service_->AddObserver(this); 422 observed_sync_service_->AddObserver(this);
429 } 423 }
430 } 424 }
431 break; 425 break;
426 case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED:
427 DCHECK_EQ(*content::Details<const std::string>(details).ptr(),
428 kAccountsPrefDeviceLocalAccounts);
429 RetrieveTrustedDevicePolicies();
430 break;
432 default: 431 default:
433 NOTREACHED(); 432 NOTREACHED();
434 } 433 }
435 } 434 }
436 435
437 void UserManagerImpl::OnStateChanged() { 436 void UserManagerImpl::OnStateChanged() {
438 DCHECK(IsUserLoggedIn() && !IsLoggedInAsGuest()); 437 DCHECK(IsLoggedInAsRegularUser());
439 GoogleServiceAuthError::State state = 438 GoogleServiceAuthError::State state =
440 observed_sync_service_->GetAuthError().state(); 439 observed_sync_service_->GetAuthError().state();
441 if (state != GoogleServiceAuthError::NONE && 440 if (state != GoogleServiceAuthError::NONE &&
442 state != GoogleServiceAuthError::CONNECTION_FAILED && 441 state != GoogleServiceAuthError::CONNECTION_FAILED &&
443 state != GoogleServiceAuthError::SERVICE_UNAVAILABLE && 442 state != GoogleServiceAuthError::SERVICE_UNAVAILABLE &&
444 state != GoogleServiceAuthError::REQUEST_CANCELED) { 443 state != GoogleServiceAuthError::REQUEST_CANCELED) {
445 // Invalidate OAuth token to force Gaia sign-in flow. This is needed 444 // Invalidate OAuth token to force Gaia sign-in flow. This is needed
446 // because sign-out/sign-in solution is suggested to the user. 445 // because sign-out/sign-in solution is suggested to the user.
447 // TODO(altimofeev): this code isn't needed after crosbug.com/25978 is 446 // TODO(altimofeev): this code isn't needed after crosbug.com/25978 is
448 // implemented. 447 // implemented.
(...skipping 28 matching lines...) Expand all
477 bool UserManagerImpl::CanCurrentUserLock() const { 476 bool UserManagerImpl::CanCurrentUserLock() const {
478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
479 return IsUserLoggedIn() && logged_in_user_->can_lock(); 478 return IsUserLoggedIn() && logged_in_user_->can_lock();
480 } 479 }
481 480
482 bool UserManagerImpl::IsUserLoggedIn() const { 481 bool UserManagerImpl::IsUserLoggedIn() const {
483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484 return logged_in_user_; 483 return logged_in_user_;
485 } 484 }
486 485
486 bool UserManagerImpl::IsLoggedInAsRegularUser() const {
487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
488 return IsUserLoggedIn() &&
489 logged_in_user_->GetType() == User::USER_TYPE_REGULAR;
490 }
491
487 bool UserManagerImpl::IsLoggedInAsDemoUser() const { 492 bool UserManagerImpl::IsLoggedInAsDemoUser() const {
488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
489 return IsUserLoggedIn() && 494 return IsUserLoggedIn() &&
490 logged_in_user_->GetType() == User::USER_TYPE_RETAIL_MODE; 495 logged_in_user_->GetType() == User::USER_TYPE_RETAIL_MODE;
491 } 496 }
492 497
493 bool UserManagerImpl::IsLoggedInAsPublicAccount() const { 498 bool UserManagerImpl::IsLoggedInAsPublicAccount() const {
494 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
495 return IsUserLoggedIn() && 500 return IsUserLoggedIn() &&
496 logged_in_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT; 501 logged_in_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 549 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
545 observer_list_.RemoveObserver(obs); 550 observer_list_.RemoveObserver(obs);
546 } 551 }
547 552
548 void UserManagerImpl::NotifyLocalStateChanged() { 553 void UserManagerImpl::NotifyLocalStateChanged() {
549 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
550 FOR_EACH_OBSERVER(UserManager::Observer, observer_list_, 555 FOR_EACH_OBSERVER(UserManager::Observer, observer_list_,
551 LocalStateChanged(this)); 556 LocalStateChanged(this));
552 } 557 }
553 558
559 bool UserManagerImpl::ParseUserList(
560 std::vector<std::string>* users_vector,
561 std::set<std::string>* users_set,
562 const ListValue& users_list,
563 const std::set<std::string>& existing_users,
564 const std::string& logged_in_user) const {
565 users_vector->clear();
566 users_set->clear();
567 bool logged_in_user_on_list = false;
568 for (size_t i = 0; i < users_list.GetSize(); ++i) {
569 std::string email;
570 if (!users_list.GetString(i, &email) || email.empty()) {
571 LOG(ERROR) << "Corrupt entry in user list.";
pastarmovj 2012/11/28 09:57:16 Please print the index here too. Could be helpful
bartfab (slow) 2012/11/28 12:30:17 Done.
572 continue;
573 }
574 if ((existing_users.find(email) != existing_users.end()) ||
pastarmovj 2012/11/28 09:57:16 I think you don't need the extra parenthesis aroun
bartfab (slow) 2012/11/28 12:30:17 Correct. I added them for readability only. Remove
575 !users_set->insert(email).second) {
576 LOG(ERROR) << "Duplicate user: " << email;
577 continue;
578 }
579 if (email == logged_in_user) {
580 logged_in_user_on_list = true;
581 continue;
582 }
583 users_vector->push_back(email);
584 }
585 users_set->erase(logged_in_user);
586 return logged_in_user_on_list;
587 }
588
554 void UserManagerImpl::EnsureUsersLoaded() { 589 void UserManagerImpl::EnsureUsersLoaded() {
555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
556 if (!users_.empty()) 591 if (users_loaded_)
557 return; 592 return;
558 if (!g_browser_process) 593 if (!g_browser_process)
pastarmovj 2012/11/28 09:57:16 Swap the two ifs and split them with an empty line
bartfab (slow) 2012/11/28 12:30:17 Done.
559 return; 594 return;
595 users_loaded_ = true;
560 596
561 PrefService* local_state = g_browser_process->local_state(); 597 PrefService* local_state = g_browser_process->local_state();
562 const ListValue* prefs_users = 598 const ListValue* prefs_regular_users = local_state->GetList(kRegularUsers);
563 local_state->GetList(kLoggedInUsers); 599 const ListValue* prefs_local_users = local_state->GetList(kLocalUsers);
564 const DictionaryValue* prefs_display_names = 600 const DictionaryValue* prefs_display_names =
565 local_state->GetDictionary(kUserDisplayName); 601 local_state->GetDictionary(kUserDisplayName);
566 const DictionaryValue* prefs_display_emails = 602 const DictionaryValue* prefs_display_emails =
567 local_state->GetDictionary(kUserDisplayEmail); 603 local_state->GetDictionary(kUserDisplayEmail);
568 604
569 if (!prefs_users) 605 // Load regular users.
570 return; 606 std::vector<std::string> regular_users;
607 std::set<std::string> regular_users_set;
608 ParseUserList(&regular_users, &regular_users_set, *prefs_regular_users,
609 std::set<std::string>(), "");
610 for (std::vector<std::string>::const_iterator it = regular_users.begin();
611 it != regular_users.end(); ++it) {
612 User* user = User::CreateRegularUser(*it);
613 user->set_oauth_token_status(LoadUserOAuthStatus(*it));
614 users_.push_back(user);
571 615
572 for (ListValue::const_iterator it = prefs_users->begin(); 616 string16 display_name;
573 it != prefs_users->end(); ++it) { 617 if (prefs_display_names->GetStringWithoutPathExpansion(*it,
574 std::string email; 618 &display_name)) {
575 if ((*it)->GetAsString(&email)) { 619 user->set_display_name(display_name);
576 User* user = User::CreateRegularUser(email); 620 }
577 user->set_oauth_token_status(LoadUserOAuthStatus(email));
578 users_.push_back(user);
579 621
580 string16 display_name; 622 std::string display_email;
581 if (prefs_display_names && 623 if (prefs_display_emails->GetStringWithoutPathExpansion(*it,
582 prefs_display_names->GetStringWithoutPathExpansion( 624 &display_email)) {
583 email, &display_name)) { 625 user->set_display_email(display_email);
584 user->set_display_name(display_name); 626 }
585 } 627 }
586 628
587 std::string display_email; 629 // Load device-local users.
588 if (prefs_display_emails && 630 std::vector<std::string> local_users;
589 prefs_display_emails->GetStringWithoutPathExpansion( 631 std::set<std::string> local_users_set;
590 email, &display_email)) { 632 ParseUserList(&local_users, &local_users_set, *prefs_local_users,
591 user->set_display_email(display_email); 633 regular_users_set, "");
592 } 634 for (std::vector<std::string>::const_iterator it = local_users.begin();
593 } 635 it != local_users.end(); ++it) {
636 // Currently, all device-local users are public account users. This may
637 // change in the future.
638 users_.push_back(User::CreatePublicAccountUser(*it));
594 } 639 }
595 640
596 user_image_manager_->LoadUserImages(users_); 641 user_image_manager_->LoadUserImages(users_);
597 } 642 }
598 643
599 void UserManagerImpl::RetrieveTrustedDevicePolicies() { 644 void UserManagerImpl::RetrieveTrustedDevicePolicies() {
600 ephemeral_users_enabled_ = false; 645 ephemeral_users_enabled_ = false;
601 owner_email_ = ""; 646 owner_email_ = "";
602 647
603 CrosSettings* cros_settings = CrosSettings::Get();
604 // Schedule a callback if device policy has not yet been verified. 648 // Schedule a callback if device policy has not yet been verified.
605 if (CrosSettingsProvider::TRUSTED != cros_settings->PrepareTrustedValues( 649 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
606 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies, 650 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
607 base::Unretained(this)))) { 651 base::Unretained(this)))) {
608 return; 652 return;
609 } 653 }
610 654
611 cros_settings->GetBoolean(kAccountsPrefEphemeralUsersEnabled, 655 cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled,
612 &ephemeral_users_enabled_); 656 &ephemeral_users_enabled_);
613 cros_settings->GetString(kDeviceOwner, &owner_email_); 657 cros_settings_->GetString(kDeviceOwner, &owner_email_);
658 const base::ListValue* local_users;
659 cros_settings_->GetList(kAccountsPrefDeviceLocalAccounts, &local_users);
660
661 bool changed = UpdateLocalUsers(*local_users);
614 662
615 // If ephemeral users are enabled and we are on the login screen, take this 663 // If ephemeral users are enabled and we are on the login screen, take this
616 // opportunity to clean up by removing all users except the owner. 664 // opportunity to clean up by removing all users except the owner.
617 if (ephemeral_users_enabled_ && !IsUserLoggedIn()) { 665 if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
618 scoped_ptr<base::ListValue> users( 666 scoped_ptr<base::ListValue> users(
619 g_browser_process->local_state()->GetList(kLoggedInUsers)->DeepCopy()); 667 g_browser_process->local_state()->GetList(kRegularUsers)->DeepCopy());
620 668
621 bool changed = false;
622 for (base::ListValue::const_iterator user = users->begin(); 669 for (base::ListValue::const_iterator user = users->begin();
623 user != users->end(); ++user) { 670 user != users->end(); ++user) {
624 std::string user_email; 671 std::string user_email;
625 (*user)->GetAsString(&user_email); 672 (*user)->GetAsString(&user_email);
626 if (user_email != owner_email_) { 673 if (user_email != owner_email_) {
627 RemoveUserFromListInternal(user_email); 674 RemoveNonCryptohomeData(user_email);
675 UpdateRegularUsers(user_email, false);
628 changed = true; 676 changed = true;
629 } 677 }
630 } 678 }
679 }
631 680
632 if (changed) { 681 // Make sure the modified data is persisted to Local State.
633 content::NotificationService::current()->Notify( 682 g_browser_process->local_state()->CommitPendingWrite();
634 chrome::NOTIFICATION_POLICY_USER_LIST_CHANGED, 683
635 content::Source<UserManager>(this), 684 if (changed) {
636 content::NotificationService::NoDetails()); 685 content::NotificationService::current()->Notify(
637 } 686 chrome::NOTIFICATION_POLICY_USER_LIST_CHANGED,
687 content::Source<UserManager>(this),
688 content::NotificationService::NoDetails());
689 }
690
691 if (!observing_cros_settings_) {
692 cros_settings_->AddSettingsObserver(kAccountsPrefDeviceLocalAccounts,
pastarmovj 2012/11/28 09:57:16 Is there any reason you don't simply do this in th
bartfab (slow) 2012/11/28 12:30:17 The RetrieveTrustedDevicePolicies() will always ru
693 weak_ptr_factory_.GetWeakPtr());
694 observing_cros_settings_ = true;
638 } 695 }
639 } 696 }
640 697
641 bool UserManagerImpl::AreEphemeralUsersEnabled() const { 698 bool UserManagerImpl::AreEphemeralUsersEnabled() const {
642 return ephemeral_users_enabled_ && 699 return ephemeral_users_enabled_ &&
643 (g_browser_process->browser_policy_connector()->IsEnterpriseManaged() || 700 (g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ||
644 !owner_email_.empty()); 701 !owner_email_.empty());
645 } 702 }
646 703
647 const User* UserManagerImpl::FindUserInList(const std::string& email) const { 704 const User* UserManagerImpl::FindUserInList(const std::string& email) const {
(...skipping 26 matching lines...) Expand all
674 731
675 SetCurrentUserIsOwner(is_owner); 732 SetCurrentUserIsOwner(is_owner);
676 } 733 }
677 734
678 void UserManagerImpl::CheckOwnership() { 735 void UserManagerImpl::CheckOwnership() {
679 DeviceSettingsService::Get()->GetOwnershipStatusAsync( 736 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
680 base::Bind(&UserManagerImpl::UpdateOwnership, 737 base::Bind(&UserManagerImpl::UpdateOwnership,
681 base::Unretained(this))); 738 base::Unretained(this)));
682 } 739 }
683 740
684 void UserManagerImpl::RemoveUserFromListInternal(const std::string& email) { 741 void UserManagerImpl::RemoveNonCryptohomeData(const std::string& email) {
685 // Clear the prefs view of the users. 742 WallpaperManager::Get()->RemoveUserWallpaperInfo(email);
743 user_image_manager_->DeleteUserImage(email);
744
686 PrefService* prefs = g_browser_process->local_state(); 745 PrefService* prefs = g_browser_process->local_state();
687 ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
688 prefs_users_update->Clear();
689
690 UserList::iterator user_to_remove = users_.end();
691 for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
692 std::string user_email = (*it)->email();
693 // Skip user that we would like to delete.
694 if (email != user_email)
695 prefs_users_update->Append(new base::StringValue(user_email));
696 else
697 user_to_remove = it;
698 }
699
700 WallpaperManager::Get()->RemoveUserWallpaperInfo(email);
701
702 DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus); 746 DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
703 int oauth_status; 747 int oauth_status;
704 prefs_oauth_update->GetIntegerWithoutPathExpansion(email, &oauth_status); 748 prefs_oauth_update->GetIntegerWithoutPathExpansion(email, &oauth_status);
705 prefs_oauth_update->RemoveWithoutPathExpansion(email, NULL); 749 prefs_oauth_update->RemoveWithoutPathExpansion(email, NULL);
706 750
707 DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName); 751 DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName);
708 prefs_display_name_update->RemoveWithoutPathExpansion(email, NULL); 752 prefs_display_name_update->RemoveWithoutPathExpansion(email, NULL);
709 753
710 DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail); 754 DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
711 prefs_display_email_update->RemoveWithoutPathExpansion(email, NULL); 755 prefs_display_email_update->RemoveWithoutPathExpansion(email, NULL);
756 }
712 757
713 if (user_to_remove != users_.end()) { 758 User *UserManagerImpl::UpdateRegularUsers(const std::string& email,
714 delete *user_to_remove; 759 bool move_to_front) {
715 users_.erase(user_to_remove); 760 ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
761 kRegularUsers);
762 prefs_users_update->Clear();
763 UserList::iterator user_it = users_.end();
764 for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
765 const std::string user_email = (*it)->email();
766 if (user_email == email)
767 user_it = it;
768 else if ((*it)->GetType() == User::USER_TYPE_REGULAR)
769 prefs_users_update->Append(new base::StringValue(user_email));
716 } 770 }
771 User* user = NULL;
772 if (user_it != users_.end()) {
773 user = *user_it;
774 users_.erase(user_it);
775 }
776
777 if (move_to_front) {
778 prefs_users_update->Insert(0, new base::StringValue(email));
779 if (!user) {
pastarmovj 2012/11/28 09:57:16 Please also document that this function will actua
bartfab (slow) 2012/11/28 12:30:17 I refactored the code so that this function no lon
780 is_current_user_new_ = true;
781 user = User::CreateRegularUser(email);
782 user->set_oauth_token_status(LoadUserOAuthStatus(email));
783 }
784 users_.insert(users_.begin(), user);
785 } else {
786 delete user;
787 user = NULL;
788 }
789
790 return user;
791 }
792
793 bool UserManagerImpl::UpdateLocalUsers(
794 const base::ListValue& local_users_list) {
795 PrefService* local_state = g_browser_process->local_state();
796
797 EnsureUsersLoaded();
798
799 // Determine the currently logged-in user's email.
800 std::string logged_in_user;
801 if (IsUserLoggedIn())
802 logged_in_user = GetLoggedInUser()->email();
803
804 // If there is a user whose data is pending removal and that user is not
805 // currently logged in, take this opportunity to remove the data.
806 std::string user_pending_data_removal =
807 local_state->GetString(kUserPendingDataRemoval);
808 if (!user_pending_data_removal.empty() &&
809 user_pending_data_removal != logged_in_user) {
810 RemoveNonCryptohomeData(user_pending_data_removal);
811 local_state->ClearPref(kUserPendingDataRemoval);
812 }
813
814 // Split the current user list into device-local users and regular users.
815 std::vector<std::string> old_local_users;
816 std::set<std::string> regular_users;
817 for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) {
818 if ((*it)->is_device_local_account())
819 old_local_users.push_back((*it)->email());
820 else
821 regular_users.insert((*it)->email());
822 }
823
824 // Get the new list of device-local users from policy.
825 std::vector<std::string> new_local_users;
826 std::set<std::string> new_local_users_set;
827 std::string pending_remove;
828 if (!ParseUserList(&new_local_users, &new_local_users_set, local_users_list,
829 regular_users, logged_in_user) && IsUserLoggedIn()) {
830 User* user = GetLoggedInUser();
831 // If the currently logged-in user is a device-local user not found on the
832 // new list, mark that user's data as pending removal after logout.
833 if (user->is_device_local_account() && !user->is_builtin_account())
834 local_state->SetString(kUserPendingDataRemoval, logged_in_user);
835 }
836
837 // Persist the new list of device-local users in a pref.
838 ListPrefUpdate prefs_local_users_update(local_state, kLocalUsers);
839 scoped_ptr<base::ListValue> prefs_local_users(local_users_list.DeepCopy());
840 prefs_local_users_update->Swap(prefs_local_users.get());
841
842 // If the list of device-local users has not changed, return.
843 if (new_local_users.size() == old_local_users.size()) {
844 bool changed = false;
845 for (size_t i = 0; i < new_local_users.size(); ++i) {
846 if (new_local_users[i] != old_local_users[i]) {
847 changed = true;
848 break;
849 }
850 }
851 if (!changed)
852 return false;
853 }
854
855 // Remove the old device-local users from the user list.
856 for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
857 if ((*it)->is_device_local_account()) {
858 delete *it;
859 it = users_.erase(it);
860 } else {
861 ++it;
862 }
863 }
864
865 // Add the new device-local users to the user list.
866 for (std::vector<std::string>::const_iterator it = new_local_users.begin();
867 it != new_local_users.end(); ++it) {
868 // Currently, all device-local users are public account users. This may
869 // change in the future.
870 users_.push_back(User::CreatePublicAccountUser(*it));
871 }
872
873 user_image_manager_->LoadUserImages(
874 UserList(users_.end() - new_local_users.size(), users_.end()));
875
876 return true;
717 } 877 }
718 878
719 } // namespace chromeos 879 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698