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"
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"
77 void InitLocaleAndInputMethodsForNewUser(
78 UserSessionManager
* session_manager
,
80 const std::string
& public_session_locale
,
81 const std::string
& public_session_input_method
) {
82 PrefService
* prefs
= profile
->GetPrefs();
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
);
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
106 input_method_ids
.push_back(public_session_input_method
);
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(
112 session_manager
->GetDefaultIMEState(profile
)->GetCurrentInputMethod(),
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(),
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
);
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())
169 CertLoader::Get()->StartWithNSSDB(database
);
174 #if defined(ENABLE_RLZ)
175 void UserSessionManagerDelegate::OnRlzInitialized() {
179 UserSessionManagerDelegate::~UserSessionManagerDelegate() {
182 void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
185 UserSessionStateObserver::~UserSessionStateObserver() {
189 UserSessionManager
* UserSessionManager::GetInstance() {
190 return Singleton
<UserSessionManager
,
191 DefaultSingletonTraits
<UserSessionManager
> >::get();
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
,
207 true /* path is absolute */,
208 false /* don't create */);
214 void UserSessionManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
215 registry
->RegisterStringPref(prefs::kRLZBrand
, std::string());
216 registry
->RegisterBooleanPref(prefs::kRLZDisabled
, false);
219 UserSessionManager::UserSessionManager()
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
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();
254 CreateUserSession(user_context
, has_auth_cookies
);
256 if (!has_active_session
)
259 // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
260 // ready to be used (http://crbug.com/361528).
261 NotifyUserLoggedIn();
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()) {
289 user_manager::User
* user
=
290 ProfileHelper::Get()->GetUserByProfile(user_profile
);
292 if (!net::NetworkChangeNotifier::IsOffline()) {
293 pending_signin_restore_sessions_
.erase(user
->email());
294 RestoreAuthSessionImpl(user_profile
, false /* has_auth_cookies */);
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
));
329 base::PostTaskAndReplyWithResult(
330 base::WorkerPool::GetTaskRunner(false).get(),
332 base::Bind(&base::PathExists
, GetRlzDisabledFlagPath()),
333 base::Bind(&UserSessionManager::InitRlzImpl
, AsWeakPtr(), profile
));
337 OAuth2LoginManager::SessionRestoreStrategy
338 UserSessionManager::GetSigninSessionRestoreStrategy() {
339 return session_restore_strategy_
;
342 void UserSessionManager::SetFirstLoginPrefs(
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()) {
359 *chrome_client_id
= chrome_client_id_
;
360 *chrome_client_secret
= chrome_client_secret_
;
364 void UserSessionManager::SetAppModeChromeClientOAuthInfo(
365 const std::string
& chrome_client_id
,
366 const std::string
& chrome_client_secret
) {
367 if (!chrome::IsRunningInForcedAppMode())
370 chrome_client_id_
= chrome_client_id
;
371 chrome_client_secret_
= chrome_client_secret
;
374 bool UserSessionManager::RespectLocalePreference(
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
)
383 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
384 if (!user
|| (user_manager
->IsUserLoggedIn() &&
385 user
!= user_manager
->GetPrimaryUser())) {
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)
394 const PrefService
* prefs
= profile
->GetPrefs();
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
) +
426 : (std::string("account_locale - unused. ")))
427 << " Selected '" << pref_locale
<< "'";
428 profile
->ChangeAppLocale(
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
);
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_
)
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
;
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;
491 case OAuth2LoginManager::SESSION_RESTORE_DONE
:
492 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_VALID
;
494 case OAuth2LoginManager::SESSION_RESTORE_FAILED
:
495 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
;
497 case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
:
498 connection_error
= true;
500 case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED
:
501 case OAuth2LoginManager::SESSION_RESTORE_PREPARING
:
502 case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS
:
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(),
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_
)
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
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
) {
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();
558 if (!(*it
)->is_profile_created())
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(),
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
,
643 void UserSessionManager::OnProfileCreated(const UserContext
& user_context
,
644 bool is_incognito_profile
,
646 Profile::CreateStatus status
) {
650 case Profile::CREATE_STATUS_CREATED
:
651 // Profile created but before initializing extensions and promo resources.
652 InitProfilePreferences(profile
, user_context
);
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());
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
:
671 void UserSessionManager::InitProfilePreferences(
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
) {
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
));
717 delegate_
->OnProfilePrepared(profile
);
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
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
=
750 ProfileAuthData::Transfer(
751 authenticator_
->authentication_profile(),
753 transfer_auth_cookies_and_channel_ids_on_first_login
,
754 transfer_saml_auth_cookies_on_subsequent_login
,
755 base::Bind(&UserSessionManager::CompleteProfileCreateAfterAuthTransfer
,
761 FinalizePrepareProfile(profile
);
764 void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
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();
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());
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
) {
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
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?
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
;
849 session_restore_strategy_
=
850 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN
;
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
;
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
)) {
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()
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();
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
910 RLZTracker::InitRlzFromProfileDelayed(
912 user_manager::UserManager::Get()->IsCurrentUserNew(),
914 base::TimeDelta::FromMilliseconds(abs(ping_delay
)));
916 delegate_
->OnRlzInitialized();
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()) {
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();
939 crl_set
->StartInitialLoad(cus
, path
);
943 void UserSessionManager::OnRestoreActiveSessions(
944 const SessionManagerClient::ActiveSessionsMap
& sessions
,
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();
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
)
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();
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();
992 const user_manager::User
* user
= (*it
);
993 if (user
->email() == user_id
) {
994 user_already_logged_in
= true;
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
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
1029 // TODO(xiyuan): Revisit this when adding tests.
1030 if (!base::SysInfo::IsRunningOnChromeOS())
1033 // Only update Easy unlock keys for regular user.
1034 // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
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
)
1041 // Bail if |user_context| does not have secret.
1042 if (user_context
.GetKey()->GetSecret().empty())
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;
1056 key_manager
->RefreshKeys(
1059 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished
,
1061 user_context
.GetUserID()));
1063 key_manager
->RemoveKeys(
1066 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished
,
1068 user_context
.GetUserID()));
1072 void UserSessionManager::OnEasyUnlockKeyOpsFinished(
1073 const std::string
& user_id
,
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.
1093 input_method::InputMethodManager
* manager
=
1094 input_method::InputMethodManager::Get();
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
];
1104 // Profile can be NULL in tests.
1105 state
= input_method::InputMethodManager::Get()->CreateNewState(profile
);
1106 default_ime_states_
[profile
] = 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