Add an exponential backoff to rechecking the app list doodle.
[chromium-blink-merge.git] / components / user_manager / user_manager_base.cc
blobbc2cc208b52c2ee089ddf0234ca118c8090d7220
1 // Copyright 2014 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 "components/user_manager/user_manager_base.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/format_macros.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/macros.h"
18 #include "base/metrics/histogram.h"
19 #include "base/prefs/pref_registry_simple.h"
20 #include "base/prefs/pref_service.h"
21 #include "base/prefs/scoped_user_pref_update.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/task_runner.h"
26 #include "base/values.h"
27 #include "chromeos/chromeos_switches.h"
28 #include "chromeos/cryptohome/async_method_caller.h"
29 #include "chromeos/login/login_state.h"
30 #include "chromeos/login/user_names.h"
31 #include "components/session_manager/core/session_manager.h"
32 #include "components/user_manager/remove_user_delegate.h"
33 #include "components/user_manager/user_type.h"
34 #include "google_apis/gaia/gaia_auth_util.h"
35 #include "ui/base/l10n/l10n_util.h"
37 namespace user_manager {
38 namespace {
40 // A vector pref of the the regular users known on this device, arranged in LRU
41 // order.
42 const char kRegularUsers[] = "LoggedInUsers";
44 // A dictionary that maps user IDs to the displayed name.
45 const char kUserDisplayName[] = "UserDisplayName";
47 // A dictionary that maps user IDs to the user's given name.
48 const char kUserGivenName[] = "UserGivenName";
50 // A dictionary that maps user IDs to the displayed (non-canonical) emails.
51 const char kUserDisplayEmail[] = "UserDisplayEmail";
53 // A dictionary that maps user IDs to OAuth token presence flag.
54 const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
56 // A dictionary that maps user IDs to a flag indicating whether online
57 // authentication against GAIA should be enforced during the next sign-in.
58 const char kUserForceOnlineSignin[] = "UserForceOnlineSignin";
60 // A dictionary that maps user ID to the user type.
61 const char kUserType[] = "UserType";
63 // A string pref containing the ID of the last user who logged in if it was
64 // a user with gaia account (regular) or an empty string if it was another type
65 // of user (guest, kiosk, public account, etc.).
66 const char kLastLoggedInGaiaUser[] = "LastLoggedInRegularUser";
68 // A string pref containing the ID of the last active user.
69 // In case of browser crash, this pref will be used to set active user after
70 // session restore.
71 const char kLastActiveUser[] = "LastActiveUser";
73 // A vector pref of preferences of known users. All new preferences should be
74 // placed in this list.
75 const char kKnownUsers[] = "KnownUsers";
77 // Known user preferences keys (stored in Local State).
79 // Key of canonical e-mail value.
80 const char kCanonicalEmail[] = "email";
82 // Key of obfuscated GAIA id value.
83 const char kGAIAIdKey[] = "gaia_id";
85 // Upper bound for a histogram metric reporting the amount of time between
86 // one regular user logging out and a different regular user logging in.
87 const int kLogoutToLoginDelayMaxSec = 1800;
89 // Callback that is called after user removal is complete.
90 void OnRemoveUserComplete(const std::string& user_email,
91 bool success,
92 cryptohome::MountError return_code) {
93 // Log the error, but there's not much we can do.
94 if (!success) {
95 LOG(ERROR) << "Removal of cryptohome for " << user_email
96 << " failed, return code: " << return_code;
100 // Runs on SequencedWorkerPool thread. Passes resolved locale to UI thread.
101 void ResolveLocale(const std::string& raw_locale,
102 std::string* resolved_locale) {
103 ignore_result(l10n_util::CheckAndResolveLocale(raw_locale, resolved_locale));
106 // Checks if values in |dict| correspond with |user_id| identity.
107 bool UserMatches(const UserID& user_id, const base::DictionaryValue& dict) {
108 std::string value;
110 bool has_email = dict.GetString(kCanonicalEmail, &value);
111 if (has_email && user_id == value)
112 return true;
114 // TODO(antrim): update code once user id is really a struct.
115 bool has_gaia_id = dict.GetString(kGAIAIdKey, &value);
116 if (has_gaia_id && user_id == value)
117 return true;
119 return false;
122 // Fills relevant |dict| values based on |user_id|.
123 void UpdateIdentity(const UserID& user_id, base::DictionaryValue& dict) {
124 dict.SetString(kCanonicalEmail, user_id);
127 } // namespace
129 // static
130 void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
131 registry->RegisterListPref(kRegularUsers);
132 registry->RegisterListPref(kKnownUsers);
133 registry->RegisterStringPref(kLastLoggedInGaiaUser, std::string());
134 registry->RegisterDictionaryPref(kUserDisplayName);
135 registry->RegisterDictionaryPref(kUserGivenName);
136 registry->RegisterDictionaryPref(kUserDisplayEmail);
137 registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
138 registry->RegisterDictionaryPref(kUserForceOnlineSignin);
139 registry->RegisterDictionaryPref(kUserType);
140 registry->RegisterStringPref(kLastActiveUser, std::string());
143 UserManagerBase::UserManagerBase(
144 scoped_refptr<base::TaskRunner> task_runner,
145 scoped_refptr<base::TaskRunner> blocking_task_runner)
146 : active_user_(NULL),
147 primary_user_(NULL),
148 user_loading_stage_(STAGE_NOT_LOADED),
149 session_started_(false),
150 is_current_user_owner_(false),
151 is_current_user_new_(false),
152 is_current_user_ephemeral_regular_user_(false),
153 ephemeral_users_enabled_(false),
154 manager_creation_time_(base::TimeTicks::Now()),
155 last_session_active_user_initialized_(false),
156 task_runner_(task_runner),
157 blocking_task_runner_(blocking_task_runner),
158 weak_factory_(this) {
159 UpdateLoginState();
162 UserManagerBase::~UserManagerBase() {
163 // Can't use STLDeleteElements because of the private destructor of User.
164 for (UserList::iterator it = users_.begin(); it != users_.end();
165 it = users_.erase(it)) {
166 DeleteUser(*it);
168 // These are pointers to the same User instances that were in users_ list.
169 logged_in_users_.clear();
170 lru_logged_in_users_.clear();
172 DeleteUser(active_user_);
175 void UserManagerBase::Shutdown() {
176 DCHECK(task_runner_->RunsTasksOnCurrentThread());
179 const UserList& UserManagerBase::GetUsers() const {
180 const_cast<UserManagerBase*>(this)->EnsureUsersLoaded();
181 return users_;
184 const UserList& UserManagerBase::GetLoggedInUsers() const {
185 return logged_in_users_;
188 const UserList& UserManagerBase::GetLRULoggedInUsers() const {
189 return lru_logged_in_users_;
192 const std::string& UserManagerBase::GetOwnerEmail() const {
193 return owner_email_;
196 void UserManagerBase::UserLoggedIn(const std::string& user_id,
197 const std::string& username_hash,
198 bool browser_restart) {
199 DCHECK(task_runner_->RunsTasksOnCurrentThread());
201 if (!last_session_active_user_initialized_) {
202 last_session_active_user_ = GetLocalState()->GetString(kLastActiveUser);
203 last_session_active_user_initialized_ = true;
206 User* user = FindUserInListAndModify(user_id);
207 if (active_user_ && user) {
208 user->set_is_logged_in(true);
209 user->set_username_hash(username_hash);
210 logged_in_users_.push_back(user);
211 lru_logged_in_users_.push_back(user);
213 // Reset the new user flag if the user already exists.
214 SetIsCurrentUserNew(false);
215 NotifyUserAddedToSession(user, true /* user switch pending */);
217 return;
220 if (user_id == chromeos::login::kGuestUserName) {
221 GuestUserLoggedIn();
222 } else if (IsKioskApp(user_id)) {
223 KioskAppLoggedIn(user_id);
224 } else if (IsDemoApp(user_id)) {
225 DemoAccountLoggedIn();
226 } else {
227 EnsureUsersLoaded();
229 if (user && user->GetType() == USER_TYPE_PUBLIC_ACCOUNT) {
230 PublicAccountUserLoggedIn(user);
231 } else if ((user && user->GetType() == USER_TYPE_SUPERVISED) ||
232 (!user &&
233 gaia::ExtractDomainName(user_id) ==
234 chromeos::login::kSupervisedUserDomain)) {
235 SupervisedUserLoggedIn(user_id);
236 } else if (browser_restart && IsPublicAccountMarkedForRemoval(user_id)) {
237 PublicAccountUserLoggedIn(User::CreatePublicAccountUser(user_id));
238 } else if (user_id != GetOwnerEmail() && !user &&
239 (AreEphemeralUsersEnabled() || browser_restart)) {
240 RegularUserLoggedInAsEphemeral(user_id);
241 } else {
242 RegularUserLoggedIn(user_id);
246 DCHECK(active_user_);
247 active_user_->set_is_logged_in(true);
248 active_user_->set_is_active(true);
249 active_user_->set_username_hash(username_hash);
251 // Place user who just signed in to the top of the logged in users.
252 logged_in_users_.insert(logged_in_users_.begin(), active_user_);
253 SetLRUUser(active_user_);
255 if (!primary_user_) {
256 primary_user_ = active_user_;
257 if (primary_user_->HasGaiaAccount())
258 SendGaiaUserLoginMetrics(user_id);
261 UMA_HISTOGRAM_ENUMERATION(
262 "UserManager.LoginUserType", active_user_->GetType(), NUM_USER_TYPES);
264 GetLocalState()->SetString(
265 kLastLoggedInGaiaUser, active_user_->HasGaiaAccount() ? user_id : "");
267 NotifyOnLogin();
268 PerformPostUserLoggedInActions(browser_restart);
271 void UserManagerBase::SwitchActiveUser(const std::string& user_id) {
272 User* user = FindUserAndModify(user_id);
273 if (!user) {
274 NOTREACHED() << "Switching to a non-existing user";
275 return;
277 if (user == active_user_) {
278 NOTREACHED() << "Switching to a user who is already active";
279 return;
281 if (!user->is_logged_in()) {
282 NOTREACHED() << "Switching to a user that is not logged in";
283 return;
285 if (!user->HasGaiaAccount()) {
286 NOTREACHED() <<
287 "Switching to a user without gaia account (non-regular one)";
288 return;
290 if (user->username_hash().empty()) {
291 NOTREACHED() << "Switching to a user that doesn't have username_hash set";
292 return;
295 DCHECK(active_user_);
296 active_user_->set_is_active(false);
297 user->set_is_active(true);
298 active_user_ = user;
300 // Move the user to the front.
301 SetLRUUser(active_user_);
303 NotifyActiveUserHashChanged(active_user_->username_hash());
304 NotifyActiveUserChanged(active_user_);
307 void UserManagerBase::SwitchToLastActiveUser() {
308 if (last_session_active_user_.empty())
309 return;
311 if (GetActiveUser()->email() != last_session_active_user_)
312 SwitchActiveUser(last_session_active_user_);
314 // Make sure that this function gets run only once.
315 last_session_active_user_.clear();
318 void UserManagerBase::SessionStarted() {
319 DCHECK(task_runner_->RunsTasksOnCurrentThread());
320 session_started_ = true;
322 UpdateLoginState();
323 session_manager::SessionManager::Get()->SetSessionState(
324 session_manager::SESSION_STATE_ACTIVE);
326 if (IsCurrentUserNew()) {
327 // Make sure that the new user's data is persisted to Local State.
328 GetLocalState()->CommitPendingWrite();
332 void UserManagerBase::RemoveUser(const std::string& user_id,
333 RemoveUserDelegate* delegate) {
334 DCHECK(task_runner_->RunsTasksOnCurrentThread());
336 if (!CanUserBeRemoved(FindUser(user_id)))
337 return;
339 RemoveUserInternal(user_id, delegate);
342 void UserManagerBase::RemoveUserInternal(const std::string& user_email,
343 RemoveUserDelegate* delegate) {
344 RemoveNonOwnerUserInternal(user_email, delegate);
347 void UserManagerBase::RemoveNonOwnerUserInternal(const std::string& user_email,
348 RemoveUserDelegate* delegate) {
349 if (delegate)
350 delegate->OnBeforeUserRemoved(user_email);
351 RemoveUserFromList(user_email);
352 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
353 user_email, base::Bind(&OnRemoveUserComplete, user_email));
355 if (delegate)
356 delegate->OnUserRemoved(user_email);
359 void UserManagerBase::RemoveUserFromList(const std::string& user_id) {
360 DCHECK(task_runner_->RunsTasksOnCurrentThread());
361 RemoveNonCryptohomeData(user_id);
362 if (user_loading_stage_ == STAGE_LOADED) {
363 DeleteUser(RemoveRegularOrSupervisedUserFromList(user_id));
364 } else if (user_loading_stage_ == STAGE_LOADING) {
365 DCHECK(gaia::ExtractDomainName(user_id) ==
366 chromeos::login::kSupervisedUserDomain ||
367 HasPendingBootstrap(user_id));
368 // Special case, removing partially-constructed supervised user or
369 // boostrapping user during user list loading.
370 ListPrefUpdate users_update(GetLocalState(), kRegularUsers);
371 users_update->Remove(base::StringValue(user_id), NULL);
372 } else {
373 NOTREACHED() << "Users are not loaded yet.";
374 return;
377 // Make sure that new data is persisted to Local State.
378 GetLocalState()->CommitPendingWrite();
381 bool UserManagerBase::IsKnownUser(const std::string& user_id) const {
382 return FindUser(user_id) != NULL;
385 const User* UserManagerBase::FindUser(const std::string& user_id) const {
386 DCHECK(task_runner_->RunsTasksOnCurrentThread());
387 if (active_user_ && active_user_->email() == user_id)
388 return active_user_;
389 return FindUserInList(user_id);
392 User* UserManagerBase::FindUserAndModify(const std::string& user_id) {
393 DCHECK(task_runner_->RunsTasksOnCurrentThread());
394 if (active_user_ && active_user_->email() == user_id)
395 return active_user_;
396 return FindUserInListAndModify(user_id);
399 const User* UserManagerBase::GetLoggedInUser() const {
400 DCHECK(task_runner_->RunsTasksOnCurrentThread());
401 return active_user_;
404 User* UserManagerBase::GetLoggedInUser() {
405 DCHECK(task_runner_->RunsTasksOnCurrentThread());
406 return active_user_;
409 const User* UserManagerBase::GetActiveUser() const {
410 DCHECK(task_runner_->RunsTasksOnCurrentThread());
411 return active_user_;
414 User* UserManagerBase::GetActiveUser() {
415 DCHECK(task_runner_->RunsTasksOnCurrentThread());
416 return active_user_;
419 const User* UserManagerBase::GetPrimaryUser() const {
420 DCHECK(task_runner_->RunsTasksOnCurrentThread());
421 return primary_user_;
424 void UserManagerBase::SaveUserOAuthStatus(
425 const std::string& user_id,
426 User::OAuthTokenStatus oauth_token_status) {
427 DCHECK(task_runner_->RunsTasksOnCurrentThread());
429 DVLOG(1) << "Saving user OAuth token status in Local State";
430 User* user = FindUserAndModify(user_id);
431 if (user)
432 user->set_oauth_token_status(oauth_token_status);
434 // Do not update local state if data stored or cached outside the user's
435 // cryptohome is to be treated as ephemeral.
436 if (IsUserNonCryptohomeDataEphemeral(user_id))
437 return;
439 DictionaryPrefUpdate oauth_status_update(GetLocalState(),
440 kUserOAuthTokenStatus);
441 oauth_status_update->SetWithoutPathExpansion(
442 user_id,
443 new base::FundamentalValue(static_cast<int>(oauth_token_status)));
446 void UserManagerBase::SaveForceOnlineSignin(const std::string& user_id,
447 bool force_online_signin) {
448 DCHECK(task_runner_->RunsTasksOnCurrentThread());
450 // Do not update local state if data stored or cached outside the user's
451 // cryptohome is to be treated as ephemeral.
452 if (IsUserNonCryptohomeDataEphemeral(user_id))
453 return;
455 DictionaryPrefUpdate force_online_update(GetLocalState(),
456 kUserForceOnlineSignin);
457 force_online_update->SetBooleanWithoutPathExpansion(user_id,
458 force_online_signin);
461 void UserManagerBase::SaveUserDisplayName(const std::string& user_id,
462 const base::string16& display_name) {
463 DCHECK(task_runner_->RunsTasksOnCurrentThread());
465 if (User* user = FindUserAndModify(user_id)) {
466 user->set_display_name(display_name);
468 // Do not update local state if data stored or cached outside the user's
469 // cryptohome is to be treated as ephemeral.
470 if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
471 DictionaryPrefUpdate display_name_update(GetLocalState(),
472 kUserDisplayName);
473 display_name_update->SetWithoutPathExpansion(
474 user_id, new base::StringValue(display_name));
479 base::string16 UserManagerBase::GetUserDisplayName(
480 const std::string& user_id) const {
481 const User* user = FindUser(user_id);
482 return user ? user->display_name() : base::string16();
485 void UserManagerBase::SaveUserDisplayEmail(const std::string& user_id,
486 const std::string& display_email) {
487 DCHECK(task_runner_->RunsTasksOnCurrentThread());
489 User* user = FindUserAndModify(user_id);
490 if (!user) {
491 LOG(ERROR) << "User not found: " << user_id;
492 return; // Ignore if there is no such user.
495 user->set_display_email(display_email);
497 // Do not update local state if data stored or cached outside the user's
498 // cryptohome is to be treated as ephemeral.
499 if (IsUserNonCryptohomeDataEphemeral(user_id))
500 return;
502 DictionaryPrefUpdate display_email_update(GetLocalState(), kUserDisplayEmail);
503 display_email_update->SetWithoutPathExpansion(
504 user_id, new base::StringValue(display_email));
507 std::string UserManagerBase::GetUserDisplayEmail(
508 const std::string& user_id) const {
509 const User* user = FindUser(user_id);
510 return user ? user->display_email() : user_id;
513 void UserManagerBase::SaveUserType(const std::string& user_id,
514 const UserType& user_type) {
515 DCHECK(task_runner_->RunsTasksOnCurrentThread());
517 User* user = FindUserAndModify(user_id);
518 if (!user) {
519 LOG(ERROR) << "User not found: " << user_id;
520 return; // Ignore if there is no such user.
523 // Do not update local state if data stored or cached outside the user's
524 // cryptohome is to be treated as ephemeral.
525 if (IsUserNonCryptohomeDataEphemeral(user_id))
526 return;
528 DictionaryPrefUpdate user_type_update(GetLocalState(), kUserType);
529 user_type_update->SetWithoutPathExpansion(
530 user_id, new base::FundamentalValue(static_cast<int>(user_type)));
531 GetLocalState()->CommitPendingWrite();
534 void UserManagerBase::UpdateUserAccountData(
535 const std::string& user_id,
536 const UserAccountData& account_data) {
537 DCHECK(task_runner_->RunsTasksOnCurrentThread());
539 SaveUserDisplayName(user_id, account_data.display_name());
541 if (User* user = FindUserAndModify(user_id)) {
542 base::string16 given_name = account_data.given_name();
543 user->set_given_name(given_name);
544 if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
545 DictionaryPrefUpdate given_name_update(GetLocalState(), kUserGivenName);
546 given_name_update->SetWithoutPathExpansion(
547 user_id, new base::StringValue(given_name));
551 UpdateUserAccountLocale(user_id, account_data.locale());
554 // static
555 void UserManagerBase::ParseUserList(const base::ListValue& users_list,
556 const std::set<std::string>& existing_users,
557 std::vector<std::string>* users_vector,
558 std::set<std::string>* users_set) {
559 users_vector->clear();
560 users_set->clear();
561 for (size_t i = 0; i < users_list.GetSize(); ++i) {
562 std::string email;
563 if (!users_list.GetString(i, &email) || email.empty()) {
564 LOG(ERROR) << "Corrupt entry in user list at index " << i << ".";
565 continue;
567 if (existing_users.find(email) != existing_users.end() ||
568 !users_set->insert(email).second) {
569 LOG(ERROR) << "Duplicate user: " << email;
570 continue;
572 users_vector->push_back(email);
576 bool UserManagerBase::IsCurrentUserOwner() const {
577 DCHECK(task_runner_->RunsTasksOnCurrentThread());
578 base::AutoLock lk(is_current_user_owner_lock_);
579 return is_current_user_owner_;
582 void UserManagerBase::SetCurrentUserIsOwner(bool is_current_user_owner) {
583 DCHECK(task_runner_->RunsTasksOnCurrentThread());
585 base::AutoLock lk(is_current_user_owner_lock_);
586 is_current_user_owner_ = is_current_user_owner;
588 UpdateLoginState();
591 bool UserManagerBase::IsCurrentUserNew() const {
592 DCHECK(task_runner_->RunsTasksOnCurrentThread());
593 return is_current_user_new_;
596 bool UserManagerBase::IsCurrentUserNonCryptohomeDataEphemeral() const {
597 DCHECK(task_runner_->RunsTasksOnCurrentThread());
598 return IsUserLoggedIn() &&
599 IsUserNonCryptohomeDataEphemeral(GetLoggedInUser()->email());
602 bool UserManagerBase::CanCurrentUserLock() const {
603 DCHECK(task_runner_->RunsTasksOnCurrentThread());
604 return IsUserLoggedIn() && active_user_->can_lock();
607 bool UserManagerBase::IsUserLoggedIn() const {
608 DCHECK(task_runner_->RunsTasksOnCurrentThread());
609 return active_user_;
612 bool UserManagerBase::IsLoggedInAsUserWithGaiaAccount() const {
613 DCHECK(task_runner_->RunsTasksOnCurrentThread());
614 return IsUserLoggedIn() && active_user_->HasGaiaAccount();
617 bool UserManagerBase::IsLoggedInAsChildUser() const {
618 DCHECK(task_runner_->RunsTasksOnCurrentThread());
619 return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_CHILD;
622 bool UserManagerBase::IsLoggedInAsPublicAccount() const {
623 DCHECK(task_runner_->RunsTasksOnCurrentThread());
624 return IsUserLoggedIn() &&
625 active_user_->GetType() == USER_TYPE_PUBLIC_ACCOUNT;
628 bool UserManagerBase::IsLoggedInAsGuest() const {
629 DCHECK(task_runner_->RunsTasksOnCurrentThread());
630 return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_GUEST;
633 bool UserManagerBase::IsLoggedInAsSupervisedUser() const {
634 DCHECK(task_runner_->RunsTasksOnCurrentThread());
635 return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_SUPERVISED;
638 bool UserManagerBase::IsLoggedInAsKioskApp() const {
639 DCHECK(task_runner_->RunsTasksOnCurrentThread());
640 return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_KIOSK_APP;
643 bool UserManagerBase::IsLoggedInAsStub() const {
644 DCHECK(task_runner_->RunsTasksOnCurrentThread());
645 return IsUserLoggedIn() &&
646 active_user_->email() == chromeos::login::kStubUser;
649 bool UserManagerBase::IsSessionStarted() const {
650 DCHECK(task_runner_->RunsTasksOnCurrentThread());
651 return session_started_;
654 bool UserManagerBase::IsUserNonCryptohomeDataEphemeral(
655 const std::string& user_id) const {
656 // Data belonging to the guest and stub users is always ephemeral.
657 if (user_id == chromeos::login::kGuestUserName ||
658 user_id == chromeos::login::kStubUser) {
659 return true;
662 // Data belonging to the owner, anyone found on the user list and obsolete
663 // public accounts whose data has not been removed yet is not ephemeral.
664 if (user_id == GetOwnerEmail() || UserExistsInList(user_id) ||
665 IsPublicAccountMarkedForRemoval(user_id)) {
666 return false;
669 // Data belonging to the currently logged-in user is ephemeral when:
670 // a) The user logged into a regular gaia account while the ephemeral users
671 // policy was enabled.
672 // - or -
673 // b) The user logged into any other account type.
674 if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) &&
675 (is_current_user_ephemeral_regular_user_ ||
676 !IsLoggedInAsUserWithGaiaAccount())) {
677 return true;
680 // Data belonging to any other user is ephemeral when:
681 // a) Going through the regular login flow and the ephemeral users policy is
682 // enabled.
683 // - or -
684 // b) The browser is restarting after a crash.
685 return AreEphemeralUsersEnabled() ||
686 session_manager::SessionManager::HasBrowserRestarted();
689 void UserManagerBase::AddObserver(UserManager::Observer* obs) {
690 DCHECK(task_runner_->RunsTasksOnCurrentThread());
691 observer_list_.AddObserver(obs);
694 void UserManagerBase::RemoveObserver(UserManager::Observer* obs) {
695 DCHECK(task_runner_->RunsTasksOnCurrentThread());
696 observer_list_.RemoveObserver(obs);
699 void UserManagerBase::AddSessionStateObserver(
700 UserManager::UserSessionStateObserver* obs) {
701 DCHECK(task_runner_->RunsTasksOnCurrentThread());
702 session_state_observer_list_.AddObserver(obs);
705 void UserManagerBase::RemoveSessionStateObserver(
706 UserManager::UserSessionStateObserver* obs) {
707 DCHECK(task_runner_->RunsTasksOnCurrentThread());
708 session_state_observer_list_.RemoveObserver(obs);
711 void UserManagerBase::NotifyLocalStateChanged() {
712 DCHECK(task_runner_->RunsTasksOnCurrentThread());
713 FOR_EACH_OBSERVER(
714 UserManager::Observer, observer_list_, LocalStateChanged(this));
717 bool UserManagerBase::CanUserBeRemoved(const User* user) const {
718 // Only regular and supervised users are allowed to be manually removed.
719 if (!user || !(user->HasGaiaAccount() || user->IsSupervised()))
720 return false;
722 // Sanity check: we must not remove single user unless it's an enterprise
723 // device. This check may seem redundant at a first sight because
724 // this single user must be an owner and we perform special check later
725 // in order not to remove an owner. However due to non-instant nature of
726 // ownership assignment this later check may sometimes fail.
727 // See http://crosbug.com/12723
728 if (users_.size() < 2 && !IsEnterpriseManaged())
729 return false;
731 // Sanity check: do not allow any of the the logged in users to be removed.
732 for (UserList::const_iterator it = logged_in_users_.begin();
733 it != logged_in_users_.end();
734 ++it) {
735 if ((*it)->email() == user->email())
736 return false;
739 return true;
742 bool UserManagerBase::GetEphemeralUsersEnabled() const {
743 return ephemeral_users_enabled_;
746 void UserManagerBase::SetEphemeralUsersEnabled(bool enabled) {
747 ephemeral_users_enabled_ = enabled;
750 void UserManagerBase::SetIsCurrentUserNew(bool is_new) {
751 is_current_user_new_ = is_new;
754 bool UserManagerBase::HasPendingBootstrap(const std::string& user_id) const {
755 return false;
758 void UserManagerBase::SetOwnerEmail(std::string owner_user_id) {
759 owner_email_ = owner_user_id;
762 const std::string& UserManagerBase::GetPendingUserSwitchID() const {
763 return pending_user_switch_;
766 void UserManagerBase::SetPendingUserSwitchID(std::string user_id) {
767 pending_user_switch_ = user_id;
770 void UserManagerBase::EnsureUsersLoaded() {
771 DCHECK(task_runner_->RunsTasksOnCurrentThread());
772 if (!GetLocalState())
773 return;
775 if (user_loading_stage_ != STAGE_NOT_LOADED)
776 return;
777 user_loading_stage_ = STAGE_LOADING;
779 PerformPreUserListLoadingActions();
781 PrefService* local_state = GetLocalState();
782 const base::ListValue* prefs_regular_users =
783 local_state->GetList(kRegularUsers);
785 const base::DictionaryValue* prefs_display_names =
786 local_state->GetDictionary(kUserDisplayName);
787 const base::DictionaryValue* prefs_given_names =
788 local_state->GetDictionary(kUserGivenName);
789 const base::DictionaryValue* prefs_display_emails =
790 local_state->GetDictionary(kUserDisplayEmail);
791 const base::DictionaryValue* prefs_user_types =
792 local_state->GetDictionary(kUserType);
794 // Load public sessions first.
795 std::set<std::string> public_sessions_set;
796 LoadPublicAccounts(&public_sessions_set);
798 // Load regular users and supervised users.
799 std::vector<std::string> regular_users;
800 std::set<std::string> regular_users_set;
801 ParseUserList(*prefs_regular_users,
802 public_sessions_set,
803 &regular_users,
804 &regular_users_set);
805 for (std::vector<std::string>::const_iterator it = regular_users.begin();
806 it != regular_users.end();
807 ++it) {
808 User* user = NULL;
809 const std::string domain = gaia::ExtractDomainName(*it);
810 if (domain == chromeos::login::kSupervisedUserDomain) {
811 user = User::CreateSupervisedUser(*it);
812 } else {
813 user = User::CreateRegularUser(*it);
814 int user_type;
815 if (prefs_user_types->GetIntegerWithoutPathExpansion(*it, &user_type) &&
816 user_type == USER_TYPE_CHILD) {
817 ChangeUserChildStatus(user, true /* is child */);
820 user->set_oauth_token_status(LoadUserOAuthStatus(*it));
821 user->set_force_online_signin(LoadForceOnlineSignin(*it));
822 users_.push_back(user);
824 base::string16 display_name;
825 if (prefs_display_names->GetStringWithoutPathExpansion(*it,
826 &display_name)) {
827 user->set_display_name(display_name);
830 base::string16 given_name;
831 if (prefs_given_names->GetStringWithoutPathExpansion(*it, &given_name)) {
832 user->set_given_name(given_name);
835 std::string display_email;
836 if (prefs_display_emails->GetStringWithoutPathExpansion(*it,
837 &display_email)) {
838 user->set_display_email(display_email);
842 user_loading_stage_ = STAGE_LOADED;
844 PerformPostUserListLoadingActions();
847 UserList& UserManagerBase::GetUsersAndModify() {
848 EnsureUsersLoaded();
849 return users_;
852 const User* UserManagerBase::FindUserInList(const std::string& user_id) const {
853 const UserList& users = GetUsers();
854 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
855 if ((*it)->email() == user_id)
856 return *it;
858 return NULL;
861 bool UserManagerBase::UserExistsInList(const std::string& user_id) const {
862 const base::ListValue* user_list = GetLocalState()->GetList(kRegularUsers);
863 for (size_t i = 0; i < user_list->GetSize(); ++i) {
864 std::string email;
865 if (user_list->GetString(i, &email) && (user_id == email))
866 return true;
868 return false;
871 User* UserManagerBase::FindUserInListAndModify(const std::string& user_id) {
872 UserList& users = GetUsersAndModify();
873 for (UserList::iterator it = users.begin(); it != users.end(); ++it) {
874 if ((*it)->email() == user_id)
875 return *it;
877 return NULL;
880 void UserManagerBase::GuestUserLoggedIn() {
881 DCHECK(task_runner_->RunsTasksOnCurrentThread());
882 active_user_ = User::CreateGuestUser();
885 void UserManagerBase::AddUserRecord(User* user) {
886 // Add the user to the front of the user list.
887 ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
888 prefs_users_update->Insert(0, new base::StringValue(user->email()));
889 users_.insert(users_.begin(), user);
892 void UserManagerBase::RegularUserLoggedIn(const std::string& user_id) {
893 // Remove the user from the user list.
894 active_user_ = RemoveRegularOrSupervisedUserFromList(user_id);
896 // If the user was not found on the user list, create a new user.
897 SetIsCurrentUserNew(!active_user_);
898 if (IsCurrentUserNew()) {
899 active_user_ = User::CreateRegularUser(user_id);
900 active_user_->set_oauth_token_status(LoadUserOAuthStatus(user_id));
901 SaveUserDisplayName(active_user_->email(),
902 base::UTF8ToUTF16(active_user_->GetAccountName(true)));
905 AddUserRecord(active_user_);
907 // Make sure that new data is persisted to Local State.
908 GetLocalState()->CommitPendingWrite();
911 void UserManagerBase::RegularUserLoggedInAsEphemeral(
912 const std::string& user_id) {
913 DCHECK(task_runner_->RunsTasksOnCurrentThread());
914 SetIsCurrentUserNew(true);
915 is_current_user_ephemeral_regular_user_ = true;
916 active_user_ = User::CreateRegularUser(user_id);
919 void UserManagerBase::NotifyOnLogin() {
920 DCHECK(task_runner_->RunsTasksOnCurrentThread());
922 NotifyActiveUserHashChanged(active_user_->username_hash());
923 NotifyActiveUserChanged(active_user_);
924 UpdateLoginState();
927 User::OAuthTokenStatus UserManagerBase::LoadUserOAuthStatus(
928 const std::string& user_id) const {
929 DCHECK(task_runner_->RunsTasksOnCurrentThread());
931 const base::DictionaryValue* prefs_oauth_status =
932 GetLocalState()->GetDictionary(kUserOAuthTokenStatus);
933 int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
934 if (prefs_oauth_status &&
935 prefs_oauth_status->GetIntegerWithoutPathExpansion(user_id,
936 &oauth_token_status)) {
937 User::OAuthTokenStatus status =
938 static_cast<User::OAuthTokenStatus>(oauth_token_status);
939 HandleUserOAuthTokenStatusChange(user_id, status);
941 return status;
943 return User::OAUTH_TOKEN_STATUS_UNKNOWN;
946 bool UserManagerBase::LoadForceOnlineSignin(const std::string& user_id) const {
947 DCHECK(task_runner_->RunsTasksOnCurrentThread());
949 const base::DictionaryValue* prefs_force_online =
950 GetLocalState()->GetDictionary(kUserForceOnlineSignin);
951 bool force_online_signin = false;
952 if (prefs_force_online) {
953 prefs_force_online->GetBooleanWithoutPathExpansion(user_id,
954 &force_online_signin);
956 return force_online_signin;
959 void UserManagerBase::RemoveNonCryptohomeData(const std::string& user_id) {
960 PrefService* prefs = GetLocalState();
961 DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName);
962 prefs_display_name_update->RemoveWithoutPathExpansion(user_id, NULL);
964 DictionaryPrefUpdate prefs_given_name_update(prefs, kUserGivenName);
965 prefs_given_name_update->RemoveWithoutPathExpansion(user_id, NULL);
967 DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
968 prefs_display_email_update->RemoveWithoutPathExpansion(user_id, NULL);
970 DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
971 prefs_oauth_update->RemoveWithoutPathExpansion(user_id, NULL);
973 DictionaryPrefUpdate prefs_force_online_update(prefs, kUserForceOnlineSignin);
974 prefs_force_online_update->RemoveWithoutPathExpansion(user_id, NULL);
976 RemoveKnownUserPrefs(user_id);
978 std::string last_active_user = GetLocalState()->GetString(kLastActiveUser);
979 if (user_id == last_active_user)
980 GetLocalState()->SetString(kLastActiveUser, std::string());
983 bool UserManagerBase::FindKnownUserPrefs(
984 const UserID& user_id,
985 const base::DictionaryValue** out_value) {
986 PrefService* local_state = GetLocalState();
987 const base::ListValue* known_users = local_state->GetList(kKnownUsers);
988 for (size_t i = 0; i < known_users->GetSize(); ++i) {
989 const base::DictionaryValue* element = nullptr;
990 if (known_users->GetDictionary(i, &element)) {
991 if (UserMatches(user_id, *element)) {
992 known_users->GetDictionary(i, out_value);
993 return true;
997 return false;
1000 void UserManagerBase::UpdateKnownUserPrefs(const UserID& user_id,
1001 const base::DictionaryValue& values,
1002 bool clear) {
1003 ListPrefUpdate update(GetLocalState(), kKnownUsers);
1004 for (size_t i = 0; i < update->GetSize(); ++i) {
1005 base::DictionaryValue* element = nullptr;
1006 if (update->GetDictionary(i, &element)) {
1007 if (UserMatches(user_id, *element)) {
1008 if (clear)
1009 element->Clear();
1010 element->MergeDictionary(&values);
1011 UpdateIdentity(user_id, *element);
1012 return;
1016 scoped_ptr<base::DictionaryValue> new_value(new base::DictionaryValue());
1017 new_value->MergeDictionary(&values);
1018 UpdateIdentity(user_id, *new_value);
1019 update->Append(new_value.release());
1022 bool UserManagerBase::GetKnownUserStringPref(const UserID& user_id,
1023 const std::string& path,
1024 std::string* out_value) {
1025 const base::DictionaryValue* user_pref_dict = nullptr;
1026 if (!FindKnownUserPrefs(user_id, &user_pref_dict))
1027 return false;
1029 return user_pref_dict->GetString(path, out_value);
1032 void UserManagerBase::SetKnownUserStringPref(const UserID& user_id,
1033 const std::string& path,
1034 const std::string& in_value) {
1035 ListPrefUpdate update(GetLocalState(), kKnownUsers);
1036 base::DictionaryValue dict;
1037 dict.SetString(path, in_value);
1038 UpdateKnownUserPrefs(user_id, dict, false);
1041 void UserManagerBase::UpdateGaiaID(const UserID& user_id,
1042 const std::string& gaia_id) {
1043 SetKnownUserStringPref(user_id, kGAIAIdKey, gaia_id);
1046 bool UserManagerBase::FindGaiaID(const UserID& user_id,
1047 std::string* out_value) {
1048 return GetKnownUserStringPref(user_id, kGAIAIdKey, out_value);
1051 User* UserManagerBase::RemoveRegularOrSupervisedUserFromList(
1052 const std::string& user_id) {
1053 ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
1054 prefs_users_update->Clear();
1055 User* user = NULL;
1056 for (UserList::iterator it = users_.begin(); it != users_.end();) {
1057 const std::string user_email = (*it)->email();
1058 if (user_email == user_id) {
1059 user = *it;
1060 it = users_.erase(it);
1061 } else {
1062 if ((*it)->HasGaiaAccount() || (*it)->IsSupervised())
1063 prefs_users_update->Append(new base::StringValue(user_email));
1064 ++it;
1067 return user;
1070 void UserManagerBase::RemoveKnownUserPrefs(const UserID& user_id) {
1071 ListPrefUpdate update(GetLocalState(), kKnownUsers);
1072 for (size_t i = 0; i < update->GetSize(); ++i) {
1073 base::DictionaryValue* element = nullptr;
1074 if (update->GetDictionary(i, &element)) {
1075 if (UserMatches(user_id, *element)) {
1076 update->Remove(i, nullptr);
1077 break;
1083 void UserManagerBase::NotifyActiveUserChanged(const User* active_user) {
1084 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1085 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1086 session_state_observer_list_,
1087 ActiveUserChanged(active_user));
1090 void UserManagerBase::NotifyUserAddedToSession(const User* added_user,
1091 bool user_switch_pending) {
1092 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1093 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1094 session_state_observer_list_,
1095 UserAddedToSession(added_user));
1098 void UserManagerBase::NotifyActiveUserHashChanged(const std::string& hash) {
1099 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1100 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1101 session_state_observer_list_,
1102 ActiveUserHashChanged(hash));
1105 void UserManagerBase::ChangeUserChildStatus(User* user, bool is_child) {
1106 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1107 if (user->IsSupervised() == is_child)
1108 return;
1109 user->SetIsChild(is_child);
1110 SaveUserType(user->email(), is_child ? user_manager::USER_TYPE_CHILD
1111 : user_manager::USER_TYPE_REGULAR);
1112 FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
1113 session_state_observer_list_,
1114 UserChangedChildStatus(user));
1117 void UserManagerBase::UpdateLoginState() {
1118 if (!chromeos::LoginState::IsInitialized())
1119 return; // LoginState may not be initialized in tests.
1121 chromeos::LoginState::LoggedInState logged_in_state;
1122 logged_in_state = active_user_ ? chromeos::LoginState::LOGGED_IN_ACTIVE
1123 : chromeos::LoginState::LOGGED_IN_NONE;
1125 chromeos::LoginState::LoggedInUserType login_user_type;
1126 if (logged_in_state == chromeos::LoginState::LOGGED_IN_NONE)
1127 login_user_type = chromeos::LoginState::LOGGED_IN_USER_NONE;
1128 else if (is_current_user_owner_)
1129 login_user_type = chromeos::LoginState::LOGGED_IN_USER_OWNER;
1130 else if (active_user_->GetType() == USER_TYPE_GUEST)
1131 login_user_type = chromeos::LoginState::LOGGED_IN_USER_GUEST;
1132 else if (active_user_->GetType() == USER_TYPE_PUBLIC_ACCOUNT)
1133 login_user_type = chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT;
1134 else if (active_user_->GetType() == USER_TYPE_SUPERVISED)
1135 login_user_type = chromeos::LoginState::LOGGED_IN_USER_SUPERVISED;
1136 else if (active_user_->GetType() == USER_TYPE_KIOSK_APP)
1137 login_user_type = chromeos::LoginState::LOGGED_IN_USER_KIOSK_APP;
1138 else
1139 login_user_type = chromeos::LoginState::LOGGED_IN_USER_REGULAR;
1141 if (primary_user_) {
1142 chromeos::LoginState::Get()->SetLoggedInStateAndPrimaryUser(
1143 logged_in_state, login_user_type, primary_user_->username_hash());
1144 } else {
1145 chromeos::LoginState::Get()->SetLoggedInState(logged_in_state,
1146 login_user_type);
1150 void UserManagerBase::SetLRUUser(User* user) {
1151 GetLocalState()->SetString(kLastActiveUser, user->email());
1152 GetLocalState()->CommitPendingWrite();
1154 UserList::iterator it =
1155 std::find(lru_logged_in_users_.begin(), lru_logged_in_users_.end(), user);
1156 if (it != lru_logged_in_users_.end())
1157 lru_logged_in_users_.erase(it);
1158 lru_logged_in_users_.insert(lru_logged_in_users_.begin(), user);
1161 void UserManagerBase::SendGaiaUserLoginMetrics(const std::string& user_id) {
1162 // If this isn't the first time Chrome was run after the system booted,
1163 // assume that Chrome was restarted because a previous session ended.
1164 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1165 chromeos::switches::kFirstExecAfterBoot)) {
1166 const std::string last_email =
1167 GetLocalState()->GetString(kLastLoggedInGaiaUser);
1168 const base::TimeDelta time_to_login =
1169 base::TimeTicks::Now() - manager_creation_time_;
1170 if (!last_email.empty() && user_id != last_email &&
1171 time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
1172 UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
1173 time_to_login.InSeconds(),
1175 kLogoutToLoginDelayMaxSec,
1176 50);
1181 void UserManagerBase::UpdateUserAccountLocale(const std::string& user_id,
1182 const std::string& locale) {
1183 scoped_ptr<std::string> resolved_locale(new std::string());
1184 if (!locale.empty() && locale != GetApplicationLocale()) {
1185 // base::Pased will NULL out |resolved_locale|, so cache the underlying ptr.
1186 std::string* raw_resolved_locale = resolved_locale.get();
1187 blocking_task_runner_->PostTaskAndReply(
1188 FROM_HERE,
1189 base::Bind(ResolveLocale,
1190 locale,
1191 base::Unretained(raw_resolved_locale)),
1192 base::Bind(&UserManagerBase::DoUpdateAccountLocale,
1193 weak_factory_.GetWeakPtr(),
1194 user_id,
1195 base::Passed(&resolved_locale)));
1196 } else {
1197 resolved_locale.reset(new std::string(locale));
1198 DoUpdateAccountLocale(user_id, resolved_locale.Pass());
1202 void UserManagerBase::DoUpdateAccountLocale(
1203 const std::string& user_id,
1204 scoped_ptr<std::string> resolved_locale) {
1205 User* user = FindUserAndModify(user_id);
1206 if (user && resolved_locale)
1207 user->SetAccountLocale(*resolved_locale);
1210 void UserManagerBase::DeleteUser(User* user) {
1211 const bool is_active_user = (user == active_user_);
1212 delete user;
1213 if (is_active_user)
1214 active_user_ = NULL;
1217 } // namespace user_manager