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