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/metrics/histogram_macros.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_member.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/sys_info.h"
21 #include "base/task_runner_util.h"
22 #include "base/thread_task_runner_handle.h"
23 #include "base/threading/worker_pool.h"
24 #include "chrome/browser/about_flags.h"
25 #include "chrome/browser/app_mode/app_mode_utils.h"
26 #include "chrome/browser/browser_process.h"
27 #include "chrome/browser/browser_process_platform_part_chromeos.h"
28 #include "chrome/browser/browser_shutdown.h"
29 #include "chrome/browser/chrome_notification_types.h"
30 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
31 #include "chrome/browser/chromeos/base/locale_util.h"
32 #include "chrome/browser/chromeos/boot_times_recorder.h"
33 #include "chrome/browser/chromeos/first_run/first_run.h"
34 #include "chrome/browser/chromeos/input_method/input_method_util.h"
35 #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h"
36 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
37 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
38 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
39 #include "chrome/browser/chromeos/login/helper.h"
40 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
41 #include "chrome/browser/chromeos/login/profile_auth_data.h"
42 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
43 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
44 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
45 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
46 #include "chrome/browser/chromeos/login/signin/token_handle_fetcher.h"
47 #include "chrome/browser/chromeos/login/startup_utils.h"
48 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
49 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
50 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
51 #include "chrome/browser/chromeos/login/user_flow.h"
52 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
53 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
54 #include "chrome/browser/chromeos/login/wizard_controller.h"
55 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
56 #include "chrome/browser/chromeos/profiles/profile_helper.h"
57 #include "chrome/browser/chromeos/settings/cros_settings.h"
58 #include "chrome/browser/component_updater/ev_whitelist_component_installer.h"
59 #include "chrome/browser/first_run/first_run.h"
60 #include "chrome/browser/google/google_brand_chromeos.h"
61 #include "chrome/browser/lifetime/application_lifetime.h"
62 #include "chrome/browser/net/crl_set_fetcher.h"
63 #include "chrome/browser/net/nss_context.h"
64 #include "chrome/browser/pref_service_flags_storage.h"
65 #include "chrome/browser/prefs/session_startup_pref.h"
66 #include "chrome/browser/profiles/profile.h"
67 #include "chrome/browser/profiles/profile_manager.h"
68 #include "chrome/browser/signin/account_tracker_service_factory.h"
69 #include "chrome/browser/signin/easy_unlock_service.h"
70 #include "chrome/browser/signin/signin_manager_factory.h"
71 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
72 #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h"
73 #include "chrome/browser/ui/app_list/start_page_service.h"
74 #include "chrome/browser/ui/startup/startup_browser_creator.h"
75 #include "chrome/common/chrome_switches.h"
76 #include "chrome/common/logging_chrome.h"
77 #include "chrome/common/pref_names.h"
78 #include "chromeos/cert_loader.h"
79 #include "chromeos/chromeos_switches.h"
80 #include "chromeos/cryptohome/cryptohome_util.h"
81 #include "chromeos/dbus/cryptohome_client.h"
82 #include "chromeos/dbus/dbus_thread_manager.h"
83 #include "chromeos/dbus/session_manager_client.h"
84 #include "chromeos/login/auth/stub_authenticator.h"
85 #include "chromeos/login/user_names.h"
86 #include "chromeos/network/portal_detector/network_portal_detector.h"
87 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
88 #include "chromeos/settings/cros_settings_names.h"
89 #include "components/component_updater/component_updater_service.h"
90 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
91 #include "components/session_manager/core/session_manager.h"
92 #include "components/signin/core/browser/account_tracker_service.h"
93 #include "components/signin/core/browser/signin_manager_base.h"
94 #include "components/user_manager/user.h"
95 #include "components/user_manager/user_manager.h"
96 #include "components/user_manager/user_type.h"
97 #include "content/public/browser/browser_thread.h"
98 #include "content/public/browser/notification_service.h"
99 #include "content/public/browser/storage_partition.h"
100 #include "ui/base/ime/chromeos/input_method_manager.h"
101 #include "url/gurl.h"
103 #if defined(ENABLE_RLZ)
104 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
105 #include "components/rlz/rlz_tracker.h"
112 // Milliseconds until we timeout our attempt to fetch flags from the child
114 static const int kFlagsFetchingLoginTimeoutMs
= 1000;
116 // ChromeVox tutorial URL (used in place of "getting started" url when
117 // accessibility is enabled).
118 const char kChromeVoxTutorialURLPattern
[] =
119 "http://www.chromevox.com/tutorial/index.html?lang=%s";
121 void InitLocaleAndInputMethodsForNewUser(
122 UserSessionManager
* session_manager
,
124 const std::string
& public_session_locale
,
125 const std::string
& public_session_input_method
) {
126 PrefService
* prefs
= profile
->GetPrefs();
128 if (!public_session_locale
.empty()) {
129 // If this is a public session and the user chose a |public_session_locale|,
130 // write it to |prefs| so that the UI switches to it.
131 locale
= public_session_locale
;
132 prefs
->SetString(prefs::kApplicationLocale
, locale
);
134 // Suppress the locale change dialog.
135 prefs
->SetString(prefs::kApplicationLocaleAccepted
, locale
);
137 // Otherwise, assume that the session will use the current UI locale.
138 locale
= g_browser_process
->GetApplicationLocale();
141 // First, we'll set kLanguagePreloadEngines.
142 input_method::InputMethodManager
* manager
=
143 input_method::InputMethodManager::Get();
144 std::vector
<std::string
> input_method_ids
;
146 if (!public_session_input_method
.empty()) {
147 // If this is a public session and the user chose a
148 // |public_session_input_method|, set kLanguagePreloadEngines to this input
150 input_method_ids
.push_back(public_session_input_method
);
152 // Otherwise, set kLanguagePreloadEngines to a list of input methods derived
153 // from the |locale| and the currently active input method.
154 manager
->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
156 session_manager
->GetDefaultIMEState(profile
)->GetCurrentInputMethod(),
160 // Save the input methods in the user's preferences.
161 StringPrefMember language_preload_engines
;
162 language_preload_engines
.Init(prefs::kLanguagePreloadEngines
, prefs
);
163 language_preload_engines
.SetValue(base::JoinString(input_method_ids
, ","));
164 BootTimesRecorder::Get()->AddLoginTimeMarker("IMEStarted", false);
166 // Second, we'll set kLanguagePreferredLanguages.
167 std::vector
<std::string
> language_codes
;
169 // The current locale should be on the top.
170 language_codes
.push_back(locale
);
172 // Add input method IDs based on the input methods, as there may be
173 // input methods that are unrelated to the current locale. Example: the
174 // hardware keyboard layout xkb:us::eng is used for logging in, but the
175 // UI language is set to French. In this case, we should set "fr,en"
176 // to the preferred languages preference.
177 std::vector
<std::string
> candidates
;
178 manager
->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
179 input_method_ids
, &candidates
);
180 for (size_t i
= 0; i
< candidates
.size(); ++i
) {
181 const std::string
& candidate
= candidates
[i
];
182 // Skip if it's already in language_codes.
183 if (std::count(language_codes
.begin(), language_codes
.end(),
185 language_codes
.push_back(candidate
);
189 // Save the preferred languages in the user's preferences.
190 prefs
->SetString(prefs::kLanguagePreferredLanguages
,
191 base::JoinString(language_codes
, ","));
193 // Indicate that we need to merge the syncable input methods when we sync,
194 // since we have not applied the synced prefs before.
195 prefs
->SetBoolean(prefs::kLanguageShouldMergeInputMethods
, true);
198 #if defined(ENABLE_RLZ)
199 // Flag file that disables RLZ tracking, when present.
200 const base::FilePath::CharType kRLZDisabledFlagName
[] =
201 FILE_PATH_LITERAL(".rlz_disabled");
203 base::FilePath
GetRlzDisabledFlagPath() {
204 base::FilePath homedir
;
205 PathService::Get(base::DIR_HOME
, &homedir
);
206 return homedir
.Append(kRLZDisabledFlagName
);
210 // Callback to GetNSSCertDatabaseForProfile. It starts CertLoader using the
211 // provided NSS database. It must be called for primary user only.
212 void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase
* database
) {
213 if (!CertLoader::IsInitialized())
216 CertLoader::Get()->StartWithNSSDB(database
);
219 // Returns new CommandLine with per-user flags.
220 base::CommandLine
CreatePerSessionCommandLine(Profile
* profile
) {
221 base::CommandLine
user_flags(base::CommandLine::NO_PROGRAM
);
222 about_flags::PrefServiceFlagsStorage
flags_storage_(profile
->GetPrefs());
223 about_flags::ConvertFlagsToSwitches(&flags_storage_
, &user_flags
,
224 about_flags::kAddSentinels
);
228 // Returns true if restart is needed to apply per-session flags.
229 bool NeedRestartToApplyPerSessionFlags(
230 const base::CommandLine
& user_flags
,
231 std::set
<base::CommandLine::StringType
>* out_command_line_difference
) {
232 // Don't restart browser if it is not first profile in session.
233 if (user_manager::UserManager::Get()->GetLoggedInUsers().size() != 1)
236 // Only restart if needed and if not going into managed mode.
237 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser())
240 if (about_flags::AreSwitchesIdenticalToCurrentCommandLine(
241 user_flags
, *base::CommandLine::ForCurrentProcess(),
242 out_command_line_difference
)) {
249 bool CanPerformEarlyRestart() {
250 // Desktop build is used for development only. Early restart is not supported.
251 if (!base::SysInfo::IsRunningOnChromeOS())
254 if (!ChromeUserManager::Get()
255 ->GetCurrentUserFlow()
256 ->SupportsEarlyRestartToApplyFlags()) {
260 const ExistingUserController
* controller
=
261 ExistingUserController::current_controller();
265 // Early restart is possible only if OAuth token is up to date.
267 if (controller
->password_changed())
270 if (controller
->auth_mode() != LoginPerformer::AUTH_MODE_INTERNAL
)
273 // No early restart if Easy unlock key needs to be updated.
274 if (UserSessionManager::GetInstance()->NeedsToUpdateEasyUnlockKeys())
280 void LogCustomSwitches(const std::set
<std::string
>& switches
) {
283 for (std::set
<std::string
>::const_iterator it
= switches
.begin();
284 it
!= switches
.end(); ++it
) {
285 VLOG(1) << "Switch leading to restart: '" << *it
<< "'";
291 UserSessionManagerDelegate::~UserSessionManagerDelegate() {
294 void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
297 UserSessionStateObserver::~UserSessionStateObserver() {
301 UserSessionManager
* UserSessionManager::GetInstance() {
302 return Singleton
<UserSessionManager
,
303 DefaultSingletonTraits
<UserSessionManager
> >::get();
307 void UserSessionManager::OverrideHomedir() {
308 // Override user homedir, check for ProfileManager being initialized as
309 // it may not exist in unit tests.
310 if (g_browser_process
->profile_manager()) {
311 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
312 if (user_manager
->GetLoggedInUsers().size() == 1) {
313 base::FilePath homedir
= ProfileHelper::GetProfilePathByUserIdHash(
314 user_manager
->GetPrimaryUser()->username_hash());
315 // This path has been either created by cryptohome (on real Chrome OS
316 // device) or by ProfileManager (on chromeos=1 desktop builds).
317 PathService::OverrideAndCreateIfNeeded(base::DIR_HOME
,
319 true /* path is absolute */,
320 false /* don't create */);
326 void UserSessionManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
327 registry
->RegisterStringPref(prefs::kRLZBrand
, std::string());
328 registry
->RegisterBooleanPref(prefs::kRLZDisabled
, false);
331 UserSessionManager::UserSessionManager()
332 : delegate_(nullptr),
333 authenticator_(nullptr),
334 has_auth_cookies_(false),
335 user_sessions_restored_(false),
336 user_sessions_restore_in_progress_(false),
337 exit_after_session_restore_(false),
338 session_restore_strategy_(
339 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN
),
340 running_easy_unlock_key_ops_(false),
341 should_obtain_handles_(true),
342 should_launch_browser_(true),
343 waiting_for_child_account_status_(false),
344 weak_factory_(this) {
345 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
346 user_manager::UserManager::Get()->AddSessionStateObserver(this);
349 UserSessionManager::~UserSessionManager() {
350 // UserManager is destroyed before singletons, so we need to check if it
352 // TODO(nkostylev): fix order of destruction of UserManager
353 // / UserSessionManager objects.
354 if (user_manager::UserManager::IsInitialized())
355 user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
356 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
359 void UserSessionManager::SetShouldObtainHandleInTests(
360 bool should_obtain_handles
) {
361 should_obtain_handles_
= should_obtain_handles
;
362 if (!should_obtain_handles_
) {
363 token_handle_fetcher_
.reset();
367 void UserSessionManager::CompleteGuestSessionLogin(const GURL
& start_url
) {
368 VLOG(1) << "Completing guest session login";
370 // For guest session we ask session_manager to restart Chrome with --bwsi
371 // flag. We keep only some of the arguments of this process.
372 const base::CommandLine
& browser_command_line
=
373 *base::CommandLine::ForCurrentProcess();
374 base::CommandLine
command_line(browser_command_line
.GetProgram());
375 std::string cmd_line_str
=
376 GetOffTheRecordCommandLine(start_url
,
377 StartupUtils::IsOobeCompleted(),
378 browser_command_line
,
381 // This makes sure that Chrome restarts with no per-session flags. The guest
382 // profile will always have empty set of per-session flags. If this is not
383 // done and device owner has some per-session flags, when Chrome is relaunched
384 // the guest profile session flags will not match the current command line and
385 // another restart will be attempted in order to reset the user flags for the
387 const base::CommandLine
user_flags(base::CommandLine::NO_PROGRAM
);
388 if (!about_flags::AreSwitchesIdenticalToCurrentCommandLine(
389 user_flags
, *base::CommandLine::ForCurrentProcess(), NULL
)) {
390 DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
391 chromeos::login::kGuestUserName
, base::CommandLine::StringVector());
394 RestartChrome(cmd_line_str
);
397 scoped_refptr
<Authenticator
> UserSessionManager::CreateAuthenticator(
398 AuthStatusConsumer
* consumer
) {
399 // Screen locker needs new Authenticator instance each time.
400 if (ScreenLocker::default_screen_locker()) {
401 if (authenticator_
.get())
402 authenticator_
->SetConsumer(NULL
);
403 authenticator_
= NULL
;
406 if (authenticator_
.get() == NULL
) {
407 if (injected_user_context_
) {
409 new StubAuthenticator(consumer
, *injected_user_context_
.get());
411 authenticator_
= new ChromeCryptohomeAuthenticator(consumer
);
414 // TODO(nkostylev): Fix this hack by improving Authenticator dependencies.
415 authenticator_
->SetConsumer(consumer
);
417 return authenticator_
;
420 void UserSessionManager::StartSession(
421 const UserContext
& user_context
,
422 StartSessionType start_session_type
,
423 bool has_auth_cookies
,
424 bool has_active_session
,
425 UserSessionManagerDelegate
* delegate
) {
426 delegate_
= delegate
;
427 start_session_type_
= start_session_type
;
429 VLOG(1) << "Starting session for " << user_context
.GetUserID();
432 CreateUserSession(user_context
, has_auth_cookies
);
434 if (!has_active_session
)
437 // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
438 // ready to be used (http://crbug.com/361528).
439 NotifyUserLoggedIn();
441 if (!user_context
.GetDeviceId().empty()) {
442 user_manager::UserManager::Get()->SetKnownUserDeviceId(
443 user_context
.GetUserID(), user_context
.GetDeviceId());
449 void UserSessionManager::DelegateDeleted(UserSessionManagerDelegate
* delegate
) {
450 if (delegate_
== delegate
)
454 void UserSessionManager::PerformPostUserLoggedInActions() {
455 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
456 if (user_manager
->GetLoggedInUsers().size() == 1) {
457 if (NetworkPortalDetector::IsInitialized()) {
458 NetworkPortalDetector::Get()->SetStrategy(
459 PortalDetectorStrategy::STRATEGY_ID_SESSION
);
464 void UserSessionManager::RestoreAuthenticationSession(Profile
* user_profile
) {
465 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
466 // We need to restore session only for logged in GAIA (regular) users.
467 // Note: stub user is a special case that is used for tests, running
468 // linux_chromeos build on dev workstations w/o user_id parameters.
469 // Stub user is considered to be a regular GAIA user but it has special
470 // user_id (kStubUser) and certain services like restoring OAuth session are
471 // explicitly disabled for it.
472 if (!user_manager
->IsUserLoggedIn() ||
473 !user_manager
->IsLoggedInAsUserWithGaiaAccount() ||
474 user_manager
->IsLoggedInAsStub()) {
478 const user_manager::User
* user
=
479 ProfileHelper::Get()->GetUserByProfile(user_profile
);
481 if (!net::NetworkChangeNotifier::IsOffline()) {
482 pending_signin_restore_sessions_
.erase(user
->email());
483 RestoreAuthSessionImpl(user_profile
, false /* has_auth_cookies */);
485 // Even if we're online we should wait till initial
486 // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
487 // end up canceling all request when initial network connection type is
488 // processed. See http://crbug.com/121643.
489 pending_signin_restore_sessions_
.insert(user
->email());
493 void UserSessionManager::RestoreActiveSessions() {
494 user_sessions_restore_in_progress_
= true;
495 DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
496 base::Bind(&UserSessionManager::OnRestoreActiveSessions
, AsWeakPtr()));
499 bool UserSessionManager::UserSessionsRestored() const {
500 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
501 return user_sessions_restored_
;
504 bool UserSessionManager::UserSessionsRestoreInProgress() const {
505 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
506 return user_sessions_restore_in_progress_
;
509 void UserSessionManager::InitRlz(Profile
* profile
) {
510 #if defined(ENABLE_RLZ)
511 if (!g_browser_process
->local_state()->HasPrefPath(prefs::kRLZBrand
)) {
512 // Read brand code asynchronously from an OEM data and repost ourselves.
513 google_brand::chromeos::InitBrand(
514 base::Bind(&UserSessionManager::InitRlz
, AsWeakPtr(), profile
));
517 base::PostTaskAndReplyWithResult(
518 base::WorkerPool::GetTaskRunner(false).get(),
520 base::Bind(&base::PathExists
, GetRlzDisabledFlagPath()),
521 base::Bind(&UserSessionManager::InitRlzImpl
, AsWeakPtr(), profile
));
525 void UserSessionManager::SetFirstLoginPrefs(
527 const std::string
& public_session_locale
,
528 const std::string
& public_session_input_method
) {
529 VLOG(1) << "Setting first login prefs";
530 InitLocaleAndInputMethodsForNewUser(
531 this, profile
, public_session_locale
, public_session_input_method
);
534 bool UserSessionManager::GetAppModeChromeClientOAuthInfo(
535 std::string
* chrome_client_id
, std::string
* chrome_client_secret
) {
536 if (!chrome::IsRunningInForcedAppMode() ||
537 chrome_client_id_
.empty() ||
538 chrome_client_secret_
.empty()) {
542 *chrome_client_id
= chrome_client_id_
;
543 *chrome_client_secret
= chrome_client_secret_
;
547 void UserSessionManager::SetAppModeChromeClientOAuthInfo(
548 const std::string
& chrome_client_id
,
549 const std::string
& chrome_client_secret
) {
550 if (!chrome::IsRunningInForcedAppMode())
553 chrome_client_id_
= chrome_client_id
;
554 chrome_client_secret_
= chrome_client_secret
;
557 void UserSessionManager::DoBrowserLaunch(Profile
* profile
,
558 LoginDisplayHost
* login_host
) {
559 DoBrowserLaunchInternal(profile
, login_host
, false /* locale_pref_checked */);
562 bool UserSessionManager::RespectLocalePreference(
564 const user_manager::User
* user
,
565 const locale_util::SwitchLanguageCallback
& callback
) const {
566 // TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
567 // the Google user profile.
568 if (g_browser_process
== NULL
)
571 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
572 if (!user
|| (user_manager
->IsUserLoggedIn() &&
573 user
!= user_manager
->GetPrimaryUser())) {
577 // In case of multi-profiles session we don't apply profile locale
578 // because it is unsafe.
579 if (user_manager
->GetLoggedInUsers().size() != 1)
582 const PrefService
* prefs
= profile
->GetPrefs();
586 std::string pref_locale
;
587 const std::string pref_app_locale
=
588 prefs
->GetString(prefs::kApplicationLocale
);
589 const std::string pref_bkup_locale
=
590 prefs
->GetString(prefs::kApplicationLocaleBackup
);
592 pref_locale
= pref_app_locale
;
593 if (pref_locale
.empty())
594 pref_locale
= pref_bkup_locale
;
596 const std::string
* account_locale
= NULL
;
597 if (pref_locale
.empty() && user
->has_gaia_account()) {
598 if (user
->GetAccountLocale() == NULL
)
599 return false; // wait until Account profile is loaded.
600 account_locale
= user
->GetAccountLocale();
601 pref_locale
= *account_locale
;
603 const std::string global_app_locale
=
604 g_browser_process
->GetApplicationLocale();
605 if (pref_locale
.empty())
606 pref_locale
= global_app_locale
;
607 DCHECK(!pref_locale
.empty());
608 VLOG(1) << "RespectLocalePreference: "
609 << "app_locale='" << pref_app_locale
<< "', "
610 << "bkup_locale='" << pref_bkup_locale
<< "', "
611 << (account_locale
!= NULL
612 ? (std::string("account_locale='") + (*account_locale
) +
614 : (std::string("account_locale - unused. ")))
615 << " Selected '" << pref_locale
<< "'";
616 profile
->ChangeAppLocale(
618 user
->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT
?
619 Profile::APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN
:
620 Profile::APP_LOCALE_CHANGED_VIA_LOGIN
);
622 // Here we don't enable keyboard layouts for normal users. Input methods
623 // are set up when the user first logs in. Then the user may customize the
624 // input methods. Hence changing input methods here, just because the user's
625 // UI language is different from the login screen UI language, is not
626 // desirable. Note that input method preferences are synced, so users can use
627 // their farovite input methods as soon as the preferences are synced.
629 // For Guest mode, user locale preferences will never get initialized.
630 // So input methods should be enabled somewhere.
631 const bool enable_layouts
=
632 user_manager::UserManager::Get()->IsLoggedInAsGuest();
633 locale_util::SwitchLanguage(pref_locale
, enable_layouts
,
634 false /* login_layouts_only */, callback
,
640 bool UserSessionManager::RestartToApplyPerSessionFlagsIfNeed(
642 bool early_restart
) {
643 if (ProfileHelper::IsSigninProfile(profile
))
646 if (early_restart
&& !CanPerformEarlyRestart())
649 // We can't really restart if we've already restarted as a part of
650 // user session restore after crash of in case when flags were changed inside
652 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginUser
))
655 // We can't restart if that's a second user sign in that is happening.
656 if (user_manager::UserManager::Get()->GetLoggedInUsers().size() > 1)
659 const base::CommandLine
user_flags(CreatePerSessionCommandLine(profile
));
660 std::set
<base::CommandLine::StringType
> command_line_difference
;
661 if (!NeedRestartToApplyPerSessionFlags(user_flags
, &command_line_difference
))
664 LogCustomSwitches(command_line_difference
);
666 about_flags::ReportCustomFlags("Login.CustomFlags", command_line_difference
);
668 base::CommandLine::StringVector flags
;
669 // argv[0] is the program name |base::CommandLine::NO_PROGRAM|.
670 flags
.assign(user_flags
.argv().begin() + 1, user_flags
.argv().end());
671 LOG(WARNING
) << "Restarting to apply per-session flags...";
672 DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
673 user_manager::UserManager::Get()->GetActiveUser()->email(), flags
);
674 AttemptRestart(profile
);
678 bool UserSessionManager::NeedsToUpdateEasyUnlockKeys() const {
679 return EasyUnlockService::IsSignInEnabled() &&
680 !user_context_
.GetUserID().empty() &&
681 user_manager::User::TypeHasGaiaAccount(user_context_
.GetUserType()) &&
682 user_context_
.GetKey() && !user_context_
.GetKey()->GetSecret().empty();
685 bool UserSessionManager::CheckEasyUnlockKeyOps(const base::Closure
& callback
) {
686 if (!running_easy_unlock_key_ops_
)
689 // Assumes only one deferred callback is needed.
690 DCHECK(easy_unlock_key_ops_finished_callback_
.is_null());
692 easy_unlock_key_ops_finished_callback_
= callback
;
696 void UserSessionManager::AddSessionStateObserver(
697 chromeos::UserSessionStateObserver
* observer
) {
698 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
699 session_state_observer_list_
.AddObserver(observer
);
702 void UserSessionManager::RemoveSessionStateObserver(
703 chromeos::UserSessionStateObserver
* observer
) {
704 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
705 session_state_observer_list_
.RemoveObserver(observer
);
708 void UserSessionManager::OnSessionRestoreStateChanged(
709 Profile
* user_profile
,
710 OAuth2LoginManager::SessionRestoreState state
) {
711 user_manager::User::OAuthTokenStatus user_status
=
712 user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN
;
713 OAuth2LoginManager
* login_manager
=
714 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile
);
716 bool connection_error
= false;
718 case OAuth2LoginManager::SESSION_RESTORE_DONE
:
719 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_VALID
;
721 case OAuth2LoginManager::SESSION_RESTORE_FAILED
:
722 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
;
724 case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
:
725 connection_error
= true;
727 case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED
:
728 case OAuth2LoginManager::SESSION_RESTORE_PREPARING
:
729 case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS
:
733 // We should not be clearing existing token state if that was a connection
734 // error. http://crbug.com/295245
735 if (!connection_error
) {
736 // We are in one of "done" states here.
737 user_manager::UserManager::Get()->SaveUserOAuthStatus(
738 user_manager::UserManager::Get()->GetLoggedInUser()->email(),
742 login_manager
->RemoveObserver(this);
744 if (exit_after_session_restore_
&&
745 (state
== OAuth2LoginManager::SESSION_RESTORE_DONE
||
746 state
== OAuth2LoginManager::SESSION_RESTORE_FAILED
||
747 state
== OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
)) {
748 LOG(WARNING
) << "Restarting Chrome after session restore finishes, "
749 << "most likely due to custom flags.";
751 // We need to restart cleanly in this case to make sure OAuth2 RT is
753 chrome::AttemptRestart();
757 void UserSessionManager::OnConnectionTypeChanged(
758 net::NetworkChangeNotifier::ConnectionType type
) {
759 bool is_running_test
=
760 base::CommandLine::ForCurrentProcess()->HasSwitch(
761 ::switches::kTestName
) ||
762 base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType
);
763 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
764 if (type
== net::NetworkChangeNotifier::CONNECTION_NONE
||
765 !user_manager
->IsUserLoggedIn() ||
766 !user_manager
->IsLoggedInAsUserWithGaiaAccount() ||
767 user_manager
->IsLoggedInAsStub() || is_running_test
) {
771 // Need to iterate over all users and their OAuth2 session state.
772 const user_manager::UserList
& users
= user_manager
->GetLoggedInUsers();
773 for (user_manager::UserList::const_iterator it
= users
.begin();
776 if (!(*it
)->is_profile_created())
779 Profile
* user_profile
= ProfileHelper::Get()->GetProfileByUserUnsafe(*it
);
780 bool should_restore_session
=
781 pending_signin_restore_sessions_
.find((*it
)->email()) !=
782 pending_signin_restore_sessions_
.end();
783 OAuth2LoginManager
* login_manager
=
784 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile
);
785 if (login_manager
->SessionRestoreIsRunning()) {
786 // If we come online for the first time after successful offline login,
787 // we need to kick off OAuth token verification process again.
788 login_manager
->ContinueSessionRestore();
789 } else if (should_restore_session
) {
790 pending_signin_restore_sessions_
.erase((*it
)->email());
791 RestoreAuthSessionImpl(user_profile
, false /* has_auth_cookies */);
796 void UserSessionManager::OnProfilePrepared(Profile
* profile
,
797 bool browser_launched
) {
798 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
799 ::switches::kTestName
)) {
800 // Did not log in (we crashed or are debugging), need to restore Sync.
801 // TODO(nkostylev): Make sure that OAuth state is restored correctly for all
802 // users once it is fully multi-profile aware. http://crbug.com/238987
803 // For now if we have other user pending sessions they'll override OAuth
804 // session restore for previous users.
805 RestoreAuthenticationSession(profile
);
808 // Restore other user sessions if any.
809 RestorePendingUserSessions();
812 void UserSessionManager::ChildAccountStatusReceivedCallback(Profile
* profile
) {
813 StopChildStatusObserving(profile
);
816 void UserSessionManager::StopChildStatusObserving(Profile
* profile
) {
817 if (!waiting_for_child_account_status_
&&
818 !SessionStartupPref::TypeIsManaged(profile
->GetPrefs())) {
819 InitializeStartUrls();
821 waiting_for_child_account_status_
= false;
824 void UserSessionManager::CreateUserSession(const UserContext
& user_context
,
825 bool has_auth_cookies
) {
826 user_context_
= user_context
;
827 has_auth_cookies_
= has_auth_cookies
;
828 InitSessionRestoreStrategy();
829 StoreUserContextDataBeforeProfileIsCreated();
832 void UserSessionManager::PreStartSession() {
833 // Switch log file as soon as possible.
834 if (base::SysInfo::IsRunningOnChromeOS())
835 logging::RedirectChromeLogging(*(base::CommandLine::ForCurrentProcess()));
838 void UserSessionManager::StoreUserContextDataBeforeProfileIsCreated() {
839 // Store obfuscated GAIA ID.
840 if (!user_context_
.GetGaiaID().empty()) {
841 user_manager::UserManager::Get()->UpdateGaiaID(user_context_
.GetUserID(),
842 user_context_
.GetGaiaID());
846 void UserSessionManager::StartCrosSession() {
847 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
848 btl
->AddLoginTimeMarker("StartSession-Start", false);
849 DBusThreadManager::Get()->GetSessionManagerClient()->
850 StartSession(user_context_
.GetUserID());
851 btl
->AddLoginTimeMarker("StartSession-End", false);
854 void UserSessionManager::NotifyUserLoggedIn() {
855 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
856 btl
->AddLoginTimeMarker("UserLoggedIn-Start", false);
857 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
858 user_manager
->UserLoggedIn(user_context_
.GetUserID(),
859 user_context_
.GetUserIDHash(),
861 btl
->AddLoginTimeMarker("UserLoggedIn-End", false);
864 void UserSessionManager::PrepareProfile() {
865 bool is_demo_session
=
866 DemoAppLauncher::IsDemoAppSession(user_context_
.GetUserID());
868 // TODO(nkostylev): Figure out whether demo session is using the right profile
869 // path or not. See https://codereview.chromium.org/171423009
870 g_browser_process
->profile_manager()->CreateProfileAsync(
871 ProfileHelper::GetProfilePathByUserIdHash(user_context_
.GetUserIDHash()),
872 base::Bind(&UserSessionManager::OnProfileCreated
,
881 void UserSessionManager::OnProfileCreated(const UserContext
& user_context
,
882 bool is_incognito_profile
,
884 Profile::CreateStatus status
) {
888 case Profile::CREATE_STATUS_CREATED
:
889 // Profile created but before initializing extensions and promo resources.
890 InitProfilePreferences(profile
, user_context
);
892 case Profile::CREATE_STATUS_INITIALIZED
:
893 // Profile is created, extensions and promo resources are initialized.
894 // At this point all other Chrome OS services will be notified that it is
895 // safe to use this profile.
896 UserProfileInitialized(profile
,
897 is_incognito_profile
,
898 user_context
.GetUserID());
900 case Profile::CREATE_STATUS_LOCAL_FAIL
:
901 case Profile::CREATE_STATUS_REMOTE_FAIL
:
902 case Profile::CREATE_STATUS_CANCELED
:
903 case Profile::MAX_CREATE_STATUS
:
909 void UserSessionManager::InitProfilePreferences(
911 const UserContext
& user_context
) {
912 const user_manager::User
* user
=
913 ProfileHelper::Get()->GetUserByProfile(profile
);
914 if (user
->GetType() == user_manager::USER_TYPE_KIOSK_APP
&&
915 profile
->IsNewProfile()) {
916 ChromeUserManager::Get()->SetIsCurrentUserNew(true);
919 if (user
->is_active()) {
920 input_method::InputMethodManager
* manager
=
921 input_method::InputMethodManager::Get();
922 manager
->SetState(GetDefaultIMEState(profile
));
924 if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
925 SetFirstLoginPrefs(profile
,
926 user_context
.GetPublicSessionLocale(),
927 user_context
.GetPublicSessionInputMethod());
930 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
931 user_manager::User
* active_user
=
932 user_manager::UserManager::Get()->GetActiveUser();
933 std::string supervised_user_sync_id
=
934 ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
935 active_user
->email());
936 profile
->GetPrefs()->SetString(prefs::kSupervisedUserId
,
937 supervised_user_sync_id
);
938 } else if (user_manager::UserManager::Get()->
939 IsLoggedInAsUserWithGaiaAccount()) {
940 // Get the Gaia ID from the user context. If it's not available, this may
941 // not be available when unlocking a previously opened profile, or when
942 // creating a supervised users. However, in these cases the gaia_id should
943 // be already available in the account tracker.
944 std::string gaia_id
= user_context
.GetGaiaID();
945 if (gaia_id
.empty()) {
946 AccountTrackerService
* account_tracker
=
947 AccountTrackerServiceFactory::GetForProfile(profile
);
948 AccountTrackerService::AccountInfo info
=
949 account_tracker
->FindAccountInfoByEmail(user_context
.GetUserID());
951 DCHECK(!gaia_id
.empty());
954 // Make sure that the google service username is properly set (we do this
955 // on every sign in, not just the first login, to deal with existing
956 // profiles that might not have it set yet).
957 SigninManagerBase
* signin_manager
=
958 SigninManagerFactory::GetForProfile(profile
);
959 signin_manager
->SetAuthenticatedAccountInfo(gaia_id
,
960 user_context
.GetUserID());
962 // Backfill GAIA ID in user prefs stored in Local State.
963 std::string tmp_gaia_id
;
964 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
965 if (!user_manager
->FindGaiaID(user_context
.GetUserID(), &tmp_gaia_id
) &&
967 user_manager
->UpdateGaiaID(user_context
.GetUserID(), gaia_id
);
972 void UserSessionManager::UserProfileInitialized(Profile
* profile
,
973 bool is_incognito_profile
,
974 const std::string
& user_id
) {
975 // Demo user signed in.
976 if (is_incognito_profile
) {
979 // Send the notification before creating the browser so additional objects
980 // that need the profile (e.g. the launcher) can be created first.
981 content::NotificationService::current()->Notify(
982 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED
,
983 content::NotificationService::AllSources(),
984 content::Details
<Profile
>(profile
));
987 delegate_
->OnProfilePrepared(profile
, false);
992 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
993 btl
->AddLoginTimeMarker("UserProfileGotten", false);
995 if (user_context_
.IsUsingOAuth()) {
996 // Retrieve the policy that indicates whether to continue copying
997 // authentication cookies set by a SAML IdP on subsequent logins after the
999 bool transfer_saml_auth_cookies_on_subsequent_login
= false;
1000 if (has_auth_cookies_
&&
1001 g_browser_process
->platform_part()->
1002 browser_policy_connector_chromeos()->GetUserAffiliation(user_id
) ==
1003 policy::USER_AFFILIATION_MANAGED
) {
1004 CrosSettings::Get()->GetBoolean(
1005 kAccountsPrefTransferSAMLCookies
,
1006 &transfer_saml_auth_cookies_on_subsequent_login
);
1009 // Transfers authentication-related data from the profile that was used for
1010 // authentication to the user's profile. The proxy authentication state is
1011 // transferred unconditionally. If the user authenticated via an auth
1012 // extension, authentication cookies and channel IDs will be transferred as
1013 // well when the user's cookie jar is empty. If the cookie jar is not empty,
1014 // the authentication states in the browser context and the user's profile
1015 // must be merged using /MergeSession instead. Authentication cookies set by
1016 // a SAML IdP will also be transferred when the user's cookie jar is not
1017 // empty if |transfer_saml_auth_cookies_on_subsequent_login| is true.
1018 const bool transfer_auth_cookies_and_channel_ids_on_first_login
=
1021 net::URLRequestContextGetter
* auth_request_context
=
1022 GetAuthRequestContext();
1024 // Authentication request context may be missing especially if user didn't
1025 // sign in using GAIA (webview) and webview didn't yet initialize.
1026 if (auth_request_context
) {
1027 ProfileAuthData::Transfer(
1028 auth_request_context
, profile
->GetRequestContext(),
1029 transfer_auth_cookies_and_channel_ids_on_first_login
,
1030 transfer_saml_auth_cookies_on_subsequent_login
,
1032 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer
,
1033 AsWeakPtr(), profile
));
1035 // We need to post task so that OnProfileCreated() caller sends out
1036 // NOTIFICATION_PROFILE_CREATED which marks user profile as initialized.
1037 base::ThreadTaskRunnerHandle::Get()->PostTask(
1040 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer
,
1041 AsWeakPtr(), profile
));
1046 FinalizePrepareProfile(profile
);
1049 void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
1051 RestoreAuthSessionImpl(profile
, has_auth_cookies_
);
1052 FinalizePrepareProfile(profile
);
1055 void UserSessionManager::FinalizePrepareProfile(Profile
* profile
) {
1056 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
1058 // Own TPM device if, for any reason, it has not been done in EULA screen.
1059 CryptohomeClient
* client
= DBusThreadManager::Get()->GetCryptohomeClient();
1060 btl
->AddLoginTimeMarker("TPMOwn-Start", false);
1061 if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
1062 if (cryptohome_util::TpmIsOwned())
1063 client
->CallTpmClearStoredPasswordAndBlock();
1065 client
->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
1067 btl
->AddLoginTimeMarker("TPMOwn-End", false);
1069 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1070 if (user_manager
->IsLoggedInAsUserWithGaiaAccount()) {
1071 if (user_context_
.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML
)
1072 user_manager
->UpdateUsingSAML(user_context_
.GetUserID(), true);
1073 SAMLOfflineSigninLimiter
* saml_offline_signin_limiter
=
1074 SAMLOfflineSigninLimiterFactory::GetForProfile(profile
);
1075 if (saml_offline_signin_limiter
)
1076 saml_offline_signin_limiter
->SignedIn(user_context_
.GetAuthFlow());
1081 g_browser_process
->platform_part()->SessionManager()->SetSessionState(
1082 session_manager::SESSION_STATE_LOGGED_IN_NOT_ACTIVE
);
1084 // Send the notification before creating the browser so additional objects
1085 // that need the profile (e.g. the launcher) can be created first.
1086 content::NotificationService::current()->Notify(
1087 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED
,
1088 content::NotificationService::AllSources(),
1089 content::Details
<Profile
>(profile
));
1091 // Initialize various services only for primary user.
1092 const user_manager::User
* user
=
1093 ProfileHelper::Get()->GetUserByProfile(profile
);
1094 if (user_manager
->GetPrimaryUser() == user
) {
1096 InitializeCerts(profile
);
1097 InitializeCRLSetFetcher(user
);
1098 InitializeEVCertificatesWhitelistComponent(user
);
1101 UpdateEasyUnlockKeys(user_context_
);
1102 user_context_
.ClearSecrets();
1103 if (TokenHandlesEnabled()) {
1104 CreateTokenUtilIfMissing();
1105 if (token_handle_util_
->ShouldObtainHandle(user
->GetUserID())) {
1106 if (!token_handle_fetcher_
.get()) {
1107 token_handle_fetcher_
.reset(new TokenHandleFetcher(
1108 token_handle_util_
.get(), user
->GetUserID()));
1109 token_handle_fetcher_
->BackfillToken(
1110 profile
, base::Bind(&UserSessionManager::OnTokenHandleObtained
,
1111 weak_factory_
.GetWeakPtr()));
1116 // Now that profile is ready, proceed to either alternative login flows or
1118 bool browser_launched
= InitializeUserSession(profile
);
1120 // TODO(nkostylev): This pointer should probably never be NULL, but it looks
1121 // like OnProfileCreated() may be getting called before
1122 // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is
1123 // killed during shutdown in tests -- see http://crosbug.com/18269. Replace
1124 // this 'if' statement with a CHECK(delegate_) once the underlying issue is
1127 delegate_
->OnProfilePrepared(profile
, browser_launched
);
1130 void UserSessionManager::ActivateWizard(const std::string
& screen_name
) {
1131 LoginDisplayHost
* host
= LoginDisplayHostImpl::default_host();
1133 host
->StartWizard(screen_name
);
1136 void UserSessionManager::InitializeStartUrls() const {
1137 // Child account status should be known by the time of this call.
1138 std::vector
<std::string
> start_urls
;
1140 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1142 bool can_show_getstarted_guide
= user_manager
->GetActiveUser()->GetType() ==
1143 user_manager::USER_TYPE_REGULAR
;
1145 // Skip the default first-run behavior for public accounts.
1146 if (!user_manager
->IsLoggedInAsPublicAccount()) {
1147 if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
1148 const char* url
= kChromeVoxTutorialURLPattern
;
1149 PrefService
* prefs
= g_browser_process
->local_state();
1150 const std::string current_locale
=
1151 base::StringToLowerASCII(prefs
->GetString(prefs::kApplicationLocale
));
1152 std::string vox_url
= base::StringPrintf(url
, current_locale
.c_str());
1153 start_urls
.push_back(vox_url
);
1154 can_show_getstarted_guide
= false;
1158 // Only show getting started guide for a new user.
1159 const bool should_show_getstarted_guide
= user_manager
->IsCurrentUserNew();
1161 if (can_show_getstarted_guide
&& should_show_getstarted_guide
) {
1162 // Don't open default Chrome window if we're going to launch the first-run
1163 // app. Because we dont' want the first-run app to be hidden in the
1165 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1166 ::switches::kSilentLaunch
);
1167 first_run::MaybeLaunchDialogAfterSessionStart();
1169 for (size_t i
= 0; i
< start_urls
.size(); ++i
) {
1170 base::CommandLine::ForCurrentProcess()->AppendArg(start_urls
[i
]);
1175 bool UserSessionManager::InitializeUserSession(Profile
* profile
) {
1176 ChildAccountService
* child_service
=
1177 ChildAccountServiceFactory::GetForProfile(profile
);
1178 child_service
->AddChildStatusReceivedCallback(
1179 base::Bind(&UserSessionManager::ChildAccountStatusReceivedCallback
,
1180 weak_factory_
.GetWeakPtr(), profile
));
1181 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1182 FROM_HERE
, base::Bind(&UserSessionManager::StopChildStatusObserving
,
1183 weak_factory_
.GetWeakPtr(), profile
),
1184 base::TimeDelta::FromMilliseconds(kFlagsFetchingLoginTimeoutMs
));
1186 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1188 // Kiosk apps has their own session initialization pipeline.
1189 if (user_manager
->IsLoggedInAsKioskApp())
1192 if (start_session_type_
== PRIMARY_USER_SESSION
) {
1193 UserFlow
* user_flow
= ChromeUserManager::Get()->GetCurrentUserFlow();
1194 WizardController
* oobe_controller
= WizardController::default_controller();
1195 base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
1196 bool skip_post_login_screens
=
1197 user_flow
->ShouldSkipPostLoginScreens() ||
1198 (oobe_controller
&& oobe_controller
->skip_post_login_screens()) ||
1199 cmdline
->HasSwitch(chromeos::switches::kOobeSkipPostLogin
);
1201 if (user_manager
->IsCurrentUserNew() && !skip_post_login_screens
) {
1202 // Don't specify start URLs if the administrator has configured the start
1204 if (!SessionStartupPref::TypeIsManaged(profile
->GetPrefs())) {
1205 if (child_service
->IsChildAccountStatusKnown())
1206 InitializeStartUrls();
1208 waiting_for_child_account_status_
= true;
1211 // Mark the device as registered., i.e. the second part of OOBE as
1213 if (!StartupUtils::IsDeviceRegistered())
1214 StartupUtils::MarkDeviceRegistered(base::Closure());
1216 ActivateWizard(WizardController::kTermsOfServiceScreenName
);
1221 DoBrowserLaunch(profile
, LoginDisplayHostImpl::default_host());
1225 void UserSessionManager::InitSessionRestoreStrategy() {
1226 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
1227 bool in_app_mode
= chrome::IsRunningInForcedAppMode();
1229 // Are we in kiosk app mode?
1231 if (command_line
->HasSwitch(::switches::kAppModeOAuth2Token
)) {
1232 user_context_
.SetRefreshToken(command_line
->GetSwitchValueASCII(
1233 ::switches::kAppModeOAuth2Token
));
1236 if (command_line
->HasSwitch(::switches::kAppModeAuthCode
)) {
1237 user_context_
.SetAuthCode(command_line
->GetSwitchValueASCII(
1238 ::switches::kAppModeAuthCode
));
1241 DCHECK(!has_auth_cookies_
);
1244 if (has_auth_cookies_
) {
1245 session_restore_strategy_
= OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR
;
1246 } else if (!user_context_
.GetRefreshToken().empty()) {
1247 session_restore_strategy_
=
1248 OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN
;
1250 session_restore_strategy_
=
1251 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN
;
1255 void UserSessionManager::RestoreAuthSessionImpl(
1257 bool restore_from_auth_cookies
) {
1258 CHECK((authenticator_
.get() && authenticator_
->authentication_context()) ||
1259 !restore_from_auth_cookies
);
1261 if (chrome::IsRunningInForcedAppMode() ||
1262 base::CommandLine::ForCurrentProcess()->HasSwitch(
1263 chromeos::switches::kDisableGaiaServices
)) {
1267 exit_after_session_restore_
= false;
1269 // Remove legacy OAuth1 token if we have one. If it's valid, we should already
1270 // have OAuth2 refresh token in OAuth2TokenService that could be used to
1271 // retrieve all other tokens and user_context.
1272 OAuth2LoginManager
* login_manager
=
1273 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile
);
1274 login_manager
->AddObserver(this);
1276 net::URLRequestContextGetter
* auth_request_context
= GetAuthRequestContext();
1278 // Authentication request context may not be available if user was not
1279 // signing in with GAIA webview (i.e. webview instance hasn't been
1280 // initialized at all). Use fallback request context if authenticator was
1282 // Authenticator instance may not be initialized for session
1283 // restore case when Chrome is restarting after crash or to apply custom user
1284 // flags. In that case auth_request_context will be nullptr which is accepted
1285 // by RestoreSession() for session restore case.
1286 if (!auth_request_context
&&
1287 (authenticator_
.get() && authenticator_
->authentication_context())) {
1288 auth_request_context
=
1289 authenticator_
->authentication_context()->GetRequestContext();
1291 login_manager
->RestoreSession(auth_request_context
, session_restore_strategy_
,
1292 user_context_
.GetRefreshToken(),
1293 user_context_
.GetAccessToken());
1296 void UserSessionManager::InitRlzImpl(Profile
* profile
, bool disabled
) {
1297 #if defined(ENABLE_RLZ)
1298 PrefService
* local_state
= g_browser_process
->local_state();
1300 // Empty brand code means an organic install (no RLZ pings are sent).
1301 google_brand::chromeos::ClearBrandForCurrentSession();
1303 if (disabled
!= local_state
->GetBoolean(prefs::kRLZDisabled
)) {
1304 // When switching to RLZ enabled/disabled state, clear all recorded events.
1305 rlz::RLZTracker::ClearRlzState();
1306 local_state
->SetBoolean(prefs::kRLZDisabled
, disabled
);
1308 // Init the RLZ library.
1309 int ping_delay
= profile
->GetPrefs()->GetInteger(
1310 ::first_run::GetPingDelayPrefName().c_str());
1311 // Negative ping delay means to send ping immediately after a first search is
1313 rlz::RLZTracker::SetRlzDelegate(
1314 make_scoped_ptr(new ChromeRLZTrackerDelegate
));
1315 rlz::RLZTracker::InitRlzDelayed(
1316 user_manager::UserManager::Get()->IsCurrentUserNew(), ping_delay
< 0,
1317 base::TimeDelta::FromMilliseconds(abs(ping_delay
)),
1318 ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile
),
1319 ChromeRLZTrackerDelegate::IsGoogleHomepage(profile
),
1320 ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile
));
1324 void UserSessionManager::InitializeCerts(Profile
* profile
) {
1325 // Now that the user profile has been initialized
1326 // |GetNSSCertDatabaseForProfile| is safe to be used.
1327 if (CertLoader::IsInitialized() && base::SysInfo::IsRunningOnChromeOS()) {
1328 GetNSSCertDatabaseForProfile(profile
,
1329 base::Bind(&OnGetNSSCertDatabaseForUser
));
1333 void UserSessionManager::InitializeCRLSetFetcher(
1334 const user_manager::User
* user
) {
1335 const std::string username_hash
= user
->username_hash();
1336 if (!username_hash
.empty()) {
1337 base::FilePath path
;
1338 path
= ProfileHelper::GetProfilePathByUserIdHash(username_hash
);
1339 component_updater::ComponentUpdateService
* cus
=
1340 g_browser_process
->component_updater();
1341 CRLSetFetcher
* crl_set
= g_browser_process
->crl_set_fetcher();
1343 crl_set
->StartInitialLoad(cus
, path
);
1347 void UserSessionManager::InitializeEVCertificatesWhitelistComponent(
1348 const user_manager::User
* user
) {
1349 const std::string username_hash
= user
->username_hash();
1350 component_updater::ComponentUpdateService
* cus
=
1351 g_browser_process
->component_updater();
1352 if (!username_hash
.empty() && cus
) {
1353 const base::FilePath path
=
1354 ProfileHelper::GetProfilePathByUserIdHash(username_hash
);
1355 RegisterEVWhitelistComponent(cus
, path
);
1359 void UserSessionManager::OnRestoreActiveSessions(
1360 const SessionManagerClient::ActiveSessionsMap
& sessions
,
1363 LOG(ERROR
) << "Could not get list of active user sessions after crash.";
1364 // If we could not get list of active user sessions it is safer to just
1365 // sign out so that we don't get in the inconsistent state.
1366 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
1370 // One profile has been already loaded on browser start.
1371 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1372 DCHECK(user_manager
->GetLoggedInUsers().size() == 1);
1373 DCHECK(user_manager
->GetActiveUser());
1374 std::string active_user_id
= user_manager
->GetActiveUser()->email();
1376 SessionManagerClient::ActiveSessionsMap::const_iterator it
;
1377 for (it
= sessions
.begin(); it
!= sessions
.end(); ++it
) {
1378 if (active_user_id
== it
->first
)
1380 pending_user_sessions_
[it
->first
] = it
->second
;
1382 RestorePendingUserSessions();
1385 void UserSessionManager::RestorePendingUserSessions() {
1386 if (pending_user_sessions_
.empty()) {
1387 user_manager::UserManager::Get()->SwitchToLastActiveUser();
1388 NotifyPendingUserSessionsRestoreFinished();
1392 // Get next user to restore sessions and delete it from list.
1393 SessionManagerClient::ActiveSessionsMap::const_iterator it
=
1394 pending_user_sessions_
.begin();
1395 std::string user_id
= it
->first
;
1396 std::string user_id_hash
= it
->second
;
1397 DCHECK(!user_id
.empty());
1398 DCHECK(!user_id_hash
.empty());
1399 pending_user_sessions_
.erase(user_id
);
1401 // Check that this user is not logged in yet.
1402 user_manager::UserList logged_in_users
=
1403 user_manager::UserManager::Get()->GetLoggedInUsers();
1404 bool user_already_logged_in
= false;
1405 for (user_manager::UserList::const_iterator it
= logged_in_users
.begin();
1406 it
!= logged_in_users
.end();
1408 const user_manager::User
* user
= (*it
);
1409 if (user
->email() == user_id
) {
1410 user_already_logged_in
= true;
1414 DCHECK(!user_already_logged_in
);
1416 if (!user_already_logged_in
) {
1417 UserContext
user_context(user_id
);
1418 user_context
.SetUserIDHash(user_id_hash
);
1419 user_context
.SetIsUsingOAuth(false);
1421 // Will call OnProfilePrepared() once profile has been loaded.
1422 // Only handling secondary users here since primary user profile
1423 // (and session) has been loaded on Chrome startup.
1424 StartSession(user_context
,
1425 SECONDARY_USER_SESSION_AFTER_CRASH
,
1426 false, // has_auth_cookies
1427 true, // has_active_session, this is restart after crash
1430 RestorePendingUserSessions();
1434 void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() {
1435 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
1436 user_sessions_restored_
= true;
1437 user_sessions_restore_in_progress_
= false;
1438 FOR_EACH_OBSERVER(chromeos::UserSessionStateObserver
,
1439 session_state_observer_list_
,
1440 PendingUserSessionsRestoreFinished());
1443 void UserSessionManager::UpdateEasyUnlockKeys(const UserContext
& user_context
) {
1444 // Skip key update because FakeCryptohomeClient always return success
1445 // and RefreshKeys op expects a failure to stop. As a result, some tests would
1447 // TODO(xiyuan): Revisit this when adding tests.
1448 if (!base::SysInfo::IsRunningOnChromeOS())
1451 // Only update Easy unlock keys for regular user.
1452 // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
1454 const user_manager::User
* user
=
1455 user_manager::UserManager::Get()->FindUser(user_context
.GetUserID());
1456 if (!user
|| !user
->HasGaiaAccount())
1459 // Bail if |user_context| does not have secret.
1460 if (user_context
.GetKey()->GetSecret().empty())
1463 const base::ListValue
* device_list
= NULL
;
1464 EasyUnlockService
* easy_unlock_service
= EasyUnlockService::GetForUser(*user
);
1465 if (easy_unlock_service
) {
1466 device_list
= easy_unlock_service
->GetRemoteDevices();
1467 easy_unlock_service
->SetHardlockState(
1468 EasyUnlockScreenlockStateHandler::NO_HARDLOCK
);
1471 base::ListValue empty_list
;
1473 device_list
= &empty_list
;
1475 EasyUnlockKeyManager
* key_manager
= GetEasyUnlockKeyManager();
1476 running_easy_unlock_key_ops_
= true;
1477 key_manager
->RefreshKeys(
1478 user_context
, *device_list
,
1479 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished
, AsWeakPtr(),
1480 user_context
.GetUserID()));
1483 net::URLRequestContextGetter
*
1484 UserSessionManager::GetAuthRequestContext() const {
1485 net::URLRequestContextGetter
* auth_request_context
= nullptr;
1487 if (StartupUtils::IsWebviewSigninEnabled()) {
1488 // Webview uses different partition storage than iframe. We need to get
1489 // cookies from the right storage for url request to get auth token into
1491 content::StoragePartition
* signin_partition
= login::GetSigninPartition();
1492 if (signin_partition
)
1493 auth_request_context
= signin_partition
->GetURLRequestContext();
1494 } else if (authenticator_
.get() && authenticator_
->authentication_context()) {
1495 auth_request_context
=
1496 authenticator_
->authentication_context()->GetRequestContext();
1498 return auth_request_context
;
1501 void UserSessionManager::AttemptRestart(Profile
* profile
) {
1502 if (CheckEasyUnlockKeyOps(base::Bind(&UserSessionManager::AttemptRestart
,
1503 AsWeakPtr(), profile
))) {
1507 if (session_restore_strategy_
!=
1508 OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR
) {
1509 chrome::AttemptRestart();
1513 // We can't really quit if the session restore process that mints new
1514 // refresh token is still in progress.
1515 OAuth2LoginManager
* login_manager
=
1516 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile
);
1517 if (login_manager
->state() != OAuth2LoginManager::SESSION_RESTORE_PREPARING
&&
1518 login_manager
->state() !=
1519 OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS
) {
1520 chrome::AttemptRestart();
1524 LOG(WARNING
) << "Attempting browser restart during session restore.";
1525 exit_after_session_restore_
= true;
1528 void UserSessionManager::OnEasyUnlockKeyOpsFinished(
1529 const std::string
& user_id
,
1531 running_easy_unlock_key_ops_
= false;
1532 if (!easy_unlock_key_ops_finished_callback_
.is_null())
1533 easy_unlock_key_ops_finished_callback_
.Run();
1535 const user_manager::User
* user
=
1536 user_manager::UserManager::Get()->FindUser(user_id
);
1537 EasyUnlockService
* easy_unlock_service
=
1538 EasyUnlockService::GetForUser(*user
);
1539 easy_unlock_service
->CheckCryptohomeKeysAndMaybeHardlock();
1542 void UserSessionManager::ActiveUserChanged(
1543 const user_manager::User
* active_user
) {
1544 if (!user_manager::UserManager::Get()->IsCurrentUserNew())
1545 SendUserPodsMetrics();
1547 Profile
* profile
= ProfileHelper::Get()->GetProfileByUser(active_user
);
1548 // If profile has not yet been initialized, delay initialization of IME.
1552 input_method::InputMethodManager
* manager
=
1553 input_method::InputMethodManager::Get();
1555 GetDefaultIMEState(ProfileHelper::Get()->GetProfileByUser(active_user
)));
1558 scoped_refptr
<input_method::InputMethodManager::State
>
1559 UserSessionManager::GetDefaultIMEState(Profile
* profile
) {
1560 scoped_refptr
<input_method::InputMethodManager::State
> state
=
1561 default_ime_states_
[profile
];
1563 // Profile can be NULL in tests.
1564 state
= input_method::InputMethodManager::Get()->CreateNewState(profile
);
1565 default_ime_states_
[profile
] = state
;
1570 EasyUnlockKeyManager
* UserSessionManager::GetEasyUnlockKeyManager() {
1571 if (!easy_unlock_key_manager_
)
1572 easy_unlock_key_manager_
.reset(new EasyUnlockKeyManager
);
1574 return easy_unlock_key_manager_
.get();
1577 void UserSessionManager::DoBrowserLaunchInternal(Profile
* profile
,
1578 LoginDisplayHost
* login_host
,
1579 bool locale_pref_checked
) {
1580 if (browser_shutdown::IsTryingToQuit())
1583 if (!locale_pref_checked
) {
1584 RespectLocalePreferenceWrapper(
1586 base::Bind(&UserSessionManager::DoBrowserLaunchInternal
, AsWeakPtr(),
1587 profile
, login_host
, true /* locale_pref_checked */));
1591 if (!ChromeUserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
1592 ChromeUserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile
);
1596 if (RestartToApplyPerSessionFlagsIfNeed(profile
, false))
1600 login_host
->SetStatusAreaVisible(true);
1601 login_host
->BeforeSessionStart();
1604 BootTimesRecorder::Get()->AddLoginTimeMarker("BrowserLaunched", false);
1606 VLOG(1) << "Launching browser...";
1607 TRACE_EVENT0("login", "LaunchBrowser");
1609 if (should_launch_browser_
) {
1610 StartupBrowserCreator browser_creator
;
1611 chrome::startup::IsFirstRun first_run
=
1612 ::first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
1613 : chrome::startup::IS_NOT_FIRST_RUN
;
1615 browser_creator
.LaunchBrowser(
1616 *base::CommandLine::ForCurrentProcess(), profile
, base::FilePath(),
1617 chrome::startup::IS_PROCESS_STARTUP
, first_run
);
1619 // Triggers app launcher start page service to load start page web contents.
1620 app_list::StartPageService::Get(profile
);
1622 LOG(WARNING
) << "Browser hasn't been launched, should_launch_browser_"
1623 << " is false. This is normal in some tests.";
1626 // Mark login host for deletion after browser starts. This
1627 // guarantees that the message loop will be referenced by the
1628 // browser before it is dereferenced by the login host.
1630 login_host
->Finalize();
1631 user_manager::UserManager::Get()->SessionStarted();
1632 chromeos::BootTimesRecorder::Get()->LoginDone(
1633 user_manager::UserManager::Get()->IsCurrentUserNew());
1636 void UserSessionManager::RespectLocalePreferenceWrapper(
1638 const base::Closure
& callback
) {
1639 if (browser_shutdown::IsTryingToQuit())
1642 const user_manager::User
* const user
=
1643 ProfileHelper::Get()->GetUserByProfile(profile
);
1644 locale_util::SwitchLanguageCallback
locale_switched_callback(base::Bind(
1645 &UserSessionManager::RunCallbackOnLocaleLoaded
, callback
,
1646 base::Owned(new InputEventsBlocker
))); // Block UI events until
1647 // the ResourceBundle is
1649 if (!RespectLocalePreference(profile
, user
, locale_switched_callback
))
1654 void UserSessionManager::RunCallbackOnLocaleLoaded(
1655 const base::Closure
& callback
,
1656 InputEventsBlocker
* /* input_events_blocker */,
1657 const locale_util::LanguageSwitchResult
& /* result */) {
1661 void UserSessionManager::RemoveProfileForTesting(Profile
* profile
) {
1662 default_ime_states_
.erase(profile
);
1665 void UserSessionManager::InjectStubUserContext(
1666 const UserContext
& user_context
) {
1667 injected_user_context_
.reset(new UserContext(user_context
));
1668 authenticator_
= NULL
;
1671 void UserSessionManager::SendUserPodsMetrics() {
1672 bool show_users_on_signin
;
1673 CrosSettings::Get()->GetBoolean(kAccountsPrefShowUserNamesOnSignIn
,
1674 &show_users_on_signin
);
1675 bool is_enterprise_managed
= g_browser_process
->platform_part()
1676 ->browser_policy_connector_chromeos()
1677 ->IsEnterpriseManaged();
1678 UserPodsDisplay display
;
1679 if (show_users_on_signin
) {
1680 if (is_enterprise_managed
)
1681 display
= USER_PODS_DISPLAY_ENABLED_MANAGED
;
1683 display
= USER_PODS_DISPLAY_ENABLED_REGULAR
;
1685 if (is_enterprise_managed
)
1686 display
= USER_PODS_DISPLAY_DISABLED_MANAGED
;
1688 display
= USER_PODS_DISPLAY_DISABLED_REGULAR
;
1690 UMA_HISTOGRAM_ENUMERATION("UserSessionManager.UserPodsDisplay", display
,
1691 NUM_USER_PODS_DISPLAY
);
1694 void UserSessionManager::OnOAuth2TokensFetched(UserContext context
) {
1695 if (StartupUtils::IsWebviewSigninEnabled() && TokenHandlesEnabled()) {
1696 CreateTokenUtilIfMissing();
1697 if (token_handle_util_
->ShouldObtainHandle(context
.GetUserID())) {
1698 token_handle_fetcher_
.reset(new TokenHandleFetcher(
1699 token_handle_util_
.get(), context
.GetUserID()));
1700 token_handle_fetcher_
->FillForNewUser(
1701 context
.GetAccessToken(),
1702 base::Bind(&UserSessionManager::OnTokenHandleObtained
,
1703 weak_factory_
.GetWeakPtr()));
1708 void UserSessionManager::OnTokenHandleObtained(const user_manager::UserID
& id
,
1711 LOG(ERROR
) << "OAuth2 token handle fetch failed.";
1712 token_handle_fetcher_
.reset();
1715 bool UserSessionManager::TokenHandlesEnabled() {
1716 if (!should_obtain_handles_
)
1718 bool ephemeral_users_enabled
= false;
1719 bool show_names_on_signin
= true;
1720 auto cros_settings
= CrosSettings::Get();
1721 cros_settings
->GetBoolean(kAccountsPrefEphemeralUsersEnabled
,
1722 &ephemeral_users_enabled
);
1723 cros_settings
->GetBoolean(kAccountsPrefShowUserNamesOnSignIn
,
1724 &show_names_on_signin
);
1725 return show_names_on_signin
&& !ephemeral_users_enabled
;
1728 void UserSessionManager::Shutdown() {
1729 token_handle_fetcher_
.reset();
1730 token_handle_util_
.reset();
1733 void UserSessionManager::CreateTokenUtilIfMissing() {
1734 if (!token_handle_util_
.get())
1735 token_handle_util_
.reset(
1736 new TokenHandleUtil(user_manager::UserManager::Get()));
1739 } // namespace chromeos