Remove supervised users from behind the flag
[chromium-blink-merge.git] / chrome / browser / chromeos / login / user_manager_impl.cc
blob6eb76c6bb4936d066ecf063271dddcb50f66231d
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/login/user_manager_impl.h"
7 #include <cstddef>
8 #include <set>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/logging.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_registry_simple.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/prefs/scoped_user_pref_update.h"
20 #include "base/rand_util.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/sys_info.h"
25 #include "base/threading/worker_pool.h"
26 #include "base/values.h"
27 #include "chrome/browser/app_mode/app_mode_utils.h"
28 #include "chrome/browser/browser_process.h"
29 #include "chrome/browser/chrome_notification_types.h"
30 #include "chrome/browser/chromeos/base/locale_util.h"
31 #include "chrome/browser/chromeos/login/auth_sync_observer.h"
32 #include "chrome/browser/chromeos/login/auth_sync_observer_factory.h"
33 #include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
34 #include "chrome/browser/chromeos/login/login_display.h"
35 #include "chrome/browser/chromeos/login/login_utils.h"
36 #include "chrome/browser/chromeos/login/multi_profile_first_run_notification.h"
37 #include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
38 #include "chrome/browser/chromeos/login/remove_user_delegate.h"
39 #include "chrome/browser/chromeos/login/supervised_user_manager_impl.h"
40 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
41 #include "chrome/browser/chromeos/login/wizard_controller.h"
42 #include "chrome/browser/chromeos/policy/device_local_account.h"
43 #include "chrome/browser/chromeos/profiles/profile_helper.h"
44 #include "chrome/browser/chromeos/session_length_limiter.h"
45 #include "chrome/browser/lifetime/application_lifetime.h"
46 #include "chrome/browser/policy/browser_policy_connector.h"
47 #include "chrome/browser/profiles/profile.h"
48 #include "chrome/browser/profiles/profile_manager.h"
49 #include "chrome/browser/sync/profile_sync_service.h"
50 #include "chrome/browser/sync/profile_sync_service_factory.h"
51 #include "chrome/common/chrome_constants.h"
52 #include "chrome/common/chrome_switches.h"
53 #include "chrome/common/pref_names.h"
54 #include "chromeos/chromeos_switches.h"
55 #include "chromeos/cryptohome/async_method_caller.h"
56 #include "chromeos/dbus/dbus_thread_manager.h"
57 #include "chromeos/login/login_state.h"
58 #include "chromeos/settings/cros_settings_names.h"
59 #include "content/public/browser/browser_thread.h"
60 #include "content/public/browser/notification_service.h"
61 #include "google_apis/gaia/gaia_auth_util.h"
62 #include "google_apis/gaia/google_service_auth_error.h"
63 #include "policy/policy_constants.h"
64 #include "ui/base/l10n/l10n_util.h"
65 #include "ui/views/corewm/corewm_switches.h"
67 using content::BrowserThread;
69 namespace chromeos {
70 namespace {
72 // A vector pref of the the regular users known on this device, arranged in LRU
73 // order.
74 const char kRegularUsers[] = "LoggedInUsers";
76 // A vector pref of the public accounts defined on this device.
77 const char kPublicAccounts[] = "PublicAccounts";
79 // A string pref that gets set when a public account is removed but a user is
80 // currently logged into that account, requiring the account's data to be
81 // removed after logout.
82 const char kPublicAccountPendingDataRemoval[] =
83 "PublicAccountPendingDataRemoval";
85 // A dictionary that maps usernames to the displayed name.
86 const char kUserDisplayName[] = "UserDisplayName";
88 // A dictionary that maps usernames to the user's given name.
89 const char kUserGivenName[] = "UserGivenName";
91 // A dictionary that maps usernames to the displayed (non-canonical) emails.
92 const char kUserDisplayEmail[] = "UserDisplayEmail";
94 // A dictionary that maps usernames to OAuth token presence flag.
95 const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
97 // A string pref containing the ID of the last user who logged in if it was
98 // a regular user or an empty string if it was another type of user (guest,
99 // kiosk, public account, etc.).
100 const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser";
102 // Upper bound for a histogram metric reporting the amount of time between
103 // one regular user logging out and a different regular user logging in.
104 const int kLogoutToLoginDelayMaxSec = 1800;
106 // Callback that is called after user removal is complete.
107 void OnRemoveUserComplete(const std::string& user_email,
108 bool success,
109 cryptohome::MountError return_code) {
110 // Log the error, but there's not much we can do.
111 if (!success) {
112 LOG(ERROR) << "Removal of cryptohome for " << user_email
113 << " failed, return code: " << return_code;
117 // Helper function that copies users from |users_list| to |users_vector| and
118 // |users_set|. Duplicates and users already present in |existing_users| are
119 // skipped.
120 void ParseUserList(const ListValue& users_list,
121 const std::set<std::string>& existing_users,
122 std::vector<std::string>* users_vector,
123 std::set<std::string>* users_set) {
124 users_vector->clear();
125 users_set->clear();
126 for (size_t i = 0; i < users_list.GetSize(); ++i) {
127 std::string email;
128 if (!users_list.GetString(i, &email) || email.empty()) {
129 LOG(ERROR) << "Corrupt entry in user list at index " << i << ".";
130 continue;
132 if (existing_users.find(email) != existing_users.end() ||
133 !users_set->insert(email).second) {
134 LOG(ERROR) << "Duplicate user: " << email;
135 continue;
137 users_vector->push_back(email);
141 class UserHashMatcher {
142 public:
143 explicit UserHashMatcher(const std::string& h) : username_hash(h) {}
144 bool operator()(const User* user) const {
145 return user->username_hash() == username_hash;
148 private:
149 const std::string& username_hash;
152 // Runs on SequencedWorkerPool thread. Passes resolved locale to
153 // |on_resolve_callback| on UI thread.
154 void ResolveLocale(
155 const std::string& raw_locale,
156 base::Callback<void(const std::string&)> on_resolve_callback) {
157 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
158 std::string resolved_locale;
159 // Ignore result
160 l10n_util::CheckAndResolveLocale(raw_locale, &resolved_locale);
161 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
162 base::Bind(on_resolve_callback, resolved_locale));
165 } // namespace
167 // static
168 void UserManager::RegisterPrefs(PrefRegistrySimple* registry) {
169 registry->RegisterListPref(kRegularUsers);
170 registry->RegisterListPref(kPublicAccounts);
171 registry->RegisterStringPref(kPublicAccountPendingDataRemoval, "");
172 registry->RegisterStringPref(kLastLoggedInRegularUser, "");
173 registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
174 registry->RegisterDictionaryPref(kUserDisplayName);
175 registry->RegisterDictionaryPref(kUserGivenName);
176 registry->RegisterDictionaryPref(kUserDisplayEmail);
177 SupervisedUserManager::RegisterPrefs(registry);
178 SessionLengthLimiter::RegisterPrefs(registry);
181 UserManagerImpl::UserManagerImpl()
182 : cros_settings_(CrosSettings::Get()),
183 device_local_account_policy_service_(NULL),
184 user_loading_stage_(STAGE_NOT_LOADED),
185 active_user_(NULL),
186 primary_user_(NULL),
187 session_started_(false),
188 user_sessions_restored_(false),
189 is_current_user_owner_(false),
190 is_current_user_new_(false),
191 is_current_user_ephemeral_regular_user_(false),
192 ephemeral_users_enabled_(false),
193 user_image_manager_(new UserImageManagerImpl(cros_settings_, this)),
194 supervised_user_manager_(new SupervisedUserManagerImpl(this)),
195 manager_creation_time_(base::TimeTicks::Now()),
196 multi_profile_first_run_notification_(
197 new MultiProfileFirstRunNotification) {
198 // UserManager instance should be used only on UI thread.
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
200 registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
201 content::NotificationService::AllSources());
202 registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
203 content::NotificationService::AllSources());
204 registrar_.Add(this,
205 chrome::NOTIFICATION_PROFILE_CREATED,
206 content::NotificationService::AllSources());
207 RetrieveTrustedDevicePolicies();
208 local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
209 kAccountsPrefDeviceLocalAccounts,
210 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
211 base::Unretained(this)));
212 supervised_users_subscription_ = cros_settings_->AddSettingsObserver(
213 kAccountsPrefSupervisedUsersEnabled,
214 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
215 base::Unretained(this)));
216 multi_profile_user_controller_.reset(new MultiProfileUserController(
217 this, g_browser_process->local_state()));
218 UpdateLoginState();
221 UserManagerImpl::~UserManagerImpl() {
222 // Can't use STLDeleteElements because of the private destructor of User.
223 for (UserList::iterator it = users_.begin(); it != users_.end();
224 it = users_.erase(it)) {
225 if (active_user_ == *it)
226 active_user_ = NULL;
227 delete *it;
229 // These are pointers to the same User instances that were in users_ list.
230 logged_in_users_.clear();
231 lru_logged_in_users_.clear();
233 delete active_user_;
236 void UserManagerImpl::Shutdown() {
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238 local_accounts_subscription_.reset();
239 supervised_users_subscription_.reset();
240 // Stop the session length limiter.
241 session_length_limiter_.reset();
243 if (device_local_account_policy_service_)
244 device_local_account_policy_service_->RemoveObserver(this);
246 user_image_manager_->Shutdown();
247 multi_profile_user_controller_.reset();
250 UserImageManager* UserManagerImpl::GetUserImageManager() {
251 return user_image_manager_.get();
254 SupervisedUserManager* UserManagerImpl::GetSupervisedUserManager() {
255 return supervised_user_manager_.get();
258 const UserList& UserManagerImpl::GetUsers() const {
259 const_cast<UserManagerImpl*>(this)->EnsureUsersLoaded();
260 return users_;
263 UserList UserManagerImpl::GetUsersAdmittedForMultiProfile() const {
264 if (!UserManager::IsMultipleProfilesAllowed())
265 return UserList();
267 UserList result;
268 const UserList& users = GetUsers();
269 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
270 if ((*it)->GetType() == User::USER_TYPE_REGULAR &&
271 !(*it)->is_logged_in() &&
272 multi_profile_user_controller_->IsUserAllowedInSession(
273 (*it)->email())) {
274 result.push_back(*it);
277 return result;
280 const UserList& UserManagerImpl::GetLoggedInUsers() const {
281 return logged_in_users_;
284 const UserList& UserManagerImpl::GetLRULoggedInUsers() {
285 // If there is no user logged in, we return the active user as the only one.
286 if (lru_logged_in_users_.empty() && active_user_) {
287 temp_single_logged_in_users_.clear();
288 temp_single_logged_in_users_.insert(temp_single_logged_in_users_.begin(),
289 active_user_);
290 return temp_single_logged_in_users_;
292 return lru_logged_in_users_;
295 UserList UserManagerImpl::GetUnlockUsers() const {
296 UserList unlock_users;
297 if (primary_user_)
298 unlock_users.push_back(primary_user_);
299 return unlock_users;
302 const std::string& UserManagerImpl::GetOwnerEmail() {
303 return owner_email_;
306 void UserManagerImpl::UserLoggedIn(const std::string& user_id,
307 const std::string& username_hash,
308 bool browser_restart) {
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
311 if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
312 DCHECK(!IsUserLoggedIn());
314 User* user = FindUserInListAndModify(user_id);
315 if (active_user_ && user) {
316 user->set_is_logged_in(true);
317 user->set_username_hash(username_hash);
318 logged_in_users_.push_back(user);
319 lru_logged_in_users_.push_back(user);
320 // Reset the new user flag if the user already exists.
321 is_current_user_new_ = false;
322 // Set active user wallpaper back.
323 WallpaperManager::Get()->SetUserWallpaper(active_user_->email());
324 NotifyUserAddedToSession(user);
325 return;
328 policy::DeviceLocalAccount::Type device_local_account_type;
329 if (user_id == UserManager::kGuestUserName) {
330 GuestUserLoggedIn();
331 } else if (user_id == UserManager::kRetailModeUserName) {
332 RetailModeUserLoggedIn();
333 } else if (policy::IsDeviceLocalAccountUser(user_id,
334 &device_local_account_type) &&
335 device_local_account_type ==
336 policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
337 KioskAppLoggedIn(user_id);
338 } else {
339 EnsureUsersLoaded();
341 if (user && user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
342 PublicAccountUserLoggedIn(user);
343 } else if ((user && user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
344 (!user && gaia::ExtractDomainName(user_id) ==
345 UserManager::kLocallyManagedUserDomain)) {
346 LocallyManagedUserLoggedIn(user_id);
347 } else if (browser_restart && user_id == g_browser_process->local_state()->
348 GetString(kPublicAccountPendingDataRemoval)) {
349 PublicAccountUserLoggedIn(User::CreatePublicAccountUser(user_id));
350 } else if (user_id != owner_email_ && !user &&
351 (AreEphemeralUsersEnabled() || browser_restart)) {
352 RegularUserLoggedInAsEphemeral(user_id);
353 } else {
354 RegularUserLoggedIn(user_id);
357 // Initialize the session length limiter and start it only if
358 // session limit is defined by the policy.
359 session_length_limiter_.reset(new SessionLengthLimiter(NULL,
360 browser_restart));
362 DCHECK(active_user_);
363 active_user_->set_is_logged_in(true);
364 active_user_->set_is_active(true);
365 active_user_->set_username_hash(username_hash);
367 // Place user who just signed in to the top of the logged in users.
368 logged_in_users_.insert(logged_in_users_.begin(), active_user_);
369 SetLRUUser(active_user_);
371 if (!primary_user_) {
372 primary_user_ = active_user_;
373 if (primary_user_->GetType() == User::USER_TYPE_REGULAR)
374 SendRegularUserLoginMetrics(user_id);
377 UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType",
378 active_user_->GetType(), User::NUM_USER_TYPES);
380 g_browser_process->local_state()->SetString(kLastLoggedInRegularUser,
381 (active_user_->GetType() == User::USER_TYPE_REGULAR) ? user_id : "");
383 NotifyOnLogin();
386 void UserManagerImpl::SwitchActiveUser(const std::string& user_id) {
387 if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kMultiProfiles))
388 return;
390 User* user = FindUserAndModify(user_id);
391 if (!user) {
392 NOTREACHED() << "Switching to a non-existing user";
393 return;
395 if (user == active_user_) {
396 NOTREACHED() << "Switching to a user who is already active";
397 return;
399 if (!user->is_logged_in()) {
400 NOTREACHED() << "Switching to a user that is not logged in";
401 return;
403 if (user->GetType() != User::USER_TYPE_REGULAR) {
404 NOTREACHED() << "Switching to a non-regular user";
405 return;
407 if (user->username_hash().empty()) {
408 NOTREACHED() << "Switching to a user that doesn't have username_hash set";
409 return;
412 DCHECK(active_user_);
413 active_user_->set_is_active(false);
414 user->set_is_active(true);
415 active_user_ = user;
417 // Move the user to the front.
418 SetLRUUser(active_user_);
420 NotifyActiveUserHashChanged(active_user_->username_hash());
421 NotifyActiveUserChanged(active_user_);
424 void UserManagerImpl::RestoreActiveSessions() {
425 DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
426 base::Bind(&UserManagerImpl::OnRestoreActiveSessions,
427 base::Unretained(this)));
430 void UserManagerImpl::SessionStarted() {
431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
432 session_started_ = true;
433 UpdateLoginState();
434 content::NotificationService::current()->Notify(
435 chrome::NOTIFICATION_SESSION_STARTED,
436 content::Source<UserManager>(this),
437 content::Details<const User>(active_user_));
438 if (is_current_user_new_) {
439 // Make sure that the new user's data is persisted to Local State.
440 g_browser_process->local_state()->CommitPendingWrite();
444 void UserManagerImpl::RemoveUser(const std::string& user_id,
445 RemoveUserDelegate* delegate) {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
448 const User* user = FindUser(user_id);
449 if (!user || (user->GetType() != User::USER_TYPE_REGULAR &&
450 user->GetType() != User::USER_TYPE_LOCALLY_MANAGED))
451 return;
453 // Sanity check: we must not remove single user. This check may seem
454 // redundant at a first sight because this single user must be an owner and
455 // we perform special check later in order not to remove an owner. However
456 // due to non-instant nature of ownership assignment this later check may
457 // sometimes fail. See http://crosbug.com/12723
458 if (users_.size() < 2)
459 return;
461 // Sanity check: do not allow any of the the logged in users to be removed.
462 for (UserList::const_iterator it = logged_in_users_.begin();
463 it != logged_in_users_.end(); ++it) {
464 if ((*it)->email() == user_id)
465 return;
468 RemoveUserInternal(user_id, delegate);
471 void UserManagerImpl::RemoveUserInternal(const std::string& user_email,
472 RemoveUserDelegate* delegate) {
473 CrosSettings* cros_settings = CrosSettings::Get();
475 // Ensure the value of owner email has been fetched.
476 if (CrosSettingsProvider::TRUSTED != cros_settings->PrepareTrustedValues(
477 base::Bind(&UserManagerImpl::RemoveUserInternal,
478 base::Unretained(this),
479 user_email, delegate))) {
480 // Value of owner email is not fetched yet. RemoveUserInternal will be
481 // called again after fetch completion.
482 return;
484 std::string owner;
485 cros_settings->GetString(kDeviceOwner, &owner);
486 if (user_email == owner) {
487 // Owner is not allowed to be removed from the device.
488 return;
490 RemoveNonOwnerUserInternal(user_email, delegate);
493 void UserManagerImpl::RemoveNonOwnerUserInternal(const std::string& user_email,
494 RemoveUserDelegate* delegate) {
495 if (delegate)
496 delegate->OnBeforeUserRemoved(user_email);
497 RemoveUserFromList(user_email);
498 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
499 user_email, base::Bind(&OnRemoveUserComplete, user_email));
501 if (delegate)
502 delegate->OnUserRemoved(user_email);
505 void UserManagerImpl::RemoveUserFromList(const std::string& user_id) {
506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
507 RemoveNonCryptohomeData(user_id);
508 if (user_loading_stage_ == STAGE_LOADED) {
509 User* user = RemoveRegularOrLocallyManagedUserFromList(user_id);
510 delete user;
511 } else if (user_loading_stage_ == STAGE_LOADING) {
512 DCHECK(gaia::ExtractDomainName(user_id) ==
513 UserManager::kLocallyManagedUserDomain);
514 // Special case, removing partially-constructed supervised user during user
515 // list loading.
516 ListPrefUpdate users_update(g_browser_process->local_state(),
517 kRegularUsers);
518 users_update->Remove(base::StringValue(user_id), NULL);
519 } else {
520 NOTREACHED() << "Users are not loaded yet.";
521 return;
523 // Make sure that new data is persisted to Local State.
524 g_browser_process->local_state()->CommitPendingWrite();
527 bool UserManagerImpl::IsKnownUser(const std::string& user_id) const {
528 return FindUser(user_id) != NULL;
531 const User* UserManagerImpl::FindUser(const std::string& user_id) const {
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
533 if (active_user_ && active_user_->email() == user_id)
534 return active_user_;
535 return FindUserInList(user_id);
538 User* UserManagerImpl::FindUserAndModify(const std::string& user_id) {
539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
540 if (active_user_ && active_user_->email() == user_id)
541 return active_user_;
542 return FindUserInListAndModify(user_id);
545 const User* UserManagerImpl::GetLoggedInUser() const {
546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
547 return active_user_;
550 User* UserManagerImpl::GetLoggedInUser() {
551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
552 return active_user_;
555 const User* UserManagerImpl::GetActiveUser() const {
556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
557 return active_user_;
560 User* UserManagerImpl::GetActiveUser() {
561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562 return active_user_;
565 const User* UserManagerImpl::GetPrimaryUser() const {
566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567 return primary_user_;
570 User* UserManagerImpl::GetUserByProfile(Profile* profile) const {
571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
572 if (ProfileHelper::IsSigninProfile(profile))
573 return NULL;
575 if (IsMultipleProfilesAllowed()) {
576 const std::string username_hash =
577 ProfileHelper::GetUserIdHashFromProfile(profile);
578 const UserList& users = GetUsers();
579 const UserList::const_iterator pos = std::find_if(
580 users.begin(), users.end(), UserHashMatcher(username_hash));
581 return (pos != users.end()) ? *pos : NULL;
583 return active_user_;
586 Profile* UserManagerImpl::GetProfileByUser(const User* user) const {
587 if (IsMultipleProfilesAllowed())
588 return ProfileHelper::GetProfileByUserIdHash(user->username_hash());
589 return g_browser_process->profile_manager()->GetDefaultProfile();
592 void UserManagerImpl::SaveUserOAuthStatus(
593 const std::string& user_id,
594 User::OAuthTokenStatus oauth_token_status) {
595 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
597 DVLOG(1) << "Saving user OAuth token status in Local State";
598 User* user = FindUserAndModify(user_id);
599 if (user)
600 user->set_oauth_token_status(oauth_token_status);
602 GetUserFlow(user_id)->HandleOAuthTokenStatusChange(oauth_token_status);
604 // Do not update local store if data stored or cached outside the user's
605 // cryptohome is to be treated as ephemeral.
606 if (IsUserNonCryptohomeDataEphemeral(user_id))
607 return;
609 PrefService* local_state = g_browser_process->local_state();
611 DictionaryPrefUpdate oauth_status_update(local_state, kUserOAuthTokenStatus);
612 oauth_status_update->SetWithoutPathExpansion(user_id,
613 new base::FundamentalValue(static_cast<int>(oauth_token_status)));
616 User::OAuthTokenStatus UserManagerImpl::LoadUserOAuthStatus(
617 const std::string& user_id) const {
618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
620 PrefService* local_state = g_browser_process->local_state();
621 const DictionaryValue* prefs_oauth_status =
622 local_state->GetDictionary(kUserOAuthTokenStatus);
623 int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
624 if (prefs_oauth_status &&
625 prefs_oauth_status->GetIntegerWithoutPathExpansion(
626 user_id, &oauth_token_status)) {
627 User::OAuthTokenStatus result =
628 static_cast<User::OAuthTokenStatus>(oauth_token_status);
629 if (result == User::OAUTH2_TOKEN_STATUS_INVALID)
630 GetUserFlow(user_id)->HandleOAuthTokenStatusChange(result);
631 return result;
633 return User::OAUTH_TOKEN_STATUS_UNKNOWN;
636 void UserManagerImpl::SaveUserDisplayName(const std::string& user_id,
637 const base::string16& display_name) {
638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
640 if (User* user = FindUserAndModify(user_id)) {
641 user->set_display_name(display_name);
643 // Do not update local store if data stored or cached outside the user's
644 // cryptohome is to be treated as ephemeral.
645 if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
646 PrefService* local_state = g_browser_process->local_state();
648 DictionaryPrefUpdate display_name_update(local_state, kUserDisplayName);
649 display_name_update->SetWithoutPathExpansion(
650 user_id,
651 new base::StringValue(display_name));
653 supervised_user_manager_->UpdateManagerName(user_id, display_name);
658 string16 UserManagerImpl::GetUserDisplayName(
659 const std::string& user_id) const {
660 const User* user = FindUser(user_id);
661 return user ? user->display_name() : base::string16();
664 void UserManagerImpl::SaveUserDisplayEmail(const std::string& user_id,
665 const std::string& display_email) {
666 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
668 User* user = FindUserAndModify(user_id);
669 if (!user)
670 return; // Ignore if there is no such user.
672 user->set_display_email(display_email);
674 // Do not update local store if data stored or cached outside the user's
675 // cryptohome is to be treated as ephemeral.
676 if (IsUserNonCryptohomeDataEphemeral(user_id))
677 return;
679 PrefService* local_state = g_browser_process->local_state();
681 DictionaryPrefUpdate display_email_update(local_state, kUserDisplayEmail);
682 display_email_update->SetWithoutPathExpansion(
683 user_id,
684 new base::StringValue(display_email));
687 std::string UserManagerImpl::GetUserDisplayEmail(
688 const std::string& user_id) const {
689 const User* user = FindUser(user_id);
690 return user ? user->display_email() : user_id;
693 void UserManagerImpl::UpdateUserAccountData(
694 const std::string& user_id,
695 const UserAccountData& account_data) {
696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
698 SaveUserDisplayName(user_id, account_data.display_name());
700 if (User* user = FindUserAndModify(user_id)) {
701 base::string16 given_name = account_data.given_name();
702 user->set_given_name(given_name);
703 if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
704 PrefService* local_state = g_browser_process->local_state();
706 DictionaryPrefUpdate given_name_update(local_state, kUserGivenName);
707 given_name_update->SetWithoutPathExpansion(
708 user_id,
709 new base::StringValue(given_name));
713 UpdateUserAccountLocale(user_id, account_data.locale());
716 // TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
717 // the Google user profile.
719 // Returns true if callback will be called.
720 bool UserManagerImpl::RespectLocalePreference(
721 Profile* profile,
722 const User* user,
723 scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
724 if (g_browser_process == NULL)
725 return false;
726 if ((user == NULL) || (user != GetPrimaryUser()) ||
727 (!user->is_profile_created()))
728 return false;
730 // In case of Multi Profile mode we don't apply profile locale because it is
731 // unsafe.
732 if (GetLoggedInUsers().size() != 1)
733 return false;
734 const PrefService* prefs = profile->GetPrefs();
735 if (prefs == NULL)
736 return false;
738 std::string pref_locale;
739 const std::string pref_app_locale =
740 prefs->GetString(prefs::kApplicationLocale);
741 const std::string pref_bkup_locale =
742 prefs->GetString(prefs::kApplicationLocaleBackup);
744 pref_locale = pref_app_locale;
745 if (pref_locale.empty())
746 pref_locale = pref_bkup_locale;
748 const std::string* account_locale = NULL;
749 if (pref_locale.empty() && user->has_gaia_account()) {
750 if (user->GetAccountLocale() == NULL)
751 return false; // wait until Account profile is loaded.
752 account_locale = user->GetAccountLocale();
753 pref_locale = *account_locale;
755 const std::string global_app_locale =
756 g_browser_process->GetApplicationLocale();
757 if (pref_locale.empty())
758 pref_locale = global_app_locale;
759 DCHECK(!pref_locale.empty());
760 LOG(WARNING) << "RespectLocalePreference: "
761 << "app_locale='" << pref_app_locale << "', "
762 << "bkup_locale='" << pref_bkup_locale << "', "
763 << (account_locale != NULL
764 ? (std::string("account_locale='") + (*account_locale) +
765 "'. ")
766 : (std::string("account_locale - unused. ")))
767 << " Selected '" << pref_locale << "'";
768 profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
769 // Here we don't enable keyboard layouts. Input methods are set up when
770 // the user first logs in. Then the user may customize the input methods.
771 // Hence changing input methods here, just because the user's UI language
772 // is different from the login screen UI language, is not desirable. Note
773 // that input method preferences are synced, so users can use their
774 // farovite input methods as soon as the preferences are synced.
775 locale_util::SwitchLanguage(pref_locale, false, callback.Pass());
777 return true;
780 void UserManagerImpl::Observe(int type,
781 const content::NotificationSource& source,
782 const content::NotificationDetails& details) {
783 switch (type) {
784 case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED:
785 if (!device_local_account_policy_service_) {
786 device_local_account_policy_service_ =
787 g_browser_process->browser_policy_connector()->
788 GetDeviceLocalAccountPolicyService();
789 if (device_local_account_policy_service_)
790 device_local_account_policy_service_->AddObserver(this);
792 RetrieveTrustedDevicePolicies();
793 UpdateOwnership();
794 break;
795 case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED:
796 if (IsUserLoggedIn() &&
797 !IsLoggedInAsGuest() &&
798 !IsLoggedInAsKioskApp()) {
799 Profile* profile = content::Details<Profile>(details).ptr();
800 if (!profile->IsOffTheRecord()) {
801 AuthSyncObserver* sync_observer =
802 AuthSyncObserverFactory::GetInstance()->GetForProfile(profile);
803 sync_observer->StartObserving();
804 multi_profile_user_controller_->StartObserving(profile);
805 multi_profile_first_run_notification_->UserProfilePrepared(profile);
808 break;
809 case chrome::NOTIFICATION_PROFILE_CREATED: {
810 Profile* profile = content::Source<Profile>(source).ptr();
811 User* user = GetUserByProfile(profile);
812 if (user != NULL)
813 user->set_profile_is_created();
815 break;
817 default:
818 NOTREACHED();
822 void UserManagerImpl::OnPolicyUpdated(const std::string& user_id) {
823 UpdatePublicAccountDisplayName(user_id);
824 NotifyUserListChanged();
827 void UserManagerImpl::OnDeviceLocalAccountsChanged() {
828 // No action needed here, changes to the list of device-local accounts get
829 // handled via the kAccountsPrefDeviceLocalAccounts device setting observer.
832 bool UserManagerImpl::IsCurrentUserOwner() const {
833 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
834 base::AutoLock lk(is_current_user_owner_lock_);
835 return is_current_user_owner_;
838 void UserManagerImpl::SetCurrentUserIsOwner(bool is_current_user_owner) {
839 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
841 base::AutoLock lk(is_current_user_owner_lock_);
842 is_current_user_owner_ = is_current_user_owner;
844 UpdateLoginState();
847 bool UserManagerImpl::IsCurrentUserNew() const {
848 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
849 return is_current_user_new_;
852 bool UserManagerImpl::IsCurrentUserNonCryptohomeDataEphemeral() const {
853 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
854 return IsUserLoggedIn() &&
855 IsUserNonCryptohomeDataEphemeral(GetLoggedInUser()->email());
858 bool UserManagerImpl::CanCurrentUserLock() const {
859 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
860 return IsUserLoggedIn() && active_user_->can_lock();
863 bool UserManagerImpl::IsUserLoggedIn() const {
864 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
865 return active_user_;
868 bool UserManagerImpl::IsLoggedInAsRegularUser() const {
869 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
870 return IsUserLoggedIn() &&
871 active_user_->GetType() == User::USER_TYPE_REGULAR;
874 bool UserManagerImpl::IsLoggedInAsDemoUser() const {
875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
876 return IsUserLoggedIn() &&
877 active_user_->GetType() == User::USER_TYPE_RETAIL_MODE;
880 bool UserManagerImpl::IsLoggedInAsPublicAccount() const {
881 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
882 return IsUserLoggedIn() &&
883 active_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
886 bool UserManagerImpl::IsLoggedInAsGuest() const {
887 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
888 return IsUserLoggedIn() &&
889 active_user_->GetType() == User::USER_TYPE_GUEST;
892 bool UserManagerImpl::IsLoggedInAsLocallyManagedUser() const {
893 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
894 return IsUserLoggedIn() &&
895 active_user_->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
898 bool UserManagerImpl::IsLoggedInAsKioskApp() const {
899 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
900 return IsUserLoggedIn() &&
901 active_user_->GetType() == User::USER_TYPE_KIOSK_APP;
904 bool UserManagerImpl::IsLoggedInAsStub() const {
905 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
906 return IsUserLoggedIn() && active_user_->email() == kStubUser;
909 bool UserManagerImpl::IsSessionStarted() const {
910 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
911 return session_started_;
914 bool UserManagerImpl::UserSessionsRestored() const {
915 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
916 return user_sessions_restored_;
919 bool UserManagerImpl::HasBrowserRestarted() const {
920 CommandLine* command_line = CommandLine::ForCurrentProcess();
921 return base::SysInfo::IsRunningOnChromeOS() &&
922 command_line->HasSwitch(switches::kLoginUser) &&
923 !command_line->HasSwitch(switches::kLoginPassword);
926 bool UserManagerImpl::IsUserNonCryptohomeDataEphemeral(
927 const std::string& user_id) const {
928 // Data belonging to the guest, retail mode and stub users is always
929 // ephemeral.
930 if (user_id == UserManager::kGuestUserName ||
931 user_id == UserManager::kRetailModeUserName ||
932 user_id == kStubUser) {
933 return true;
936 // Data belonging to the owner, anyone found on the user list and obsolete
937 // public accounts whose data has not been removed yet is not ephemeral.
938 if (user_id == owner_email_ || UserExistsInList(user_id) ||
939 user_id == g_browser_process->local_state()->
940 GetString(kPublicAccountPendingDataRemoval)) {
941 return false;
944 // Data belonging to the currently logged-in user is ephemeral when:
945 // a) The user logged into a regular account while the ephemeral users policy
946 // was enabled.
947 // - or -
948 // b) The user logged into any other account type.
949 if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) &&
950 (is_current_user_ephemeral_regular_user_ || !IsLoggedInAsRegularUser())) {
951 return true;
954 // Data belonging to any other user is ephemeral when:
955 // a) Going through the regular login flow and the ephemeral users policy is
956 // enabled.
957 // - or -
958 // b) The browser is restarting after a crash.
959 return AreEphemeralUsersEnabled() || HasBrowserRestarted();
962 void UserManagerImpl::AddObserver(UserManager::Observer* obs) {
963 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
964 observer_list_.AddObserver(obs);
967 void UserManagerImpl::RemoveObserver(UserManager::Observer* obs) {
968 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
969 observer_list_.RemoveObserver(obs);
972 void UserManagerImpl::AddSessionStateObserver(
973 UserManager::UserSessionStateObserver* obs) {
974 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
975 session_state_observer_list_.AddObserver(obs);
978 void UserManagerImpl::RemoveSessionStateObserver(
979 UserManager::UserSessionStateObserver* obs) {
980 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
981 session_state_observer_list_.RemoveObserver(obs);
984 void UserManagerImpl::NotifyLocalStateChanged() {
985 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
986 FOR_EACH_OBSERVER(UserManager::Observer, observer_list_,
987 LocalStateChanged(this));
990 void UserManagerImpl::OnProfilePrepared(Profile* profile) {
991 LoginUtils::Get()->DoBrowserLaunch(profile,
992 NULL); // host_, not needed here
994 if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestName)) {
995 // Did not log in (we crashed or are debugging), need to restore Sync.
996 // TODO(nkostylev): Make sure that OAuth state is restored correctly for all
997 // users once it is fully multi-profile aware. http://crbug.com/238987
998 // For now if we have other user pending sessions they'll override OAuth
999 // session restore for previous users.
1000 LoginUtils::Get()->RestoreAuthenticationSession(profile);
1003 // Restore other user sessions if any.
1004 RestorePendingUserSessions();
1007 void UserManagerImpl::EnsureUsersLoaded() {
1008 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1009 if (!g_browser_process || !g_browser_process->local_state())
1010 return;
1012 if (user_loading_stage_ != STAGE_NOT_LOADED)
1013 return;
1014 user_loading_stage_ = STAGE_LOADING;
1015 // Clean up user list first. All code down the path should be synchronous,
1016 // so that local state after transaction rollback is in consistent state.
1017 // This process also should not trigger EnsureUsersLoaded again.
1018 if (supervised_user_manager_->HasFailedUserCreationTransaction())
1019 supervised_user_manager_->RollbackUserCreationTransaction();
1021 PrefService* local_state = g_browser_process->local_state();
1022 const ListValue* prefs_regular_users = local_state->GetList(kRegularUsers);
1023 const ListValue* prefs_public_accounts =
1024 local_state->GetList(kPublicAccounts);
1025 const DictionaryValue* prefs_display_names =
1026 local_state->GetDictionary(kUserDisplayName);
1027 const DictionaryValue* prefs_given_names =
1028 local_state->GetDictionary(kUserGivenName);
1029 const DictionaryValue* prefs_display_emails =
1030 local_state->GetDictionary(kUserDisplayEmail);
1032 // Load regular users and locally managed users.
1033 std::vector<std::string> regular_users;
1034 std::set<std::string> regular_users_set;
1035 ParseUserList(*prefs_regular_users, std::set<std::string>(),
1036 &regular_users, &regular_users_set);
1037 for (std::vector<std::string>::const_iterator it = regular_users.begin();
1038 it != regular_users.end(); ++it) {
1039 User* user = NULL;
1040 const std::string domain = gaia::ExtractDomainName(*it);
1041 if (domain == UserManager::kLocallyManagedUserDomain)
1042 user = User::CreateLocallyManagedUser(*it);
1043 else
1044 user = User::CreateRegularUser(*it);
1045 user->set_oauth_token_status(LoadUserOAuthStatus(*it));
1046 users_.push_back(user);
1048 base::string16 display_name;
1049 if (prefs_display_names->GetStringWithoutPathExpansion(*it,
1050 &display_name)) {
1051 user->set_display_name(display_name);
1054 base::string16 given_name;
1055 if (prefs_given_names->GetStringWithoutPathExpansion(*it, &given_name)) {
1056 user->set_given_name(given_name);
1059 std::string display_email;
1060 if (prefs_display_emails->GetStringWithoutPathExpansion(*it,
1061 &display_email)) {
1062 user->set_display_email(display_email);
1066 // Load public accounts.
1067 std::vector<std::string> public_accounts;
1068 std::set<std::string> public_accounts_set;
1069 ParseUserList(*prefs_public_accounts, regular_users_set,
1070 &public_accounts, &public_accounts_set);
1071 for (std::vector<std::string>::const_iterator it = public_accounts.begin();
1072 it != public_accounts.end(); ++it) {
1073 users_.push_back(User::CreatePublicAccountUser(*it));
1074 UpdatePublicAccountDisplayName(*it);
1076 user_loading_stage_ = STAGE_LOADED;
1078 user_image_manager_->LoadUserImages(users_);
1081 void UserManagerImpl::RetrieveTrustedDevicePolicies() {
1082 ephemeral_users_enabled_ = false;
1083 owner_email_ = "";
1085 // Schedule a callback if device policy has not yet been verified.
1086 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
1087 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies,
1088 base::Unretained(this)))) {
1089 return;
1092 cros_settings_->GetBoolean(kAccountsPrefEphemeralUsersEnabled,
1093 &ephemeral_users_enabled_);
1094 cros_settings_->GetString(kDeviceOwner, &owner_email_);
1096 EnsureUsersLoaded();
1098 bool changed = UpdateAndCleanUpPublicAccounts(
1099 policy::GetDeviceLocalAccounts(cros_settings_));
1101 // If ephemeral users are enabled and we are on the login screen, take this
1102 // opportunity to clean up by removing all regular users except the owner.
1103 if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
1104 ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
1105 kRegularUsers);
1106 prefs_users_update->Clear();
1107 for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
1108 const std::string user_email = (*it)->email();
1109 if ((*it)->GetType() == User::USER_TYPE_REGULAR &&
1110 user_email != owner_email_) {
1111 RemoveNonCryptohomeData(user_email);
1112 delete *it;
1113 it = users_.erase(it);
1114 changed = true;
1115 } else {
1116 if ((*it)->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
1117 prefs_users_update->Append(new base::StringValue(user_email));
1118 ++it;
1123 if (changed)
1124 NotifyUserListChanged();
1127 bool UserManagerImpl::AreEphemeralUsersEnabled() const {
1128 return ephemeral_users_enabled_ &&
1129 (g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ||
1130 !owner_email_.empty());
1133 UserList& UserManagerImpl::GetUsersAndModify() {
1134 EnsureUsersLoaded();
1135 return users_;
1138 const User* UserManagerImpl::FindUserInList(const std::string& user_id) const {
1139 const UserList& users = GetUsers();
1140 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1141 if ((*it)->email() == user_id)
1142 return *it;
1144 return NULL;
1147 const bool UserManagerImpl::UserExistsInList(const std::string& user_id) const {
1148 PrefService* local_state = g_browser_process->local_state();
1149 const ListValue* user_list = local_state->GetList(kRegularUsers);
1150 for (size_t i = 0; i < user_list->GetSize(); ++i) {
1151 std::string email;
1152 if (user_list->GetString(i, &email) && (user_id == email))
1153 return true;
1155 return false;
1158 User* UserManagerImpl::FindUserInListAndModify(const std::string& user_id) {
1159 UserList& users = GetUsersAndModify();
1160 for (UserList::iterator it = users.begin(); it != users.end(); ++it) {
1161 if ((*it)->email() == user_id)
1162 return *it;
1164 return NULL;
1167 void UserManagerImpl::GuestUserLoggedIn() {
1168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1169 active_user_ = User::CreateGuestUser();
1170 // TODO(nkostylev): Add support for passing guest session cryptohome
1171 // mount point. Legacy (--login-profile) value will be used for now.
1172 // http://crosbug.com/230859
1173 active_user_->SetStubImage(User::kInvalidImageIndex, false);
1174 // Initializes wallpaper after active_user_ is set.
1175 WallpaperManager::Get()->SetInitialUserWallpaper(UserManager::kGuestUserName,
1176 false);
1179 void UserManagerImpl::AddUserRecord(User* user) {
1180 // Add the user to the front of the user list.
1181 ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
1182 kRegularUsers);
1183 prefs_users_update->Insert(0, new base::StringValue(user->email()));
1184 users_.insert(users_.begin(), user);
1187 void UserManagerImpl::RegularUserLoggedIn(const std::string& user_id) {
1188 // Remove the user from the user list.
1189 active_user_ = RemoveRegularOrLocallyManagedUserFromList(user_id);
1191 // If the user was not found on the user list, create a new user.
1192 is_current_user_new_ = !active_user_;
1193 if (!active_user_) {
1194 active_user_ = User::CreateRegularUser(user_id);
1195 active_user_->set_oauth_token_status(LoadUserOAuthStatus(user_id));
1196 SaveUserDisplayName(active_user_->email(),
1197 UTF8ToUTF16(active_user_->GetAccountName(true)));
1198 WallpaperManager::Get()->SetInitialUserWallpaper(user_id, true);
1201 AddUserRecord(active_user_);
1203 user_image_manager_->UserLoggedIn(user_id, is_current_user_new_, false);
1205 WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
1207 default_pinned_apps_field_trial::SetupForUser(user_id, is_current_user_new_);
1209 // Make sure that new data is persisted to Local State.
1210 g_browser_process->local_state()->CommitPendingWrite();
1213 void UserManagerImpl::RegularUserLoggedInAsEphemeral(
1214 const std::string& user_id) {
1215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1216 is_current_user_new_ = true;
1217 is_current_user_ephemeral_regular_user_ = true;
1218 active_user_ = User::CreateRegularUser(user_id);
1219 user_image_manager_->UserLoggedIn(user_id, is_current_user_new_, false);
1220 WallpaperManager::Get()->SetInitialUserWallpaper(user_id, false);
1223 void UserManagerImpl::LocallyManagedUserLoggedIn(
1224 const std::string& user_id) {
1225 // TODO(nkostylev): Refactor, share code with RegularUserLoggedIn().
1227 // Remove the user from the user list.
1228 active_user_ = RemoveRegularOrLocallyManagedUserFromList(user_id);
1229 // If the user was not found on the user list, create a new user.
1230 if (!active_user_) {
1231 is_current_user_new_ = true;
1232 active_user_ = User::CreateLocallyManagedUser(user_id);
1233 // Leaving OAuth token status at the default state = unknown.
1234 WallpaperManager::Get()->SetInitialUserWallpaper(user_id, true);
1235 } else {
1236 if (supervised_user_manager_->CheckForFirstRun(user_id)) {
1237 is_current_user_new_ = true;
1238 WallpaperManager::Get()->SetInitialUserWallpaper(user_id, true);
1239 } else {
1240 is_current_user_new_ = false;
1244 // Add the user to the front of the user list.
1245 ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
1246 kRegularUsers);
1247 prefs_users_update->Insert(0, new base::StringValue(user_id));
1248 users_.insert(users_.begin(), active_user_);
1250 // Now that user is in the list, save display name.
1251 if (is_current_user_new_) {
1252 SaveUserDisplayName(active_user_->email(),
1253 active_user_->GetDisplayName());
1256 user_image_manager_->UserLoggedIn(user_id, is_current_user_new_, true);
1257 WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
1259 // Make sure that new data is persisted to Local State.
1260 g_browser_process->local_state()->CommitPendingWrite();
1263 void UserManagerImpl::PublicAccountUserLoggedIn(User* user) {
1264 is_current_user_new_ = true;
1265 active_user_ = user;
1266 // The UserImageManager chooses a random avatar picture when a user logs in
1267 // for the first time. Tell the UserImageManager that this user is not new to
1268 // prevent the avatar from getting changed.
1269 user_image_manager_->UserLoggedIn(user->email(), false, true);
1270 WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded();
1273 void UserManagerImpl::KioskAppLoggedIn(const std::string& app_id) {
1274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1275 policy::DeviceLocalAccount::Type device_local_account_type;
1276 DCHECK(policy::IsDeviceLocalAccountUser(app_id,
1277 &device_local_account_type));
1278 DCHECK_EQ(policy::DeviceLocalAccount::TYPE_KIOSK_APP,
1279 device_local_account_type);
1281 active_user_ = User::CreateKioskAppUser(app_id);
1282 active_user_->SetStubImage(User::kInvalidImageIndex, false);
1283 WallpaperManager::Get()->SetInitialUserWallpaper(app_id, false);
1285 // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like
1286 // the kiosk_app_id in these objects, removing the need to re-parse the
1287 // device-local account list here to extract the kiosk_app_id.
1288 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
1289 policy::GetDeviceLocalAccounts(cros_settings_);
1290 const policy::DeviceLocalAccount* account = NULL;
1291 for (std::vector<policy::DeviceLocalAccount>::const_iterator
1292 it = device_local_accounts.begin();
1293 it != device_local_accounts.end(); ++it) {
1294 if (it->user_id == app_id) {
1295 account = &*it;
1296 break;
1299 std::string kiosk_app_id;
1300 if (account) {
1301 kiosk_app_id = account->kiosk_app_id;
1302 } else {
1303 LOG(ERROR) << "Logged into nonexistent kiosk-app account: " << app_id;
1304 NOTREACHED();
1307 CommandLine* command_line = CommandLine::ForCurrentProcess();
1308 command_line->AppendSwitch(::switches::kForceAppMode);
1309 command_line->AppendSwitchASCII(::switches::kAppId, kiosk_app_id);
1311 // Disable window animation since kiosk app runs in a single full screen
1312 // window and window animation causes start-up janks.
1313 command_line->AppendSwitch(
1314 views::corewm::switches::kWindowAnimationsDisabled);
1317 void UserManagerImpl::RetailModeUserLoggedIn() {
1318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1319 is_current_user_new_ = true;
1320 active_user_ = User::CreateRetailModeUser();
1321 user_image_manager_->UserLoggedIn(UserManager::kRetailModeUserName,
1322 is_current_user_new_,
1323 true);
1324 WallpaperManager::Get()->SetInitialUserWallpaper(
1325 UserManager::kRetailModeUserName, false);
1328 void UserManagerImpl::NotifyOnLogin() {
1329 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1330 NotifyActiveUserHashChanged(active_user_->username_hash());
1331 NotifyActiveUserChanged(active_user_);
1333 UpdateLoginState();
1334 // TODO(nkostylev): Deprecate this notification in favor of
1335 // ActiveUserChanged() observer call.
1336 content::NotificationService::current()->Notify(
1337 chrome::NOTIFICATION_LOGIN_USER_CHANGED,
1338 content::Source<UserManager>(this),
1339 content::Details<const User>(active_user_));
1341 // Owner must be first user in session. DeviceSettingsService can't deal with
1342 // multiple user and will mix up ownership, crbug.com/230018.
1343 if (GetLoggedInUsers().size() == 1) {
1344 // Indicate to DeviceSettingsService that the owner key may have become
1345 // available.
1346 DeviceSettingsService::Get()->SetUsername(active_user_->email());
1350 void UserManagerImpl::UpdateOwnership() {
1351 bool is_owner = DeviceSettingsService::Get()->HasPrivateOwnerKey();
1352 VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner");
1354 SetCurrentUserIsOwner(is_owner);
1357 void UserManagerImpl::RemoveNonCryptohomeData(const std::string& user_id) {
1358 WallpaperManager::Get()->RemoveUserWallpaperInfo(user_id);
1359 user_image_manager_->DeleteUserImage(user_id);
1361 PrefService* prefs = g_browser_process->local_state();
1362 DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
1363 int oauth_status;
1364 prefs_oauth_update->GetIntegerWithoutPathExpansion(user_id, &oauth_status);
1365 prefs_oauth_update->RemoveWithoutPathExpansion(user_id, NULL);
1367 DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName);
1368 prefs_display_name_update->RemoveWithoutPathExpansion(user_id, NULL);
1370 DictionaryPrefUpdate prefs_given_name_update(prefs, kUserGivenName);
1371 prefs_given_name_update->RemoveWithoutPathExpansion(user_id, NULL);
1373 DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
1374 prefs_display_email_update->RemoveWithoutPathExpansion(user_id, NULL);
1376 supervised_user_manager_->RemoveNonCryptohomeData(user_id);
1378 multi_profile_user_controller_->RemoveCachedValue(user_id);
1381 User* UserManagerImpl::RemoveRegularOrLocallyManagedUserFromList(
1382 const std::string& user_id) {
1383 ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
1384 kRegularUsers);
1385 prefs_users_update->Clear();
1386 User* user = NULL;
1387 for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
1388 const std::string user_email = (*it)->email();
1389 if (user_email == user_id) {
1390 user = *it;
1391 it = users_.erase(it);
1392 } else {
1393 if ((*it)->GetType() == User::USER_TYPE_REGULAR ||
1394 (*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) {
1395 prefs_users_update->Append(new base::StringValue(user_email));
1397 ++it;
1400 return user;
1403 void UserManagerImpl::CleanUpPublicAccountNonCryptohomeDataPendingRemoval() {
1404 PrefService* local_state = g_browser_process->local_state();
1405 const std::string public_account_pending_data_removal =
1406 local_state->GetString(kPublicAccountPendingDataRemoval);
1407 if (public_account_pending_data_removal.empty() ||
1408 (IsUserLoggedIn() &&
1409 public_account_pending_data_removal == GetActiveUser()->email())) {
1410 return;
1413 RemoveNonCryptohomeData(public_account_pending_data_removal);
1414 local_state->ClearPref(kPublicAccountPendingDataRemoval);
1417 void UserManagerImpl::CleanUpPublicAccountNonCryptohomeData(
1418 const std::vector<std::string>& old_public_accounts) {
1419 std::set<std::string> users;
1420 for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it)
1421 users.insert((*it)->email());
1423 // If the user is logged into a public account that has been removed from the
1424 // user list, mark the account's data as pending removal after logout.
1425 if (IsLoggedInAsPublicAccount()) {
1426 const std::string active_user_id = GetActiveUser()->email();
1427 if (users.find(active_user_id) == users.end()) {
1428 g_browser_process->local_state()->SetString(
1429 kPublicAccountPendingDataRemoval, active_user_id);
1430 users.insert(active_user_id);
1434 // Remove the data belonging to any other public accounts that are no longer
1435 // found on the user list.
1436 for (std::vector<std::string>::const_iterator
1437 it = old_public_accounts.begin();
1438 it != old_public_accounts.end(); ++it) {
1439 if (users.find(*it) == users.end())
1440 RemoveNonCryptohomeData(*it);
1444 bool UserManagerImpl::UpdateAndCleanUpPublicAccounts(
1445 const std::vector<policy::DeviceLocalAccount>& device_local_accounts) {
1446 // Try to remove any public account data marked as pending removal.
1447 CleanUpPublicAccountNonCryptohomeDataPendingRemoval();
1449 // Get the current list of public accounts.
1450 std::vector<std::string> old_public_accounts;
1451 for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) {
1452 if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT)
1453 old_public_accounts.push_back((*it)->email());
1456 // Get the new list of public accounts from policy.
1457 std::vector<std::string> new_public_accounts;
1458 for (std::vector<policy::DeviceLocalAccount>::const_iterator it =
1459 device_local_accounts.begin();
1460 it != device_local_accounts.end(); ++it) {
1461 // TODO(mnissler, nkostylev, bartfab): Process Kiosk Apps within the
1462 // standard login framework: http://crbug.com/234694
1463 if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
1464 new_public_accounts.push_back(it->user_id);
1467 // If the list of public accounts has not changed, return.
1468 if (new_public_accounts.size() == old_public_accounts.size()) {
1469 bool changed = false;
1470 for (size_t i = 0; i < new_public_accounts.size(); ++i) {
1471 if (new_public_accounts[i] != old_public_accounts[i]) {
1472 changed = true;
1473 break;
1476 if (!changed)
1477 return false;
1480 // Persist the new list of public accounts in a pref.
1481 ListPrefUpdate prefs_public_accounts_update(g_browser_process->local_state(),
1482 kPublicAccounts);
1483 prefs_public_accounts_update->Clear();
1484 for (std::vector<std::string>::const_iterator
1485 it = new_public_accounts.begin();
1486 it != new_public_accounts.end(); ++it) {
1487 prefs_public_accounts_update->AppendString(*it);
1490 // Remove the old public accounts from the user list.
1491 for (UserList::iterator it = users_.begin(); it != users_.end(); ) {
1492 if ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
1493 if (*it != GetLoggedInUser())
1494 delete *it;
1495 it = users_.erase(it);
1496 } else {
1497 ++it;
1501 // Add the new public accounts to the front of the user list.
1502 for (std::vector<std::string>::const_reverse_iterator
1503 it = new_public_accounts.rbegin();
1504 it != new_public_accounts.rend(); ++it) {
1505 if (IsLoggedInAsPublicAccount() && *it == GetActiveUser()->email())
1506 users_.insert(users_.begin(), GetLoggedInUser());
1507 else
1508 users_.insert(users_.begin(), User::CreatePublicAccountUser(*it));
1509 UpdatePublicAccountDisplayName(*it);
1512 user_image_manager_->LoadUserImages(
1513 UserList(users_.begin(), users_.begin() + new_public_accounts.size()));
1515 // Remove data belonging to public accounts that are no longer found on the
1516 // user list.
1517 CleanUpPublicAccountNonCryptohomeData(old_public_accounts);
1519 return true;
1522 void UserManagerImpl::UpdatePublicAccountDisplayName(
1523 const std::string& user_id) {
1524 std::string display_name;
1526 if (device_local_account_policy_service_) {
1527 policy::DeviceLocalAccountPolicyBroker* broker =
1528 device_local_account_policy_service_->GetBrokerForUser(user_id);
1529 if (broker)
1530 display_name = broker->GetDisplayName();
1533 // Set or clear the display name.
1534 SaveUserDisplayName(user_id, UTF8ToUTF16(display_name));
1537 UserFlow* UserManagerImpl::GetCurrentUserFlow() const {
1538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1539 if (!IsUserLoggedIn())
1540 return GetDefaultUserFlow();
1541 return GetUserFlow(GetLoggedInUser()->email());
1544 UserFlow* UserManagerImpl::GetUserFlow(const std::string& user_id) const {
1545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1546 FlowMap::const_iterator it = specific_flows_.find(user_id);
1547 if (it != specific_flows_.end())
1548 return it->second;
1549 return GetDefaultUserFlow();
1552 void UserManagerImpl::SetUserFlow(const std::string& user_id, UserFlow* flow) {
1553 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1554 ResetUserFlow(user_id);
1555 specific_flows_[user_id] = flow;
1558 void UserManagerImpl::ResetUserFlow(const std::string& user_id) {
1559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1560 FlowMap::iterator it = specific_flows_.find(user_id);
1561 if (it != specific_flows_.end()) {
1562 delete it->second;
1563 specific_flows_.erase(it);
1567 bool UserManagerImpl::GetAppModeChromeClientOAuthInfo(
1568 std::string* chrome_client_id, std::string* chrome_client_secret) {
1569 if (!chrome::IsRunningInForcedAppMode() ||
1570 chrome_client_id_.empty() ||
1571 chrome_client_secret_.empty()) {
1572 return false;
1575 *chrome_client_id = chrome_client_id_;
1576 *chrome_client_secret = chrome_client_secret_;
1577 return true;
1580 void UserManagerImpl::SetAppModeChromeClientOAuthInfo(
1581 const std::string& chrome_client_id,
1582 const std::string& chrome_client_secret) {
1583 if (!chrome::IsRunningInForcedAppMode())
1584 return;
1586 chrome_client_id_ = chrome_client_id;
1587 chrome_client_secret_ = chrome_client_secret;
1590 bool UserManagerImpl::AreLocallyManagedUsersAllowed() const {
1591 bool locally_managed_users_allowed = false;
1592 cros_settings_->GetBoolean(kAccountsPrefSupervisedUsersEnabled,
1593 &locally_managed_users_allowed);
1594 return locally_managed_users_allowed ||
1595 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged();
1598 base::FilePath UserManagerImpl::GetUserProfileDir(
1599 const std::string& user_id) const {
1600 // TODO(dpolukhin): Remove Chrome OS specific profile path logic from
1601 // ProfileManager and use only this function to construct profile path.
1602 // TODO(nkostylev): Cleanup profile dir related code paths crbug.com/294233
1603 base::FilePath profile_dir;
1604 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1605 if (command_line.HasSwitch(::switches::kMultiProfiles)) {
1606 const User* user = FindUser(user_id);
1607 if (user && !user->username_hash().empty())
1608 profile_dir = ProfileHelper::GetUserProfileDir(user->username_hash());
1609 } else if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
1610 profile_dir = ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
1611 } else {
1612 // We should never be logged in with no profile dir unless
1613 // multi-profiles are enabled.
1614 NOTREACHED();
1615 profile_dir = base::FilePath();
1618 ProfileManager* profile_manager = g_browser_process->profile_manager();
1619 profile_dir = profile_manager->user_data_dir().Append(profile_dir);
1621 return profile_dir;
1624 UserFlow* UserManagerImpl::GetDefaultUserFlow() const {
1625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1626 if (!default_flow_.get())
1627 default_flow_.reset(new DefaultUserFlow());
1628 return default_flow_.get();
1631 void UserManagerImpl::NotifyUserListChanged() {
1632 content::NotificationService::current()->Notify(
1633 chrome::NOTIFICATION_USER_LIST_CHANGED,
1634 content::Source<UserManager>(this),
1635 content::NotificationService::NoDetails());
1638 void UserManagerImpl::NotifyActiveUserChanged(const User* active_user) {
1639 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1640 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1641 session_state_observer_list_,
1642 ActiveUserChanged(active_user));
1645 void UserManagerImpl::NotifyUserAddedToSession(const User* added_user) {
1646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1647 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1648 session_state_observer_list_,
1649 UserAddedToSession(added_user));
1652 void UserManagerImpl::NotifyActiveUserHashChanged(const std::string& hash) {
1653 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1654 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1655 session_state_observer_list_,
1656 ActiveUserHashChanged(hash));
1659 void UserManagerImpl::NotifyPendingUserSessionsRestoreFinished() {
1660 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1661 user_sessions_restored_ = true;
1662 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1663 session_state_observer_list_,
1664 PendingUserSessionsRestoreFinished());
1667 void UserManagerImpl::UpdateLoginState() {
1668 if (!LoginState::IsInitialized())
1669 return; // LoginState may not be intialized in tests.
1670 LoginState::LoggedInState logged_in_state;
1671 logged_in_state = active_user_ ? LoginState::LOGGED_IN_ACTIVE
1672 : LoginState::LOGGED_IN_NONE;
1674 LoginState::LoggedInUserType login_user_type;
1675 if (logged_in_state == LoginState::LOGGED_IN_NONE)
1676 login_user_type = LoginState::LOGGED_IN_USER_NONE;
1677 else if (is_current_user_owner_)
1678 login_user_type = LoginState::LOGGED_IN_USER_OWNER;
1679 else if (active_user_->GetType() == User::USER_TYPE_GUEST)
1680 login_user_type = LoginState::LOGGED_IN_USER_GUEST;
1681 else if (active_user_->GetType() == User::USER_TYPE_RETAIL_MODE)
1682 login_user_type = LoginState::LOGGED_IN_USER_RETAIL_MODE;
1683 else if (active_user_->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT)
1684 login_user_type = LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT;
1685 else if (active_user_->GetType() == User::USER_TYPE_LOCALLY_MANAGED)
1686 login_user_type = LoginState::LOGGED_IN_USER_LOCALLY_MANAGED;
1687 else if (active_user_->GetType() == User::USER_TYPE_KIOSK_APP)
1688 login_user_type = LoginState::LOGGED_IN_USER_KIOSK_APP;
1689 else
1690 login_user_type = LoginState::LOGGED_IN_USER_REGULAR;
1692 LoginState::Get()->SetLoggedInState(logged_in_state, login_user_type);
1695 void UserManagerImpl::SetLRUUser(User* user) {
1696 UserList::iterator it = std::find(lru_logged_in_users_.begin(),
1697 lru_logged_in_users_.end(),
1698 user);
1699 if (it != lru_logged_in_users_.end())
1700 lru_logged_in_users_.erase(it);
1701 lru_logged_in_users_.insert(lru_logged_in_users_.begin(), user);
1704 void UserManagerImpl::OnRestoreActiveSessions(
1705 const SessionManagerClient::ActiveSessionsMap& sessions,
1706 bool success) {
1707 if (!success) {
1708 LOG(ERROR) << "Could not get list of active user sessions after crash.";
1709 // If we could not get list of active user sessions it is safer to just
1710 // sign out so that we don't get in the inconsistent state.
1711 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
1712 return;
1715 // One profile has been already loaded on browser start.
1716 DCHECK(GetLoggedInUsers().size() == 1);
1717 DCHECK(GetActiveUser());
1718 std::string active_user_id = GetActiveUser()->email();
1720 SessionManagerClient::ActiveSessionsMap::const_iterator it;
1721 for (it = sessions.begin(); it != sessions.end(); ++it) {
1722 if (active_user_id == it->first)
1723 continue;
1724 pending_user_sessions_[it->first] = it->second;
1726 RestorePendingUserSessions();
1729 void UserManagerImpl::RestorePendingUserSessions() {
1730 if (pending_user_sessions_.empty()) {
1731 NotifyPendingUserSessionsRestoreFinished();
1732 return;
1735 // Get next user to restore sessions and delete it from list.
1736 SessionManagerClient::ActiveSessionsMap::const_iterator it =
1737 pending_user_sessions_.begin();
1738 std::string user_id = it->first;
1739 std::string user_id_hash = it->second;
1740 DCHECK(!user_id.empty());
1741 DCHECK(!user_id_hash.empty());
1742 pending_user_sessions_.erase(user_id);
1744 // Check that this user is not logged in yet.
1745 UserList logged_in_users = GetLoggedInUsers();
1746 bool user_already_logged_in = false;
1747 for (UserList::const_iterator it = logged_in_users.begin();
1748 it != logged_in_users.end(); ++it) {
1749 const User* user = (*it);
1750 if (user->email() == user_id) {
1751 user_already_logged_in = true;
1752 break;
1755 DCHECK(!user_already_logged_in);
1757 if (!user_already_logged_in) {
1758 // Will call OnProfilePrepared() once profile has been loaded.
1759 LoginUtils::Get()->PrepareProfile(UserContext(user_id,
1760 std::string(), // password
1761 std::string(), // auth_code
1762 user_id_hash,
1763 false), // using_oauth
1764 std::string(), // display_email
1765 false, // has_cookies
1766 true, // has_active_session
1767 this);
1768 } else {
1769 RestorePendingUserSessions();
1773 void UserManagerImpl::SendRegularUserLoginMetrics(const std::string& user_id) {
1774 // If this isn't the first time Chrome was run after the system booted,
1775 // assume that Chrome was restarted because a previous session ended.
1776 if (!CommandLine::ForCurrentProcess()->HasSwitch(
1777 switches::kFirstExecAfterBoot)) {
1778 const std::string last_email =
1779 g_browser_process->local_state()->GetString(kLastLoggedInRegularUser);
1780 const base::TimeDelta time_to_login =
1781 base::TimeTicks::Now() - manager_creation_time_;
1782 if (!last_email.empty() && user_id != last_email &&
1783 time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
1784 UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
1785 time_to_login.InSeconds(), 0, kLogoutToLoginDelayMaxSec, 50);
1790 void UserManagerImpl::OnUserNotAllowed() {
1791 LOG(ERROR) << "Shutdown session because a user is not allowed to be in the "
1792 "current session";
1793 chrome::AttemptUserExit();
1796 void UserManagerImpl::UpdateUserAccountLocale(const std::string& user_id,
1797 const std::string& locale) {
1798 if (!locale.empty() &&
1799 locale != g_browser_process->GetApplicationLocale()) {
1800 BrowserThread::PostBlockingPoolTask(
1801 FROM_HERE,
1802 base::Bind(ResolveLocale, locale,
1803 base::Bind(&UserManagerImpl::DoUpdateAccountLocale,
1804 base::Unretained(this),
1805 user_id)));
1806 } else {
1807 DoUpdateAccountLocale(user_id, locale);
1811 void UserManagerImpl::DoUpdateAccountLocale(
1812 const std::string& user_id,
1813 const std::string& resolved_locale) {
1814 if (User* user = FindUserAndModify(user_id))
1815 user->SetAccountLocale(resolved_locale);
1819 } // namespace chromeos