Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 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/login_utils.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/chromeos/chromeos_version.h"
     11 #include "base/command_line.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/file_util.h"
     14 #include "base/files/file_path.h"
     15 #include "base/location.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/memory/singleton.h"
     19 #include "base/memory/weak_ptr.h"
     20 #include "base/path_service.h"
     21 #include "base/prefs/pref_member.h"
     22 #include "base/prefs/pref_registry_simple.h"
     23 #include "base/prefs/pref_service.h"
     24 #include "base/strings/string_util.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "base/synchronization/lock.h"
     27 #include "base/task_runner_util.h"
     28 #include "base/threading/worker_pool.h"
     29 #include "base/time/time.h"
     30 #include "chrome/browser/about_flags.h"
     31 #include "chrome/browser/app_mode/app_mode_utils.h"
     32 #include "chrome/browser/browser_process.h"
     33 #include "chrome/browser/browser_shutdown.h"
     34 #include "chrome/browser/chrome_notification_types.h"
     35 #include "chrome/browser/chromeos/boot_times_loader.h"
     36 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     37 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
     38 #include "chrome/browser/chromeos/login/language_switch_menu.h"
     39 #include "chrome/browser/chromeos/login/login_display_host.h"
     40 #include "chrome/browser/chromeos/login/oauth_login_manager.h"
     41 #include "chrome/browser/chromeos/login/parallel_authenticator.h"
     42 #include "chrome/browser/chromeos/login/profile_auth_data.h"
     43 #include "chrome/browser/chromeos/login/screen_locker.h"
     44 #include "chrome/browser/chromeos/login/user_manager.h"
     45 #include "chrome/browser/chromeos/settings/cros_settings.h"
     46 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
     47 #include "chrome/browser/extensions/extension_service.h"
     48 #include "chrome/browser/first_run/first_run.h"
     49 #include "chrome/browser/google/google_util_chromeos.h"
     50 #include "chrome/browser/lifetime/application_lifetime.h"
     51 #include "chrome/browser/pref_service_flags_storage.h"
     52 #include "chrome/browser/profiles/profile.h"
     53 #include "chrome/browser/profiles/profile_manager.h"
     54 #include "chrome/browser/rlz/rlz.h"
     55 #include "chrome/browser/signin/signin_manager.h"
     56 #include "chrome/browser/signin/signin_manager_factory.h"
     57 #include "chrome/browser/signin/token_service.h"
     58 #include "chrome/browser/signin/token_service_factory.h"
     59 #include "chrome/browser/sync/profile_sync_service.h"
     60 #include "chrome/browser/sync/profile_sync_service_factory.h"
     61 #include "chrome/browser/ui/startup/startup_browser_creator.h"
     62 #include "chrome/common/chrome_paths.h"
     63 #include "chrome/common/chrome_switches.h"
     64 #include "chrome/common/logging_chrome.h"
     65 #include "chrome/common/pref_names.h"
     66 #include "chromeos/chromeos_switches.h"
     67 #include "chromeos/cryptohome/cryptohome_library.h"
     68 #include "chromeos/dbus/dbus_thread_manager.h"
     69 #include "chromeos/dbus/session_manager_client.h"
     70 #include "chromeos/ime/input_method_manager.h"
     71 #include "content/public/browser/browser_thread.h"
     72 #include "content/public/browser/notification_service.h"
     73 #include "google_apis/gaia/gaia_auth_consumer.h"
     74 #include "net/base/network_change_notifier.h"
     75 #include "net/url_request/url_request_context.h"
     76 #include "net/url_request/url_request_context_getter.h"
     77 #include "url/gurl.h"
     78 
     79 using content::BrowserThread;
     80 
     81 namespace chromeos {
     82 
     83 namespace {
     84 
     85 #if defined(ENABLE_RLZ)
     86 // Flag file that disables RLZ tracking, when present.
     87 const base::FilePath::CharType kRLZDisabledFlagName[] =
     88     FILE_PATH_LITERAL(".rlz_disabled");
     89 
     90 base::FilePath GetRlzDisabledFlagPath() {
     91   return file_util::GetHomeDir().Append(kRLZDisabledFlagName);
     92 }
     93 #endif
     94 
     95 }  // namespace
     96 
     97 class LoginUtilsImpl
     98     : public LoginUtils,
     99       public OAuthLoginManager::Delegate,
    100       public net::NetworkChangeNotifier::ConnectionTypeObserver,
    101       public base::SupportsWeakPtr<LoginUtilsImpl> {
    102  public:
    103   LoginUtilsImpl()
    104       : using_oauth_(false),
    105         has_web_auth_cookies_(false),
    106         login_manager_(OAuthLoginManager::Create(this)),
    107         delegate_(NULL),
    108         should_restore_auth_session_(false),
    109         exit_after_session_restore_(false),
    110         session_restore_strategy_(
    111             OAuthLoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) {
    112     net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
    113   }
    114 
    115   virtual ~LoginUtilsImpl() {
    116     net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
    117   }
    118 
    119   // LoginUtils implementation:
    120   virtual void DoBrowserLaunch(Profile* profile,
    121                                LoginDisplayHost* login_host) OVERRIDE;
    122   virtual void PrepareProfile(
    123       const UserContext& user_context,
    124       const std::string& display_email,
    125       bool using_oauth,
    126       bool has_cookies,
    127       bool has_active_session,
    128       LoginUtils::Delegate* delegate) OVERRIDE;
    129   virtual void DelegateDeleted(LoginUtils::Delegate* delegate) OVERRIDE;
    130   virtual void CompleteOffTheRecordLogin(const GURL& start_url) OVERRIDE;
    131   virtual void SetFirstLoginPrefs(PrefService* prefs) OVERRIDE;
    132   virtual scoped_refptr<Authenticator> CreateAuthenticator(
    133       LoginStatusConsumer* consumer) OVERRIDE;
    134   virtual void RestoreAuthenticationSession(Profile* profile) OVERRIDE;
    135   virtual void StopBackgroundFetchers() OVERRIDE;
    136   virtual void InitRlzDelayed(Profile* user_profile) OVERRIDE;
    137 
    138   // OAuthLoginManager::Delegate overrides.
    139   virtual void OnCompletedMergeSession() OVERRIDE;
    140   virtual void OnCompletedAuthentication(Profile* user_profile) OVERRIDE;
    141   virtual void OnFoundStoredTokens() OVERRIDE;
    142   virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) OVERRIDE;
    143 
    144   // net::NetworkChangeNotifier::ConnectionTypeObserver overrides.
    145   virtual void OnConnectionTypeChanged(
    146       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
    147 
    148  private:
    149   // Restarts OAuth session authentication check.
    150   void KickStartAuthentication(Profile* profile);
    151 
    152   // Check user's profile for kApplicationLocale setting.
    153   void RespectLocalePreference(Profile* pref);
    154 
    155   // Callback for Profile::CREATE_STATUS_CREATED profile state.
    156   // Initializes basic preferences for newly created profile. Any other
    157   // early profile initialization that needs to happen before
    158   // ProfileManager::DoFinalInit() gets called is done here.
    159   void InitProfilePreferences(Profile* user_profile);
    160 
    161   // Callback for asynchronous profile creation.
    162   void OnProfileCreated(Profile* profile,
    163                         Profile::CreateStatus status);
    164 
    165   // Callback for Profile::CREATE_STATUS_INITIALIZED profile state.
    166   // Profile is created, extensions and promo resources are initialized.
    167   void UserProfileInitialized(Profile* user_profile);
    168 
    169   // Callback to resume profile creation after transferring auth data from
    170   // the authentication profile.
    171   void CompleteProfileCreate(Profile* user_profile);
    172 
    173   // Finalized profile preparation.
    174   void FinalizePrepareProfile(Profile* user_profile);
    175 
    176   // Initializes member variables needed for session restore process via
    177   // OAuthLoginManager.
    178   void InitSessionRestoreStrategy();
    179 
    180   // Restores GAIA auth cookies for the created user profile from OAuth2 token.
    181   void RestoreAuthSession(Profile* user_profile,
    182                           bool restore_from_auth_cookies);
    183 
    184   // Initializes RLZ. If |disabled| is true, RLZ pings are disabled.
    185   void InitRlz(Profile* user_profile, bool disabled);
    186 
    187   // Starts signing related services. Initiates TokenService token retrieval.
    188   void StartSignedInServices(Profile* profile);
    189 
    190   // Attempts exiting browser process and esures this does not happen
    191   // while we are still fetching new OAuth refresh tokens.
    192   void AttemptExit(Profile* profile);
    193 
    194   UserContext user_context_;
    195   bool using_oauth_;
    196   // True if the authentication profile's cookie jar should contain
    197   // authentication cookies from the authentication extension log in flow.
    198   bool has_web_auth_cookies_;
    199   // Has to be scoped_refptr, see comment for CreateAuthenticator(...).
    200   scoped_refptr<Authenticator> authenticator_;
    201   scoped_ptr<OAuthLoginManager> login_manager_;
    202 
    203   // Delegate to be fired when the profile will be prepared.
    204   LoginUtils::Delegate* delegate_;
    205 
    206   // True if should restore authentication session when notified about
    207   // online state change.
    208   bool should_restore_auth_session_;
    209 
    210   // True if we should restart chrome right after session restore.
    211   bool exit_after_session_restore_;
    212 
    213   // Sesion restore strategy.
    214   OAuthLoginManager::SessionRestoreStrategy session_restore_strategy_;
    215   // OAuth2 refresh token for session restore.
    216   std::string oauth2_refresh_token_;
    217 
    218   DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
    219 };
    220 
    221 class LoginUtilsWrapper {
    222  public:
    223   static LoginUtilsWrapper* GetInstance() {
    224     return Singleton<LoginUtilsWrapper>::get();
    225   }
    226 
    227   LoginUtils* get() {
    228     base::AutoLock create(create_lock_);
    229     if (!ptr_.get())
    230       reset(new LoginUtilsImpl);
    231     return ptr_.get();
    232   }
    233 
    234   void reset(LoginUtils* ptr) {
    235     ptr_.reset(ptr);
    236   }
    237 
    238  private:
    239   friend struct DefaultSingletonTraits<LoginUtilsWrapper>;
    240 
    241   LoginUtilsWrapper() {}
    242 
    243   base::Lock create_lock_;
    244   scoped_ptr<LoginUtils> ptr_;
    245 
    246   DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
    247 };
    248 
    249 void LoginUtilsImpl::DoBrowserLaunch(Profile* profile,
    250                                      LoginDisplayHost* login_host) {
    251   if (browser_shutdown::IsTryingToQuit())
    252     return;
    253 
    254   if (!UserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
    255     UserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile);
    256     return;
    257   }
    258 
    259   CommandLine user_flags(CommandLine::NO_PROGRAM);
    260   about_flags::PrefServiceFlagsStorage flags_storage_(profile->GetPrefs());
    261   about_flags::ConvertFlagsToSwitches(&flags_storage_, &user_flags);
    262   // Only restart if needed and if not going into managed mode.
    263   if (!UserManager::Get()->IsLoggedInAsLocallyManagedUser() &&
    264       !about_flags::AreSwitchesIdenticalToCurrentCommandLine(
    265           user_flags, *CommandLine::ForCurrentProcess())) {
    266     CommandLine::StringVector flags;
    267     // argv[0] is the program name |CommandLine::NO_PROGRAM|.
    268     flags.assign(user_flags.argv().begin() + 1, user_flags.argv().end());
    269     VLOG(1) << "Restarting to apply per-session flags...";
    270     DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
    271         UserManager::Get()->GetActiveUser()->email(), flags);
    272     AttemptExit(profile);
    273     return;
    274   }
    275 
    276   if (login_host) {
    277     login_host->SetStatusAreaVisible(true);
    278     login_host->BeforeSessionStart();
    279   }
    280 
    281   BootTimesLoader::Get()->AddLoginTimeMarker("BrowserLaunched", false);
    282 
    283   VLOG(1) << "Launching browser...";
    284   StartupBrowserCreator browser_creator;
    285   int return_code;
    286   chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
    287       chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
    288 
    289   browser_creator.LaunchBrowser(*CommandLine::ForCurrentProcess(),
    290                                 profile,
    291                                 base::FilePath(),
    292                                 chrome::startup::IS_PROCESS_STARTUP,
    293                                 first_run,
    294                                 &return_code);
    295 
    296   // Mark login host for deletion after browser starts.  This
    297   // guarantees that the message loop will be referenced by the
    298   // browser before it is dereferenced by the login host.
    299   if (login_host)
    300     login_host->Finalize();
    301   UserManager::Get()->SessionStarted();
    302 }
    303 
    304 void LoginUtilsImpl::PrepareProfile(
    305     const UserContext& user_context,
    306     const std::string& display_email,
    307     bool using_oauth,
    308     bool has_cookies,
    309     bool has_active_session,
    310     LoginUtils::Delegate* delegate) {
    311   BootTimesLoader* btl = BootTimesLoader::Get();
    312 
    313   VLOG(1) << "Completing login for " << user_context.username;
    314 
    315   if (!has_active_session) {
    316     btl->AddLoginTimeMarker("StartSession-Start", false);
    317     DBusThreadManager::Get()->GetSessionManagerClient()->StartSession(
    318         user_context.username);
    319     btl->AddLoginTimeMarker("StartSession-End", false);
    320   }
    321 
    322   btl->AddLoginTimeMarker("UserLoggedIn-Start", false);
    323   UserManager* user_manager = UserManager::Get();
    324   user_manager->UserLoggedIn(user_context.username,
    325                              user_context.username_hash,
    326                              false);
    327   btl->AddLoginTimeMarker("UserLoggedIn-End", false);
    328 
    329   // Switch log file as soon as possible.
    330   if (base::chromeos::IsRunningOnChromeOS())
    331     logging::RedirectChromeLogging(*(CommandLine::ForCurrentProcess()));
    332 
    333   // Update user's displayed email.
    334   if (!display_email.empty())
    335     user_manager->SaveUserDisplayEmail(user_context.username, display_email);
    336 
    337   user_context_ = user_context;
    338 
    339   using_oauth_ = using_oauth;
    340   has_web_auth_cookies_ = has_cookies;
    341   delegate_ = delegate;
    342   InitSessionRestoreStrategy();
    343 
    344   // The default profile will have been changed because the ProfileManager
    345   // will process the notification that the UserManager sends out so
    346   // username_hash has been already propogated to ProfileManager.
    347   ProfileManager::CreateDefaultProfileAsync(
    348       base::Bind(&LoginUtilsImpl::OnProfileCreated, AsWeakPtr()));
    349 }
    350 
    351 void LoginUtilsImpl::DelegateDeleted(LoginUtils::Delegate* delegate) {
    352   if (delegate_ == delegate)
    353     delegate_ = NULL;
    354 }
    355 
    356 void LoginUtilsImpl::InitProfilePreferences(Profile* user_profile) {
    357   if (UserManager::Get()->IsCurrentUserNew())
    358     SetFirstLoginPrefs(user_profile->GetPrefs());
    359 
    360   if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) {
    361     user_profile->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true);
    362   } else {
    363     // Make sure that the google service username is properly set (we do this
    364     // on every sign in, not just the first login, to deal with existing
    365     // profiles that might not have it set yet).
    366     StringPrefMember google_services_username;
    367     google_services_username.Init(prefs::kGoogleServicesUsername,
    368                                   user_profile->GetPrefs());
    369     google_services_username.SetValue(
    370         UserManager::Get()->GetLoggedInUser()->display_email());
    371   }
    372 
    373   RespectLocalePreference(user_profile);
    374 }
    375 
    376 void LoginUtilsImpl::InitSessionRestoreStrategy() {
    377   CommandLine* command_line = CommandLine::ForCurrentProcess();
    378   bool in_app_mode = chrome::IsRunningInForcedAppMode();
    379 
    380   // Are we in kiosk app mode?
    381   if (in_app_mode) {
    382     if (command_line->HasSwitch(::switches::kAppModeOAuth2Token)) {
    383       oauth2_refresh_token_ = command_line->GetSwitchValueASCII(
    384           ::switches::kAppModeOAuth2Token);
    385     }
    386 
    387     if (command_line->HasSwitch(::switches::kAppModeAuthCode)) {
    388       user_context_.auth_code = command_line->GetSwitchValueASCII(
    389           ::switches::kAppModeAuthCode);
    390     }
    391 
    392     DCHECK(!has_web_auth_cookies_);
    393     if (!user_context_.auth_code.empty()) {
    394       session_restore_strategy_ = OAuthLoginManager::RESTORE_FROM_AUTH_CODE;
    395     } else if (!oauth2_refresh_token_.empty()) {
    396       session_restore_strategy_ =
    397           OAuthLoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN;
    398     } else {
    399       session_restore_strategy_ =
    400           OAuthLoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
    401     }
    402     return;
    403   }
    404 
    405   if (has_web_auth_cookies_) {
    406     session_restore_strategy_ = OAuthLoginManager::RESTORE_FROM_COOKIE_JAR;
    407   } else if (!user_context_.auth_code.empty()) {
    408     session_restore_strategy_ = OAuthLoginManager::RESTORE_FROM_AUTH_CODE;
    409   } else {
    410     session_restore_strategy_ =
    411         OAuthLoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN;
    412   }
    413 }
    414 
    415 
    416 void LoginUtilsImpl::OnProfileCreated(
    417     Profile* user_profile,
    418     Profile::CreateStatus status) {
    419   CHECK(user_profile);
    420 
    421   switch (status) {
    422     case Profile::CREATE_STATUS_INITIALIZED:
    423       UserProfileInitialized(user_profile);
    424       break;
    425     case Profile::CREATE_STATUS_CREATED:
    426       InitProfilePreferences(user_profile);
    427       break;
    428     case Profile::CREATE_STATUS_LOCAL_FAIL:
    429     case Profile::CREATE_STATUS_REMOTE_FAIL:
    430     case Profile::CREATE_STATUS_CANCELED:
    431     case Profile::MAX_CREATE_STATUS:
    432       NOTREACHED();
    433       break;
    434   }
    435 }
    436 
    437 void LoginUtilsImpl::UserProfileInitialized(Profile* user_profile) {
    438   BootTimesLoader* btl = BootTimesLoader::Get();
    439   btl->AddLoginTimeMarker("UserProfileGotten", false);
    440 
    441   if (using_oauth_) {
    442     // Transfer proxy authentication cache, cookies (optionally) and server
    443     // bound certs from the profile that was used for authentication.  This
    444     // profile contains cookies that auth extension should have already put in
    445     // place that will ensure that the newly created session is authenticated
    446     // for the websites that work with the used authentication schema.
    447     ProfileAuthData::Transfer(authenticator_->authentication_profile(),
    448                               user_profile,
    449                               has_web_auth_cookies_,  // transfer_cookies
    450                               base::Bind(
    451                                   &LoginUtilsImpl::CompleteProfileCreate,
    452                                   AsWeakPtr(),
    453                                   user_profile));
    454     return;
    455   }
    456 
    457   FinalizePrepareProfile(user_profile);
    458 }
    459 
    460 void LoginUtilsImpl::CompleteProfileCreate(Profile* user_profile) {
    461   RestoreAuthSession(user_profile, has_web_auth_cookies_);
    462   FinalizePrepareProfile(user_profile);
    463 }
    464 
    465 void LoginUtilsImpl::RestoreAuthSession(Profile* user_profile,
    466                                         bool restore_from_auth_cookies) {
    467   CHECK((authenticator_.get() && authenticator_->authentication_profile()) ||
    468         !restore_from_auth_cookies);
    469   if (!login_manager_.get())
    470     return;
    471 
    472   if (chrome::IsRunningInForcedAppMode() ||
    473       CommandLine::ForCurrentProcess()->HasSwitch(
    474           chromeos::switches::kOobeSkipPostLogin))
    475     return;
    476 
    477   UserManager::Get()->SetMergeSessionState(
    478       UserManager::MERGE_STATUS_IN_PROCESS);
    479   exit_after_session_restore_ = false;
    480   // Remove legacy OAuth1 token if we have one. If it's valid, we should already
    481   // have OAuth2 refresh token in TokenService that could be used to retrieve
    482   // all other tokens and user_context.
    483   login_manager_->RestoreSession(
    484       user_profile,
    485       authenticator_.get() && authenticator_->authentication_profile()
    486           ? authenticator_->authentication_profile()->GetRequestContext()
    487           : NULL,
    488       session_restore_strategy_,
    489       oauth2_refresh_token_,
    490       user_context_.auth_code);
    491 }
    492 
    493 void LoginUtilsImpl::FinalizePrepareProfile(Profile* user_profile) {
    494   BootTimesLoader* btl = BootTimesLoader::Get();
    495   // Own TPM device if, for any reason, it has not been done in EULA
    496   // wizard screen.
    497   CryptohomeLibrary* cryptohome = CryptohomeLibrary::Get();
    498   btl->AddLoginTimeMarker("TPMOwn-Start", false);
    499   if (cryptohome->TpmIsEnabled() && !cryptohome->TpmIsBeingOwned()) {
    500     if (cryptohome->TpmIsOwned()) {
    501       cryptohome->TpmClearStoredPassword();
    502     } else {
    503       cryptohome->TpmCanAttemptOwnership();
    504     }
    505   }
    506   btl->AddLoginTimeMarker("TPMOwn-End", false);
    507 
    508   user_profile->OnLogin();
    509 
    510   // Send the notification before creating the browser so additional objects
    511   // that need the profile (e.g. the launcher) can be created first.
    512   content::NotificationService::current()->Notify(
    513       chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
    514       content::NotificationService::AllSources(),
    515       content::Details<Profile>(user_profile));
    516 
    517   InitRlzDelayed(user_profile);
    518 
    519   // TODO(altimofeev): This pointer should probably never be NULL, but it looks
    520   // like LoginUtilsImpl::OnProfileCreated() may be getting called before
    521   // LoginUtilsImpl::PrepareProfile() has set |delegate_| when Chrome is killed
    522   // during shutdown in tests -- see http://crosbug.com/18269.  Replace this
    523   // 'if' statement with a CHECK(delegate_) once the underlying issue is
    524   // resolved.
    525   if (delegate_)
    526     delegate_->OnProfilePrepared(user_profile);
    527 }
    528 
    529 void LoginUtilsImpl::InitRlzDelayed(Profile* user_profile) {
    530 #if defined(ENABLE_RLZ)
    531   if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand)) {
    532     // Read brand code asynchronously from an OEM file and repost ourselves.
    533     google_util::chromeos::SetBrandFromFile(
    534         base::Bind(&LoginUtilsImpl::InitRlzDelayed, AsWeakPtr(), user_profile));
    535     return;
    536   }
    537   base::PostTaskAndReplyWithResult(
    538       base::WorkerPool::GetTaskRunner(false),
    539       FROM_HERE,
    540       base::Bind(&base::PathExists, GetRlzDisabledFlagPath()),
    541       base::Bind(&LoginUtilsImpl::InitRlz, AsWeakPtr(), user_profile));
    542 #endif
    543 }
    544 
    545 void LoginUtilsImpl::InitRlz(Profile* user_profile, bool disabled) {
    546 #if defined(ENABLE_RLZ)
    547   PrefService* local_state = g_browser_process->local_state();
    548   if (disabled) {
    549     // Empty brand code means an organic install (no RLZ pings are sent).
    550     google_util::chromeos::ClearBrandForCurrentSession();
    551   }
    552   if (disabled != local_state->GetBoolean(prefs::kRLZDisabled)) {
    553     // When switching to RLZ enabled/disabled state, clear all recorded events.
    554     RLZTracker::ClearRlzState();
    555     local_state->SetBoolean(prefs::kRLZDisabled, disabled);
    556   }
    557   // Init the RLZ library.
    558   int ping_delay = user_profile->GetPrefs()->GetInteger(
    559       first_run::GetPingDelayPrefName().c_str());
    560   // Negative ping delay means to send ping immediately after a first search is
    561   // recorded.
    562   RLZTracker::InitRlzFromProfileDelayed(
    563       user_profile, UserManager::Get()->IsCurrentUserNew(),
    564       ping_delay < 0, base::TimeDelta::FromMilliseconds(abs(ping_delay)));
    565   if (delegate_)
    566     delegate_->OnRlzInitialized(user_profile);
    567 #endif
    568 }
    569 
    570 void LoginUtilsImpl::StartSignedInServices(Profile* user_profile) {
    571   // Fetch/Create the SigninManager - this will cause the TokenService to load
    572   // tokens for the currently signed-in user if the SigninManager hasn't
    573   // already been initialized.
    574   SigninManagerBase* signin =
    575       SigninManagerFactory::GetForProfile(user_profile);
    576   DCHECK(signin);
    577   // Make sure SigninManager is connected to our current user (this should
    578   // happen automatically because we set kGoogleServicesUsername in
    579   // OnProfileCreated()).
    580   DCHECK_EQ(UserManager::Get()->GetLoggedInUser()->display_email(),
    581             signin->GetAuthenticatedUsername());
    582   static bool initialized = false;
    583   if (!initialized) {
    584     initialized = true;
    585     // Notify the sync service that signin was successful. Note: Since the sync
    586     // service is lazy-initialized, we need to make sure it has been created.
    587     ProfileSyncService* sync_service =
    588         ProfileSyncServiceFactory::GetInstance()->GetForProfile(user_profile);
    589     // We may not always have a passphrase (for example, on a restart after a
    590     // browser crash). Only notify the sync service if we have a passphrase,
    591     // so it can do any required re-encryption.
    592     if (!user_context_.password.empty() && sync_service) {
    593       GoogleServiceSigninSuccessDetails details(
    594           signin->GetAuthenticatedUsername(),
    595           user_context_.password);
    596       content::NotificationService::current()->Notify(
    597           chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
    598           content::Source<Profile>(user_profile),
    599           content::Details<const GoogleServiceSigninSuccessDetails>(&details));
    600     }
    601   }
    602   user_context_.password.clear();
    603   user_context_.auth_code.clear();
    604 }
    605 
    606 void LoginUtilsImpl::RespectLocalePreference(Profile* profile) {
    607   DCHECK(profile != NULL);
    608   PrefService* prefs = profile->GetPrefs();
    609   DCHECK(prefs != NULL);
    610   if (g_browser_process == NULL)
    611     return;
    612 
    613   std::string pref_locale = prefs->GetString(prefs::kApplicationLocale);
    614   if (pref_locale.empty())
    615     pref_locale = prefs->GetString(prefs::kApplicationLocaleBackup);
    616   if (pref_locale.empty())
    617     pref_locale = g_browser_process->GetApplicationLocale();
    618   DCHECK(!pref_locale.empty());
    619   profile->ChangeAppLocale(pref_locale, Profile::APP_LOCALE_CHANGED_VIA_LOGIN);
    620   // Here we don't enable keyboard layouts. Input methods are set up when
    621   // the user first logs in. Then the user may customize the input methods.
    622   // Hence changing input methods here, just because the user's UI language
    623   // is different from the login screen UI language, is not desirable. Note
    624   // that input method preferences are synced, so users can use their
    625   // farovite input methods as soon as the preferences are synced.
    626   LanguageSwitchMenu::SwitchLanguage(pref_locale);
    627 }
    628 
    629 void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
    630   VLOG(1) << "Completing incognito login";
    631 
    632   // For guest session we ask session manager to restart Chrome with --bwsi
    633   // flag. We keep only some of the arguments of this process.
    634   const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
    635   CommandLine command_line(browser_command_line.GetProgram());
    636   std::string cmd_line_str = GetOffTheRecordCommandLine(start_url,
    637                                                         browser_command_line,
    638                                                         &command_line);
    639 
    640   RestartChrome(cmd_line_str);
    641 }
    642 
    643 void LoginUtilsImpl::SetFirstLoginPrefs(PrefService* prefs) {
    644   VLOG(1) << "Setting first login prefs";
    645   BootTimesLoader* btl = BootTimesLoader::Get();
    646   std::string locale = g_browser_process->GetApplicationLocale();
    647 
    648   // First, we'll set kLanguagePreloadEngines.
    649   input_method::InputMethodManager* manager =
    650       input_method::InputMethodManager::Get();
    651   std::vector<std::string> input_method_ids;
    652   manager->GetInputMethodUtil()->GetFirstLoginInputMethodIds(
    653       locale, manager->GetCurrentInputMethod(), &input_method_ids);
    654   // Save the input methods in the user's preferences.
    655   StringPrefMember language_preload_engines;
    656   language_preload_engines.Init(prefs::kLanguagePreloadEngines,
    657                                 prefs);
    658   language_preload_engines.SetValue(JoinString(input_method_ids, ','));
    659   btl->AddLoginTimeMarker("IMEStarted", false);
    660 
    661   // Second, we'll set kLanguagePreferredLanguages.
    662   std::vector<std::string> language_codes;
    663   // The current locale should be on the top.
    664   language_codes.push_back(locale);
    665 
    666   // Add input method IDs based on the input methods, as there may be
    667   // input methods that are unrelated to the current locale. Example: the
    668   // hardware keyboard layout xkb:us::eng is used for logging in, but the
    669   // UI language is set to French. In this case, we should set "fr,en"
    670   // to the preferred languages preference.
    671   std::vector<std::string> candidates;
    672   manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds(
    673       input_method_ids, &candidates);
    674   for (size_t i = 0; i < candidates.size(); ++i) {
    675     const std::string& candidate = candidates[i];
    676     // Skip if it's already in language_codes.
    677     if (std::count(language_codes.begin(), language_codes.end(),
    678                    candidate) == 0) {
    679       language_codes.push_back(candidate);
    680     }
    681   }
    682   // Save the preferred languages in the user's preferences.
    683   StringPrefMember language_preferred_languages;
    684   language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
    685                                     prefs);
    686   language_preferred_languages.SetValue(JoinString(language_codes, ','));
    687 }
    688 
    689 scoped_refptr<Authenticator> LoginUtilsImpl::CreateAuthenticator(
    690     LoginStatusConsumer* consumer) {
    691   // Screen locker needs new Authenticator instance each time.
    692   if (ScreenLocker::default_screen_locker()) {
    693     if (authenticator_.get())
    694       authenticator_->SetConsumer(NULL);
    695     authenticator_ = NULL;
    696   }
    697 
    698   if (authenticator_.get() == NULL) {
    699     authenticator_ = new ParallelAuthenticator(consumer);
    700   } else {
    701     // TODO(nkostylev): Fix this hack by improving Authenticator dependencies.
    702     authenticator_->SetConsumer(consumer);
    703   }
    704   return authenticator_;
    705 }
    706 
    707 void LoginUtilsImpl::RestoreAuthenticationSession(Profile* user_profile) {
    708   // We don't need to restore session for demo/guest/stub/public account users.
    709   if (!UserManager::Get()->IsUserLoggedIn() ||
    710       UserManager::Get()->IsLoggedInAsGuest() ||
    711       UserManager::Get()->IsLoggedInAsPublicAccount() ||
    712       UserManager::Get()->IsLoggedInAsDemoUser() ||
    713       UserManager::Get()->IsLoggedInAsStub()) {
    714     return;
    715   }
    716 
    717   if (!net::NetworkChangeNotifier::IsOffline()) {
    718     should_restore_auth_session_ = false;
    719     RestoreAuthSession(user_profile, false);
    720   } else {
    721     // Even if we're online we should wait till initial
    722     // OnConnectionTypeChanged() call. Otherwise starting fetchers too early may
    723     // end up cancelling all request when initial network connection type is
    724     // processed. See http://crbug.com/121643.
    725     should_restore_auth_session_ = true;
    726   }
    727 }
    728 
    729 void LoginUtilsImpl::StopBackgroundFetchers() {
    730   login_manager_.reset();
    731 }
    732 
    733 void LoginUtilsImpl::OnCompletedAuthentication(Profile* user_profile) {
    734   StartSignedInServices(user_profile);
    735 }
    736 
    737 void LoginUtilsImpl::OnNewRefreshTokenAvaiable(Profile* user_profile) {
    738   // Check if we were waiting to restart chrome.
    739   if (!exit_after_session_restore_)
    740     return;
    741 
    742   // Mark user auth token status as valid.
    743   UserManager::Get()->SaveUserOAuthStatus(
    744       UserManager::Get()->GetLoggedInUser()->email(),
    745       User::OAUTH2_TOKEN_STATUS_VALID);
    746 
    747   LOG(WARNING) << "Exiting after new refresh token fetched";
    748   // We need to exit cleanly in this case to make sure OAuth2 RT is actually
    749   // saved.
    750   chrome::ExitCleanly();
    751 }
    752 
    753 void LoginUtilsImpl::OnCompletedMergeSession() {
    754   UserManager::Get()->SetMergeSessionState(UserManager::MERGE_STATUS_DONE);
    755 }
    756 
    757 void LoginUtilsImpl::OnFoundStoredTokens() {
    758   // We don't need authenticator instance any more since its cookie jar
    759   // is not going to needed to mint OAuth tokens. Reset it so that
    760   // ScreenLocker would create a separate instance.
    761   authenticator_ = NULL;
    762 }
    763 
    764 void LoginUtilsImpl::OnConnectionTypeChanged(
    765     net::NetworkChangeNotifier::ConnectionType type) {
    766   if (!login_manager_.get())
    767     return;
    768 
    769   if (type != net::NetworkChangeNotifier::CONNECTION_NONE &&
    770       UserManager::Get()->IsUserLoggedIn()) {
    771     if (login_manager_->state() ==
    772             OAuthLoginManager::SESSION_RESTORE_IN_PROGRESS) {
    773       // If we come online for the first time after successful offline login,
    774       // we need to kick off OAuth token verification process again.
    775       login_manager_->ContinueSessionRestore();
    776     } else if (should_restore_auth_session_) {
    777       should_restore_auth_session_ = false;
    778       Profile* user_profile = ProfileManager::GetDefaultProfile();
    779       RestoreAuthSession(user_profile, has_web_auth_cookies_);
    780     }
    781   }
    782 }
    783 
    784 void LoginUtilsImpl::AttemptExit(Profile* profile) {
    785   if (!login_manager_.get() ||
    786       session_restore_strategy_ !=
    787           OAuthLoginManager::RESTORE_FROM_COOKIE_JAR) {
    788     chrome::ExitCleanly();
    789     return;
    790   }
    791 
    792   // We can't really quit if the session restore process that mints new
    793   // refresh token is still in progress.
    794   if (login_manager_->state() !=
    795           OAuthLoginManager::SESSION_RESTORE_IN_PROGRESS) {
    796     chrome::ExitCleanly();
    797     return;
    798   }
    799 
    800   LOG(WARNING) << "Attempting browser restart during session restore.";
    801   exit_after_session_restore_ = true;
    802 }
    803 
    804 // static
    805 void LoginUtils::RegisterPrefs(PrefRegistrySimple* registry) {
    806   registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
    807   registry->RegisterStringPref(prefs::kRLZBrand, std::string());
    808   registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
    809 }
    810 
    811 // static
    812 LoginUtils* LoginUtils::Get() {
    813   return LoginUtilsWrapper::GetInstance()->get();
    814 }
    815 
    816 // static
    817 void LoginUtils::Set(LoginUtils* mock) {
    818   LoginUtilsWrapper::GetInstance()->reset(mock);
    819 }
    820 
    821 // static
    822 bool LoginUtils::IsWhitelisted(const std::string& username) {
    823   CrosSettings* cros_settings = CrosSettings::Get();
    824   bool allow_new_user = false;
    825   cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
    826   if (allow_new_user)
    827     return true;
    828   return cros_settings->FindEmailInList(kAccountsPrefUsers, username);
    829 }
    830 
    831 }  // namespace chromeos
    832