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