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.
4
5#include "components/user_manager/user_manager_base.h"
6
7#include <cstddef>
8#include <set>
9
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"
36
37namespace user_manager {
38namespace {
39
40// A vector pref of the the regular users known on this device, arranged in LRU
41// order.
42const char kRegularUsers[] = "LoggedInUsers";
43
44// A dictionary that maps user IDs to the displayed name.
45const char kUserDisplayName[] = "UserDisplayName";
46
47// A dictionary that maps user IDs to the user's given name.
48const char kUserGivenName[] = "UserGivenName";
49
50// A dictionary that maps user IDs to the displayed (non-canonical) emails.
51const char kUserDisplayEmail[] = "UserDisplayEmail";
52
53// A dictionary that maps user IDs to OAuth token presence flag.
54const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
55
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.
58const char kUserForceOnlineSignin[] = "UserForceOnlineSignin";
59
60// A string pref containing the ID of the last user who logged in if it was
61// a regular user or an empty string if it was another type of user (guest,
62// kiosk, public account, etc.).
63const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser";
64
65// A string pref containing the ID of the last active user.
66// In case of browser crash, this pref will be used to set active user after
67// session restore.
68const char kLastActiveUser[] = "LastActiveUser";
69
70// Upper bound for a histogram metric reporting the amount of time between
71// one regular user logging out and a different regular user logging in.
72const int kLogoutToLoginDelayMaxSec = 1800;
73
74// Callback that is called after user removal is complete.
75void OnRemoveUserComplete(const std::string& user_email,
76                          bool success,
77                          cryptohome::MountError return_code) {
78  // Log the error, but there's not much we can do.
79  if (!success) {
80    LOG(ERROR) << "Removal of cryptohome for " << user_email
81               << " failed, return code: " << return_code;
82  }
83}
84
85// Runs on SequencedWorkerPool thread. Passes resolved locale to UI thread.
86void ResolveLocale(const std::string& raw_locale,
87                   std::string* resolved_locale) {
88  ignore_result(l10n_util::CheckAndResolveLocale(raw_locale, resolved_locale));
89}
90
91}  // namespace
92
93// static
94void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
95  registry->RegisterListPref(kRegularUsers);
96  registry->RegisterStringPref(kLastLoggedInRegularUser, std::string());
97  registry->RegisterDictionaryPref(kUserDisplayName);
98  registry->RegisterDictionaryPref(kUserGivenName);
99  registry->RegisterDictionaryPref(kUserDisplayEmail);
100  registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
101  registry->RegisterDictionaryPref(kUserForceOnlineSignin);
102  registry->RegisterStringPref(kLastActiveUser, std::string());
103}
104
105UserManagerBase::UserManagerBase(
106    scoped_refptr<base::TaskRunner> task_runner,
107    scoped_refptr<base::TaskRunner> blocking_task_runner)
108    : active_user_(NULL),
109      primary_user_(NULL),
110      user_loading_stage_(STAGE_NOT_LOADED),
111      session_started_(false),
112      is_current_user_owner_(false),
113      is_current_user_new_(false),
114      is_current_user_ephemeral_regular_user_(false),
115      ephemeral_users_enabled_(false),
116      manager_creation_time_(base::TimeTicks::Now()),
117      last_session_active_user_initialized_(false),
118      task_runner_(task_runner),
119      blocking_task_runner_(blocking_task_runner),
120      weak_factory_(this) {
121  UpdateLoginState();
122}
123
124UserManagerBase::~UserManagerBase() {
125  // Can't use STLDeleteElements because of the private destructor of User.
126  for (UserList::iterator it = users_.begin(); it != users_.end();
127       it = users_.erase(it)) {
128    DeleteUser(*it);
129  }
130  // These are pointers to the same User instances that were in users_ list.
131  logged_in_users_.clear();
132  lru_logged_in_users_.clear();
133
134  DeleteUser(active_user_);
135}
136
137void UserManagerBase::Shutdown() {
138  DCHECK(task_runner_->RunsTasksOnCurrentThread());
139}
140
141const UserList& UserManagerBase::GetUsers() const {
142  const_cast<UserManagerBase*>(this)->EnsureUsersLoaded();
143  return users_;
144}
145
146const UserList& UserManagerBase::GetLoggedInUsers() const {
147  return logged_in_users_;
148}
149
150const UserList& UserManagerBase::GetLRULoggedInUsers() const {
151  return lru_logged_in_users_;
152}
153
154const std::string& UserManagerBase::GetOwnerEmail() const {
155  return owner_email_;
156}
157
158void UserManagerBase::UserLoggedIn(const std::string& user_id,
159                                   const std::string& username_hash,
160                                   bool browser_restart) {
161  DCHECK(task_runner_->RunsTasksOnCurrentThread());
162
163  if (!last_session_active_user_initialized_) {
164    last_session_active_user_ = GetLocalState()->GetString(kLastActiveUser);
165    last_session_active_user_initialized_ = true;
166  }
167
168  User* user = FindUserInListAndModify(user_id);
169  if (active_user_ && user) {
170    user->set_is_logged_in(true);
171    user->set_username_hash(username_hash);
172    logged_in_users_.push_back(user);
173    lru_logged_in_users_.push_back(user);
174
175    // Reset the new user flag if the user already exists.
176    SetIsCurrentUserNew(false);
177    NotifyUserAddedToSession(user, true /* user switch pending */);
178
179    return;
180  }
181
182  if (user_id == chromeos::login::kGuestUserName) {
183    GuestUserLoggedIn();
184  } else if (user_id == chromeos::login::kRetailModeUserName) {
185    RetailModeUserLoggedIn();
186  } else if (IsKioskApp(user_id)) {
187    KioskAppLoggedIn(user_id);
188  } else if (IsDemoApp(user_id)) {
189    DemoAccountLoggedIn();
190  } else {
191    EnsureUsersLoaded();
192
193    if (user && user->GetType() == USER_TYPE_PUBLIC_ACCOUNT) {
194      PublicAccountUserLoggedIn(user);
195    } else if ((user && user->GetType() == USER_TYPE_SUPERVISED) ||
196               (!user &&
197                gaia::ExtractDomainName(user_id) ==
198                    chromeos::login::kSupervisedUserDomain)) {
199      SupervisedUserLoggedIn(user_id);
200    } else if (browser_restart && IsPublicAccountMarkedForRemoval(user_id)) {
201      PublicAccountUserLoggedIn(User::CreatePublicAccountUser(user_id));
202    } else if (user_id != GetOwnerEmail() && !user &&
203               (AreEphemeralUsersEnabled() || browser_restart)) {
204      RegularUserLoggedInAsEphemeral(user_id);
205    } else {
206      RegularUserLoggedIn(user_id);
207    }
208  }
209
210  DCHECK(active_user_);
211  active_user_->set_is_logged_in(true);
212  active_user_->set_is_active(true);
213  active_user_->set_username_hash(username_hash);
214
215  // Place user who just signed in to the top of the logged in users.
216  logged_in_users_.insert(logged_in_users_.begin(), active_user_);
217  SetLRUUser(active_user_);
218
219  if (!primary_user_) {
220    primary_user_ = active_user_;
221    if (primary_user_->GetType() == USER_TYPE_REGULAR)
222      SendRegularUserLoginMetrics(user_id);
223  }
224
225  UMA_HISTOGRAM_ENUMERATION(
226      "UserManager.LoginUserType", active_user_->GetType(), NUM_USER_TYPES);
227
228  GetLocalState()->SetString(
229      kLastLoggedInRegularUser,
230      (active_user_->GetType() == USER_TYPE_REGULAR) ? user_id : "");
231
232  NotifyOnLogin();
233  PerformPostUserLoggedInActions(browser_restart);
234}
235
236void UserManagerBase::SwitchActiveUser(const std::string& user_id) {
237  User* user = FindUserAndModify(user_id);
238  if (!user) {
239    NOTREACHED() << "Switching to a non-existing user";
240    return;
241  }
242  if (user == active_user_) {
243    NOTREACHED() << "Switching to a user who is already active";
244    return;
245  }
246  if (!user->is_logged_in()) {
247    NOTREACHED() << "Switching to a user that is not logged in";
248    return;
249  }
250  if (user->GetType() != USER_TYPE_REGULAR) {
251    NOTREACHED() << "Switching to a non-regular user";
252    return;
253  }
254  if (user->username_hash().empty()) {
255    NOTREACHED() << "Switching to a user that doesn't have username_hash set";
256    return;
257  }
258
259  DCHECK(active_user_);
260  active_user_->set_is_active(false);
261  user->set_is_active(true);
262  active_user_ = user;
263
264  // Move the user to the front.
265  SetLRUUser(active_user_);
266
267  NotifyActiveUserHashChanged(active_user_->username_hash());
268  NotifyActiveUserChanged(active_user_);
269}
270
271void UserManagerBase::SwitchToLastActiveUser() {
272  if (last_session_active_user_.empty())
273    return;
274
275  if (GetActiveUser()->email() != last_session_active_user_)
276    SwitchActiveUser(last_session_active_user_);
277
278  // Make sure that this function gets run only once.
279  last_session_active_user_.clear();
280}
281
282void UserManagerBase::SessionStarted() {
283  DCHECK(task_runner_->RunsTasksOnCurrentThread());
284  session_started_ = true;
285
286  UpdateLoginState();
287  session_manager::SessionManager::Get()->SetSessionState(
288      session_manager::SESSION_STATE_ACTIVE);
289
290  if (IsCurrentUserNew()) {
291    // Make sure that the new user's data is persisted to Local State.
292    GetLocalState()->CommitPendingWrite();
293  }
294}
295
296void UserManagerBase::RemoveUser(const std::string& user_id,
297                                 RemoveUserDelegate* delegate) {
298  DCHECK(task_runner_->RunsTasksOnCurrentThread());
299
300  if (!CanUserBeRemoved(FindUser(user_id)))
301    return;
302
303  RemoveUserInternal(user_id, delegate);
304}
305
306void UserManagerBase::RemoveUserInternal(const std::string& user_email,
307                                         RemoveUserDelegate* delegate) {
308  RemoveNonOwnerUserInternal(user_email, delegate);
309}
310
311void UserManagerBase::RemoveNonOwnerUserInternal(const std::string& user_email,
312                                                 RemoveUserDelegate* delegate) {
313  if (delegate)
314    delegate->OnBeforeUserRemoved(user_email);
315  RemoveUserFromList(user_email);
316  cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
317      user_email, base::Bind(&OnRemoveUserComplete, user_email));
318
319  if (delegate)
320    delegate->OnUserRemoved(user_email);
321}
322
323void UserManagerBase::RemoveUserFromList(const std::string& user_id) {
324  DCHECK(task_runner_->RunsTasksOnCurrentThread());
325  RemoveNonCryptohomeData(user_id);
326  if (user_loading_stage_ == STAGE_LOADED) {
327    DeleteUser(RemoveRegularOrSupervisedUserFromList(user_id));
328  } else if (user_loading_stage_ == STAGE_LOADING) {
329    DCHECK(gaia::ExtractDomainName(user_id) ==
330           chromeos::login::kSupervisedUserDomain);
331    // Special case, removing partially-constructed supervised user during user
332    // list loading.
333    ListPrefUpdate users_update(GetLocalState(), kRegularUsers);
334    users_update->Remove(base::StringValue(user_id), NULL);
335  } else {
336    NOTREACHED() << "Users are not loaded yet.";
337    return;
338  }
339
340  // Make sure that new data is persisted to Local State.
341  GetLocalState()->CommitPendingWrite();
342}
343
344bool UserManagerBase::IsKnownUser(const std::string& user_id) const {
345  return FindUser(user_id) != NULL;
346}
347
348const User* UserManagerBase::FindUser(const std::string& user_id) const {
349  DCHECK(task_runner_->RunsTasksOnCurrentThread());
350  if (active_user_ && active_user_->email() == user_id)
351    return active_user_;
352  return FindUserInList(user_id);
353}
354
355User* UserManagerBase::FindUserAndModify(const std::string& user_id) {
356  DCHECK(task_runner_->RunsTasksOnCurrentThread());
357  if (active_user_ && active_user_->email() == user_id)
358    return active_user_;
359  return FindUserInListAndModify(user_id);
360}
361
362const User* UserManagerBase::GetLoggedInUser() const {
363  DCHECK(task_runner_->RunsTasksOnCurrentThread());
364  return active_user_;
365}
366
367User* UserManagerBase::GetLoggedInUser() {
368  DCHECK(task_runner_->RunsTasksOnCurrentThread());
369  return active_user_;
370}
371
372const User* UserManagerBase::GetActiveUser() const {
373  DCHECK(task_runner_->RunsTasksOnCurrentThread());
374  return active_user_;
375}
376
377User* UserManagerBase::GetActiveUser() {
378  DCHECK(task_runner_->RunsTasksOnCurrentThread());
379  return active_user_;
380}
381
382const User* UserManagerBase::GetPrimaryUser() const {
383  DCHECK(task_runner_->RunsTasksOnCurrentThread());
384  return primary_user_;
385}
386
387void UserManagerBase::SaveUserOAuthStatus(
388    const std::string& user_id,
389    User::OAuthTokenStatus oauth_token_status) {
390  DCHECK(task_runner_->RunsTasksOnCurrentThread());
391
392  DVLOG(1) << "Saving user OAuth token status in Local State";
393  User* user = FindUserAndModify(user_id);
394  if (user)
395    user->set_oauth_token_status(oauth_token_status);
396
397  // Do not update local state if data stored or cached outside the user's
398  // cryptohome is to be treated as ephemeral.
399  if (IsUserNonCryptohomeDataEphemeral(user_id))
400    return;
401
402  DictionaryPrefUpdate oauth_status_update(GetLocalState(),
403                                           kUserOAuthTokenStatus);
404  oauth_status_update->SetWithoutPathExpansion(
405      user_id,
406      new base::FundamentalValue(static_cast<int>(oauth_token_status)));
407}
408
409void UserManagerBase::SaveForceOnlineSignin(const std::string& user_id,
410                                            bool force_online_signin) {
411  DCHECK(task_runner_->RunsTasksOnCurrentThread());
412
413  // Do not update local state if data stored or cached outside the user's
414  // cryptohome is to be treated as ephemeral.
415  if (IsUserNonCryptohomeDataEphemeral(user_id))
416    return;
417
418  DictionaryPrefUpdate force_online_update(GetLocalState(),
419                                           kUserForceOnlineSignin);
420  force_online_update->SetBooleanWithoutPathExpansion(user_id,
421                                                      force_online_signin);
422}
423
424void UserManagerBase::SaveUserDisplayName(const std::string& user_id,
425                                          const base::string16& display_name) {
426  DCHECK(task_runner_->RunsTasksOnCurrentThread());
427
428  if (User* user = FindUserAndModify(user_id)) {
429    user->set_display_name(display_name);
430
431    // Do not update local state if data stored or cached outside the user's
432    // cryptohome is to be treated as ephemeral.
433    if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
434      DictionaryPrefUpdate display_name_update(GetLocalState(),
435                                               kUserDisplayName);
436      display_name_update->SetWithoutPathExpansion(
437          user_id, new base::StringValue(display_name));
438    }
439  }
440}
441
442base::string16 UserManagerBase::GetUserDisplayName(
443    const std::string& user_id) const {
444  const User* user = FindUser(user_id);
445  return user ? user->display_name() : base::string16();
446}
447
448void UserManagerBase::SaveUserDisplayEmail(const std::string& user_id,
449                                           const std::string& display_email) {
450  DCHECK(task_runner_->RunsTasksOnCurrentThread());
451
452  User* user = FindUserAndModify(user_id);
453  if (!user) {
454    LOG(ERROR) << "User not found: " << user_id;
455    return;  // Ignore if there is no such user.
456  }
457
458  user->set_display_email(display_email);
459
460  // Do not update local state if data stored or cached outside the user's
461  // cryptohome is to be treated as ephemeral.
462  if (IsUserNonCryptohomeDataEphemeral(user_id))
463    return;
464
465  DictionaryPrefUpdate display_email_update(GetLocalState(), kUserDisplayEmail);
466  display_email_update->SetWithoutPathExpansion(
467      user_id, new base::StringValue(display_email));
468}
469
470std::string UserManagerBase::GetUserDisplayEmail(
471    const std::string& user_id) const {
472  const User* user = FindUser(user_id);
473  return user ? user->display_email() : user_id;
474}
475
476void UserManagerBase::UpdateUserAccountData(
477    const std::string& user_id,
478    const UserAccountData& account_data) {
479  DCHECK(task_runner_->RunsTasksOnCurrentThread());
480
481  SaveUserDisplayName(user_id, account_data.display_name());
482
483  if (User* user = FindUserAndModify(user_id)) {
484    base::string16 given_name = account_data.given_name();
485    user->set_given_name(given_name);
486    if (!IsUserNonCryptohomeDataEphemeral(user_id)) {
487      DictionaryPrefUpdate given_name_update(GetLocalState(), kUserGivenName);
488      given_name_update->SetWithoutPathExpansion(
489          user_id, new base::StringValue(given_name));
490    }
491  }
492
493  UpdateUserAccountLocale(user_id, account_data.locale());
494}
495
496// static
497void UserManagerBase::ParseUserList(const base::ListValue& users_list,
498                                    const std::set<std::string>& existing_users,
499                                    std::vector<std::string>* users_vector,
500                                    std::set<std::string>* users_set) {
501  users_vector->clear();
502  users_set->clear();
503  for (size_t i = 0; i < users_list.GetSize(); ++i) {
504    std::string email;
505    if (!users_list.GetString(i, &email) || email.empty()) {
506      LOG(ERROR) << "Corrupt entry in user list at index " << i << ".";
507      continue;
508    }
509    if (existing_users.find(email) != existing_users.end() ||
510        !users_set->insert(email).second) {
511      LOG(ERROR) << "Duplicate user: " << email;
512      continue;
513    }
514    users_vector->push_back(email);
515  }
516}
517
518bool UserManagerBase::IsCurrentUserOwner() const {
519  DCHECK(task_runner_->RunsTasksOnCurrentThread());
520  base::AutoLock lk(is_current_user_owner_lock_);
521  return is_current_user_owner_;
522}
523
524void UserManagerBase::SetCurrentUserIsOwner(bool is_current_user_owner) {
525  DCHECK(task_runner_->RunsTasksOnCurrentThread());
526  {
527    base::AutoLock lk(is_current_user_owner_lock_);
528    is_current_user_owner_ = is_current_user_owner;
529  }
530  UpdateLoginState();
531}
532
533bool UserManagerBase::IsCurrentUserNew() const {
534  DCHECK(task_runner_->RunsTasksOnCurrentThread());
535  return is_current_user_new_;
536}
537
538bool UserManagerBase::IsCurrentUserNonCryptohomeDataEphemeral() const {
539  DCHECK(task_runner_->RunsTasksOnCurrentThread());
540  return IsUserLoggedIn() &&
541         IsUserNonCryptohomeDataEphemeral(GetLoggedInUser()->email());
542}
543
544bool UserManagerBase::CanCurrentUserLock() const {
545  DCHECK(task_runner_->RunsTasksOnCurrentThread());
546  return IsUserLoggedIn() && active_user_->can_lock();
547}
548
549bool UserManagerBase::IsUserLoggedIn() const {
550  DCHECK(task_runner_->RunsTasksOnCurrentThread());
551  return active_user_;
552}
553
554bool UserManagerBase::IsLoggedInAsRegularUser() const {
555  DCHECK(task_runner_->RunsTasksOnCurrentThread());
556  return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_REGULAR;
557}
558
559bool UserManagerBase::IsLoggedInAsDemoUser() const {
560  DCHECK(task_runner_->RunsTasksOnCurrentThread());
561  return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_RETAIL_MODE;
562}
563
564bool UserManagerBase::IsLoggedInAsPublicAccount() const {
565  DCHECK(task_runner_->RunsTasksOnCurrentThread());
566  return IsUserLoggedIn() &&
567         active_user_->GetType() == USER_TYPE_PUBLIC_ACCOUNT;
568}
569
570bool UserManagerBase::IsLoggedInAsGuest() const {
571  DCHECK(task_runner_->RunsTasksOnCurrentThread());
572  return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_GUEST;
573}
574
575bool UserManagerBase::IsLoggedInAsSupervisedUser() const {
576  DCHECK(task_runner_->RunsTasksOnCurrentThread());
577  return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_SUPERVISED;
578}
579
580bool UserManagerBase::IsLoggedInAsKioskApp() const {
581  DCHECK(task_runner_->RunsTasksOnCurrentThread());
582  return IsUserLoggedIn() && active_user_->GetType() == USER_TYPE_KIOSK_APP;
583}
584
585bool UserManagerBase::IsLoggedInAsStub() const {
586  DCHECK(task_runner_->RunsTasksOnCurrentThread());
587  return IsUserLoggedIn() &&
588         active_user_->email() == chromeos::login::kStubUser;
589}
590
591bool UserManagerBase::IsSessionStarted() const {
592  DCHECK(task_runner_->RunsTasksOnCurrentThread());
593  return session_started_;
594}
595
596bool UserManagerBase::IsUserNonCryptohomeDataEphemeral(
597    const std::string& user_id) const {
598  // Data belonging to the guest, retail mode and stub users is always
599  // ephemeral.
600  if (user_id == chromeos::login::kGuestUserName ||
601      user_id == chromeos::login::kRetailModeUserName ||
602      user_id == chromeos::login::kStubUser) {
603    return true;
604  }
605
606  // Data belonging to the owner, anyone found on the user list and obsolete
607  // public accounts whose data has not been removed yet is not ephemeral.
608  if (user_id == GetOwnerEmail() || UserExistsInList(user_id) ||
609      IsPublicAccountMarkedForRemoval(user_id)) {
610    return false;
611  }
612
613  // Data belonging to the currently logged-in user is ephemeral when:
614  // a) The user logged into a regular account while the ephemeral users policy
615  //    was enabled.
616  //    - or -
617  // b) The user logged into any other account type.
618  if (IsUserLoggedIn() && (user_id == GetLoggedInUser()->email()) &&
619      (is_current_user_ephemeral_regular_user_ || !IsLoggedInAsRegularUser())) {
620    return true;
621  }
622
623  // Data belonging to any other user is ephemeral when:
624  // a) Going through the regular login flow and the ephemeral users policy is
625  //    enabled.
626  //    - or -
627  // b) The browser is restarting after a crash.
628  return AreEphemeralUsersEnabled() ||
629         session_manager::SessionManager::HasBrowserRestarted();
630}
631
632void UserManagerBase::AddObserver(UserManager::Observer* obs) {
633  DCHECK(task_runner_->RunsTasksOnCurrentThread());
634  observer_list_.AddObserver(obs);
635}
636
637void UserManagerBase::RemoveObserver(UserManager::Observer* obs) {
638  DCHECK(task_runner_->RunsTasksOnCurrentThread());
639  observer_list_.RemoveObserver(obs);
640}
641
642void UserManagerBase::AddSessionStateObserver(
643    UserManager::UserSessionStateObserver* obs) {
644  DCHECK(task_runner_->RunsTasksOnCurrentThread());
645  session_state_observer_list_.AddObserver(obs);
646}
647
648void UserManagerBase::RemoveSessionStateObserver(
649    UserManager::UserSessionStateObserver* obs) {
650  DCHECK(task_runner_->RunsTasksOnCurrentThread());
651  session_state_observer_list_.RemoveObserver(obs);
652}
653
654void UserManagerBase::NotifyLocalStateChanged() {
655  DCHECK(task_runner_->RunsTasksOnCurrentThread());
656  FOR_EACH_OBSERVER(
657      UserManager::Observer, observer_list_, LocalStateChanged(this));
658}
659
660void UserManagerBase::ForceUpdateState() {
661  UpdateLoginState();
662}
663
664bool UserManagerBase::CanUserBeRemoved(const User* user) const {
665  // Only regular and supervised users are allowed to be manually removed.
666  if (!user || (user->GetType() != USER_TYPE_REGULAR &&
667                user->GetType() != USER_TYPE_SUPERVISED)) {
668    return false;
669  }
670
671  // Sanity check: we must not remove single user unless it's an enterprise
672  // device. This check may seem redundant at a first sight because
673  // this single user must be an owner and we perform special check later
674  // in order not to remove an owner. However due to non-instant nature of
675  // ownership assignment this later check may sometimes fail.
676  // See http://crosbug.com/12723
677  if (users_.size() < 2 && !IsEnterpriseManaged())
678    return false;
679
680  // Sanity check: do not allow any of the the logged in users to be removed.
681  for (UserList::const_iterator it = logged_in_users_.begin();
682       it != logged_in_users_.end();
683       ++it) {
684    if ((*it)->email() == user->email())
685      return false;
686  }
687
688  return true;
689}
690
691bool UserManagerBase::GetEphemeralUsersEnabled() const {
692  return ephemeral_users_enabled_;
693}
694
695void UserManagerBase::SetEphemeralUsersEnabled(bool enabled) {
696  ephemeral_users_enabled_ = enabled;
697}
698
699void UserManagerBase::SetIsCurrentUserNew(bool is_new) {
700  is_current_user_new_ = is_new;
701}
702
703void UserManagerBase::SetOwnerEmail(std::string owner_user_id) {
704  owner_email_ = owner_user_id;
705}
706
707const std::string& UserManagerBase::GetPendingUserSwitchID() const {
708  return pending_user_switch_;
709}
710
711void UserManagerBase::SetPendingUserSwitchID(std::string user_id) {
712  pending_user_switch_ = user_id;
713}
714
715void UserManagerBase::EnsureUsersLoaded() {
716  DCHECK(task_runner_->RunsTasksOnCurrentThread());
717  if (!GetLocalState())
718    return;
719
720  if (user_loading_stage_ != STAGE_NOT_LOADED)
721    return;
722  user_loading_stage_ = STAGE_LOADING;
723
724  PerformPreUserListLoadingActions();
725
726  PrefService* local_state = GetLocalState();
727  const base::ListValue* prefs_regular_users =
728      local_state->GetList(kRegularUsers);
729
730  const base::DictionaryValue* prefs_display_names =
731      local_state->GetDictionary(kUserDisplayName);
732  const base::DictionaryValue* prefs_given_names =
733      local_state->GetDictionary(kUserGivenName);
734  const base::DictionaryValue* prefs_display_emails =
735      local_state->GetDictionary(kUserDisplayEmail);
736
737  // Load public sessions first.
738  std::set<std::string> public_sessions_set;
739  LoadPublicAccounts(&public_sessions_set);
740
741  // Load regular users and supervised users.
742  std::vector<std::string> regular_users;
743  std::set<std::string> regular_users_set;
744  ParseUserList(*prefs_regular_users,
745                public_sessions_set,
746                &regular_users,
747                &regular_users_set);
748  for (std::vector<std::string>::const_iterator it = regular_users.begin();
749       it != regular_users.end();
750       ++it) {
751    User* user = NULL;
752    const std::string domain = gaia::ExtractDomainName(*it);
753    if (domain == chromeos::login::kSupervisedUserDomain)
754      user = User::CreateSupervisedUser(*it);
755    else
756      user = User::CreateRegularUser(*it);
757    user->set_oauth_token_status(LoadUserOAuthStatus(*it));
758    user->set_force_online_signin(LoadForceOnlineSignin(*it));
759    users_.push_back(user);
760
761    base::string16 display_name;
762    if (prefs_display_names->GetStringWithoutPathExpansion(*it,
763                                                           &display_name)) {
764      user->set_display_name(display_name);
765    }
766
767    base::string16 given_name;
768    if (prefs_given_names->GetStringWithoutPathExpansion(*it, &given_name)) {
769      user->set_given_name(given_name);
770    }
771
772    std::string display_email;
773    if (prefs_display_emails->GetStringWithoutPathExpansion(*it,
774                                                            &display_email)) {
775      user->set_display_email(display_email);
776    }
777  }
778
779  user_loading_stage_ = STAGE_LOADED;
780
781  PerformPostUserListLoadingActions();
782}
783
784UserList& UserManagerBase::GetUsersAndModify() {
785  EnsureUsersLoaded();
786  return users_;
787}
788
789const User* UserManagerBase::FindUserInList(const std::string& user_id) const {
790  const UserList& users = GetUsers();
791  for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
792    if ((*it)->email() == user_id)
793      return *it;
794  }
795  return NULL;
796}
797
798const bool UserManagerBase::UserExistsInList(const std::string& user_id) const {
799  const base::ListValue* user_list = GetLocalState()->GetList(kRegularUsers);
800  for (size_t i = 0; i < user_list->GetSize(); ++i) {
801    std::string email;
802    if (user_list->GetString(i, &email) && (user_id == email))
803      return true;
804  }
805  return false;
806}
807
808User* UserManagerBase::FindUserInListAndModify(const std::string& user_id) {
809  UserList& users = GetUsersAndModify();
810  for (UserList::iterator it = users.begin(); it != users.end(); ++it) {
811    if ((*it)->email() == user_id)
812      return *it;
813  }
814  return NULL;
815}
816
817void UserManagerBase::GuestUserLoggedIn() {
818  DCHECK(task_runner_->RunsTasksOnCurrentThread());
819  active_user_ = User::CreateGuestUser();
820}
821
822void UserManagerBase::AddUserRecord(User* user) {
823  // Add the user to the front of the user list.
824  ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
825  prefs_users_update->Insert(0, new base::StringValue(user->email()));
826  users_.insert(users_.begin(), user);
827}
828
829void UserManagerBase::RegularUserLoggedIn(const std::string& user_id) {
830  // Remove the user from the user list.
831  active_user_ = RemoveRegularOrSupervisedUserFromList(user_id);
832
833  // If the user was not found on the user list, create a new user.
834  SetIsCurrentUserNew(!active_user_);
835  if (IsCurrentUserNew()) {
836    active_user_ = User::CreateRegularUser(user_id);
837    active_user_->set_oauth_token_status(LoadUserOAuthStatus(user_id));
838    SaveUserDisplayName(active_user_->email(),
839                        base::UTF8ToUTF16(active_user_->GetAccountName(true)));
840  }
841
842  AddUserRecord(active_user_);
843
844  // Make sure that new data is persisted to Local State.
845  GetLocalState()->CommitPendingWrite();
846}
847
848void UserManagerBase::RegularUserLoggedInAsEphemeral(
849    const std::string& user_id) {
850  DCHECK(task_runner_->RunsTasksOnCurrentThread());
851  SetIsCurrentUserNew(true);
852  is_current_user_ephemeral_regular_user_ = true;
853  active_user_ = User::CreateRegularUser(user_id);
854}
855
856void UserManagerBase::NotifyOnLogin() {
857  DCHECK(task_runner_->RunsTasksOnCurrentThread());
858
859  NotifyActiveUserHashChanged(active_user_->username_hash());
860  NotifyActiveUserChanged(active_user_);
861  UpdateLoginState();
862}
863
864User::OAuthTokenStatus UserManagerBase::LoadUserOAuthStatus(
865    const std::string& user_id) const {
866  DCHECK(task_runner_->RunsTasksOnCurrentThread());
867
868  const base::DictionaryValue* prefs_oauth_status =
869      GetLocalState()->GetDictionary(kUserOAuthTokenStatus);
870  int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
871  if (prefs_oauth_status &&
872      prefs_oauth_status->GetIntegerWithoutPathExpansion(user_id,
873                                                         &oauth_token_status)) {
874    User::OAuthTokenStatus status =
875        static_cast<User::OAuthTokenStatus>(oauth_token_status);
876    HandleUserOAuthTokenStatusChange(user_id, status);
877
878    return status;
879  }
880  return User::OAUTH_TOKEN_STATUS_UNKNOWN;
881}
882
883bool UserManagerBase::LoadForceOnlineSignin(const std::string& user_id) const {
884  DCHECK(task_runner_->RunsTasksOnCurrentThread());
885
886  const base::DictionaryValue* prefs_force_online =
887      GetLocalState()->GetDictionary(kUserForceOnlineSignin);
888  bool force_online_signin = false;
889  if (prefs_force_online) {
890    prefs_force_online->GetBooleanWithoutPathExpansion(user_id,
891                                                       &force_online_signin);
892  }
893  return force_online_signin;
894}
895
896void UserManagerBase::RemoveNonCryptohomeData(const std::string& user_id) {
897  PrefService* prefs = GetLocalState();
898  DictionaryPrefUpdate prefs_display_name_update(prefs, kUserDisplayName);
899  prefs_display_name_update->RemoveWithoutPathExpansion(user_id, NULL);
900
901  DictionaryPrefUpdate prefs_given_name_update(prefs, kUserGivenName);
902  prefs_given_name_update->RemoveWithoutPathExpansion(user_id, NULL);
903
904  DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
905  prefs_display_email_update->RemoveWithoutPathExpansion(user_id, NULL);
906
907  DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
908  prefs_oauth_update->RemoveWithoutPathExpansion(user_id, NULL);
909
910  DictionaryPrefUpdate prefs_force_online_update(prefs, kUserForceOnlineSignin);
911  prefs_force_online_update->RemoveWithoutPathExpansion(user_id, NULL);
912
913  std::string last_active_user = GetLocalState()->GetString(kLastActiveUser);
914  if (user_id == last_active_user)
915    GetLocalState()->SetString(kLastActiveUser, std::string());
916}
917
918User* UserManagerBase::RemoveRegularOrSupervisedUserFromList(
919    const std::string& user_id) {
920  ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
921  prefs_users_update->Clear();
922  User* user = NULL;
923  for (UserList::iterator it = users_.begin(); it != users_.end();) {
924    const std::string user_email = (*it)->email();
925    if (user_email == user_id) {
926      user = *it;
927      it = users_.erase(it);
928    } else {
929      if ((*it)->GetType() == USER_TYPE_REGULAR ||
930          (*it)->GetType() == USER_TYPE_SUPERVISED) {
931        prefs_users_update->Append(new base::StringValue(user_email));
932      }
933      ++it;
934    }
935  }
936  return user;
937}
938
939void UserManagerBase::NotifyActiveUserChanged(const User* active_user) {
940  DCHECK(task_runner_->RunsTasksOnCurrentThread());
941  FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
942                    session_state_observer_list_,
943                    ActiveUserChanged(active_user));
944}
945
946void UserManagerBase::NotifyUserAddedToSession(const User* added_user,
947                                               bool user_switch_pending) {
948  DCHECK(task_runner_->RunsTasksOnCurrentThread());
949  FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
950                    session_state_observer_list_,
951                    UserAddedToSession(added_user));
952}
953
954void UserManagerBase::NotifyActiveUserHashChanged(const std::string& hash) {
955  DCHECK(task_runner_->RunsTasksOnCurrentThread());
956  FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver,
957                    session_state_observer_list_,
958                    ActiveUserHashChanged(hash));
959}
960
961void UserManagerBase::UpdateLoginState() {
962  if (!chromeos::LoginState::IsInitialized())
963    return;  // LoginState may not be intialized in tests.
964
965  chromeos::LoginState::LoggedInState logged_in_state;
966  logged_in_state = active_user_ ? chromeos::LoginState::LOGGED_IN_ACTIVE
967                                 : chromeos::LoginState::LOGGED_IN_NONE;
968
969  chromeos::LoginState::LoggedInUserType login_user_type;
970  if (logged_in_state == chromeos::LoginState::LOGGED_IN_NONE)
971    login_user_type = chromeos::LoginState::LOGGED_IN_USER_NONE;
972  else if (is_current_user_owner_)
973    login_user_type = chromeos::LoginState::LOGGED_IN_USER_OWNER;
974  else if (active_user_->GetType() == USER_TYPE_GUEST)
975    login_user_type = chromeos::LoginState::LOGGED_IN_USER_GUEST;
976  else if (active_user_->GetType() == USER_TYPE_RETAIL_MODE)
977    login_user_type = chromeos::LoginState::LOGGED_IN_USER_RETAIL_MODE;
978  else if (active_user_->GetType() == USER_TYPE_PUBLIC_ACCOUNT)
979    login_user_type = chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT;
980  else if (active_user_->GetType() == USER_TYPE_SUPERVISED)
981    login_user_type = chromeos::LoginState::LOGGED_IN_USER_SUPERVISED;
982  else if (active_user_->GetType() == USER_TYPE_KIOSK_APP)
983    login_user_type = chromeos::LoginState::LOGGED_IN_USER_KIOSK_APP;
984  else
985    login_user_type = chromeos::LoginState::LOGGED_IN_USER_REGULAR;
986
987  if (primary_user_) {
988    chromeos::LoginState::Get()->SetLoggedInStateAndPrimaryUser(
989        logged_in_state, login_user_type, primary_user_->username_hash());
990  } else {
991    chromeos::LoginState::Get()->SetLoggedInState(logged_in_state,
992                                                  login_user_type);
993  }
994}
995
996void UserManagerBase::SetLRUUser(User* user) {
997  GetLocalState()->SetString(kLastActiveUser, user->email());
998  GetLocalState()->CommitPendingWrite();
999
1000  UserList::iterator it =
1001      std::find(lru_logged_in_users_.begin(), lru_logged_in_users_.end(), user);
1002  if (it != lru_logged_in_users_.end())
1003    lru_logged_in_users_.erase(it);
1004  lru_logged_in_users_.insert(lru_logged_in_users_.begin(), user);
1005}
1006
1007void UserManagerBase::SendRegularUserLoginMetrics(const std::string& user_id) {
1008  // If this isn't the first time Chrome was run after the system booted,
1009  // assume that Chrome was restarted because a previous session ended.
1010  if (!CommandLine::ForCurrentProcess()->HasSwitch(
1011          chromeos::switches::kFirstExecAfterBoot)) {
1012    const std::string last_email =
1013        GetLocalState()->GetString(kLastLoggedInRegularUser);
1014    const base::TimeDelta time_to_login =
1015        base::TimeTicks::Now() - manager_creation_time_;
1016    if (!last_email.empty() && user_id != last_email &&
1017        time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
1018      UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
1019                                  time_to_login.InSeconds(),
1020                                  0,
1021                                  kLogoutToLoginDelayMaxSec,
1022                                  50);
1023    }
1024  }
1025}
1026
1027void UserManagerBase::UpdateUserAccountLocale(const std::string& user_id,
1028                                              const std::string& locale) {
1029  scoped_ptr<std::string> resolved_locale(new std::string());
1030  if (!locale.empty() && locale != GetApplicationLocale()) {
1031    // base::Pased will NULL out |resolved_locale|, so cache the underlying ptr.
1032    std::string* raw_resolved_locale = resolved_locale.get();
1033    blocking_task_runner_->PostTaskAndReply(
1034        FROM_HERE,
1035        base::Bind(ResolveLocale,
1036                   locale,
1037                   base::Unretained(raw_resolved_locale)),
1038        base::Bind(&UserManagerBase::DoUpdateAccountLocale,
1039                   weak_factory_.GetWeakPtr(),
1040                   user_id,
1041                   base::Passed(&resolved_locale)));
1042  } else {
1043    resolved_locale.reset(new std::string(locale));
1044    DoUpdateAccountLocale(user_id, resolved_locale.Pass());
1045  }
1046}
1047
1048void UserManagerBase::DoUpdateAccountLocale(
1049    const std::string& user_id,
1050    scoped_ptr<std::string> resolved_locale) {
1051  User* user = FindUserAndModify(user_id);
1052  if (user && resolved_locale)
1053    user->SetAccountLocale(*resolved_locale);
1054}
1055
1056void UserManagerBase::DeleteUser(User* user) {
1057  const bool is_active_user = (user == active_user_);
1058  delete user;
1059  if (is_active_user)
1060    active_user_ = NULL;
1061}
1062
1063}  // namespace user_manager
1064