Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / chromeos / login / session / user_session_manager.cc
blobf30aab8e2eff53d065a8d489f8744e5a8aa77c8f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
7 #include <string>
9 #include "base/base_paths.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/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"
108 #endif
110 namespace chromeos {
112 namespace {
114 // Milliseconds until we timeout our attempt to fetch flags from the child
115 // account service.
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,
129 Profile* profile,
130 const std::string& public_session_locale,
131 const std::string& public_session_input_method) {
132 PrefService* prefs = profile->GetPrefs();
133 std::string locale;
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);
142 } else {
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);
158 if (descriptor) {
159 preferred_input_method = *descriptor;
160 } else {
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
167 // method.
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(),
202 candidate) == 0) {
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);
226 #endif
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())
232 return;
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);
243 return user_flags;
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)
252 return false;
254 // Only restart if needed and if not going into managed mode.
255 if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser())
256 return false;
258 if (about_flags::AreSwitchesIdenticalToCurrentCommandLine(
259 user_flags, *base::CommandLine::ForCurrentProcess(),
260 out_command_line_difference)) {
261 return false;
264 return true;
267 bool CanPerformEarlyRestart() {
268 // Desktop build is used for development only. Early restart is not supported.
269 if (!base::SysInfo::IsRunningOnChromeOS())
270 return false;
272 if (!ChromeUserManager::Get()
273 ->GetCurrentUserFlow()
274 ->SupportsEarlyRestartToApplyFlags()) {
275 return false;
278 const ExistingUserController* controller =
279 ExistingUserController::current_controller();
280 if (!controller)
281 return true;
283 // Early restart is possible only if OAuth token is up to date.
285 if (controller->password_changed())
286 return false;
288 if (controller->auth_mode() != LoginPerformer::AUTH_MODE_INTERNAL)
289 return false;
291 // No early restart if Easy unlock key needs to be updated.
292 if (UserSessionManager::GetInstance()->NeedsToUpdateEasyUnlockKeys())
293 return false;
295 return true;
298 void LogCustomSwitches(const std::set<std::string>& switches) {
299 if (!VLOG_IS_ON(1))
300 return;
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();
313 } // namespace
315 UserSessionManagerDelegate::~UserSessionManagerDelegate() {
318 void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
321 UserSessionStateObserver::~UserSessionStateObserver() {
324 // static
325 UserSessionManager* UserSessionManager::GetInstance() {
326 return base::Singleton<UserSessionManager, base::DefaultSingletonTraits<
327 UserSessionManager>>::get();
330 // static
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,
342 homedir,
343 true /* path is absolute */,
344 false /* don't create */);
349 // static
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
375 // still exists.
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
407 // guest user.
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_) {
429 authenticator_ =
430 new StubAuthenticator(consumer, *injected_user_context_.get());
431 } else {
432 authenticator_ = new ChromeCryptohomeAuthenticator(consumer);
434 } else {
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();
452 PreStartSession();
453 CreateUserSession(user_context, has_auth_cookies);
455 if (!has_active_session)
456 StartCrosSession();
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());
467 PrepareProfile();
470 void UserSessionManager::DelegateDeleted(UserSessionManagerDelegate* delegate) {
471 if (delegate_ == delegate)
472 delegate_ = nullptr;
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()) {
496 return;
499 const user_manager::User* user =
500 ProfileHelper::Get()->GetUserByProfile(user_profile);
501 DCHECK(user);
502 if (!net::NetworkChangeNotifier::IsOffline()) {
503 pending_signin_restore_sessions_.erase(user->email());
504 RestoreAuthSessionImpl(user_profile, false /* has_auth_cookies */);
505 } else {
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));
536 return;
538 base::PostTaskAndReplyWithResult(
539 base::WorkerPool::GetTaskRunner(false).get(),
540 FROM_HERE,
541 base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
542 base::Bind(&UserSessionManager::InitRlzImpl, AsWeakPtr(), profile));
543 #endif
546 void UserSessionManager::SetFirstLoginPrefs(
547 Profile* profile,
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()) {
560 return false;
563 *chrome_client_id = chrome_client_id_;
564 *chrome_client_secret = chrome_client_secret_;
565 return true;
568 void UserSessionManager::SetAppModeChromeClientOAuthInfo(
569 const std::string& chrome_client_id,
570 const std::string& chrome_client_secret) {
571 if (!chrome::IsRunningInForcedAppMode())
572 return;
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(
584 Profile* profile,
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)
590 return false;
592 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
593 if (!user || (user_manager->IsUserLoggedIn() &&
594 user != user_manager->GetPrimaryUser())) {
595 return false;
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)
601 return false;
603 const PrefService* prefs = profile->GetPrefs();
604 if (prefs == NULL)
605 return false;
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) +
634 "'. ")
635 : (std::string("account_locale - unused. ")))
636 << " Selected '" << pref_locale << "'";
637 profile->ChangeAppLocale(
638 pref_locale,
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,
656 profile);
658 return true;
661 bool UserSessionManager::RestartToApplyPerSessionFlagsIfNeed(
662 Profile* profile,
663 bool early_restart) {
664 if (ProfileHelper::IsSigninProfile(profile))
665 return false;
667 if (early_restart && !CanPerformEarlyRestart())
668 return false;
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
672 // user session.
673 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginUser))
674 return false;
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)
678 return false;
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))
683 return false;
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);
696 return true;
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_)
707 return false;
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;
713 return true;
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;
737 switch (state) {
738 case OAuth2LoginManager::SESSION_RESTORE_DONE:
739 user_status = user_manager::User::OAUTH2_TOKEN_STATUS_VALID;
740 break;
741 case OAuth2LoginManager::SESSION_RESTORE_FAILED:
742 user_status = user_manager::User::OAUTH2_TOKEN_STATUS_INVALID;
743 break;
744 case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
745 connection_error = true;
746 break;
747 case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
748 case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
749 case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
750 return;
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(),
759 user_status);
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
772 // actually saved.
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) {
788 return;
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();
794 it != users.end();
795 ++it) {
796 if (!(*it)->is_profile_created())
797 continue;
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(),
880 false);
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,
893 AsWeakPtr(),
894 user_context_,
895 is_demo_session),
896 base::string16(),
897 base::string16(),
898 std::string());
901 void UserSessionManager::OnProfileCreated(const UserContext& user_context,
902 bool is_incognito_profile,
903 Profile* profile,
904 Profile::CreateStatus status) {
905 CHECK(profile);
907 switch (status) {
908 case Profile::CREATE_STATUS_CREATED:
909 // Profile created but before initializing extensions and promo resources.
910 InitProfilePreferences(profile, user_context);
911 break;
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());
919 break;
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:
924 NOTREACHED();
925 break;
929 void UserSessionManager::InitProfilePreferences(
930 Profile* profile,
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);
968 AccountInfo info =
969 account_tracker->FindAccountInfoByEmail(user_context.GetUserID());
970 gaia_id = info.gaia;
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) &&
986 !gaia_id.empty()) {
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) {
997 profile->OnLogin();
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));
1006 if (delegate_)
1007 delegate_->OnProfilePrepared(profile, false);
1009 return;
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
1018 // first.
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 =
1039 has_auth_cookies_;
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,
1051 base::Bind(
1052 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer,
1053 AsWeakPtr(), profile));
1054 } else {
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(
1058 FROM_HERE,
1059 base::Bind(
1060 &UserSessionManager::CompleteProfileCreateAfterAuthTransfer,
1061 AsWeakPtr(), profile));
1063 return;
1066 FinalizePrepareProfile(profile);
1069 void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
1070 Profile* profile) {
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();
1084 else
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());
1099 profile->OnLogin();
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) {
1115 InitRlz(profile);
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
1137 // launch browser.
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
1145 // resolved.
1146 if (delegate_)
1147 delegate_->OnProfilePrepared(profile, browser_launched);
1150 void UserSessionManager::ActivateWizard(const std::string& screen_name) {
1151 LoginDisplayHost* host = LoginDisplayHostImpl::default_host();
1152 CHECK(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
1184 // background.
1185 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1186 ::switches::kSilentLaunch);
1187 first_run::MaybeLaunchDialogAfterSessionStart();
1188 } else {
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())
1210 return false;
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
1223 // URLs via policy.
1224 if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs())) {
1225 if (child_service->IsChildAccountStatusKnown())
1226 InitializeStartUrls();
1227 else
1228 waiting_for_child_account_status_ = true;
1231 // Mark the device as registered., i.e. the second part of OOBE as
1232 // completed.
1233 if (!StartupUtils::IsDeviceRegistered())
1234 StartupUtils::MarkDeviceRegistered(base::Closure());
1236 ActivateWizard(WizardController::kTermsOfServiceScreenName);
1237 return false;
1241 DoBrowserLaunch(profile, LoginDisplayHostImpl::default_host());
1242 return true;
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?
1250 if (in_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;
1269 } else {
1270 session_restore_strategy_ =
1271 OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
1275 void UserSessionManager::RestoreAuthSessionImpl(
1276 Profile* profile,
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)) {
1284 return;
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
1301 // provided.
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();
1319 if (disabled) {
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
1332 // recorded.
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));
1341 #endif
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();
1362 if (crl_set && cus)
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,
1381 bool success) {
1382 if (!success) {
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();
1387 return;
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)
1399 continue;
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();
1409 return;
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();
1427 ++it) {
1428 const user_manager::User* user = (*it);
1429 if (user->email() == user_id) {
1430 user_already_logged_in = true;
1431 break;
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
1448 this);
1449 } else {
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
1466 // timeout.
1467 // TODO(xiyuan): Revisit this when adding tests.
1468 if (!base::SysInfo::IsRunningOnChromeOS())
1469 return;
1471 // Only update Easy unlock keys for regular user.
1472 // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
1473 // authenticator.
1474 const user_manager::User* user =
1475 user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
1476 if (!user || !user->HasGaiaAccount())
1477 return;
1479 // Bail if |user_context| does not have secret.
1480 if (user_context.GetKey()->GetSecret().empty())
1481 return;
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;
1492 if (!device_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
1510 // session.
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))) {
1530 return;
1533 if (session_restore_strategy_ !=
1534 OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR) {
1535 chrome::AttemptRestart();
1536 return;
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();
1547 return;
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,
1556 bool success) {
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.
1575 if (!profile)
1576 return;
1578 input_method::InputMethodManager* manager =
1579 input_method::InputMethodManager::Get();
1580 manager->SetState(
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];
1588 if (!state.get()) {
1589 // Profile can be NULL in tests.
1590 state = input_method::InputMethodManager::Get()->CreateNewState(profile);
1591 default_ime_states_[profile] = state;
1593 return 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())
1607 return;
1609 if (!locale_pref_checked) {
1610 RespectLocalePreferenceWrapper(
1611 profile,
1612 base::Bind(&UserSessionManager::DoBrowserLaunchInternal, AsWeakPtr(),
1613 profile, login_host, true /* locale_pref_checked */));
1614 return;
1617 if (!ChromeUserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
1618 ChromeUserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile);
1619 return;
1622 if (RestartToApplyPerSessionFlagsIfNeed(profile, false))
1623 return;
1625 if (login_host) {
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);
1647 } else {
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.
1655 if (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(
1663 Profile* profile,
1664 const base::Closure& callback) {
1665 if (browser_shutdown::IsTryingToQuit())
1666 return;
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
1674 // reloaded.
1675 if (!RespectLocalePreference(profile, user, locale_switched_callback))
1676 callback.Run();
1679 // static
1680 void UserSessionManager::RunCallbackOnLocaleLoaded(
1681 const base::Closure& callback,
1682 InputEventsBlocker* /* input_events_blocker */,
1683 const locale_util::LanguageSwitchResult& /* result */) {
1684 callback.Run();
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;
1708 else
1709 display = USER_PODS_DISPLAY_ENABLED_REGULAR;
1710 } else {
1711 if (is_enterprise_managed)
1712 display = USER_PODS_DISPLAY_DISABLED_MANAGED;
1713 else
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,
1735 bool success) {
1736 if (!success)
1737 LOG(ERROR) << "OAuth2 token handle fetch failed.";
1738 token_handle_fetcher_.reset();
1741 bool UserSessionManager::TokenHandlesEnabled() {
1742 if (!should_obtain_handles_)
1743 return false;
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