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