Fix a startup crash from https://crrev.com/5eb3ae10901fa65657abc902910265ab492c5dbf
[chromium-blink-merge.git] / chrome / browser / chromeos / login / session / user_session_manager.cc
blob236c38aeabbec729c613752c2783c748a978451b
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 "chrome/browser/chromeos/login/session/user_session_manager.h"
7 #include <string>
9 #include "base/base_paths.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/path_service.h"
14 #include "base/prefs/pref_member.h"
15 #include "base/prefs/pref_registry_simple.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string16.h"
18 #include "base/sys_info.h"
19 #include "base/task_runner_util.h"
20 #include "base/threading/worker_pool.h"
21 #include "chrome/browser/app_mode/app_mode_utils.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/browser_process_platform_part_chromeos.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/chromeos/base/locale_util.h"
26 #include "chrome/browser/chromeos/boot_times_loader.h"
27 #include "chrome/browser/chromeos/input_method/input_method_util.h"
28 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
29 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
30 #include "chrome/browser/chromeos/login/profile_auth_data.h"
31 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
32 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
33 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
34 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
35 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
36 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
37 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
38 #include "chrome/browser/chromeos/profiles/profile_helper.h"
39 #include "chrome/browser/chromeos/settings/cros_settings.h"
40 #include "chrome/browser/first_run/first_run.h"
41 #include "chrome/browser/google/google_brand_chromeos.h"
42 #include "chrome/browser/lifetime/application_lifetime.h"
43 #include "chrome/browser/net/crl_set_fetcher.h"
44 #include "chrome/browser/net/nss_context.h"
45 #include "chrome/browser/profiles/profile.h"
46 #include "chrome/browser/profiles/profile_manager.h"
47 #include "chrome/browser/rlz/rlz.h"
48 #include "chrome/browser/signin/easy_unlock_service.h"
49 #include "chrome/browser/signin/signin_manager_factory.h"
50 #include "chrome/common/chrome_switches.h"
51 #include "chrome/common/logging_chrome.h"
52 #include "chrome/common/pref_names.h"
53 #include "chromeos/cert_loader.h"
54 #include "chromeos/chromeos_switches.h"
55 #include "chromeos/cryptohome/cryptohome_util.h"
56 #include "chromeos/dbus/cryptohome_client.h"
57 #include "chromeos/dbus/dbus_thread_manager.h"
58 #include "chromeos/dbus/session_manager_client.h"
59 #include "chromeos/ime/input_method_manager.h"
60 #include "chromeos/network/portal_detector/network_portal_detector.h"
61 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
62 #include "chromeos/settings/cros_settings_names.h"
63 #include "components/component_updater/component_updater_service.h"
64 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
65 #include "components/session_manager/core/session_manager.h"
66 #include "components/signin/core/browser/signin_manager_base.h"
67 #include "components/user_manager/user.h"
68 #include "components/user_manager/user_manager.h"
69 #include "components/user_manager/user_type.h"
70 #include "content/public/browser/browser_thread.h"
71 #include "content/public/browser/notification_service.h"
73 namespace chromeos {
75 namespace {
77 void InitLocaleAndInputMethodsForNewUser(
78 UserSessionManager* session_manager,
79 Profile* profile,
80 const std::string& public_session_locale,
81 const std::string& public_session_input_method) {
82 PrefService* prefs = profile->GetPrefs();
83 std::string locale;
84 if (!public_session_locale.empty()) {
85 // If this is a public session and the user chose a |public_session_locale|,
86 // write it to |prefs| so that the UI switches to it.
87 locale = public_session_locale;
88 prefs->SetString(prefs::kApplicationLocale, locale);
90 // Suppress the locale change dialog.
91 prefs->SetString(prefs::kApplicationLocaleAccepted, locale);
92 } else {
93 // Otherwise, assume that the session will use the current UI locale.
94 locale = g_browser_process->GetApplicationLocale();
97 // First, we'll set kLanguagePreloadEngines.
98 input_method::InputMethodManager* manager =
99 input_method::InputMethodManager::Get();
100 std::vector<std::string> input_method_ids;
102 if (!public_session_input_method.empty()) {
103 // If this is a public session and the user chose a
104 // |public_session_input_method|, set kLanguagePreloadEngines to this input
105 // method only.
106 input_method_ids.push_back(public_session_input_method);
107 } else {
108 // Otherwise, set kLanguagePreloadEngines to a list of input methods derived
109 // from the |locale| and the currently active input method.
110 manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
111 locale,
112 session_manager->GetDefaultIMEState(profile)->GetCurrentInputMethod(),
113 &input_method_ids);
116 // Save the input methods in the user's preferences.
117 StringPrefMember language_preload_engines;
118 language_preload_engines.Init(prefs::kLanguagePreloadEngines, prefs);
119 language_preload_engines.SetValue(JoinString(input_method_ids, ','));
120 BootTimesLoader::Get()->AddLoginTimeMarker("IMEStarted", false);
122 // Second, we'll set kLanguagePreferredLanguages.
123 std::vector<std::string> language_codes;
125 // The current locale should be on the top.
126 language_codes.push_back(locale);
128 // Add input method IDs based on the input methods, as there may be
129 // input methods that are unrelated to the current locale. Example: the
130 // hardware keyboard layout xkb:us::eng is used for logging in, but the
131 // UI language is set to French. In this case, we should set "fr,en"
132 // to the preferred languages preference.
133 std::vector<std::string> candidates;
134 manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
135 input_method_ids, &candidates);
136 for (size_t i = 0; i < candidates.size(); ++i) {
137 const std::string& candidate = candidates[i];
138 // Skip if it's already in language_codes.
139 if (std::count(language_codes.begin(), language_codes.end(),
140 candidate) == 0) {
141 language_codes.push_back(candidate);
145 // Save the preferred languages in the user's preferences.
146 StringPrefMember language_preferred_languages;
147 language_preferred_languages.Init(prefs::kLanguagePreferredLanguages, prefs);
148 language_preferred_languages.SetValue(JoinString(language_codes, ','));
151 #if defined(ENABLE_RLZ)
152 // Flag file that disables RLZ tracking, when present.
153 const base::FilePath::CharType kRLZDisabledFlagName[] =
154 FILE_PATH_LITERAL(".rlz_disabled");
156 base::FilePath GetRlzDisabledFlagPath() {
157 base::FilePath homedir;
158 PathService::Get(base::DIR_HOME, &homedir);
159 return homedir.Append(kRLZDisabledFlagName);
161 #endif
163 // Callback to GetNSSCertDatabaseForProfile. It starts CertLoader using the
164 // provided NSS database. It must be called for primary user only.
165 void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) {
166 if (!CertLoader::IsInitialized())
167 return;
169 CertLoader::Get()->StartWithNSSDB(database);
172 } // namespace
174 #if defined(ENABLE_RLZ)
175 void UserSessionManagerDelegate::OnRlzInitialized() {
177 #endif
179 UserSessionManagerDelegate::~UserSessionManagerDelegate() {
182 void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
185 UserSessionStateObserver::~UserSessionStateObserver() {
188 // static
189 UserSessionManager* UserSessionManager::GetInstance() {
190 return Singleton<UserSessionManager,
191 DefaultSingletonTraits<UserSessionManager> >::get();
194 // static
195 void UserSessionManager::OverrideHomedir() {
196 // Override user homedir, check for ProfileManager being initialized as
197 // it may not exist in unit tests.
198 if (g_browser_process->profile_manager()) {
199 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
200 if (user_manager->GetLoggedInUsers().size() == 1) {
201 base::FilePath homedir = ProfileHelper::GetProfilePathByUserIdHash(
202 user_manager->GetPrimaryUser()->username_hash());
203 // This path has been either created by cryptohome (on real Chrome OS
204 // device) or by ProfileManager (on chromeos=1 desktop builds).
205 PathService::OverrideAndCreateIfNeeded(base::DIR_HOME,
206 homedir,
207 true /* path is absolute */,
208 false /* don't create */);
213 // static
214 void UserSessionManager::RegisterPrefs(PrefRegistrySimple* registry) {
215 registry->RegisterStringPref(prefs::kRLZBrand, std::string());
216 registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
219 UserSessionManager::UserSessionManager()
220 : delegate_(NULL),
221 has_auth_cookies_(false),
222 user_sessions_restored_(false),
223 user_sessions_restore_in_progress_(false),
224 exit_after_session_restore_(false),
225 session_restore_strategy_(
226 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN),
227 running_easy_unlock_key_ops_(false) {
228 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
229 user_manager::UserManager::Get()->AddSessionStateObserver(this);
232 UserSessionManager::~UserSessionManager() {
233 // UserManager is destroyed before singletons, so we need to check if it
234 // still exists.
235 // TODO(nkostylev): fix order of destruction of UserManager
236 // / UserSessionManager objects.
237 if (user_manager::UserManager::IsInitialized())
238 user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
239 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
242 void UserSessionManager::StartSession(
243 const UserContext& user_context,
244 scoped_refptr<Authenticator> authenticator,
245 bool has_auth_cookies,
246 bool has_active_session,
247 UserSessionManagerDelegate* delegate) {
248 authenticator_ = authenticator;
249 delegate_ = delegate;
251 VLOG(1) << "Starting session for " << user_context.GetUserID();
253 PreStartSession();
254 CreateUserSession(user_context, has_auth_cookies);
256 if (!has_active_session)
257 StartCrosSession();
259 // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
260 // ready to be used (http://crbug.com/361528).
261 NotifyUserLoggedIn();
262 PrepareProfile();
265 void UserSessionManager::PerformPostUserLoggedInActions() {
266 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
267 if (user_manager->GetLoggedInUsers().size() == 1) {
268 if (NetworkPortalDetector::IsInitialized()) {
269 NetworkPortalDetector::Get()->SetStrategy(
270 PortalDetectorStrategy::STRATEGY_ID_SESSION);
275 void UserSessionManager::RestoreAuthenticationSession(Profile* user_profile) {
276 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
277 // We need to restore session only for logged in regular (GAIA) users.
278 // Note: stub user is a special case that is used for tests, running
279 // linux_chromeos build on dev workstations w/o user_id parameters.
280 // Stub user is considered to be a regular GAIA user but it has special
281 // user_id (kStubUser) and certain services like restoring OAuth session are
282 // explicitly disabled for it.
283 if (!user_manager->IsUserLoggedIn() ||
284 !user_manager->IsLoggedInAsRegularUser() ||
285 user_manager->IsLoggedInAsStub()) {
286 return;
289 user_manager::User* user =
290 ProfileHelper::Get()->GetUserByProfile(user_profile);
291 DCHECK(user);
292 if (!net::NetworkChangeNotifier::IsOffline()) {
293 pending_signin_restore_sessions_.erase(user->email());
294 RestoreAuthSessionImpl(user_profile, false /* has_auth_cookies */);
295 } else {
296 // Even if we're online we should wait till initial
297 // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
298 // end up canceling all request when initial network connection type is
299 // processed. See http://crbug.com/121643.
300 pending_signin_restore_sessions_.insert(user->email());
304 void UserSessionManager::RestoreActiveSessions() {
305 user_sessions_restore_in_progress_ = true;
306 DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
307 base::Bind(&UserSessionManager::OnRestoreActiveSessions,
308 base::Unretained(this)));
311 bool UserSessionManager::UserSessionsRestored() const {
312 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
313 return user_sessions_restored_;
316 bool UserSessionManager::UserSessionsRestoreInProgress() const {
317 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
318 return user_sessions_restore_in_progress_;
321 void UserSessionManager::InitRlz(Profile* profile) {
322 #if defined(ENABLE_RLZ)
323 if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
324 // Read brand code asynchronously from an OEM data and repost ourselves.
325 google_brand::chromeos::InitBrand(
326 base::Bind(&UserSessionManager::InitRlz, AsWeakPtr(), profile));
327 return;
329 base::PostTaskAndReplyWithResult(
330 base::WorkerPool::GetTaskRunner(false).get(),
331 FROM_HERE,
332 base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
333 base::Bind(&UserSessionManager::InitRlzImpl, AsWeakPtr(), profile));
334 #endif
337 OAuth2LoginManager::SessionRestoreStrategy
338 UserSessionManager::GetSigninSessionRestoreStrategy() {
339 return session_restore_strategy_;
342 void UserSessionManager::SetFirstLoginPrefs(
343 Profile* profile,
344 const std::string& public_session_locale,
345 const std::string& public_session_input_method) {
346 VLOG(1) << "Setting first login prefs";
347 InitLocaleAndInputMethodsForNewUser(
348 this, profile, public_session_locale, public_session_input_method);
351 bool UserSessionManager::GetAppModeChromeClientOAuthInfo(
352 std::string* chrome_client_id, std::string* chrome_client_secret) {
353 if (!chrome::IsRunningInForcedAppMode() ||
354 chrome_client_id_.empty() ||
355 chrome_client_secret_.empty()) {
356 return false;
359 *chrome_client_id = chrome_client_id_;
360 *chrome_client_secret = chrome_client_secret_;
361 return true;
364 void UserSessionManager::SetAppModeChromeClientOAuthInfo(
365 const std::string& chrome_client_id,
366 const std::string& chrome_client_secret) {
367 if (!chrome::IsRunningInForcedAppMode())
368 return;
370 chrome_client_id_ = chrome_client_id;
371 chrome_client_secret_ = chrome_client_secret;
374 bool UserSessionManager::RespectLocalePreference(
375 Profile* profile,
376 const user_manager::User* user,
377 const locale_util::SwitchLanguageCallback& callback) const {
378 // TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
379 // the Google user profile.
380 if (g_browser_process == NULL)
381 return false;
383 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
384 if (!user || (user_manager->IsUserLoggedIn() &&
385 user != user_manager->GetPrimaryUser())) {
386 return false;
389 // In case of multi-profiles session we don't apply profile locale
390 // because it is unsafe.
391 if (user_manager->GetLoggedInUsers().size() != 1)
392 return false;
394 const PrefService* prefs = profile->GetPrefs();
395 if (prefs == NULL)
396 return false;
398 std::string pref_locale;
399 const std::string pref_app_locale =
400 prefs->GetString(prefs::kApplicationLocale);
401 const std::string pref_bkup_locale =
402 prefs->GetString(prefs::kApplicationLocaleBackup);
404 pref_locale = pref_app_locale;
405 if (pref_locale.empty())
406 pref_locale = pref_bkup_locale;
408 const std::string* account_locale = NULL;
409 if (pref_locale.empty() && user->has_gaia_account()) {
410 if (user->GetAccountLocale() == NULL)
411 return false; // wait until Account profile is loaded.
412 account_locale = user->GetAccountLocale();
413 pref_locale = *account_locale;
415 const std::string global_app_locale =
416 g_browser_process->GetApplicationLocale();
417 if (pref_locale.empty())
418 pref_locale = global_app_locale;
419 DCHECK(!pref_locale.empty());
420 VLOG(1) << "RespectLocalePreference: "
421 << "app_locale='" << pref_app_locale << "', "
422 << "bkup_locale='" << pref_bkup_locale << "', "
423 << (account_locale != NULL
424 ? (std::string("account_locale='") + (*account_locale) +
425 "'. ")
426 : (std::string("account_locale - unused. ")))
427 << " Selected '" << pref_locale << "'";
428 profile->ChangeAppLocale(
429 pref_locale,
430 user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT ?
431 Profile::APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN :
432 Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
434 // Here we don't enable keyboard layouts for normal users. Input methods
435 // are set up when the user first logs in. Then the user may customize the
436 // input methods. Hence changing input methods here, just because the user's
437 // UI language is different from the login screen UI language, is not
438 // desirable. Note that input method preferences are synced, so users can use
439 // their farovite input methods as soon as the preferences are synced.
441 // For Guest mode, user locale preferences will never get initialized.
442 // So input methods should be enabled somewhere.
443 const bool enable_layouts =
444 user_manager::UserManager::Get()->IsLoggedInAsGuest();
445 locale_util::SwitchLanguage(
446 pref_locale, enable_layouts, false /* login_layouts_only */, callback);
448 return true;
451 bool UserSessionManager::NeedsToUpdateEasyUnlockKeys() const {
452 return EasyUnlockService::IsSignInEnabled() &&
453 !user_context_.GetUserID().empty() &&
454 user_context_.GetUserType() == user_manager::USER_TYPE_REGULAR &&
455 user_context_.GetKey() && !user_context_.GetKey()->GetSecret().empty();
458 bool UserSessionManager::CheckEasyUnlockKeyOps(const base::Closure& callback) {
459 if (!running_easy_unlock_key_ops_)
460 return false;
462 // Assumes only one deferred callback is needed.
463 DCHECK(easy_unlock_key_ops_finished_callback_.is_null());
465 easy_unlock_key_ops_finished_callback_ = callback;
466 return true;
469 void UserSessionManager::AddSessionStateObserver(
470 chromeos::UserSessionStateObserver* observer) {
471 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
472 session_state_observer_list_.AddObserver(observer);
475 void UserSessionManager::RemoveSessionStateObserver(
476 chromeos::UserSessionStateObserver* observer) {
477 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
478 session_state_observer_list_.RemoveObserver(observer);
481 void UserSessionManager::OnSessionRestoreStateChanged(
482 Profile* user_profile,
483 OAuth2LoginManager::SessionRestoreState state) {
484 user_manager::User::OAuthTokenStatus user_status =
485 user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN;
486 OAuth2LoginManager* login_manager =
487 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
489 bool connection_error = false;
490 switch (state) {
491 case OAuth2LoginManager::SESSION_RESTORE_DONE:
492 user_status = user_manager::User::OAUTH2_TOKEN_STATUS_VALID;
493 break;
494 case OAuth2LoginManager::SESSION_RESTORE_FAILED:
495 user_status = user_manager::User::OAUTH2_TOKEN_STATUS_INVALID;
496 break;
497 case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
498 connection_error = true;
499 break;
500 case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
501 case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
502 case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
503 return;
506 // We should not be clearing existing token state if that was a connection
507 // error. http://crbug.com/295245
508 if (!connection_error) {
509 // We are in one of "done" states here.
510 user_manager::UserManager::Get()->SaveUserOAuthStatus(
511 user_manager::UserManager::Get()->GetLoggedInUser()->email(),
512 user_status);
515 login_manager->RemoveObserver(this);
518 void UserSessionManager::OnNewRefreshTokenAvaiable(Profile* user_profile) {
519 // Check if we were waiting to restart chrome.
520 if (!exit_after_session_restore_)
521 return;
523 OAuth2LoginManager* login_manager =
524 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
525 login_manager->RemoveObserver(this);
527 // Mark user auth token status as valid.
528 user_manager::UserManager::Get()->SaveUserOAuthStatus(
529 user_manager::UserManager::Get()->GetLoggedInUser()->email(),
530 user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
532 VLOG(1) << "Exiting after new refresh token fetched";
534 // We need to restart cleanly in this case to make sure OAuth2 RT is actually
535 // saved.
536 chrome::AttemptRestart();
539 void UserSessionManager::OnConnectionTypeChanged(
540 net::NetworkChangeNotifier::ConnectionType type) {
541 bool is_running_test =
542 base::CommandLine::ForCurrentProcess()->HasSwitch(
543 ::switches::kTestName) ||
544 base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType);
545 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
546 if (type == net::NetworkChangeNotifier::CONNECTION_NONE ||
547 !user_manager->IsUserLoggedIn() ||
548 !user_manager->IsLoggedInAsRegularUser() ||
549 user_manager->IsLoggedInAsStub() || is_running_test) {
550 return;
553 // Need to iterate over all users and their OAuth2 session state.
554 const user_manager::UserList& users = user_manager->GetLoggedInUsers();
555 for (user_manager::UserList::const_iterator it = users.begin();
556 it != users.end();
557 ++it) {
558 if (!(*it)->is_profile_created())
559 continue;
561 Profile* user_profile = ProfileHelper::Get()->GetProfileByUserUnsafe(*it);
562 bool should_restore_session =
563 pending_signin_restore_sessions_.find((*it)->email()) !=
564 pending_signin_restore_sessions_.end();
565 OAuth2LoginManager* login_manager =
566 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
567 if (login_manager->state() ==
568 OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
569 // If we come online for the first time after successful offline login,
570 // we need to kick off OAuth token verification process again.
571 login_manager->ContinueSessionRestore();
572 } else if (should_restore_session) {
573 pending_signin_restore_sessions_.erase((*it)->email());
574 RestoreAuthSessionImpl(user_profile, false /* has_auth_cookies */);
579 void UserSessionManager::OnProfilePrepared(Profile* profile) {
580 LoginUtils::Get()->DoBrowserLaunch(profile, NULL); // host_, not needed here
582 if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestName)) {
583 // Did not log in (we crashed or are debugging), need to restore Sync.
584 // TODO(nkostylev): Make sure that OAuth state is restored correctly for all
585 // users once it is fully multi-profile aware. http://crbug.com/238987
586 // For now if we have other user pending sessions they'll override OAuth
587 // session restore for previous users.
588 UserSessionManager::GetInstance()->RestoreAuthenticationSession(profile);
591 // Restore other user sessions if any.
592 RestorePendingUserSessions();
595 void UserSessionManager::CreateUserSession(const UserContext& user_context,
596 bool has_auth_cookies) {
597 user_context_ = user_context;
598 has_auth_cookies_ = has_auth_cookies;
599 InitSessionRestoreStrategy();
602 void UserSessionManager::PreStartSession() {
603 // Switch log file as soon as possible.
604 if (base::SysInfo::IsRunningOnChromeOS())
605 logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
608 void UserSessionManager::StartCrosSession() {
609 BootTimesLoader* btl = BootTimesLoader::Get();
610 btl->AddLoginTimeMarker("StartSession-Start", false);
611 DBusThreadManager::Get()->GetSessionManagerClient()->
612 StartSession(user_context_.GetUserID());
613 btl->AddLoginTimeMarker("StartSession-End", false);
616 void UserSessionManager::NotifyUserLoggedIn() {
617 BootTimesLoader* btl = BootTimesLoader::Get();
618 btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
619 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
620 user_manager->UserLoggedIn(user_context_.GetUserID(),
621 user_context_.GetUserIDHash(),
622 false);
623 btl->AddLoginTimeMarker("UserLoggedIn-End", false);
626 void UserSessionManager::PrepareProfile() {
627 bool is_demo_session =
628 DemoAppLauncher::IsDemoAppSession(user_context_.GetUserID());
630 // TODO(nkostylev): Figure out whether demo session is using the right profile
631 // path or not. See https://codereview.chromium.org/171423009
632 g_browser_process->profile_manager()->CreateProfileAsync(
633 ProfileHelper::GetProfilePathByUserIdHash(user_context_.GetUserIDHash()),
634 base::Bind(&UserSessionManager::OnProfileCreated,
635 AsWeakPtr(),
636 user_context_,
637 is_demo_session),
638 base::string16(),
639 base::string16(),
640 std::string());
643 void UserSessionManager::OnProfileCreated(const UserContext& user_context,
644 bool is_incognito_profile,
645 Profile* profile,
646 Profile::CreateStatus status) {
647 CHECK(profile);
649 switch (status) {
650 case Profile::CREATE_STATUS_CREATED:
651 // Profile created but before initializing extensions and promo resources.
652 InitProfilePreferences(profile, user_context);
653 break;
654 case Profile::CREATE_STATUS_INITIALIZED:
655 // Profile is created, extensions and promo resources are initialized.
656 // At this point all other Chrome OS services will be notified that it is
657 // safe to use this profile.
658 UserProfileInitialized(profile,
659 is_incognito_profile,
660 user_context.GetUserID());
661 break;
662 case Profile::CREATE_STATUS_LOCAL_FAIL:
663 case Profile::CREATE_STATUS_REMOTE_FAIL:
664 case Profile::CREATE_STATUS_CANCELED:
665 case Profile::MAX_CREATE_STATUS:
666 NOTREACHED();
667 break;
671 void UserSessionManager::InitProfilePreferences(
672 Profile* profile,
673 const UserContext& user_context) {
674 user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
675 if (user->is_active()) {
676 input_method::InputMethodManager* manager =
677 input_method::InputMethodManager::Get();
678 manager->SetState(GetDefaultIMEState(profile));
680 if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
681 SetFirstLoginPrefs(profile,
682 user_context.GetPublicSessionLocale(),
683 user_context.GetPublicSessionInputMethod());
686 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
687 user_manager::User* active_user =
688 user_manager::UserManager::Get()->GetActiveUser();
689 std::string supervised_user_sync_id =
690 ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
691 active_user->email());
692 profile->GetPrefs()->SetString(prefs::kSupervisedUserId,
693 supervised_user_sync_id);
694 } else if (user_manager::UserManager::Get()->IsLoggedInAsRegularUser()) {
695 // Make sure that the google service username is properly set (we do this
696 // on every sign in, not just the first login, to deal with existing
697 // profiles that might not have it set yet).
698 SigninManagerBase* signin_manager =
699 SigninManagerFactory::GetForProfile(profile);
700 signin_manager->SetAuthenticatedUsername(user_context.GetUserID());
704 void UserSessionManager::UserProfileInitialized(Profile* profile,
705 bool is_incognito_profile,
706 const std::string& user_id) {
707 if (is_incognito_profile) {
708 profile->OnLogin();
709 // Send the notification before creating the browser so additional objects
710 // that need the profile (e.g. the launcher) can be created first.
711 content::NotificationService::current()->Notify(
712 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
713 content::NotificationService::AllSources(),
714 content::Details<Profile>(profile));
716 if (delegate_)
717 delegate_->OnProfilePrepared(profile);
719 return;
722 BootTimesLoader* btl = BootTimesLoader::Get();
723 btl->AddLoginTimeMarker("UserProfileGotten", false);
725 if (user_context_.IsUsingOAuth()) {
726 // Retrieve the policy that indicates whether to continue copying
727 // authentication cookies set by a SAML IdP on subsequent logins after the
728 // first.
729 bool transfer_saml_auth_cookies_on_subsequent_login = false;
730 if (has_auth_cookies_ &&
731 g_browser_process->platform_part()->
732 browser_policy_connector_chromeos()->GetUserAffiliation(user_id) ==
733 policy::USER_AFFILIATION_MANAGED) {
734 CrosSettings::Get()->GetBoolean(
735 kAccountsPrefTransferSAMLCookies,
736 &transfer_saml_auth_cookies_on_subsequent_login);
739 // Transfers authentication-related data from the profile that was used for
740 // authentication to the user's profile. The proxy authentication state is
741 // transferred unconditionally. If the user authenticated via an auth
742 // extension, authentication cookies and channel IDs will be transferred as
743 // well when the user's cookie jar is empty. If the cookie jar is not empty,
744 // the authentication states in the login profile and the user's profile
745 // must be merged using /MergeSession instead. Authentication cookies set by
746 // a SAML IdP will also be transferred when the user's cookie jar is not
747 // empty if |transfer_saml_auth_cookies_on_subsequent_login| is true.
748 const bool transfer_auth_cookies_and_channel_ids_on_first_login =
749 has_auth_cookies_;
750 ProfileAuthData::Transfer(
751 authenticator_->authentication_profile(),
752 profile,
753 transfer_auth_cookies_and_channel_ids_on_first_login,
754 transfer_saml_auth_cookies_on_subsequent_login,
755 base::Bind(&UserSessionManager::CompleteProfileCreateAfterAuthTransfer,
756 AsWeakPtr(),
757 profile));
758 return;
761 FinalizePrepareProfile(profile);
764 void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
765 Profile* profile) {
766 RestoreAuthSessionImpl(profile, has_auth_cookies_);
767 FinalizePrepareProfile(profile);
770 void UserSessionManager::FinalizePrepareProfile(Profile* profile) {
771 BootTimesLoader* btl = BootTimesLoader::Get();
773 // Own TPM device if, for any reason, it has not been done in EULA screen.
774 CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient();
775 btl->AddLoginTimeMarker("TPMOwn-Start", false);
776 if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
777 if (cryptohome_util::TpmIsOwned())
778 client->CallTpmClearStoredPasswordAndBlock();
779 else
780 client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
782 btl->AddLoginTimeMarker("TPMOwn-End", false);
784 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
785 if (user_manager->IsLoggedInAsRegularUser()) {
786 SAMLOfflineSigninLimiter* saml_offline_signin_limiter =
787 SAMLOfflineSigninLimiterFactory::GetForProfile(profile);
788 if (saml_offline_signin_limiter)
789 saml_offline_signin_limiter->SignedIn(user_context_.GetAuthFlow());
792 profile->OnLogin();
794 g_browser_process->platform_part()->SessionManager()->SetSessionState(
795 session_manager::SESSION_STATE_LOGGED_IN_NOT_ACTIVE);
797 // Send the notification before creating the browser so additional objects
798 // that need the profile (e.g. the launcher) can be created first.
799 content::NotificationService::current()->Notify(
800 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
801 content::NotificationService::AllSources(),
802 content::Details<Profile>(profile));
804 // Initialize various services only for primary user.
805 const user_manager::User* user =
806 ProfileHelper::Get()->GetUserByProfile(profile);
807 if (user_manager->GetPrimaryUser() == user) {
808 InitRlz(profile);
809 InitializeCerts(profile);
810 InitializeCRLSetFetcher(user);
813 UpdateEasyUnlockKeys(user_context_);
814 user_context_.ClearSecrets();
816 // TODO(nkostylev): This pointer should probably never be NULL, but it looks
817 // like LoginUtilsImpl::OnProfileCreated() may be getting called before
818 // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is
819 // killed during shutdown in tests -- see http://crosbug.com/18269. Replace
820 // this 'if' statement with a CHECK(delegate_) once the underlying issue is
821 // resolved.
822 if (delegate_)
823 delegate_->OnProfilePrepared(profile);
826 void UserSessionManager::InitSessionRestoreStrategy() {
827 CommandLine* command_line = CommandLine::ForCurrentProcess();
828 bool in_app_mode = chrome::IsRunningInForcedAppMode();
830 // Are we in kiosk app mode?
831 if (in_app_mode) {
832 if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
833 oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
834 ::switches::kAppModeOAuth2Token);
837 if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
838 user_context_.SetAuthCode(command_line->GetSwitchValueASCII(
839 ::switches::kAppModeAuthCode));
842 DCHECK(!has_auth_cookies_);
843 if (!user_context_.GetAuthCode().empty()) {
844 session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
845 } else if (!oauth2_refresh_token_.empty()) {
846 session_restore_strategy_ =
847 OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
848 } else {
849 session_restore_strategy_ =
850 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
852 return;
855 if (has_auth_cookies_) {
856 session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR;
857 } else if (!user_context_.GetAuthCode().empty()) {
858 session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
859 } else {
860 session_restore_strategy_ =
861 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
865 void UserSessionManager::RestoreAuthSessionImpl(Profile* profile,
866 bool restore_from_auth_cookies) {
867 CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
868 !restore_from_auth_cookies);
870 if (chrome::IsRunningInForcedAppMode() ||
871 CommandLine::ForCurrentProcess()->HasSwitch(
872 chromeos::switches::kDisableGaiaServices)) {
873 return;
876 exit_after_session_restore_ = false;
878 // Remove legacy OAuth1 token if we have one. If it's valid, we should already
879 // have OAuth2 refresh token in OAuth2TokenService that could be used to
880 // retrieve all other tokens and user_context.
881 OAuth2LoginManager* login_manager =
882 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
883 login_manager->AddObserver(this);
884 login_manager->RestoreSession(
885 authenticator_.get() && authenticator_->authentication_profile()
886 ? authenticator_->authentication_profile()->GetRequestContext()
887 : NULL,
888 session_restore_strategy_,
889 oauth2_refresh_token_,
890 user_context_.GetAuthCode());
893 void UserSessionManager::InitRlzImpl(Profile* profile, bool disabled) {
894 #if defined(ENABLE_RLZ)
895 PrefService* local_state = g_browser_process->local_state();
896 if (disabled) {
897 // Empty brand code means an organic install (no RLZ pings are sent).
898 google_brand::chromeos::ClearBrandForCurrentSession();
900 if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
901 // When switching to RLZ enabled/disabled state, clear all recorded events.
902 RLZTracker::ClearRlzState();
903 local_state->SetBoolean(prefs::kRLZDisabled, disabled);
905 // Init the RLZ library.
906 int ping_delay = profile->GetPrefs()->GetInteger(
907 first_run::GetPingDelayPrefName().c_str());
908 // Negative ping delay means to send ping immediately after a first search is
909 // recorded.
910 RLZTracker::InitRlzFromProfileDelayed(
911 profile,
912 user_manager::UserManager::Get()->IsCurrentUserNew(),
913 ping_delay < 0,
914 base::TimeDelta::FromMilliseconds(abs(ping_delay)));
915 if (delegate_)
916 delegate_->OnRlzInitialized();
917 #endif
920 void UserSessionManager::InitializeCerts(Profile* profile) {
921 // Now that the user profile has been initialized
922 // |GetNSSCertDatabaseForProfile| is safe to be used.
923 if (CertLoader::IsInitialized() && base::SysInfo::IsRunningOnChromeOS()) {
924 GetNSSCertDatabaseForProfile(profile,
925 base::Bind(&OnGetNSSCertDatabaseForUser));
929 void UserSessionManager::InitializeCRLSetFetcher(
930 const user_manager::User* user) {
931 const std::string username_hash = user->username_hash();
932 if (!username_hash.empty()) {
933 base::FilePath path;
934 path = ProfileHelper::GetProfilePathByUserIdHash(username_hash);
935 component_updater::ComponentUpdateService* cus =
936 g_browser_process->component_updater();
937 CRLSetFetcher* crl_set = g_browser_process->crl_set_fetcher();
938 if (crl_set && cus)
939 crl_set->StartInitialLoad(cus, path);
943 void UserSessionManager::OnRestoreActiveSessions(
944 const SessionManagerClient::ActiveSessionsMap& sessions,
945 bool success) {
946 if (!success) {
947 LOG(ERROR) << "Could not get list of active user sessions after crash.";
948 // If we could not get list of active user sessions it is safer to just
949 // sign out so that we don't get in the inconsistent state.
950 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
951 return;
954 // One profile has been already loaded on browser start.
955 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
956 DCHECK(user_manager->GetLoggedInUsers().size() == 1);
957 DCHECK(user_manager->GetActiveUser());
958 std::string active_user_id = user_manager->GetActiveUser()->email();
960 SessionManagerClient::ActiveSessionsMap::const_iterator it;
961 for (it = sessions.begin(); it != sessions.end(); ++it) {
962 if (active_user_id == it->first)
963 continue;
964 pending_user_sessions_[it->first] = it->second;
966 RestorePendingUserSessions();
969 void UserSessionManager::RestorePendingUserSessions() {
970 if (pending_user_sessions_.empty()) {
971 user_manager::UserManager::Get()->SwitchToLastActiveUser();
972 NotifyPendingUserSessionsRestoreFinished();
973 return;
976 // Get next user to restore sessions and delete it from list.
977 SessionManagerClient::ActiveSessionsMap::const_iterator it =
978 pending_user_sessions_.begin();
979 std::string user_id = it->first;
980 std::string user_id_hash = it->second;
981 DCHECK(!user_id.empty());
982 DCHECK(!user_id_hash.empty());
983 pending_user_sessions_.erase(user_id);
985 // Check that this user is not logged in yet.
986 user_manager::UserList logged_in_users =
987 user_manager::UserManager::Get()->GetLoggedInUsers();
988 bool user_already_logged_in = false;
989 for (user_manager::UserList::const_iterator it = logged_in_users.begin();
990 it != logged_in_users.end();
991 ++it) {
992 const user_manager::User* user = (*it);
993 if (user->email() == user_id) {
994 user_already_logged_in = true;
995 break;
998 DCHECK(!user_already_logged_in);
1000 if (!user_already_logged_in) {
1001 UserContext user_context(user_id);
1002 user_context.SetUserIDHash(user_id_hash);
1003 user_context.SetIsUsingOAuth(false);
1005 // Will call OnProfilePrepared() once profile has been loaded.
1006 StartSession(user_context,
1007 NULL, // authenticator
1008 false, // has_auth_cookies
1009 true, // has_active_session
1010 this);
1011 } else {
1012 RestorePendingUserSessions();
1016 void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() {
1017 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1018 user_sessions_restored_ = true;
1019 user_sessions_restore_in_progress_ = false;
1020 FOR_EACH_OBSERVER(chromeos::UserSessionStateObserver,
1021 session_state_observer_list_,
1022 PendingUserSessionsRestoreFinished());
1025 void UserSessionManager::UpdateEasyUnlockKeys(const UserContext& user_context) {
1026 // Skip key update because FakeCryptohomeClient always return success
1027 // and RemoveKey op expects a failure to stop. As a result, some tests would
1028 // timeout.
1029 // TODO(xiyuan): Revisit this when adding tests.
1030 if (!base::SysInfo::IsRunningOnChromeOS())
1031 return;
1033 // Only update Easy unlock keys for regular user.
1034 // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
1035 // authenticator.
1036 const user_manager::User* user =
1037 user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
1038 if (!user || user->GetType() != user_manager::USER_TYPE_REGULAR)
1039 return;
1041 // Bail if |user_context| does not have secret.
1042 if (user_context.GetKey()->GetSecret().empty())
1043 return;
1045 const base::ListValue* device_list = NULL;
1046 EasyUnlockService* easy_unlock_service = EasyUnlockService::GetForUser(*user);
1047 if (easy_unlock_service) {
1048 device_list = easy_unlock_service->GetRemoteDevices();
1049 easy_unlock_service->SetHardlockState(
1050 EasyUnlockScreenlockStateHandler::NO_HARDLOCK);
1053 EasyUnlockKeyManager* key_manager = GetEasyUnlockKeyManager();
1054 running_easy_unlock_key_ops_ = true;
1055 if (device_list) {
1056 key_manager->RefreshKeys(
1057 user_context,
1058 *device_list,
1059 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished,
1060 AsWeakPtr(),
1061 user_context.GetUserID()));
1062 } else {
1063 key_manager->RemoveKeys(
1064 user_context,
1066 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished,
1067 AsWeakPtr(),
1068 user_context.GetUserID()));
1072 void UserSessionManager::OnEasyUnlockKeyOpsFinished(
1073 const std::string& user_id,
1074 bool success) {
1075 running_easy_unlock_key_ops_ = false;
1076 if (!easy_unlock_key_ops_finished_callback_.is_null())
1077 easy_unlock_key_ops_finished_callback_.Run();
1079 const user_manager::User* user =
1080 user_manager::UserManager::Get()->FindUser(user_id);
1081 EasyUnlockService* easy_unlock_service =
1082 EasyUnlockService::GetForUser(*user);
1083 easy_unlock_service->CheckCryptohomeKeysAndMaybeHardlock();
1086 void UserSessionManager::ActiveUserChanged(
1087 const user_manager::User* active_user) {
1088 Profile* profile = ProfileHelper::Get()->GetProfileByUser(active_user);
1089 // If profile has not yet been initialized, delay initialization of IME.
1090 if (!profile)
1091 return;
1093 input_method::InputMethodManager* manager =
1094 input_method::InputMethodManager::Get();
1095 manager->SetState(
1096 GetDefaultIMEState(ProfileHelper::Get()->GetProfileByUser(active_user)));
1099 scoped_refptr<input_method::InputMethodManager::State>
1100 UserSessionManager::GetDefaultIMEState(Profile* profile) {
1101 scoped_refptr<input_method::InputMethodManager::State> state =
1102 default_ime_states_[profile];
1103 if (!state.get()) {
1104 // Profile can be NULL in tests.
1105 state = input_method::InputMethodManager::Get()->CreateNewState(profile);
1106 default_ime_states_[profile] = state;
1108 return state;
1111 EasyUnlockKeyManager* UserSessionManager::GetEasyUnlockKeyManager() {
1112 if (!easy_unlock_key_manager_)
1113 easy_unlock_key_manager_.reset(new EasyUnlockKeyManager);
1115 return easy_unlock_key_manager_.get();
1118 } // namespace chromeos