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