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.
4
5#include "chrome/browser/chromeos/login/session/user_session_manager.h"
6
7#include <string>
8
9#include "base/base_paths.h"
10#include "base/bind.h"
11#include "base/command_line.h"
12#include "base/logging.h"
13#include "base/path_service.h"
14#include "base/prefs/pref_member.h"
15#include "base/prefs/pref_registry_simple.h"
16#include "base/prefs/pref_service.h"
17#include "base/strings/string16.h"
18#include "base/sys_info.h"
19#include "base/task_runner_util.h"
20#include "base/threading/worker_pool.h"
21#include "chrome/browser/app_mode/app_mode_utils.h"
22#include "chrome/browser/browser_process.h"
23#include "chrome/browser/browser_process_platform_part_chromeos.h"
24#include "chrome/browser/chrome_notification_types.h"
25#include "chrome/browser/chromeos/base/locale_util.h"
26#include "chrome/browser/chromeos/boot_times_loader.h"
27#include "chrome/browser/chromeos/input_method/input_method_util.h"
28#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
29#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
30#include "chrome/browser/chromeos/login/profile_auth_data.h"
31#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
32#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
33#include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h"
34#include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
35#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
36#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
37#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
38#include "chrome/browser/chromeos/profiles/profile_helper.h"
39#include "chrome/browser/chromeos/settings/cros_settings.h"
40#include "chrome/browser/first_run/first_run.h"
41#include "chrome/browser/google/google_brand_chromeos.h"
42#include "chrome/browser/lifetime/application_lifetime.h"
43#include "chrome/browser/net/crl_set_fetcher.h"
44#include "chrome/browser/net/nss_context.h"
45#include "chrome/browser/profiles/profile.h"
46#include "chrome/browser/profiles/profile_manager.h"
47#include "chrome/browser/rlz/rlz.h"
48#include "chrome/browser/signin/easy_unlock_service.h"
49#include "chrome/browser/signin/signin_manager_factory.h"
50#include "chrome/common/chrome_switches.h"
51#include "chrome/common/logging_chrome.h"
52#include "chrome/common/pref_names.h"
53#include "chromeos/cert_loader.h"
54#include "chromeos/chromeos_switches.h"
55#include "chromeos/cryptohome/cryptohome_util.h"
56#include "chromeos/dbus/cryptohome_client.h"
57#include "chromeos/dbus/dbus_thread_manager.h"
58#include "chromeos/dbus/session_manager_client.h"
59#include "chromeos/ime/input_method_manager.h"
60#include "chromeos/network/portal_detector/network_portal_detector.h"
61#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
62#include "chromeos/settings/cros_settings_names.h"
63#include "components/component_updater/component_updater_service.h"
64#include "components/policy/core/common/cloud/cloud_policy_constants.h"
65#include "components/session_manager/core/session_manager.h"
66#include "components/signin/core/browser/signin_manager_base.h"
67#include "components/user_manager/user.h"
68#include "components/user_manager/user_manager.h"
69#include "components/user_manager/user_type.h"
70#include "content/public/browser/browser_thread.h"
71#include "content/public/browser/notification_service.h"
72
73namespace chromeos {
74
75namespace {
76
77void InitLocaleAndInputMethodsForNewUser(
78    UserSessionManager* session_manager,
79    Profile* profile,
80    const std::string& public_session_locale,
81    const std::string& public_session_input_method) {
82  PrefService* prefs = profile->GetPrefs();
83  std::string locale;
84  if (!public_session_locale.empty()) {
85    // If this is a public session and the user chose a |public_session_locale|,
86    // write it to |prefs| so that the UI switches to it.
87    locale = public_session_locale;
88    prefs->SetString(prefs::kApplicationLocale, locale);
89
90    // Suppress the locale change dialog.
91    prefs->SetString(prefs::kApplicationLocaleAccepted, locale);
92  } else {
93    // Otherwise, assume that the session will use the current UI locale.
94    locale = g_browser_process->GetApplicationLocale();
95  }
96
97  // First, we'll set kLanguagePreloadEngines.
98  input_method::InputMethodManager* manager =
99      input_method::InputMethodManager::Get();
100  std::vector<std::string> input_method_ids;
101
102  if (!public_session_input_method.empty()) {
103    // If this is a public session and the user chose a
104    // |public_session_input_method|, set kLanguagePreloadEngines to this input
105    // method only.
106    input_method_ids.push_back(public_session_input_method);
107  } else {
108    // Otherwise, set kLanguagePreloadEngines to a list of input methods derived
109    // from the |locale| and the currently active input method.
110    manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
111        locale,
112        session_manager->GetDefaultIMEState(profile)->GetCurrentInputMethod(),
113        &input_method_ids);
114  }
115
116  // Save the input methods in the user's preferences.
117  StringPrefMember language_preload_engines;
118  language_preload_engines.Init(prefs::kLanguagePreloadEngines, prefs);
119  language_preload_engines.SetValue(JoinString(input_method_ids, ','));
120  BootTimesLoader::Get()->AddLoginTimeMarker("IMEStarted", false);
121
122  // Second, we'll set kLanguagePreferredLanguages.
123  std::vector<std::string> language_codes;
124
125  // The current locale should be on the top.
126  language_codes.push_back(locale);
127
128  // Add input method IDs based on the input methods, as there may be
129  // input methods that are unrelated to the current locale. Example: the
130  // hardware keyboard layout xkb:us::eng is used for logging in, but the
131  // UI language is set to French. In this case, we should set "fr,en"
132  // to the preferred languages preference.
133  std::vector<std::string> candidates;
134  manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
135      input_method_ids, &candidates);
136  for (size_t i = 0; i < candidates.size(); ++i) {
137    const std::string& candidate = candidates[i];
138    // Skip if it's already in language_codes.
139    if (std::count(language_codes.begin(), language_codes.end(),
140                   candidate) == 0) {
141      language_codes.push_back(candidate);
142    }
143  }
144
145  // Save the preferred languages in the user's preferences.
146  StringPrefMember language_preferred_languages;
147  language_preferred_languages.Init(prefs::kLanguagePreferredLanguages, prefs);
148  language_preferred_languages.SetValue(JoinString(language_codes, ','));
149}
150
151#if defined(ENABLE_RLZ)
152// Flag file that disables RLZ tracking, when present.
153const base::FilePath::CharType kRLZDisabledFlagName[] =
154    FILE_PATH_LITERAL(".rlz_disabled");
155
156base::FilePath GetRlzDisabledFlagPath() {
157  base::FilePath homedir;
158  PathService::Get(base::DIR_HOME, &homedir);
159  return homedir.Append(kRLZDisabledFlagName);
160}
161#endif
162
163// Callback to GetNSSCertDatabaseForProfile. It starts CertLoader using the
164// provided NSS database. It must be called for primary user only.
165void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) {
166  if (!CertLoader::IsInitialized())
167    return;
168
169  CertLoader::Get()->StartWithNSSDB(database);
170}
171
172}  // namespace
173
174#if defined(ENABLE_RLZ)
175void UserSessionManagerDelegate::OnRlzInitialized() {
176}
177#endif
178
179UserSessionManagerDelegate::~UserSessionManagerDelegate() {
180}
181
182void UserSessionStateObserver::PendingUserSessionsRestoreFinished() {
183}
184
185UserSessionStateObserver::~UserSessionStateObserver() {
186}
187
188// static
189UserSessionManager* UserSessionManager::GetInstance() {
190  return Singleton<UserSessionManager,
191      DefaultSingletonTraits<UserSessionManager> >::get();
192}
193
194// static
195void UserSessionManager::OverrideHomedir() {
196  // Override user homedir, check for ProfileManager being initialized as
197  // it may not exist in unit tests.
198  if (g_browser_process->profile_manager()) {
199    user_manager::UserManager* user_manager = user_manager::UserManager::Get();
200    if (user_manager->GetLoggedInUsers().size() == 1) {
201      base::FilePath homedir = ProfileHelper::GetProfilePathByUserIdHash(
202          user_manager->GetPrimaryUser()->username_hash());
203      // This path has been either created by cryptohome (on real Chrome OS
204      // device) or by ProfileManager (on chromeos=1 desktop builds).
205      PathService::OverrideAndCreateIfNeeded(base::DIR_HOME,
206                                             homedir,
207                                             true /* path is absolute */,
208                                             false /* don't create */);
209    }
210  }
211}
212
213// static
214void UserSessionManager::RegisterPrefs(PrefRegistrySimple* registry) {
215  registry->RegisterStringPref(prefs::kRLZBrand, std::string());
216  registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
217}
218
219UserSessionManager::UserSessionManager()
220    : delegate_(NULL),
221      has_auth_cookies_(false),
222      user_sessions_restored_(false),
223      user_sessions_restore_in_progress_(false),
224      exit_after_session_restore_(false),
225      session_restore_strategy_(
226          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN),
227      running_easy_unlock_key_ops_(false) {
228  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
229  user_manager::UserManager::Get()->AddSessionStateObserver(this);
230}
231
232UserSessionManager::~UserSessionManager() {
233  // UserManager is destroyed before singletons, so we need to check if it
234  // still exists.
235  // TODO(nkostylev): fix order of destruction of UserManager
236  // / UserSessionManager objects.
237  if (user_manager::UserManager::IsInitialized())
238    user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
239  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
240}
241
242void UserSessionManager::StartSession(
243    const UserContext& user_context,
244    scoped_refptr<Authenticator> authenticator,
245    bool has_auth_cookies,
246    bool has_active_session,
247    UserSessionManagerDelegate* delegate) {
248  authenticator_ = authenticator;
249  delegate_ = delegate;
250
251  VLOG(1) << "Starting session for " << user_context.GetUserID();
252
253  PreStartSession();
254  CreateUserSession(user_context, has_auth_cookies);
255
256  if (!has_active_session)
257    StartCrosSession();
258
259  // TODO(nkostylev): Notify UserLoggedIn() after profile is actually
260  // ready to be used (http://crbug.com/361528).
261  NotifyUserLoggedIn();
262  PrepareProfile();
263}
264
265void UserSessionManager::PerformPostUserLoggedInActions() {
266  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
267  if (user_manager->GetLoggedInUsers().size() == 1) {
268    if (NetworkPortalDetector::IsInitialized()) {
269      NetworkPortalDetector::Get()->SetStrategy(
270          PortalDetectorStrategy::STRATEGY_ID_SESSION);
271    }
272  }
273}
274
275void UserSessionManager::RestoreAuthenticationSession(Profile* user_profile) {
276  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
277  // We need to restore session only for logged in regular (GAIA) users.
278  // Note: stub user is a special case that is used for tests, running
279  // linux_chromeos build on dev workstations w/o user_id parameters.
280  // Stub user is considered to be a regular GAIA user but it has special
281  // user_id (kStubUser) and certain services like restoring OAuth session are
282  // explicitly disabled for it.
283  if (!user_manager->IsUserLoggedIn() ||
284      !user_manager->IsLoggedInAsRegularUser() ||
285      user_manager->IsLoggedInAsStub()) {
286    return;
287  }
288
289  user_manager::User* user =
290      ProfileHelper::Get()->GetUserByProfile(user_profile);
291  DCHECK(user);
292  if (!net::NetworkChangeNotifier::IsOffline()) {
293    pending_signin_restore_sessions_.erase(user->email());
294    RestoreAuthSessionImpl(user_profile, false /* has_auth_cookies */);
295  } else {
296    // Even if we're online we should wait till initial
297    // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
298    // end up canceling all request when initial network connection type is
299    // processed. See http://crbug.com/121643.
300    pending_signin_restore_sessions_.insert(user->email());
301  }
302}
303
304void UserSessionManager::RestoreActiveSessions() {
305  user_sessions_restore_in_progress_ = true;
306  DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
307      base::Bind(&UserSessionManager::OnRestoreActiveSessions,
308                 base::Unretained(this)));
309}
310
311bool UserSessionManager::UserSessionsRestored() const {
312  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
313  return user_sessions_restored_;
314}
315
316bool UserSessionManager::UserSessionsRestoreInProgress() const {
317  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
318  return user_sessions_restore_in_progress_;
319}
320
321void UserSessionManager::InitRlz(Profile* profile) {
322#if defined(ENABLE_RLZ)
323  if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
324    // Read brand code asynchronously from an OEM data and repost ourselves.
325    google_brand::chromeos::InitBrand(
326        base::Bind(&UserSessionManager::InitRlz, AsWeakPtr(), profile));
327    return;
328  }
329  base::PostTaskAndReplyWithResult(
330      base::WorkerPool::GetTaskRunner(false).get(),
331      FROM_HERE,
332      base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
333      base::Bind(&UserSessionManager::InitRlzImpl, AsWeakPtr(), profile));
334#endif
335}
336
337OAuth2LoginManager::SessionRestoreStrategy
338UserSessionManager::GetSigninSessionRestoreStrategy() {
339  return session_restore_strategy_;
340}
341
342void UserSessionManager::SetFirstLoginPrefs(
343    Profile* profile,
344    const std::string& public_session_locale,
345    const std::string& public_session_input_method) {
346  VLOG(1) << "Setting first login prefs";
347  InitLocaleAndInputMethodsForNewUser(
348      this, profile, public_session_locale, public_session_input_method);
349}
350
351bool UserSessionManager::GetAppModeChromeClientOAuthInfo(
352    std::string* chrome_client_id, std::string* chrome_client_secret) {
353  if (!chrome::IsRunningInForcedAppMode() ||
354      chrome_client_id_.empty() ||
355      chrome_client_secret_.empty()) {
356    return false;
357  }
358
359  *chrome_client_id = chrome_client_id_;
360  *chrome_client_secret = chrome_client_secret_;
361  return true;
362}
363
364void UserSessionManager::SetAppModeChromeClientOAuthInfo(
365    const std::string& chrome_client_id,
366    const std::string& chrome_client_secret) {
367  if (!chrome::IsRunningInForcedAppMode())
368    return;
369
370  chrome_client_id_ = chrome_client_id;
371  chrome_client_secret_ = chrome_client_secret;
372}
373
374bool UserSessionManager::RespectLocalePreference(
375    Profile* profile,
376    const user_manager::User* user,
377    scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
378  // TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
379  // the Google user profile.
380  if (g_browser_process == NULL)
381    return false;
382
383  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
384  if (!user || (user_manager->IsUserLoggedIn() &&
385                user != user_manager->GetPrimaryUser())) {
386    return false;
387  }
388
389  // In case of multi-profiles session we don't apply profile locale
390  // because it is unsafe.
391  if (user_manager->GetLoggedInUsers().size() != 1)
392    return false;
393
394  const PrefService* prefs = profile->GetPrefs();
395  if (prefs == NULL)
396    return false;
397
398  std::string pref_locale;
399  const std::string pref_app_locale =
400      prefs->GetString(prefs::kApplicationLocale);
401  const std::string pref_bkup_locale =
402      prefs->GetString(prefs::kApplicationLocaleBackup);
403
404  pref_locale = pref_app_locale;
405  if (pref_locale.empty())
406    pref_locale = pref_bkup_locale;
407
408  const std::string* account_locale = NULL;
409  if (pref_locale.empty() && user->has_gaia_account()) {
410    if (user->GetAccountLocale() == NULL)
411      return false;  // wait until Account profile is loaded.
412    account_locale = user->GetAccountLocale();
413    pref_locale = *account_locale;
414  }
415  const std::string global_app_locale =
416      g_browser_process->GetApplicationLocale();
417  if (pref_locale.empty())
418    pref_locale = global_app_locale;
419  DCHECK(!pref_locale.empty());
420  VLOG(1) << "RespectLocalePreference: "
421          << "app_locale='" << pref_app_locale << "', "
422          << "bkup_locale='" << pref_bkup_locale << "', "
423          << (account_locale != NULL
424              ? (std::string("account_locale='") + (*account_locale) +
425                 "'. ")
426              : (std::string("account_locale - unused. ")))
427          << " Selected '" << pref_locale << "'";
428  profile->ChangeAppLocale(
429      pref_locale,
430      user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT ?
431          Profile::APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN :
432          Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
433
434  // Here we don't enable keyboard layouts for normal users. Input methods
435  // are set up when the user first logs in. Then the user may customize the
436  // input methods.  Hence changing input methods here, just because the user's
437  // UI language is different from the login screen UI language, is not
438  // desirable. Note that input method preferences are synced, so users can use
439  // their farovite input methods as soon as the preferences are synced.
440  //
441  // For Guest mode, user locale preferences will never get initialized.
442  // So input methods should be enabled somewhere.
443  const bool enable_layouts =
444      user_manager::UserManager::Get()->IsLoggedInAsGuest();
445  locale_util::SwitchLanguage(pref_locale,
446                              enable_layouts,
447                              false /* login_layouts_only */,
448                              callback.Pass());
449
450  return true;
451}
452
453bool UserSessionManager::NeedsToUpdateEasyUnlockKeys() const {
454  return EasyUnlockService::IsSignInEnabled() &&
455         !user_context_.GetUserID().empty() &&
456         user_context_.GetUserType() == user_manager::USER_TYPE_REGULAR &&
457         user_context_.GetKey() && !user_context_.GetKey()->GetSecret().empty();
458}
459
460bool UserSessionManager::CheckEasyUnlockKeyOps(const base::Closure& callback) {
461  if (!running_easy_unlock_key_ops_)
462    return false;
463
464  // Assumes only one deferred callback is needed.
465  DCHECK(easy_unlock_key_ops_finished_callback_.is_null());
466
467  easy_unlock_key_ops_finished_callback_ = callback;
468  return true;
469}
470
471void UserSessionManager::AddSessionStateObserver(
472    chromeos::UserSessionStateObserver* observer) {
473  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
474  session_state_observer_list_.AddObserver(observer);
475}
476
477void UserSessionManager::RemoveSessionStateObserver(
478    chromeos::UserSessionStateObserver* observer) {
479  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
480  session_state_observer_list_.RemoveObserver(observer);
481}
482
483void UserSessionManager::OnSessionRestoreStateChanged(
484    Profile* user_profile,
485    OAuth2LoginManager::SessionRestoreState state) {
486  user_manager::User::OAuthTokenStatus user_status =
487      user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN;
488  OAuth2LoginManager* login_manager =
489      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
490
491  bool connection_error = false;
492  switch (state) {
493    case OAuth2LoginManager::SESSION_RESTORE_DONE:
494      user_status = user_manager::User::OAUTH2_TOKEN_STATUS_VALID;
495      break;
496    case OAuth2LoginManager::SESSION_RESTORE_FAILED:
497      user_status = user_manager::User::OAUTH2_TOKEN_STATUS_INVALID;
498      break;
499    case OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED:
500      connection_error = true;
501      break;
502    case OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
503    case OAuth2LoginManager::SESSION_RESTORE_PREPARING:
504    case OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS:
505      return;
506  }
507
508  // We should not be clearing existing token state if that was a connection
509  // error. http://crbug.com/295245
510  if (!connection_error) {
511    // We are in one of "done" states here.
512    user_manager::UserManager::Get()->SaveUserOAuthStatus(
513        user_manager::UserManager::Get()->GetLoggedInUser()->email(),
514        user_status);
515  }
516
517  login_manager->RemoveObserver(this);
518}
519
520void UserSessionManager::OnNewRefreshTokenAvaiable(Profile* user_profile) {
521  // Check if we were waiting to restart chrome.
522  if (!exit_after_session_restore_)
523    return;
524
525  OAuth2LoginManager* login_manager =
526      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
527  login_manager->RemoveObserver(this);
528
529  // Mark user auth token status as valid.
530  user_manager::UserManager::Get()->SaveUserOAuthStatus(
531      user_manager::UserManager::Get()->GetLoggedInUser()->email(),
532      user_manager::User::OAUTH2_TOKEN_STATUS_VALID);
533
534  VLOG(1) << "Exiting after new refresh token fetched";
535
536  // We need to restart cleanly in this case to make sure OAuth2 RT is actually
537  // saved.
538  chrome::AttemptRestart();
539}
540
541void UserSessionManager::OnConnectionTypeChanged(
542    net::NetworkChangeNotifier::ConnectionType type) {
543  bool is_running_test =
544      base::CommandLine::ForCurrentProcess()->HasSwitch(
545          ::switches::kTestName) ||
546      base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType);
547  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
548  if (type == net::NetworkChangeNotifier::CONNECTION_NONE ||
549      !user_manager->IsUserLoggedIn() ||
550      !user_manager->IsLoggedInAsRegularUser() ||
551      user_manager->IsLoggedInAsStub() || is_running_test) {
552    return;
553  }
554
555  // Need to iterate over all users and their OAuth2 session state.
556  const user_manager::UserList& users = user_manager->GetLoggedInUsers();
557  for (user_manager::UserList::const_iterator it = users.begin();
558       it != users.end();
559       ++it) {
560    if (!(*it)->is_profile_created())
561      continue;
562
563    Profile* user_profile = ProfileHelper::Get()->GetProfileByUserUnsafe(*it);
564    bool should_restore_session =
565        pending_signin_restore_sessions_.find((*it)->email()) !=
566        pending_signin_restore_sessions_.end();
567    OAuth2LoginManager* login_manager =
568        OAuth2LoginManagerFactory::GetInstance()->GetForProfile(user_profile);
569    if (login_manager->state() ==
570            OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS) {
571      // If we come online for the first time after successful offline login,
572      // we need to kick off OAuth token verification process again.
573      login_manager->ContinueSessionRestore();
574    } else if (should_restore_session) {
575      pending_signin_restore_sessions_.erase((*it)->email());
576      RestoreAuthSessionImpl(user_profile, false /* has_auth_cookies */);
577    }
578  }
579}
580
581void UserSessionManager::OnProfilePrepared(Profile* profile) {
582  LoginUtils::Get()->DoBrowserLaunch(profile, NULL);  // host_, not needed here
583
584  if (!CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestName)) {
585    // Did not log in (we crashed or are debugging), need to restore Sync.
586    // TODO(nkostylev): Make sure that OAuth state is restored correctly for all
587    // users once it is fully multi-profile aware. http://crbug.com/238987
588    // For now if we have other user pending sessions they'll override OAuth
589    // session restore for previous users.
590    UserSessionManager::GetInstance()->RestoreAuthenticationSession(profile);
591  }
592
593  // Restore other user sessions if any.
594  RestorePendingUserSessions();
595}
596
597void UserSessionManager::CreateUserSession(const UserContext& user_context,
598                                           bool has_auth_cookies) {
599  user_context_ = user_context;
600  has_auth_cookies_ = has_auth_cookies;
601  InitSessionRestoreStrategy();
602}
603
604void UserSessionManager::PreStartSession() {
605  // Switch log file as soon as possible.
606  if (base::SysInfo::IsRunningOnChromeOS())
607    logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
608}
609
610void UserSessionManager::StartCrosSession() {
611  BootTimesLoader* btl = BootTimesLoader::Get();
612  btl->AddLoginTimeMarker("StartSession-Start", false);
613  DBusThreadManager::Get()->GetSessionManagerClient()->
614      StartSession(user_context_.GetUserID());
615  btl->AddLoginTimeMarker("StartSession-End", false);
616}
617
618void UserSessionManager::NotifyUserLoggedIn() {
619  BootTimesLoader* btl = BootTimesLoader::Get();
620  btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
621  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
622  user_manager->UserLoggedIn(user_context_.GetUserID(),
623                             user_context_.GetUserIDHash(),
624                             false);
625  btl->AddLoginTimeMarker("UserLoggedIn-End", false);
626}
627
628void UserSessionManager::PrepareProfile() {
629  bool is_demo_session =
630      DemoAppLauncher::IsDemoAppSession(user_context_.GetUserID());
631
632  // TODO(nkostylev): Figure out whether demo session is using the right profile
633  // path or not. See https://codereview.chromium.org/171423009
634  g_browser_process->profile_manager()->CreateProfileAsync(
635      ProfileHelper::GetProfilePathByUserIdHash(user_context_.GetUserIDHash()),
636      base::Bind(&UserSessionManager::OnProfileCreated,
637                 AsWeakPtr(),
638                 user_context_,
639                 is_demo_session),
640      base::string16(),
641      base::string16(),
642      std::string());
643}
644
645void UserSessionManager::OnProfileCreated(const UserContext& user_context,
646                                          bool is_incognito_profile,
647                                          Profile* profile,
648                                          Profile::CreateStatus status) {
649  CHECK(profile);
650
651  switch (status) {
652    case Profile::CREATE_STATUS_CREATED:
653      // Profile created but before initializing extensions and promo resources.
654      InitProfilePreferences(profile, user_context);
655      break;
656    case Profile::CREATE_STATUS_INITIALIZED:
657      // Profile is created, extensions and promo resources are initialized.
658      // At this point all other Chrome OS services will be notified that it is
659      // safe to use this profile.
660      UserProfileInitialized(profile,
661                             is_incognito_profile,
662                             user_context.GetUserID());
663      break;
664    case Profile::CREATE_STATUS_LOCAL_FAIL:
665    case Profile::CREATE_STATUS_REMOTE_FAIL:
666    case Profile::CREATE_STATUS_CANCELED:
667    case Profile::MAX_CREATE_STATUS:
668      NOTREACHED();
669      break;
670  }
671}
672
673void UserSessionManager::InitProfilePreferences(
674    Profile* profile,
675    const UserContext& user_context) {
676  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
677  if (user->is_active()) {
678    input_method::InputMethodManager* manager =
679        input_method::InputMethodManager::Get();
680    manager->SetState(GetDefaultIMEState(profile));
681  }
682  if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
683    SetFirstLoginPrefs(profile,
684                       user_context.GetPublicSessionLocale(),
685                       user_context.GetPublicSessionInputMethod());
686  }
687
688  if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) {
689    user_manager::User* active_user =
690        user_manager::UserManager::Get()->GetActiveUser();
691    std::string supervised_user_sync_id =
692        ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
693            active_user->email());
694    profile->GetPrefs()->SetString(prefs::kSupervisedUserId,
695                                   supervised_user_sync_id);
696  } else if (user_manager::UserManager::Get()->IsLoggedInAsRegularUser()) {
697    // Make sure that the google service username is properly set (we do this
698    // on every sign in, not just the first login, to deal with existing
699    // profiles that might not have it set yet).
700    SigninManagerBase* signin_manager =
701        SigninManagerFactory::GetForProfile(profile);
702    signin_manager->SetAuthenticatedUsername(user_context.GetUserID());
703  }
704}
705
706void UserSessionManager::UserProfileInitialized(Profile* profile,
707                                                bool is_incognito_profile,
708                                                const std::string& user_id) {
709  if (is_incognito_profile) {
710    profile->OnLogin();
711    // Send the notification before creating the browser so additional objects
712    // that need the profile (e.g. the launcher) can be created first.
713    content::NotificationService::current()->Notify(
714        chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
715        content::NotificationService::AllSources(),
716        content::Details<Profile>(profile));
717
718    if (delegate_)
719      delegate_->OnProfilePrepared(profile);
720
721    return;
722  }
723
724  BootTimesLoader* btl = BootTimesLoader::Get();
725  btl->AddLoginTimeMarker("UserProfileGotten", false);
726
727  if (user_context_.IsUsingOAuth()) {
728    // Retrieve the policy that indicates whether to continue copying
729    // authentication cookies set by a SAML IdP on subsequent logins after the
730    // first.
731    bool transfer_saml_auth_cookies_on_subsequent_login = false;
732    if (has_auth_cookies_ &&
733        g_browser_process->platform_part()->
734            browser_policy_connector_chromeos()->GetUserAffiliation(user_id) ==
735                policy::USER_AFFILIATION_MANAGED) {
736      CrosSettings::Get()->GetBoolean(
737          kAccountsPrefTransferSAMLCookies,
738          &transfer_saml_auth_cookies_on_subsequent_login);
739    }
740
741    // Transfers authentication-related data from the profile that was used for
742    // authentication to the user's profile. The proxy authentication state is
743    // transferred unconditionally. If the user authenticated via an auth
744    // extension, authentication cookies and channel IDs will be transferred as
745    // well when the user's cookie jar is empty. If the cookie jar is not empty,
746    // the authentication states in the login profile and the user's profile
747    // must be merged using /MergeSession instead. Authentication cookies set by
748    // a SAML IdP will also be transferred when the user's cookie jar is not
749    // empty if |transfer_saml_auth_cookies_on_subsequent_login| is true.
750    const bool transfer_auth_cookies_and_channel_ids_on_first_login =
751        has_auth_cookies_;
752    ProfileAuthData::Transfer(
753        authenticator_->authentication_profile(),
754        profile,
755        transfer_auth_cookies_and_channel_ids_on_first_login,
756        transfer_saml_auth_cookies_on_subsequent_login,
757        base::Bind(&UserSessionManager::CompleteProfileCreateAfterAuthTransfer,
758                   AsWeakPtr(),
759                   profile));
760    return;
761  }
762
763  FinalizePrepareProfile(profile);
764}
765
766void UserSessionManager::CompleteProfileCreateAfterAuthTransfer(
767    Profile* profile) {
768  RestoreAuthSessionImpl(profile, has_auth_cookies_);
769  FinalizePrepareProfile(profile);
770}
771
772void UserSessionManager::FinalizePrepareProfile(Profile* profile) {
773  BootTimesLoader* btl = BootTimesLoader::Get();
774
775  // Own TPM device if, for any reason, it has not been done in EULA screen.
776  CryptohomeClient* client = DBusThreadManager::Get()->GetCryptohomeClient();
777  btl->AddLoginTimeMarker("TPMOwn-Start", false);
778  if (cryptohome_util::TpmIsEnabled() && !cryptohome_util::TpmIsBeingOwned()) {
779    if (cryptohome_util::TpmIsOwned())
780      client->CallTpmClearStoredPasswordAndBlock();
781    else
782      client->TpmCanAttemptOwnership(EmptyVoidDBusMethodCallback());
783  }
784  btl->AddLoginTimeMarker("TPMOwn-End", false);
785
786  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
787  if (user_manager->IsLoggedInAsRegularUser()) {
788    SAMLOfflineSigninLimiter* saml_offline_signin_limiter =
789        SAMLOfflineSigninLimiterFactory::GetForProfile(profile);
790    if (saml_offline_signin_limiter)
791      saml_offline_signin_limiter->SignedIn(user_context_.GetAuthFlow());
792  }
793
794  profile->OnLogin();
795
796  g_browser_process->platform_part()->SessionManager()->SetSessionState(
797      session_manager::SESSION_STATE_LOGGED_IN_NOT_ACTIVE);
798
799  // Send the notification before creating the browser so additional objects
800  // that need the profile (e.g. the launcher) can be created first.
801  content::NotificationService::current()->Notify(
802      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
803      content::NotificationService::AllSources(),
804      content::Details<Profile>(profile));
805
806  // Initialize various services only for primary user.
807  const user_manager::User* user =
808      ProfileHelper::Get()->GetUserByProfile(profile);
809  if (user_manager->GetPrimaryUser() == user) {
810    InitRlz(profile);
811    InitializeCerts(profile);
812    InitializeCRLSetFetcher(user);
813  }
814
815  UpdateEasyUnlockKeys(user_context_);
816  user_context_.ClearSecrets();
817
818  // TODO(nkostylev): This pointer should probably never be NULL, but it looks
819  // like LoginUtilsImpl::OnProfileCreated() may be getting called before
820  // UserSessionManager::PrepareProfile() has set |delegate_| when Chrome is
821  // killed during shutdown in tests -- see http://crosbug.com/18269.  Replace
822  // this 'if' statement with a CHECK(delegate_) once the underlying issue is
823  // resolved.
824  if (delegate_)
825    delegate_->OnProfilePrepared(profile);
826}
827
828void UserSessionManager::InitSessionRestoreStrategy() {
829  CommandLine* command_line = CommandLine::ForCurrentProcess();
830  bool in_app_mode = chrome::IsRunningInForcedAppMode();
831
832  // Are we in kiosk app mode?
833  if (in_app_mode) {
834    if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
835      oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
836          ::switches::kAppModeOAuth2Token);
837    }
838
839    if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
840      user_context_.SetAuthCode(command_line->GetSwitchValueASCII(
841          ::switches::kAppModeAuthCode));
842    }
843
844    DCHECK(!has_auth_cookies_);
845    if (!user_context_.GetAuthCode().empty()) {
846      session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
847    } else if (!oauth2_refresh_token_.empty()) {
848      session_restore_strategy_ =
849          OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
850    } else {
851      session_restore_strategy_ =
852          OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
853    }
854    return;
855  }
856
857  if (has_auth_cookies_) {
858    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR;
859  } else if (!user_context_.GetAuthCode().empty()) {
860    session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE;
861  } else {
862    session_restore_strategy_ =
863        OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
864  }
865}
866
867void UserSessionManager::RestoreAuthSessionImpl(Profile* profile,
868                                            bool restore_from_auth_cookies) {
869  CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
870        !restore_from_auth_cookies);
871
872  if (chrome::IsRunningInForcedAppMode() ||
873      CommandLine::ForCurrentProcess()->HasSwitch(
874          chromeos::switches::kDisableGaiaServices)) {
875    return;
876  }
877
878  exit_after_session_restore_ = false;
879
880  // Remove legacy OAuth1 token if we have one. If it's valid, we should already
881  // have OAuth2 refresh token in OAuth2TokenService that could be used to
882  // retrieve all other tokens and user_context.
883  OAuth2LoginManager* login_manager =
884      OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
885  login_manager->AddObserver(this);
886  login_manager->RestoreSession(
887      authenticator_.get() && authenticator_->authentication_profile()
888          ? authenticator_->authentication_profile()->GetRequestContext()
889          : NULL,
890      session_restore_strategy_,
891      oauth2_refresh_token_,
892      user_context_.GetAuthCode());
893}
894
895void UserSessionManager::InitRlzImpl(Profile* profile, bool disabled) {
896#if defined(ENABLE_RLZ)
897  PrefService* local_state = g_browser_process->local_state();
898  if (disabled) {
899    // Empty brand code means an organic install (no RLZ pings are sent).
900    google_brand::chromeos::ClearBrandForCurrentSession();
901  }
902  if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
903    // When switching to RLZ enabled/disabled state, clear all recorded events.
904    RLZTracker::ClearRlzState();
905    local_state->SetBoolean(prefs::kRLZDisabled, disabled);
906  }
907  // Init the RLZ library.
908  int ping_delay = profile->GetPrefs()->GetInteger(
909      first_run::GetPingDelayPrefName().c_str());
910  // Negative ping delay means to send ping immediately after a first search is
911  // recorded.
912  RLZTracker::InitRlzFromProfileDelayed(
913      profile,
914      user_manager::UserManager::Get()->IsCurrentUserNew(),
915      ping_delay < 0,
916      base::TimeDelta::FromMilliseconds(abs(ping_delay)));
917  if (delegate_)
918    delegate_->OnRlzInitialized();
919#endif
920}
921
922void UserSessionManager::InitializeCerts(Profile* profile) {
923  // Now that the user profile has been initialized
924  // |GetNSSCertDatabaseForProfile| is safe to be used.
925  if (CertLoader::IsInitialized() && base::SysInfo::IsRunningOnChromeOS()) {
926    GetNSSCertDatabaseForProfile(profile,
927                                 base::Bind(&OnGetNSSCertDatabaseForUser));
928  }
929}
930
931void UserSessionManager::InitializeCRLSetFetcher(
932    const user_manager::User* user) {
933  const std::string username_hash = user->username_hash();
934  if (!username_hash.empty()) {
935    base::FilePath path;
936    path = ProfileHelper::GetProfilePathByUserIdHash(username_hash);
937    component_updater::ComponentUpdateService* cus =
938        g_browser_process->component_updater();
939    CRLSetFetcher* crl_set = g_browser_process->crl_set_fetcher();
940    if (crl_set && cus)
941      crl_set->StartInitialLoad(cus, path);
942  }
943}
944
945void UserSessionManager::OnRestoreActiveSessions(
946    const SessionManagerClient::ActiveSessionsMap& sessions,
947    bool success) {
948  if (!success) {
949    LOG(ERROR) << "Could not get list of active user sessions after crash.";
950    // If we could not get list of active user sessions it is safer to just
951    // sign out so that we don't get in the inconsistent state.
952    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
953    return;
954  }
955
956  // One profile has been already loaded on browser start.
957  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
958  DCHECK(user_manager->GetLoggedInUsers().size() == 1);
959  DCHECK(user_manager->GetActiveUser());
960  std::string active_user_id = user_manager->GetActiveUser()->email();
961
962  SessionManagerClient::ActiveSessionsMap::const_iterator it;
963  for (it = sessions.begin(); it != sessions.end(); ++it) {
964    if (active_user_id == it->first)
965      continue;
966    pending_user_sessions_[it->first] = it->second;
967  }
968  RestorePendingUserSessions();
969}
970
971void UserSessionManager::RestorePendingUserSessions() {
972  if (pending_user_sessions_.empty()) {
973    user_manager::UserManager::Get()->SwitchToLastActiveUser();
974    NotifyPendingUserSessionsRestoreFinished();
975    return;
976  }
977
978  // Get next user to restore sessions and delete it from list.
979  SessionManagerClient::ActiveSessionsMap::const_iterator it =
980      pending_user_sessions_.begin();
981  std::string user_id = it->first;
982  std::string user_id_hash = it->second;
983  DCHECK(!user_id.empty());
984  DCHECK(!user_id_hash.empty());
985  pending_user_sessions_.erase(user_id);
986
987  // Check that this user is not logged in yet.
988  user_manager::UserList logged_in_users =
989      user_manager::UserManager::Get()->GetLoggedInUsers();
990  bool user_already_logged_in = false;
991  for (user_manager::UserList::const_iterator it = logged_in_users.begin();
992       it != logged_in_users.end();
993       ++it) {
994    const user_manager::User* user = (*it);
995    if (user->email() == user_id) {
996      user_already_logged_in = true;
997      break;
998    }
999  }
1000  DCHECK(!user_already_logged_in);
1001
1002  if (!user_already_logged_in) {
1003    UserContext user_context(user_id);
1004    user_context.SetUserIDHash(user_id_hash);
1005    user_context.SetIsUsingOAuth(false);
1006
1007    // Will call OnProfilePrepared() once profile has been loaded.
1008    StartSession(user_context,
1009                 NULL,   // authenticator
1010                 false,  // has_auth_cookies
1011                 true,   // has_active_session
1012                 this);
1013  } else {
1014    RestorePendingUserSessions();
1015  }
1016}
1017
1018void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() {
1019  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1020  user_sessions_restored_ = true;
1021  user_sessions_restore_in_progress_ = false;
1022  FOR_EACH_OBSERVER(chromeos::UserSessionStateObserver,
1023                    session_state_observer_list_,
1024                    PendingUserSessionsRestoreFinished());
1025}
1026
1027void UserSessionManager::UpdateEasyUnlockKeys(const UserContext& user_context) {
1028  // Skip key update because FakeCryptohomeClient always return success
1029  // and RemoveKey op expects a failure to stop. As a result, some tests would
1030  // timeout.
1031  // TODO(xiyuan): Revisit this when adding tests.
1032  if (!base::SysInfo::IsRunningOnChromeOS())
1033    return;
1034
1035  // Only update Easy unlock keys for regular user.
1036  // TODO(xiyuan): Fix inconsistency user type of |user_context| introduced in
1037  // authenticator.
1038  const user_manager::User* user =
1039      user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
1040  if (!user || user->GetType() != user_manager::USER_TYPE_REGULAR)
1041    return;
1042
1043  // Bail if |user_context| does not have secret.
1044  if (user_context.GetKey()->GetSecret().empty())
1045    return;
1046
1047  const base::ListValue* device_list = NULL;
1048  EasyUnlockService* easy_unlock_service = EasyUnlockService::GetForUser(*user);
1049  if (easy_unlock_service) {
1050    device_list = easy_unlock_service->GetRemoteDevices();
1051    easy_unlock_service->SetHardlockState(
1052        EasyUnlockScreenlockStateHandler::NO_HARDLOCK);
1053  }
1054
1055  EasyUnlockKeyManager* key_manager = GetEasyUnlockKeyManager();
1056  running_easy_unlock_key_ops_ = true;
1057  if (device_list) {
1058    key_manager->RefreshKeys(
1059        user_context,
1060        *device_list,
1061        base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished,
1062                   AsWeakPtr(),
1063                   user_context.GetUserID()));
1064  } else {
1065    key_manager->RemoveKeys(
1066        user_context,
1067        0,
1068        base::Bind(&UserSessionManager::OnEasyUnlockKeyOpsFinished,
1069                   AsWeakPtr(),
1070                   user_context.GetUserID()));
1071  }
1072}
1073
1074void UserSessionManager::OnEasyUnlockKeyOpsFinished(
1075    const std::string& user_id,
1076    bool success) {
1077  running_easy_unlock_key_ops_ = false;
1078  if (!easy_unlock_key_ops_finished_callback_.is_null())
1079    easy_unlock_key_ops_finished_callback_.Run();
1080
1081  const user_manager::User* user =
1082      user_manager::UserManager::Get()->FindUser(user_id);
1083  EasyUnlockService* easy_unlock_service =
1084        EasyUnlockService::GetForUser(*user);
1085  easy_unlock_service->CheckCryptohomeKeysAndMaybeHardlock();
1086}
1087
1088void UserSessionManager::ActiveUserChanged(
1089    const user_manager::User* active_user) {
1090  Profile* profile = ProfileHelper::Get()->GetProfileByUser(active_user);
1091  // If profile has not yet been initialized, delay initialization of IME.
1092  if (!profile)
1093    return;
1094
1095  input_method::InputMethodManager* manager =
1096      input_method::InputMethodManager::Get();
1097  manager->SetState(
1098      GetDefaultIMEState(ProfileHelper::Get()->GetProfileByUser(active_user)));
1099}
1100
1101scoped_refptr<input_method::InputMethodManager::State>
1102UserSessionManager::GetDefaultIMEState(Profile* profile) {
1103  scoped_refptr<input_method::InputMethodManager::State> state =
1104      default_ime_states_[profile];
1105  if (!state.get()) {
1106    // Profile can be NULL in tests.
1107    state = input_method::InputMethodManager::Get()->CreateNewState(profile);
1108    default_ime_states_[profile] = state;
1109  }
1110  return state;
1111}
1112
1113EasyUnlockKeyManager* UserSessionManager::GetEasyUnlockKeyManager() {
1114  if (!easy_unlock_key_manager_)
1115    easy_unlock_key_manager_.reset(new EasyUnlockKeyManager);
1116
1117  return easy_unlock_key_manager_.get();
1118}
1119
1120}  // namespace chromeos
1121