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/message_loop/message_loop.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/path_service.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/prefs/pref_registry_simple.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/sys_info.h"
22 #include "base/task_runner_util.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "base/threading/worker_pool.h"
25 #include "chrome/browser/about_flags.h"
26 #include "chrome/browser/app_mode/app_mode_utils.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/browser_process_platform_part_chromeos.h"
29 #include "chrome/browser/browser_shutdown.h"
30 #include "chrome/browser/chrome_notification_types.h"
31 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
32 #include "chrome/browser/chromeos/base/locale_util.h"
33 #include "chrome/browser/chromeos/boot_times_recorder.h"
34 #include "chrome/browser/chromeos/first_run/first_run.h"
35 #include "chrome/browser/chromeos/input_method/input_method_util.h"
36 #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h"
37 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
38 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
39 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
40 #include "chrome/browser/chromeos/login/helper.h"
41 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
42 #include "chrome/browser/chromeos/login/profile_auth_data.h"
43 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
44 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
45 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
46 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
47 #include "chrome/browser/chromeos/login/signin/token_handle_fetcher.h"
48 #include "chrome/browser/chromeos/login/startup_utils.h"
49 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
50 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
51 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
52 #include "chrome/browser/chromeos/login/user_flow.h"
53 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
54 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
55 #include "chrome/browser/chromeos/login/wizard_controller.h"
56 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
57 #include "chrome/browser/chromeos/profiles/profile_helper.h"
58 #include "chrome/browser/chromeos/settings/cros_settings.h"
59 #include "chrome/browser/component_updater/ev_whitelist_component_installer.h"
60 #include "chrome/browser/first_run/first_run.h"
61 #include "chrome/browser/google/google_brand_chromeos.h"
62 #include "chrome/browser/lifetime/application_lifetime.h"
63 #include "chrome/browser/net/crl_set_fetcher.h"
64 #include "chrome/browser/net/nss_context.h"
65 #include "chrome/browser/pref_service_flags_storage.h"
66 #include "chrome/browser/prefs/session_startup_pref.h"
67 #include "chrome/browser/profiles/profile.h"
68 #include "chrome/browser/profiles/profile_manager.h"
69 #include "chrome/browser/signin/account_tracker_service_factory.h"
70 #include "chrome/browser/signin/easy_unlock_service.h"
71 #include "chrome/browser/signin/signin_manager_factory.h"
72 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
73 #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h"
74 #include "chrome/browser/ui/app_list/start_page_service.h"
75 #include "chrome/browser/ui/startup/startup_browser_creator.h"
76 #include "chrome/common/chrome_switches.h"
77 #include "chrome/common/logging_chrome.h"
78 #include "chrome/common/pref_names.h"
79 #include "chromeos/cert_loader.h"
80 #include "chromeos/chromeos_switches.h"
81 #include "chromeos/cryptohome/cryptohome_util.h"
82 #include "chromeos/dbus/cryptohome_client.h"
83 #include "chromeos/dbus/dbus_thread_manager.h"
84 #include "chromeos/dbus/session_manager_client.h"
85 #include "chromeos/login/auth/stub_authenticator.h"
86 #include "chromeos/login/user_names.h"
87 #include "chromeos/network/portal_detector/network_portal_detector.h"
88 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
89 #include "chromeos/settings/cros_settings_names.h"
90 #include "components/component_updater/component_updater_service.h"
91 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
92 #include "components/session_manager/core/session_manager.h"
93 #include "components/signin/core/browser/account_tracker_service.h"
94 #include "components/signin/core/browser/signin_manager_base.h"
95 #include "components/user_manager/user.h"
96 #include "components/user_manager/user_manager.h"
97 #include "components/user_manager/user_type.h"
98 #include "content/public/browser/browser_thread.h"
99 #include "content/public/browser/notification_service.h"
100 #include "content/public/browser/storage_partition.h"
101 #include "ui/base/ime/chromeos/input_method_descriptor.h"
102 #include "ui/base/ime/chromeos/input_method_manager.h"
103 #include "url/gurl.h"
105 #if defined(ENABLE_RLZ)
106 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
107 #include "components/rlz/rlz_tracker.h"
114 // Milliseconds until we timeout our attempt to fetch flags from the child
116 static const int kFlagsFetchingLoginTimeoutMs
= 1000;
118 // The maximum ammount of time that we are willing to delay a browser restart
119 // for, waiting for a session restore to finish.
120 static const int kMaxRestartDelaySeconds
= 10;
122 // ChromeVox tutorial URL (used in place of "getting started" url when
123 // accessibility is enabled).
124 const char kChromeVoxTutorialURLPattern
[] =
125 "http://www.chromevox.com/tutorial/index.html?lang=%s";
127 void InitLocaleAndInputMethodsForNewUser(
128 UserSessionManager
* session_manager
,
130 const std::string
& public_session_locale
,
131 const std::string
& public_session_input_method
) {
132 PrefService
* prefs
= profile
->GetPrefs();
134 if (!public_session_locale
.empty()) {
135 // If this is a public session and the user chose a |public_session_locale|,
136 // write it to |prefs| so that the UI switches to it.
137 locale
= public_session_locale
;
138 prefs
->SetString(prefs::kApplicationLocale
, locale
);
140 // Suppress the locale change dialog.
141 prefs
->SetString(prefs::kApplicationLocaleAccepted
, locale
);
143 // Otherwise, assume that the session will use the current UI locale.
144 locale
= g_browser_process
->GetApplicationLocale();
147 // First, we'll set kLanguagePreloadEngines.
148 input_method::InputMethodManager
* manager
=
149 input_method::InputMethodManager::Get();
151 input_method::InputMethodDescriptor preferred_input_method
;
152 if (!public_session_input_method
.empty()) {
153 // If this is a public session and the user chose a valid
154 // |public_session_input_method|, use it as the |preferred_input_method|.
155 const input_method::InputMethodDescriptor
* const descriptor
=
156 manager
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
157 public_session_input_method
);
159 preferred_input_method
= *descriptor
;
161 LOG(WARNING
) << "Public session is initialized with an invalid IME"
162 << ", id=" << public_session_input_method
;
166 // If |preferred_input_method| is not set, use the currently active input
168 if (preferred_input_method
.id().empty()) {
169 preferred_input_method
=
170 session_manager
->GetDefaultIMEState(profile
)->GetCurrentInputMethod();
173 // Derive kLanguagePreloadEngines from |locale| and |preferred_input_method|.
174 std::vector
<std::string
> input_method_ids
;
175 manager
->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
176 locale
, preferred_input_method
, &input_method_ids
);
178 // Save the input methods in the user's preferences.
179 StringPrefMember language_preload_engines
;
180 language_preload_engines
.Init(prefs::kLanguagePreloadEngines
, prefs
);
181 language_preload_engines
.SetValue(base::JoinString(input_method_ids
, ","));
182 BootTimesRecorder::Get()->AddLoginTimeMarker("IMEStarted", false);
184 // Second, we'll set kLanguagePreferredLanguages.
185 std::vector
<std::string
> language_codes
;
187 // The current locale should be on the top.
188 language_codes
.push_back(locale
);
190 // Add input method IDs based on the input methods, as there may be
191 // input methods that are unrelated to the current locale. Example: the
192 // hardware keyboard layout xkb:us::eng is used for logging in, but the
193 // UI language is set to French. In this case, we should set "fr,en"
194 // to the preferred languages preference.
195 std::vector
<std::string
> candidates
;
196 manager
->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
197 input_method_ids
, &candidates
);
198 for (size_t i
= 0; i
< candidates
.size(); ++i
) {
199 const std::string
& candidate
= candidates
[i
];
200 // Skip if it's already in language_codes.
201 if (std::count(language_codes
.begin(), language_codes
.end(),
203 language_codes
.push_back(candidate
);
207 // Save the preferred languages in the user's preferences.
208 prefs
->SetString(prefs::kLanguagePreferredLanguages
,
209 base::JoinString(language_codes
, ","));
211 // Indicate that we need to merge the syncable input methods when we sync,
212 // since we have not applied the synced prefs before.
213 prefs
->SetBoolean(prefs::kLanguageShouldMergeInputMethods
, true);
216 #if defined(ENABLE_RLZ)
217 // Flag file that disables RLZ tracking, when present.
218 const base::FilePath::CharType kRLZDisabledFlagName
[] =
219 FILE_PATH_LITERAL(".rlz_disabled");
221 base::FilePath
GetRlzDisabledFlagPath() {
222 base::FilePath homedir
;
223 PathService::Get(base::DIR_HOME
, &homedir
);
224 return homedir
.Append(kRLZDisabledFlagName
);
228 // Callback to GetNSSCertDatabaseForProfile. It starts CertLoader using the
229 // provided NSS database. It must be called for primary user only.
230 void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase
* database
) {
231 if (!CertLoader::IsInitialized())
234 CertLoader::Get()->StartWithNSSDB(database
);
237 // Returns new CommandLine with per-user flags.
238 base::CommandLine
CreatePerSessionCommandLine(Profile
* profile
) {
239 base::CommandLine
user_flags(base::CommandLine::NO_PROGRAM
);
240 about_flags::PrefServiceFlagsStorage
flags_storage_(profile
->GetPrefs());
241 about_flags::ConvertFlagsToSwitches(&flags_storage_
, &user_flags
,
242 about_flags::kAddSentinels
);
246 // Returns true if restart is needed to apply per-session flags.
247 bool NeedRestartToApplyPerSessionFlags(
248 const base::CommandLine
& user_flags
,
249 std::set
<base::CommandLine::StringType
>* out_command_line_difference
) {
250 // Don't restart browser if it is not first profile in session.
251 if (user_manager::UserManager::Get()->GetLoggedInUsers().size() != 1)
254 // Only restart if needed and if not going into managed mode.
255 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser())
258 if (about_flags::AreSwitchesIdenticalToCurrentCommandLine(
259 user_flags
, *base::CommandLine::ForCurrentProcess(),
260 out_command_line_difference
)) {
267 bool CanPerformEarlyRestart() {
268 // Desktop build is used for development only. Early restart is not supported.
269 if (!base::SysInfo::IsRunningOnChromeOS())
272 if (!ChromeUserManager::Get()
273 ->GetCurrentUserFlow()
274 ->SupportsEarlyRestartToApplyFlags()) {
278 const ExistingUserController
* controller
=
279 ExistingUserController::current_controller();
283 // Early restart is possible only if OAuth token is up to date.
285 if (controller
->password_changed())
288 if (controller
->auth_mode() != LoginPerformer::AUTH_MODE_INTERNAL
)
291 // No early restart if Easy unlock key needs to be updated.
292 if (UserSessionManager::GetInstance()->NeedsToUpdateEasyUnlockKeys())
298 void LogCustomSwitches(const std::set
<std::string
>& switches
) {
301 for (std::set
<std::string
>::const_iterator it
= switches
.begin();
302 it
!= switches
.end(); ++it
) {
303 VLOG(1) << "Switch leading to restart: '" << *it
<< "'";
307 void RestartOnTimeout() {
308 LOG(WARNING
) << "Restarting Chrome because the time out was reached."
309 "The session restore has not finished.";
310 chrome::AttemptRestart();
315 UserSessionManagerDelegate::~UserSessionManagerDelegate() {
318 void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
321 UserSessionStateObserver::~UserSessionStateObserver() {
325 UserSessionManager
* UserSessionManager::GetInstance() {
326 return Singleton
<UserSessionManager
,
327 DefaultSingletonTraits
<UserSessionManager
> >::get();
331 void UserSessionManager::OverrideHomedir() {
332 // Override user homedir, check for ProfileManager being initialized as
333 // it may not exist in unit tests.
334 if (g_browser_process
->profile_manager()) {
335 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
336 if (user_manager
->GetLoggedInUsers().size() == 1) {
337 base::FilePath homedir
= ProfileHelper::GetProfilePathByUserIdHash(
338 user_manager
->GetPrimaryUser()->username_hash());
339 // This path has been either created by cryptohome (on real Chrome OS
340 // device) or by ProfileManager (on chromeos=1 desktop builds).
341 PathService::OverrideAndCreateIfNeeded(base::DIR_HOME
,
343 true /* path is absolute */,
344 false /* don't create */);
350 void UserSessionManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
351 registry
->RegisterStringPref(prefs::kRLZBrand
, std::string());
352 registry
->RegisterBooleanPref(prefs::kRLZDisabled
, false);
355 UserSessionManager::UserSessionManager()
356 : delegate_(nullptr),
357 authenticator_(nullptr),
358 has_auth_cookies_(false),
359 user_sessions_restored_(false),
360 user_sessions_restore_in_progress_(false),
361 exit_after_session_restore_(false),
362 session_restore_strategy_(
363 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN
),
364 running_easy_unlock_key_ops_(false),
365 should_obtain_handles_(true),
366 should_launch_browser_(true),
367 waiting_for_child_account_status_(false),
368 weak_factory_(this) {
369 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
370 user_manager::UserManager::Get()->AddSessionStateObserver(this);
373 UserSessionManager::~UserSessionManager() {
374 // UserManager is destroyed before singletons, so we need to check if it
376 // TODO(nkostylev): fix order of destruction of UserManager
377 // / UserSessionManager objects.
378 if (user_manager::UserManager::IsInitialized())
379 user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
380 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
383 void UserSessionManager::SetShouldObtainHandleInTests(
384 bool should_obtain_handles
) {
385 should_obtain_handles_
= should_obtain_handles
;
386 if (!should_obtain_handles_
) {
387 token_handle_fetcher_
.reset();
391 void UserSessionManager::CompleteGuestSessionLogin(const GURL
& start_url
) {
392 VLOG(1) << "Completing guest session login";
394 // For guest session we ask session_manager to restart Chrome with --bwsi
395 // flag. We keep only some of the arguments of this process.
396 const base::CommandLine
& browser_command_line
=
397 *base::CommandLine::ForCurrentProcess();
398 base::CommandLine
command_line(browser_command_line
.GetProgram());
399 GetOffTheRecordCommandLine(start_url
, StartupUtils::IsOobeCompleted(),
400 browser_command_line
, &command_line
);
402 // This makes sure that Chrome restarts with no per-session flags. The guest
403 // profile will always have empty set of per-session flags. If this is not
404 // done and device owner has some per-session flags, when Chrome is relaunched
405 // the guest profile session flags will not match the current command line and
406 // another restart will be attempted in order to reset the user flags for the
408 const base::CommandLine
user_flags(base::CommandLine::NO_PROGRAM
);
409 if (!about_flags::AreSwitchesIdenticalToCurrentCommandLine(
410 user_flags
, *base::CommandLine::ForCurrentProcess(), NULL
)) {
411 DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
412 chromeos::login::kGuestUserName
, base::CommandLine::StringVector());
415 RestartChrome(command_line
);
418 scoped_refptr
<Authenticator
> UserSessionManager::CreateAuthenticator(
419 AuthStatusConsumer
* consumer
) {
420 // Screen locker needs new Authenticator instance each time.
421 if (ScreenLocker::default_screen_locker()) {
422 if (authenticator_
.get())
423 authenticator_
->SetConsumer(NULL
);
424 authenticator_
= NULL
;
427 if (authenticator_
.get() == NULL
) {
428 if (injected_user_context_
) {
430 new StubAuthenticator(consumer
, *injected_user_context_
.get());
432 authenticator_
= new ChromeCryptohomeAuthenticator(consumer
);
435 // TODO(nkostylev): Fix this hack by improving Authenticator dependencies.
436 authenticator_
->SetConsumer(consumer
);
438 return authenticator_
;
441 void UserSessionManager::StartSession(
442 const UserContext
& user_context
,
443 StartSessionType start_session_type
,
444 bool has_auth_cookies
,
445 bool has_active_session
,
446 UserSessionManagerDelegate
* delegate
) {
447 delegate_
= delegate
;
448 start_session_type_
= start_session_type
;
450 VLOG(1) << "Starting session for " << user_context
.GetUserID();
453 CreateUserSession(user_context
, has_auth_cookies
);
455 if (!has_active_session
)
458 // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
459 // ready to be used (http://crbug.com/361528).
460 NotifyUserLoggedIn();
462 if (!user_context
.GetDeviceId().empty()) {
463 user_manager::UserManager::Get()->SetKnownUserDeviceId(
464 user_context
.GetUserID(), user_context
.GetDeviceId());
470 void UserSessionManager::DelegateDeleted(UserSessionManagerDelegate
* delegate
) {
471 if (delegate_
== delegate
)
475 void UserSessionManager::PerformPostUserLoggedInActions() {
476 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
477 if (user_manager
->GetLoggedInUsers().size() == 1) {
478 if (NetworkPortalDetector::IsInitialized()) {
479 NetworkPortalDetector::Get()->SetStrategy(
480 PortalDetectorStrategy::STRATEGY_ID_SESSION
);
485 void UserSessionManager::RestoreAuthenticationSession(Profile
* user_profile
) {
486 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
487 // We need to restore session only for logged in GAIA (regular) users.
488 // Note: stub user is a special case that is used for tests, running
489 // linux_chromeos build on dev workstations w/o user_id parameters.
490 // Stub user is considered to be a regular GAIA user but it has special
491 // user_id (kStubUser) and certain services like restoring OAuth session are
492 // explicitly disabled for it.
493 if (!user_manager
->IsUserLoggedIn() ||
494 !user_manager
->IsLoggedInAsUserWithGaiaAccount() ||
495 user_manager
->IsLoggedInAsStub()) {
499 const user_manager::User
* user
=
500 ProfileHelper::Get()->GetUserByProfile(user_profile
);
502 if (!net::NetworkChangeNotifier::IsOffline()) {
503 pending_signin_restore_sessions_
.erase(user
->email());
504 RestoreAuthSessionImpl(user_profile
, false /* has_auth_cookies */);
506 // Even if we're online we should wait till initial
507 // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
508 // end up canceling all request when initial network connection type is
509 // processed. See http://crbug.com/121643.
510 pending_signin_restore_sessions_
.insert(user
->email());
514 void UserSessionManager::RestoreActiveSessions() {
515 user_sessions_restore_in_progress_
= true;
516 DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
517 base::Bind(&UserSessionManager::OnRestoreActiveSessions
, AsWeakPtr()));
520 bool UserSessionManager::UserSessionsRestored() const {
521 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
522 return user_sessions_restored_
;
525 bool UserSessionManager::UserSessionsRestoreInProgress() const {
526 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
527 return user_sessions_restore_in_progress_
;
530 void UserSessionManager::InitRlz(Profile
* profile
) {
531 #if defined(ENABLE_RLZ)
532 if (!g_browser_process
->local_state()->HasPrefPath(prefs::kRLZBrand
)) {
533 // Read brand code asynchronously from an OEM data and repost ourselves.
534 google_brand::chromeos::InitBrand(
535 base::Bind(&UserSessionManager::InitRlz
, AsWeakPtr(), profile
));
538 base::PostTaskAndReplyWithResult(
539 base::WorkerPool::GetTaskRunner(false).get(),
541 base::Bind(&base::PathExists
, GetRlzDisabledFlagPath()),
542 base::Bind(&UserSessionManager::InitRlzImpl
, AsWeakPtr(), profile
));
546 void UserSessionManager::SetFirstLoginPrefs(
548 const std::string
& public_session_locale
,
549 const std::string
& public_session_input_method
) {
550 VLOG(1) << "Setting first login prefs";
551 InitLocaleAndInputMethodsForNewUser(
552 this, profile
, public_session_locale
, public_session_input_method
);
555 bool UserSessionManager::GetAppModeChromeClientOAuthInfo(
556 std::string
* chrome_client_id
, std::string
* chrome_client_secret
) {
557 if (!chrome::IsRunningInForcedAppMode() ||
558 chrome_client_id_
.empty() ||
559 chrome_client_secret_
.empty()) {
563 *chrome_client_id
= chrome_client_id_
;
564 *chrome_client_secret
= chrome_client_secret_
;
568 void UserSessionManager::SetAppModeChromeClientOAuthInfo(
569 const std::string
& chrome_client_id
,
570 const std::string
& chrome_client_secret
) {
571 if (!chrome::IsRunningInForcedAppMode())
574 chrome_client_id_
= chrome_client_id
;
575 chrome_client_secret_
= chrome_client_secret
;
578 void UserSessionManager::DoBrowserLaunch(Profile
* profile
,
579 LoginDisplayHost
* login_host
) {
580 DoBrowserLaunchInternal(profile
, login_host
, false /* locale_pref_checked */);
583 bool UserSessionManager::RespectLocalePreference(
585 const user_manager::User
* user
,
586 const locale_util::SwitchLanguageCallback
& callback
) const {
587 // TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
588 // the Google user profile.
589 if (g_browser_process
== NULL
)
592 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
593 if (!user
|| (user_manager
->IsUserLoggedIn() &&
594 user
!= user_manager
->GetPrimaryUser())) {
598 // In case of multi-profiles session we don't apply profile locale
599 // because it is unsafe.
600 if (user_manager
->GetLoggedInUsers().size() != 1)
603 const PrefService
* prefs
= profile
->GetPrefs();
607 std::string pref_locale
;
608 const std::string pref_app_locale
=
609 prefs
->GetString(prefs::kApplicationLocale
);
610 const std::string pref_bkup_locale
=
611 prefs
->GetString(prefs::kApplicationLocaleBackup
);
613 pref_locale
= pref_app_locale
;
614 if (pref_locale
.empty())
615 pref_locale
= pref_bkup_locale
;
617 const std::string
* account_locale
= NULL
;
618 if (pref_locale
.empty() && user
->has_gaia_account()) {
619 if (user
->GetAccountLocale() == NULL
)
620 return false; // wait until Account profile is loaded.
621 account_locale
= user
->GetAccountLocale();
622 pref_locale
= *account_locale
;
624 const std::string global_app_locale
=
625 g_browser_process
->GetApplicationLocale();
626 if (pref_locale
.empty())
627 pref_locale
= global_app_locale
;
628 DCHECK(!pref_locale
.empty());
629 VLOG(1) << "RespectLocalePreference: "
630 << "app_locale='" << pref_app_locale
<< "', "
631 << "bkup_locale='" << pref_bkup_locale
<< "', "
632 << (account_locale
!= NULL
633 ? (std::string("account_locale='") + (*account_locale
) +
635 : (std::string("account_locale - unused. ")))
636 << " Selected '" << pref_locale
<< "'";
637 profile
->ChangeAppLocale(
639 user
->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT
?
640 Profile::APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN
:
641 Profile::APP_LOCALE_CHANGED_VIA_LOGIN
);
643 // Here we don't enable keyboard layouts for normal users. Input methods
644 // are set up when the user first logs in. Then the user may customize the
645 // input methods. Hence changing input methods here, just because the user's
646 // UI language is different from the login screen UI language, is not
647 // desirable. Note that input method preferences are synced, so users can use
648 // their farovite input methods as soon as the preferences are synced.
650 // For Guest mode, user locale preferences will never get initialized.
651 // So input methods should be enabled somewhere.
652 const bool enable_layouts
=
653 user_manager::UserManager::Get()->IsLoggedInAsGuest();
654 locale_util::SwitchLanguage(pref_locale
, enable_layouts
,
655 false /* login_layouts_only */, callback
,
661 bool UserSessionManager::RestartToApplyPerSessionFlagsIfNeed(
663 bool early_restart
) {
664 if (ProfileHelper::IsSigninProfile(profile
))
667 if (early_restart
&& !CanPerformEarlyRestart())
670 // We can't really restart if we've already restarted as a part of
671 // user session restore after crash of in case when flags were changed inside
673 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginUser
))
676 // We can't restart if that's a second user sign in that is happening.
677 if (user_manager::UserManager::Get()->GetLoggedInUsers().size() > 1)
680 const base::CommandLine
user_flags(CreatePerSessionCommandLine(profile
));
681 std::set
<base::CommandLine::StringType
> command_line_difference
;
682 if (!NeedRestartToApplyPerSessionFlags(user_flags
, &command_line_difference
))
685 LogCustomSwitches(command_line_difference
);
687 about_flags::ReportCustomFlags("Login.CustomFlags", command_line_difference
);
689 base::CommandLine::StringVector flags
;
690 // argv[0] is the program name |base::CommandLine::NO_PROGRAM|.
691 flags
.assign(user_flags
.argv().begin() + 1, user_flags
.argv().end());
692 LOG(WARNING
) << "Restarting to apply per-session flags...";
693 DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
694 user_manager::UserManager::Get()->GetActiveUser()->email(), flags
);
695 AttemptRestart(profile
);
699 bool UserSessionManager::NeedsToUpdateEasyUnlockKeys() const {
700 return !user_context_
.GetUserID().empty() &&
701 user_manager::User::TypeHasGaiaAccount(user_context_
.GetUserType()) &&
702 user_context_
.GetKey() && !user_context_
.GetKey()->GetSecret().empty();
705 bool UserSessionManager::CheckEasyUnlockKeyOps(const base::Closure
& callback
) {
706 if (!running_easy_unlock_key_ops_
)
709 // Assumes only one deferred callback is needed.
710 DCHECK(easy_unlock_key_ops_finished_callback_
.is_null());
712 easy_unlock_key_ops_finished_callback_
= callback
;
716 void UserSessionManager::AddSessionStateObserver(
717 chromeos::UserSessionStateObserver
* observer
) {
718 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
719 session_state_observer_list_
.AddObserver(observer
);
722 void UserSessionManager::RemoveSessionStateObserver(
723 chromeos::UserSessionStateObserver
* observer
) {
724 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
725 session_state_observer_list_
.RemoveObserver(observer
);
728 void UserSessionManager::OnSessionRestoreStateChanged(
729 Profile
* user_profile
,
730 OAuth2LoginManager::SessionRestoreState state
) {
731 user_manager::User::OAuthTokenStatus user_status
=
732 user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN
;
733 OAuth2LoginManager
* login_manager
=
734 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile
);
736 bool connection_error
= false;
738 case OAuth2LoginManager::SESSION_RESTORE_DONE
:
739 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_VALID
;
741 case OAuth2LoginManager::SESSION_RESTORE_FAILED
:
742 user_status
= user_manager::User::OAUTH2_TOKEN_STATUS_INVALID
;
744 case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
:
745 connection_error
= true;
747 case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED
:
748 case OAuth2LoginManager::SESSION_RESTORE_PREPARING
:
749 case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS
:
753 // We should not be clearing existing token state if that was a connection
754 // error. http://crbug.com/295245
755 if (!connection_error
) {
756 // We are in one of "done" states here.
757 user_manager::UserManager::Get()->SaveUserOAuthStatus(
758 user_manager::UserManager::Get()->GetLoggedInUser()->email(),
762 login_manager
->RemoveObserver(this);
764 if (exit_after_session_restore_
&&
765 (state
== OAuth2LoginManager::SESSION_RESTORE_DONE
||
766 state
== OAuth2LoginManager::SESSION_RESTORE_FAILED
||
767 state
== OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
)) {
768 LOG(WARNING
) << "Restarting Chrome after session restore finishes, "
769 << "most likely due to custom flags.";
771 // We need to restart cleanly in this case to make sure OAuth2 RT is
773 chrome::AttemptRestart();
777 void UserSessionManager::OnConnectionTypeChanged(
778 net::NetworkChangeNotifier::ConnectionType type
) {
779 bool is_running_test
=
780 base::CommandLine::ForCurrentProcess()->HasSwitch(
781 ::switches::kTestName
) ||
782 base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType
);
783 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
784 if (type
== net::NetworkChangeNotifier::CONNECTION_NONE
||
785 !user_manager
->IsUserLoggedIn() ||
786 !user_manager
->IsLoggedInAsUserWithGaiaAccount() ||
787 user_manager
->IsLoggedInAsStub() || is_running_test
) {
791 // Need to iterate over all users and their OAuth2 session state.
792 const user_manager::UserList
& users
= user_manager
->GetLoggedInUsers();
793 for (user_manager::UserList::const_iterator it
= users
.begin();
796 if (!(*it
)->is_profile_created())
799 Profile
* user_profile
= ProfileHelper::Get()->GetProfileByUserUnsafe(*it
);
800 bool should_restore_session
=
801 pending_signin_restore_sessions_
.find((*it
)->email()) !=
802 pending_signin_restore_sessions_
.end();
803 OAuth2LoginManager
* login_manager
=
804 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile
);
805 if (login_manager
->SessionRestoreIsRunning()) {
806 // If we come online for the first time after successful offline login,
807 // we need to kick off OAuth token verification process again.
808 login_manager
->ContinueSessionRestore();
809 } else if (should_restore_session
) {
810 pending_signin_restore_sessions_
.erase((*it
)->email());
811 RestoreAuthSessionImpl(user_profile
, false /* has_auth_cookies */);
816 void UserSessionManager::OnProfilePrepared(Profile
* profile
,
817 bool browser_launched
) {
818 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
819 ::switches::kTestName
)) {
820 // Did not log in (we crashed or are debugging), need to restore Sync.
821 // TODO(nkostylev): Make sure that OAuth state is restored correctly for all
822 // users once it is fully multi-profile aware. http://crbug.com/238987
823 // For now if we have other user pending sessions they'll override OAuth
824 // session restore for previous users.
825 RestoreAuthenticationSession(profile
);
828 // Restore other user sessions if any.
829 RestorePendingUserSessions();
832 void UserSessionManager::ChildAccountStatusReceivedCallback(Profile
* profile
) {
833 StopChildStatusObserving(profile
);
836 void UserSessionManager::StopChildStatusObserving(Profile
* profile
) {
837 if (!waiting_for_child_account_status_
&&
838 !SessionStartupPref::TypeIsManaged(profile
->GetPrefs())) {
839 InitializeStartUrls();
841 waiting_for_child_account_status_
= false;
844 void UserSessionManager::CreateUserSession(const UserContext
& user_context
,
845 bool has_auth_cookies
) {
846 user_context_
= user_context
;
847 has_auth_cookies_
= has_auth_cookies
;
848 InitSessionRestoreStrategy();
849 StoreUserContextDataBeforeProfileIsCreated();
852 void UserSessionManager::PreStartSession() {
853 // Switch log file as soon as possible.
854 if (base::SysInfo::IsRunningOnChromeOS())
855 logging::RedirectChromeLogging(*(base::CommandLine::ForCurrentProcess()));
858 void UserSessionManager::StoreUserContextDataBeforeProfileIsCreated() {
859 // Store obfuscated GAIA ID.
860 if (!user_context_
.GetGaiaID().empty()) {
861 user_manager::UserManager::Get()->UpdateGaiaID(user_context_
.GetUserID(),
862 user_context_
.GetGaiaID());
866 void UserSessionManager::StartCrosSession() {
867 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
868 btl
->AddLoginTimeMarker("StartSession-Start", false);
869 DBusThreadManager::Get()->GetSessionManagerClient()->
870 StartSession(user_context_
.GetUserID());
871 btl
->AddLoginTimeMarker("StartSession-End", false);
874 void UserSessionManager::NotifyUserLoggedIn() {
875 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
876 btl
->AddLoginTimeMarker("UserLoggedIn-Start", false);
877 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
878 user_manager
->UserLoggedIn(user_context_
.GetUserID(),
879 user_context_
.GetUserIDHash(),
881 btl
->AddLoginTimeMarker("UserLoggedIn-End", false);
884 void UserSessionManager::PrepareProfile() {
885 bool is_demo_session
=
886 DemoAppLauncher::IsDemoAppSession(user_context_
.GetUserID());
888 // TODO(nkostylev): Figure out whether demo session is using the right profile
889 // path or not. See https://codereview.chromium.org/171423009
890 g_browser_process
->profile_manager()->CreateProfileAsync(
891 ProfileHelper::GetProfilePathByUserIdHash(user_context_
.GetUserIDHash()),
892 base::Bind(&UserSessionManager::OnProfileCreated
,
901 void UserSessionManager::OnProfileCreated(const UserContext
& user_context
,
902 bool is_incognito_profile
,
904 Profile::CreateStatus status
) {
908 case Profile::CREATE_STATUS_CREATED
:
909 // Profile created but before initializing extensions and promo resources.
910 InitProfilePreferences(profile
, user_context
);
912 case Profile::CREATE_STATUS_INITIALIZED
:
913 // Profile is created, extensions and promo resources are initialized.
914 // At this point all other Chrome OS services will be notified that it is
915 // safe to use this profile.
916 UserProfileInitialized(profile
,
917 is_incognito_profile
,
918 user_context
.GetUserID());
920 case Profile::CREATE_STATUS_LOCAL_FAIL
:
921 case Profile::CREATE_STATUS_REMOTE_FAIL
:
922 case Profile::CREATE_STATUS_CANCELED
:
923 case Profile::MAX_CREATE_STATUS
:
929 void UserSessionManager::InitProfilePreferences(
931 const UserContext
& user_context
) {
932 const user_manager::User
* user
=
933 ProfileHelper::Get()->GetUserByProfile(profile
);
934 if (user
->GetType() == user_manager::USER_TYPE_KIOSK_APP
&&
935 profile
->IsNewProfile()) {
936 ChromeUserManager::Get()->SetIsCurrentUserNew(true);
939 if (user
->is_active()) {
940 input_method::InputMethodManager
* manager
=
941 input_method::InputMethodManager::Get();
942 manager
->SetState(GetDefaultIMEState(profile
));
944 if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
945 SetFirstLoginPrefs(profile
,
946 user_context
.GetPublicSessionLocale(),
947 user_context
.GetPublicSessionInputMethod());
950 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
951 user_manager::User
* active_user
=
952 user_manager::UserManager::Get()->GetActiveUser();
953 std::string supervised_user_sync_id
=
954 ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
955 active_user
->email());
956 profile
->GetPrefs()->SetString(prefs::kSupervisedUserId
,
957 supervised_user_sync_id
);
958 } else if (user_manager::UserManager::Get()->
959 IsLoggedInAsUserWithGaiaAccount()) {
960 // Get the Gaia ID from the user context. If it's not available, this may
961 // not be available when unlocking a previously opened profile, or when
962 // creating a supervised users. However, in these cases the gaia_id should
963 // be already available in the account tracker.
964 std::string gaia_id
= user_context
.GetGaiaID();
965 if (gaia_id
.empty()) {
966 AccountTrackerService
* account_tracker
=
967 AccountTrackerServiceFactory::GetForProfile(profile
);
969 account_tracker
->FindAccountInfoByEmail(user_context
.GetUserID());
971 DCHECK(!gaia_id
.empty());
974 // Make sure that the google service username is properly set (we do this
975 // on every sign in, not just the first login, to deal with existing
976 // profiles that might not have it set yet).
977 SigninManagerBase
* signin_manager
=
978 SigninManagerFactory::GetForProfile(profile
);
979 signin_manager
->SetAuthenticatedAccountInfo(gaia_id
,
980 user_context
.GetUserID());
982 // Backfill GAIA ID in user prefs stored in Local State.
983 std::string tmp_gaia_id
;
984 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
985 if (!user_manager
->FindGaiaID(user_context
.GetUserID(), &tmp_gaia_id
) &&
987 user_manager
->UpdateGaiaID(user_context
.GetUserID(), gaia_id
);
992 void UserSessionManager::UserProfileInitialized(Profile
* profile
,
993 bool is_incognito_profile
,
994 const std::string
& user_id
) {
995 // Demo user signed in.
996 if (is_incognito_profile
) {
999 // Send the notification before creating the browser so additional objects
1000 // that need the profile (e.g. the launcher) can be created first.
1001 content::NotificationService::current()->Notify(
1002 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED
,
1003 content::NotificationService::AllSources(),
1004 content::Details
<Profile
>(profile
));
1007 delegate_
->OnProfilePrepared(profile
, false);
1012 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
1013 btl
->AddLoginTimeMarker("UserProfileGotten", false);
1015 if (user_context_
.IsUsingOAuth()) {
1016 // Retrieve the policy that indicates whether to continue copying
1017 // authentication cookies set by a SAML IdP on subsequent logins after the
1019 bool transfer_saml_auth_cookies_on_subsequent_login
= false;
1020 if (has_auth_cookies_
&&
1021 g_browser_process
->platform_part()->
1022 browser_policy_connector_chromeos()->GetUserAffiliation(user_id
) ==
1023 policy::USER_AFFILIATION_MANAGED
) {
1024 CrosSettings::Get()->GetBoolean(
1025 kAccountsPrefTransferSAMLCookies
,
1026 &transfer_saml_auth_cookies_on_subsequent_login
);
1029 // Transfers authentication-related data from the profile that was used for
1030 // authentication to the user's profile. The proxy authentication state is
1031 // transferred unconditionally. If the user authenticated via an auth
1032 // extension, authentication cookies and channel IDs will be transferred as
1033 // well when the user's cookie jar is empty. If the cookie jar is not empty,
1034 // the authentication states in the browser context and the user's profile
1035 // must be merged using /MergeSession instead. Authentication cookies set by
1036 // a SAML IdP will also be transferred when the user's cookie jar is not
1037 // empty if |transfer_saml_auth_cookies_on_subsequent_login| is true.
1038 const bool transfer_auth_cookies_and_channel_ids_on_first_login
=
1041 net::URLRequestContextGetter
* auth_request_context
=
1042 GetAuthRequestContext();
1044 // Authentication request context may be missing especially if user didn't
1045 // sign in using GAIA (webview) and webview didn't yet initialize.
1046 if (auth_request_context
) {
1047 ProfileAuthData::Transfer(
1048 auth_request_context
, profile
->GetRequestContext(),
1049 transfer_auth_cookies_and_channel_ids_on_first_login
,
1050 transfer_saml_auth_cookies_on_subsequent_login
,
1052 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer
,
1053 AsWeakPtr(), profile
));
1055 // We need to post task so that OnProfileCreated() caller sends out
1056 // NOTIFICATION_PROFILE_CREATED which marks user profile as initialized.
1057 base::ThreadTaskRunnerHandle::Get()->PostTask(
1060 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer
,
1061 AsWeakPtr(), profile
));
1066 FinalizePrepareProfile(profile
);
1069 void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
1071 RestoreAuthSessionImpl(profile
, has_auth_cookies_
);
1072 FinalizePrepareProfile(profile
);
1075 void UserSessionManager::FinalizePrepareProfile(Profile
* profile
) {
1076 BootTimesRecorder
* btl
= BootTimesRecorder::Get();
1078 // Own TPM device if, for any reason, it has not been done in EULA screen.
1079 CryptohomeClient
* client
= DBusThreadManager::Get()->GetCryptohomeClient();
1080 btl
->AddLoginTimeMarker("TPMOwn-Start", false);
1081 if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
1082 if (cryptohome_util::TpmIsOwned())
1083 client
->CallTpmClearStoredPasswordAndBlock();
1085 client
->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
1087 btl
->AddLoginTimeMarker("TPMOwn-End", false);
1089 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1090 if (user_manager
->IsLoggedInAsUserWithGaiaAccount()) {
1091 if (user_context_
.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML
)
1092 user_manager
->UpdateUsingSAML(user_context_
.GetUserID(), true);
1093 SAMLOfflineSigninLimiter
* saml_offline_signin_limiter
=
1094 SAMLOfflineSigninLimiterFactory::GetForProfile(profile
);
1095 if (saml_offline_signin_limiter
)
1096 saml_offline_signin_limiter
->SignedIn(user_context_
.GetAuthFlow());
1101 g_browser_process
->platform_part()->SessionManager()->SetSessionState(
1102 session_manager::SESSION_STATE_LOGGED_IN_NOT_ACTIVE
);
1104 // Send the notification before creating the browser so additional objects
1105 // that need the profile (e.g. the launcher) can be created first.
1106 content::NotificationService::current()->Notify(
1107 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED
,
1108 content::NotificationService::AllSources(),
1109 content::Details
<Profile
>(profile
));
1111 // Initialize various services only for primary user.
1112 const user_manager::User
* user
=
1113 ProfileHelper::Get()->GetUserByProfile(profile
);
1114 if (user_manager
->GetPrimaryUser() == user
) {
1116 InitializeCerts(profile
);
1117 InitializeCRLSetFetcher(user
);
1118 InitializeEVCertificatesWhitelistComponent(user
);
1121 UpdateEasyUnlockKeys(user_context_
);
1122 user_context_
.ClearSecrets();
1123 if (TokenHandlesEnabled()) {
1124 CreateTokenUtilIfMissing();
1125 if (token_handle_util_
->ShouldObtainHandle(user
->GetUserID())) {
1126 if (!token_handle_fetcher_
.get()) {
1127 token_handle_fetcher_
.reset(new TokenHandleFetcher(
1128 token_handle_util_
.get(), user
->GetUserID()));
1129 token_handle_fetcher_
->BackfillToken(
1130 profile
, base::Bind(&UserSessionManager::OnTokenHandleObtained
,
1131 weak_factory_
.GetWeakPtr()));
1136 // Now that profile is ready, proceed to either alternative login flows or
1138 bool browser_launched
= InitializeUserSession(profile
);
1140 // TODO(nkostylev): This pointer should probably never be NULL, but it looks
1141 // like OnProfileCreated() may be getting called before
1142 // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is
1143 // killed during shutdown in tests -- see http://crosbug.com/18269. Replace
1144 // this 'if' statement with a CHECK(delegate_) once the underlying issue is
1147 delegate_
->OnProfilePrepared(profile
, browser_launched
);
1150 void UserSessionManager::ActivateWizard(const std::string
& screen_name
) {
1151 LoginDisplayHost
* host
= LoginDisplayHostImpl::default_host();
1153 host
->StartWizard(screen_name
);
1156 void UserSessionManager::InitializeStartUrls() const {
1157 // Child account status should be known by the time of this call.
1158 std::vector
<std::string
> start_urls
;
1160 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1162 bool can_show_getstarted_guide
= user_manager
->GetActiveUser()->GetType() ==
1163 user_manager::USER_TYPE_REGULAR
;
1165 // Skip the default first-run behavior for public accounts.
1166 if (!user_manager
->IsLoggedInAsPublicAccount()) {
1167 if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
1168 const char* url
= kChromeVoxTutorialURLPattern
;
1169 PrefService
* prefs
= g_browser_process
->local_state();
1170 const std::string current_locale
=
1171 base::ToLowerASCII(prefs
->GetString(prefs::kApplicationLocale
));
1172 std::string vox_url
= base::StringPrintf(url
, current_locale
.c_str());
1173 start_urls
.push_back(vox_url
);
1174 can_show_getstarted_guide
= false;
1178 // Only show getting started guide for a new user.
1179 const bool should_show_getstarted_guide
= user_manager
->IsCurrentUserNew();
1181 if (can_show_getstarted_guide
&& should_show_getstarted_guide
) {
1182 // Don't open default Chrome window if we're going to launch the first-run
1183 // app. Because we dont' want the first-run app to be hidden in the
1185 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1186 ::switches::kSilentLaunch
);
1187 first_run::MaybeLaunchDialogAfterSessionStart();
1189 for (size_t i
= 0; i
< start_urls
.size(); ++i
) {
1190 base::CommandLine::ForCurrentProcess()->AppendArg(start_urls
[i
]);
1195 bool UserSessionManager::InitializeUserSession(Profile
* profile
) {
1196 ChildAccountService
* child_service
=
1197 ChildAccountServiceFactory::GetForProfile(profile
);
1198 child_service
->AddChildStatusReceivedCallback(
1199 base::Bind(&UserSessionManager::ChildAccountStatusReceivedCallback
,
1200 weak_factory_
.GetWeakPtr(), profile
));
1201 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1202 FROM_HERE
, base::Bind(&UserSessionManager::StopChildStatusObserving
,
1203 weak_factory_
.GetWeakPtr(), profile
),
1204 base::TimeDelta::FromMilliseconds(kFlagsFetchingLoginTimeoutMs
));
1206 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1208 // Kiosk apps has their own session initialization pipeline.
1209 if (user_manager
->IsLoggedInAsKioskApp())
1212 if (start_session_type_
== PRIMARY_USER_SESSION
) {
1213 UserFlow
* user_flow
= ChromeUserManager::Get()->GetCurrentUserFlow();
1214 WizardController
* oobe_controller
= WizardController::default_controller();
1215 base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
1216 bool skip_post_login_screens
=
1217 user_flow
->ShouldSkipPostLoginScreens() ||
1218 (oobe_controller
&& oobe_controller
->skip_post_login_screens()) ||
1219 cmdline
->HasSwitch(chromeos::switches::kOobeSkipPostLogin
);
1221 if (user_manager
->IsCurrentUserNew() && !skip_post_login_screens
) {
1222 // Don't specify start URLs if the administrator has configured the start
1224 if (!SessionStartupPref::TypeIsManaged(profile
->GetPrefs())) {
1225 if (child_service
->IsChildAccountStatusKnown())
1226 InitializeStartUrls();
1228 waiting_for_child_account_status_
= true;
1231 // Mark the device as registered., i.e. the second part of OOBE as
1233 if (!StartupUtils::IsDeviceRegistered())
1234 StartupUtils::MarkDeviceRegistered(base::Closure());
1236 ActivateWizard(WizardController::kTermsOfServiceScreenName
);
1241 DoBrowserLaunch(profile
, LoginDisplayHostImpl::default_host());
1245 void UserSessionManager::InitSessionRestoreStrategy() {
1246 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
1247 bool in_app_mode
= chrome::IsRunningInForcedAppMode();
1249 // Are we in kiosk app mode?
1251 if (command_line
->HasSwitch(::switches::kAppModeOAuth2Token
)) {
1252 user_context_
.SetRefreshToken(command_line
->GetSwitchValueASCII(
1253 ::switches::kAppModeOAuth2Token
));
1256 if (command_line
->HasSwitch(::switches::kAppModeAuthCode
)) {
1257 user_context_
.SetAuthCode(command_line
->GetSwitchValueASCII(
1258 ::switches::kAppModeAuthCode
));
1261 DCHECK(!has_auth_cookies_
);
1264 if (has_auth_cookies_
) {
1265 session_restore_strategy_
= OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR
;
1266 } else if (!user_context_
.GetRefreshToken().empty()) {
1267 session_restore_strategy_
=
1268 OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN
;
1270 session_restore_strategy_
=
1271 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN
;
1275 void UserSessionManager::RestoreAuthSessionImpl(
1277 bool restore_from_auth_cookies
) {
1278 CHECK((authenticator_
.get() && authenticator_
->authentication_context()) ||
1279 !restore_from_auth_cookies
);
1281 if (chrome::IsRunningInForcedAppMode() ||
1282 base::CommandLine::ForCurrentProcess()->HasSwitch(
1283 chromeos::switches::kDisableGaiaServices
)) {
1287 exit_after_session_restore_
= false;
1289 // Remove legacy OAuth1 token if we have one. If it's valid, we should already
1290 // have OAuth2 refresh token in OAuth2TokenService that could be used to
1291 // retrieve all other tokens and user_context.
1292 OAuth2LoginManager
* login_manager
=
1293 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile
);
1294 login_manager
->AddObserver(this);
1296 net::URLRequestContextGetter
* auth_request_context
= GetAuthRequestContext();
1298 // Authentication request context may not be available if user was not
1299 // signing in with GAIA webview (i.e. webview instance hasn't been
1300 // initialized at all). Use fallback request context if authenticator was
1302 // Authenticator instance may not be initialized for session
1303 // restore case when Chrome is restarting after crash or to apply custom user
1304 // flags. In that case auth_request_context will be nullptr which is accepted
1305 // by RestoreSession() for session restore case.
1306 if (!auth_request_context
&&
1307 (authenticator_
.get() && authenticator_
->authentication_context())) {
1308 auth_request_context
=
1309 authenticator_
->authentication_context()->GetRequestContext();
1311 login_manager
->RestoreSession(auth_request_context
, session_restore_strategy_
,
1312 user_context_
.GetRefreshToken(),
1313 user_context_
.GetAccessToken());
1316 void UserSessionManager::InitRlzImpl(Profile
* profile
, bool disabled
) {
1317 #if defined(ENABLE_RLZ)
1318 PrefService
* local_state
= g_browser_process
->local_state();
1320 // Empty brand code means an organic install (no RLZ pings are sent).
1321 google_brand::chromeos::ClearBrandForCurrentSession();
1323 if (disabled
!= local_state
->GetBoolean(prefs::kRLZDisabled
)) {
1324 // When switching to RLZ enabled/disabled state, clear all recorded events.
1325 rlz::RLZTracker::ClearRlzState();
1326 local_state
->SetBoolean(prefs::kRLZDisabled
, disabled
);
1328 // Init the RLZ library.
1329 int ping_delay
= profile
->GetPrefs()->GetInteger(
1330 ::first_run::GetPingDelayPrefName().c_str());
1331 // Negative ping delay means to send ping immediately after a first search is
1333 rlz::RLZTracker::SetRlzDelegate(
1334 make_scoped_ptr(new ChromeRLZTrackerDelegate
));
1335 rlz::RLZTracker::InitRlzDelayed(
1336 user_manager::UserManager::Get()->IsCurrentUserNew(), ping_delay
< 0,
1337 base::TimeDelta::FromMilliseconds(abs(ping_delay
)),
1338 ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile
),
1339 ChromeRLZTrackerDelegate::IsGoogleHomepage(profile
),
1340 ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile
));
1344 void UserSessionManager::InitializeCerts(Profile
* profile
) {
1345 // Now that the user profile has been initialized
1346 // |GetNSSCertDatabaseForProfile| is safe to be used.
1347 if (CertLoader::IsInitialized() && base::SysInfo::IsRunningOnChromeOS()) {
1348 GetNSSCertDatabaseForProfile(profile
,
1349 base::Bind(&OnGetNSSCertDatabaseForUser
));
1353 void UserSessionManager::InitializeCRLSetFetcher(
1354 const user_manager::User
* user
) {
1355 const std::string username_hash
= user
->username_hash();
1356 if (!username_hash
.empty()) {
1357 base::FilePath path
;
1358 path
= ProfileHelper::GetProfilePathByUserIdHash(username_hash
);
1359 component_updater::ComponentUpdateService
* cus
=
1360 g_browser_process
->component_updater();
1361 CRLSetFetcher
* crl_set
= g_browser_process
->crl_set_fetcher();
1363 crl_set
->StartInitialLoad(cus
, path
);
1367 void UserSessionManager::InitializeEVCertificatesWhitelistComponent(
1368 const user_manager::User
* user
) {
1369 const std::string username_hash
= user
->username_hash();
1370 component_updater::ComponentUpdateService
* cus
=
1371 g_browser_process
->component_updater();
1372 if (!username_hash
.empty() && cus
) {
1373 const base::FilePath path
=
1374 ProfileHelper::GetProfilePathByUserIdHash(username_hash
);
1375 RegisterEVWhitelistComponent(cus
, path
);
1379 void UserSessionManager::OnRestoreActiveSessions(
1380 const SessionManagerClient::ActiveSessionsMap
& sessions
,
1383 LOG(ERROR
) << "Could not get list of active user sessions after crash.";
1384 // If we could not get list of active user sessions it is safer to just
1385 // sign out so that we don't get in the inconsistent state.
1386 DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
1390 // One profile has been already loaded on browser start.
1391 user_manager::UserManager
* user_manager
= user_manager::UserManager::Get();
1392 DCHECK(user_manager
->GetLoggedInUsers().size() == 1);
1393 DCHECK(user_manager
->GetActiveUser());
1394 std::string active_user_id
= user_manager
->GetActiveUser()->email();
1396 SessionManagerClient::ActiveSessionsMap::const_iterator it
;
1397 for (it
= sessions
.begin(); it
!= sessions
.end(); ++it
) {
1398 if (active_user_id
== it
->first
)
1400 pending_user_sessions_
[it
->first
] = it
->second
;
1402 RestorePendingUserSessions();
1405 void UserSessionManager::RestorePendingUserSessions() {
1406 if (pending_user_sessions_
.empty()) {
1407 user_manager::UserManager::Get()->SwitchToLastActiveUser();
1408 NotifyPendingUserSessionsRestoreFinished();
1412 // Get next user to restore sessions and delete it from list.
1413 SessionManagerClient::ActiveSessionsMap::const_iterator it
=
1414 pending_user_sessions_
.begin();
1415 std::string user_id
= it
->first
;
1416 std::string user_id_hash
= it
->second
;
1417 DCHECK(!user_id
.empty());
1418 DCHECK(!user_id_hash
.empty());
1419 pending_user_sessions_
.erase(user_id
);
1421 // Check that this user is not logged in yet.
1422 user_manager::UserList logged_in_users
=
1423 user_manager::UserManager::Get()->GetLoggedInUsers();
1424 bool user_already_logged_in
= false;
1425 for (user_manager::UserList::const_iterator it
= logged_in_users
.begin();
1426 it
!= logged_in_users
.end();
1428 const user_manager::User
* user
= (*it
);
1429 if (user
->email() == user_id
) {
1430 user_already_logged_in
= true;
1434 DCHECK(!user_already_logged_in
);
1436 if (!user_already_logged_in
) {
1437 UserContext
user_context(user_id
);
1438 user_context
.SetUserIDHash(user_id_hash
);
1439 user_context
.SetIsUsingOAuth(false);
1441 // Will call OnProfilePrepared() once profile has been loaded.
1442 // Only handling secondary users here since primary user profile
1443 // (and session) has been loaded on Chrome startup.
1444 StartSession(user_context
,
1445 SECONDARY_USER_SESSION_AFTER_CRASH
,
1446 false, // has_auth_cookies
1447 true, // has_active_session, this is restart after crash
1450 RestorePendingUserSessions();
1454 void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() {
1455 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
1456 user_sessions_restored_
= true;
1457 user_sessions_restore_in_progress_
= false;
1458 FOR_EACH_OBSERVER(chromeos::UserSessionStateObserver
,
1459 session_state_observer_list_
,
1460 PendingUserSessionsRestoreFinished());
1463 void UserSessionManager::UpdateEasyUnlockKeys(const UserContext
& user_context
) {
1464 // Skip key update because FakeCryptohomeClient always return success
1465 // and RefreshKeys op expects a failure to stop. As a result, some tests would
1467 // TODO(xiyuan): Revisit this when adding tests.
1468 if (!base::SysInfo::IsRunningOnChromeOS())
1471 // Only update Easy unlock keys for regular user.
1472 // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
1474 const user_manager::User
* user
=
1475 user_manager::UserManager::Get()->FindUser(user_context
.GetUserID());
1476 if (!user
|| !user
->HasGaiaAccount())
1479 // Bail if |user_context| does not have secret.
1480 if (user_context
.GetKey()->GetSecret().empty())
1483 const base::ListValue
* device_list
= NULL
;
1484 EasyUnlockService
* easy_unlock_service
= EasyUnlockService::GetForUser(*user
);
1485 if (easy_unlock_service
) {
1486 device_list
= easy_unlock_service
->GetRemoteDevices();
1487 easy_unlock_service
->SetHardlockState(
1488 EasyUnlockScreenlockStateHandler::NO_HARDLOCK
);
1491 base::ListValue empty_list
;
1493 device_list
= &empty_list
;
1495 EasyUnlockKeyManager
* key_manager
= GetEasyUnlockKeyManager();
1496 running_easy_unlock_key_ops_
= true;
1497 key_manager
->RefreshKeys(
1498 user_context
, *device_list
,
1499 base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished
, AsWeakPtr(),
1500 user_context
.GetUserID()));
1503 net::URLRequestContextGetter
*
1504 UserSessionManager::GetAuthRequestContext() const {
1505 net::URLRequestContextGetter
* auth_request_context
= nullptr;
1507 if (StartupUtils::IsWebviewSigninEnabled()) {
1508 // Webview uses different partition storage than iframe. We need to get
1509 // cookies from the right storage for url request to get auth token into
1511 content::StoragePartition
* signin_partition
= login::GetSigninPartition();
1512 if (signin_partition
)
1513 auth_request_context
= signin_partition
->GetURLRequestContext();
1514 } else if (authenticator_
.get() && authenticator_
->authentication_context()) {
1515 auth_request_context
=
1516 authenticator_
->authentication_context()->GetRequestContext();
1518 return auth_request_context
;
1521 void UserSessionManager::AttemptRestart(Profile
* profile
) {
1522 // Restart unconditionally in case if we are stuck somewhere in a session
1523 // restore process. http://crbug.com/520346.
1524 base::MessageLoop::current()->PostDelayedTask(
1525 FROM_HERE
, base::Bind(RestartOnTimeout
),
1526 base::TimeDelta::FromSeconds(kMaxRestartDelaySeconds
));
1528 if (CheckEasyUnlockKeyOps(base::Bind(&UserSessionManager::AttemptRestart
,
1529 AsWeakPtr(), profile
))) {
1533 if (session_restore_strategy_
!=
1534 OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR
) {
1535 chrome::AttemptRestart();
1539 // We can't really quit if the session restore process that mints new
1540 // refresh token is still in progress.
1541 OAuth2LoginManager
* login_manager
=
1542 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile
);
1543 if (login_manager
->state() != OAuth2LoginManager::SESSION_RESTORE_PREPARING
&&
1544 login_manager
->state() !=
1545 OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS
) {
1546 chrome::AttemptRestart();
1550 LOG(WARNING
) << "Attempting browser restart during session restore.";
1551 exit_after_session_restore_
= true;
1554 void UserSessionManager::OnEasyUnlockKeyOpsFinished(
1555 const std::string
& user_id
,
1557 running_easy_unlock_key_ops_
= false;
1558 if (!easy_unlock_key_ops_finished_callback_
.is_null())
1559 easy_unlock_key_ops_finished_callback_
.Run();
1561 const user_manager::User
* user
=
1562 user_manager::UserManager::Get()->FindUser(user_id
);
1563 EasyUnlockService
* easy_unlock_service
=
1564 EasyUnlockService::GetForUser(*user
);
1565 easy_unlock_service
->CheckCryptohomeKeysAndMaybeHardlock();
1568 void UserSessionManager::ActiveUserChanged(
1569 const user_manager::User
* active_user
) {
1570 if (!user_manager::UserManager::Get()->IsCurrentUserNew())
1571 SendUserPodsMetrics();
1573 Profile
* profile
= ProfileHelper::Get()->GetProfileByUser(active_user
);
1574 // If profile has not yet been initialized, delay initialization of IME.
1578 input_method::InputMethodManager
* manager
=
1579 input_method::InputMethodManager::Get();
1581 GetDefaultIMEState(ProfileHelper::Get()->GetProfileByUser(active_user
)));
1584 scoped_refptr
<input_method::InputMethodManager::State
>
1585 UserSessionManager::GetDefaultIMEState(Profile
* profile
) {
1586 scoped_refptr
<input_method::InputMethodManager::State
> state
=
1587 default_ime_states_
[profile
];
1589 // Profile can be NULL in tests.
1590 state
= input_method::InputMethodManager::Get()->CreateNewState(profile
);
1591 default_ime_states_
[profile
] = state
;
1596 EasyUnlockKeyManager
* UserSessionManager::GetEasyUnlockKeyManager() {
1597 if (!easy_unlock_key_manager_
)
1598 easy_unlock_key_manager_
.reset(new EasyUnlockKeyManager
);
1600 return easy_unlock_key_manager_
.get();
1603 void UserSessionManager::DoBrowserLaunchInternal(Profile
* profile
,
1604 LoginDisplayHost
* login_host
,
1605 bool locale_pref_checked
) {
1606 if (browser_shutdown::IsTryingToQuit())
1609 if (!locale_pref_checked
) {
1610 RespectLocalePreferenceWrapper(
1612 base::Bind(&UserSessionManager::DoBrowserLaunchInternal
, AsWeakPtr(),
1613 profile
, login_host
, true /* locale_pref_checked */));
1617 if (!ChromeUserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
1618 ChromeUserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile
);
1622 if (RestartToApplyPerSessionFlagsIfNeed(profile
, false))
1626 login_host
->SetStatusAreaVisible(true);
1627 login_host
->BeforeSessionStart();
1630 BootTimesRecorder::Get()->AddLoginTimeMarker("BrowserLaunched", false);
1632 VLOG(1) << "Launching browser...";
1633 TRACE_EVENT0("login", "LaunchBrowser");
1635 if (should_launch_browser_
) {
1636 StartupBrowserCreator browser_creator
;
1637 chrome::startup::IsFirstRun first_run
=
1638 ::first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
1639 : chrome::startup::IS_NOT_FIRST_RUN
;
1641 browser_creator
.LaunchBrowser(
1642 *base::CommandLine::ForCurrentProcess(), profile
, base::FilePath(),
1643 chrome::startup::IS_PROCESS_STARTUP
, first_run
);
1645 // Triggers app launcher start page service to load start page web contents.
1646 app_list::StartPageService::Get(profile
);
1648 LOG(WARNING
) << "Browser hasn't been launched, should_launch_browser_"
1649 << " is false. This is normal in some tests.";
1652 // Mark login host for deletion after browser starts. This
1653 // guarantees that the message loop will be referenced by the
1654 // browser before it is dereferenced by the login host.
1656 login_host
->Finalize();
1657 user_manager::UserManager::Get()->SessionStarted();
1658 chromeos::BootTimesRecorder::Get()->LoginDone(
1659 user_manager::UserManager::Get()->IsCurrentUserNew());
1662 void UserSessionManager::RespectLocalePreferenceWrapper(
1664 const base::Closure
& callback
) {
1665 if (browser_shutdown::IsTryingToQuit())
1668 const user_manager::User
* const user
=
1669 ProfileHelper::Get()->GetUserByProfile(profile
);
1670 locale_util::SwitchLanguageCallback
locale_switched_callback(base::Bind(
1671 &UserSessionManager::RunCallbackOnLocaleLoaded
, callback
,
1672 base::Owned(new InputEventsBlocker
))); // Block UI events until
1673 // the ResourceBundle is
1675 if (!RespectLocalePreference(profile
, user
, locale_switched_callback
))
1680 void UserSessionManager::RunCallbackOnLocaleLoaded(
1681 const base::Closure
& callback
,
1682 InputEventsBlocker
* /* input_events_blocker */,
1683 const locale_util::LanguageSwitchResult
& /* result */) {
1687 void UserSessionManager::RemoveProfileForTesting(Profile
* profile
) {
1688 default_ime_states_
.erase(profile
);
1691 void UserSessionManager::InjectStubUserContext(
1692 const UserContext
& user_context
) {
1693 injected_user_context_
.reset(new UserContext(user_context
));
1694 authenticator_
= NULL
;
1697 void UserSessionManager::SendUserPodsMetrics() {
1698 bool show_users_on_signin
;
1699 CrosSettings::Get()->GetBoolean(kAccountsPrefShowUserNamesOnSignIn
,
1700 &show_users_on_signin
);
1701 bool is_enterprise_managed
= g_browser_process
->platform_part()
1702 ->browser_policy_connector_chromeos()
1703 ->IsEnterpriseManaged();
1704 UserPodsDisplay display
;
1705 if (show_users_on_signin
) {
1706 if (is_enterprise_managed
)
1707 display
= USER_PODS_DISPLAY_ENABLED_MANAGED
;
1709 display
= USER_PODS_DISPLAY_ENABLED_REGULAR
;
1711 if (is_enterprise_managed
)
1712 display
= USER_PODS_DISPLAY_DISABLED_MANAGED
;
1714 display
= USER_PODS_DISPLAY_DISABLED_REGULAR
;
1716 UMA_HISTOGRAM_ENUMERATION("UserSessionManager.UserPodsDisplay", display
,
1717 NUM_USER_PODS_DISPLAY
);
1720 void UserSessionManager::OnOAuth2TokensFetched(UserContext context
) {
1721 if (StartupUtils::IsWebviewSigninEnabled() && TokenHandlesEnabled()) {
1722 CreateTokenUtilIfMissing();
1723 if (token_handle_util_
->ShouldObtainHandle(context
.GetUserID())) {
1724 token_handle_fetcher_
.reset(new TokenHandleFetcher(
1725 token_handle_util_
.get(), context
.GetUserID()));
1726 token_handle_fetcher_
->FillForNewUser(
1727 context
.GetAccessToken(),
1728 base::Bind(&UserSessionManager::OnTokenHandleObtained
,
1729 weak_factory_
.GetWeakPtr()));
1734 void UserSessionManager::OnTokenHandleObtained(const user_manager::UserID
& id
,
1737 LOG(ERROR
) << "OAuth2 token handle fetch failed.";
1738 token_handle_fetcher_
.reset();
1741 bool UserSessionManager::TokenHandlesEnabled() {
1742 if (!should_obtain_handles_
)
1744 bool ephemeral_users_enabled
= false;
1745 bool show_names_on_signin
= true;
1746 auto cros_settings
= CrosSettings::Get();
1747 cros_settings
->GetBoolean(kAccountsPrefEphemeralUsersEnabled
,
1748 &ephemeral_users_enabled
);
1749 cros_settings
->GetBoolean(kAccountsPrefShowUserNamesOnSignIn
,
1750 &show_names_on_signin
);
1751 return show_names_on_signin
&& !ephemeral_users_enabled
;
1754 void UserSessionManager::Shutdown() {
1755 token_handle_fetcher_
.reset();
1756 token_handle_util_
.reset();
1759 void UserSessionManager::CreateTokenUtilIfMissing() {
1760 if (!token_handle_util_
.get())
1761 token_handle_util_
.reset(
1762 new TokenHandleUtil(user_manager::UserManager::Get()));
1765 } // namespace chromeos