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/existing_user_controller.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/callback.h" 12 #include "base/command_line.h" 13 #include "base/logging.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/metrics/histogram.h" 17 #include "base/prefs/pref_service.h" 18 #include "base/strings/string_util.h" 19 #include "base/strings/stringprintf.h" 20 #include "base/strings/utf_string_conversions.h" 21 #include "base/values.h" 22 #include "base/version.h" 23 #include "chrome/browser/accessibility/accessibility_events.h" 24 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/chrome_notification_types.h" 26 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" 27 #include "chrome/browser/chromeos/boot_times_loader.h" 28 #include "chrome/browser/chromeos/customization_document.h" 29 #include "chrome/browser/chromeos/first_run/first_run.h" 30 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" 31 #include "chrome/browser/chromeos/login/helper.h" 32 #include "chrome/browser/chromeos/login/login_display_host.h" 33 #include "chrome/browser/chromeos/login/login_utils.h" 34 #include "chrome/browser/chromeos/login/startup_utils.h" 35 #include "chrome/browser/chromeos/login/user_manager.h" 36 #include "chrome/browser/chromeos/login/wizard_controller.h" 37 #include "chrome/browser/chromeos/policy/device_local_account.h" 38 #include "chrome/browser/chromeos/profiles/profile_helper.h" 39 #include "chrome/browser/chromeos/settings/cros_settings.h" 40 #include "chrome/browser/google/google_util.h" 41 #include "chrome/browser/prefs/session_startup_pref.h" 42 #include "chrome/common/chrome_switches.h" 43 #include "chrome/common/chrome_version_info.h" 44 #include "chrome/common/pref_names.h" 45 #include "chrome/common/url_constants.h" 46 #include "chromeos/chromeos_switches.h" 47 #include "chromeos/dbus/dbus_thread_manager.h" 48 #include "chromeos/dbus/power_manager_client.h" 49 #include "chromeos/dbus/session_manager_client.h" 50 #include "chromeos/settings/cros_settings_names.h" 51 #include "components/policy/core/common/policy_service.h" 52 #include "content/public/browser/browser_thread.h" 53 #include "content/public/browser/notification_service.h" 54 #include "content/public/browser/notification_types.h" 55 #include "content/public/browser/user_metrics.h" 56 #include "google_apis/gaia/gaia_auth_util.h" 57 #include "google_apis/gaia/google_service_auth_error.h" 58 #include "grit/generated_resources.h" 59 #include "net/http/http_auth_cache.h" 60 #include "net/http/http_network_session.h" 61 #include "net/http/http_transaction_factory.h" 62 #include "net/url_request/url_request_context.h" 63 #include "net/url_request/url_request_context_getter.h" 64 #include "ui/base/accessibility/accessibility_types.h" 65 #include "ui/base/l10n/l10n_util.h" 66 #include "ui/views/widget/widget.h" 67 68 namespace chromeos { 69 70 namespace { 71 72 // URL for account creation. 73 const char kCreateAccountURL[] = 74 "https://accounts.google.com/NewAccount?service=mail"; 75 76 // ChromeVox tutorial URL (used in place of "getting started" url when 77 // accessibility is enabled). 78 const char kChromeVoxTutorialURLPattern[] = 79 "http://www.chromevox.com/tutorial/index.html?lang=%s"; 80 81 // Delay for transferring the auth cache to the system profile. 82 const long int kAuthCacheTransferDelayMs = 2000; 83 84 // Delay for restarting the ui if safe-mode login has failed. 85 const long int kSafeModeRestartUiDelayMs = 30000; 86 87 // Makes a call to the policy subsystem to reload the policy when we detect 88 // authentication change. 89 void RefreshPoliciesOnUIThread() { 90 if (g_browser_process->policy_service()) 91 g_browser_process->policy_service()->RefreshPolicies(base::Closure()); 92 } 93 94 // Copies any authentication details that were entered in the login profile in 95 // the mail profile to make sure all subsystems of Chrome can access the network 96 // with the provided authentication which are possibly for a proxy server. 97 void TransferContextAuthenticationsOnIOThread( 98 net::URLRequestContextGetter* default_profile_context_getter, 99 net::URLRequestContextGetter* browser_process_context_getter) { 100 net::HttpAuthCache* new_cache = 101 browser_process_context_getter->GetURLRequestContext()-> 102 http_transaction_factory()->GetSession()->http_auth_cache(); 103 net::HttpAuthCache* old_cache = 104 default_profile_context_getter->GetURLRequestContext()-> 105 http_transaction_factory()->GetSession()->http_auth_cache(); 106 new_cache->UpdateAllFrom(*old_cache); 107 VLOG(1) << "Main request context populated with authentication data."; 108 // Last but not least tell the policy subsystem to refresh now as it might 109 // have been stuck until now too. 110 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 111 base::Bind(&RefreshPoliciesOnUIThread)); 112 } 113 114 } // namespace 115 116 // static 117 ExistingUserController* ExistingUserController::current_controller_ = NULL; 118 119 //////////////////////////////////////////////////////////////////////////////// 120 // ExistingUserController, public: 121 122 ExistingUserController::ExistingUserController(LoginDisplayHost* host) 123 : login_status_consumer_(NULL), 124 host_(host), 125 login_display_(host_->CreateLoginDisplay(this)), 126 num_login_attempts_(0), 127 cros_settings_(CrosSettings::Get()), 128 weak_factory_(this), 129 offline_failed_(false), 130 is_login_in_progress_(false), 131 password_changed_(false), 132 do_auto_enrollment_(false), 133 signin_screen_ready_(false), 134 network_state_helper_(new login::NetworkStateHelper) { 135 DCHECK(current_controller_ == NULL); 136 current_controller_ = this; 137 138 registrar_.Add(this, 139 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, 140 content::NotificationService::AllSources()); 141 registrar_.Add(this, 142 chrome::NOTIFICATION_USER_LIST_CHANGED, 143 content::NotificationService::AllSources()); 144 registrar_.Add(this, 145 chrome::NOTIFICATION_AUTH_SUPPLIED, 146 content::NotificationService::AllSources()); 147 registrar_.Add(this, 148 chrome::NOTIFICATION_SESSION_STARTED, 149 content::NotificationService::AllSources()); 150 show_user_names_subscription_ = cros_settings_->AddSettingsObserver( 151 kAccountsPrefShowUserNamesOnSignIn, 152 base::Bind(&ExistingUserController::DeviceSettingsChanged, 153 base::Unretained(this))); 154 allow_new_user_subscription_ = cros_settings_->AddSettingsObserver( 155 kAccountsPrefAllowNewUser, 156 base::Bind(&ExistingUserController::DeviceSettingsChanged, 157 base::Unretained(this))); 158 allow_guest_subscription_ = cros_settings_->AddSettingsObserver( 159 kAccountsPrefAllowGuest, 160 base::Bind(&ExistingUserController::DeviceSettingsChanged, 161 base::Unretained(this))); 162 users_subscription_ = cros_settings_->AddSettingsObserver( 163 kAccountsPrefUsers, 164 base::Bind(&ExistingUserController::DeviceSettingsChanged, 165 base::Unretained(this))); 166 local_account_auto_login_id_subscription_ = 167 cros_settings_->AddSettingsObserver( 168 kAccountsPrefDeviceLocalAccountAutoLoginId, 169 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin, 170 base::Unretained(this))); 171 local_account_auto_login_delay_subscription_ = 172 cros_settings_->AddSettingsObserver( 173 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 174 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin, 175 base::Unretained(this))); 176 } 177 178 void ExistingUserController::Init(const UserList& users) { 179 time_init_ = base::Time::Now(); 180 UpdateLoginDisplay(users); 181 ConfigurePublicSessionAutoLogin(); 182 183 DBusThreadManager::Get()->GetSessionManagerClient()->EmitLoginPromptReady(); 184 } 185 186 void ExistingUserController::UpdateLoginDisplay(const UserList& users) { 187 bool show_users_on_signin; 188 UserList filtered_users; 189 190 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, 191 &show_users_on_signin); 192 if (show_users_on_signin) { 193 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 194 // TODO(xiyuan): Clean user profile whose email is not in whitelist. 195 bool meets_locally_managed_requirements = 196 (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED || 197 UserManager::Get()->AreLocallyManagedUsersAllowed(); 198 bool meets_whitelist_requirements = 199 LoginUtils::IsWhitelisted((*it)->email(), NULL) || 200 (*it)->GetType() != User::USER_TYPE_REGULAR; 201 if (meets_locally_managed_requirements && meets_whitelist_requirements) { 202 filtered_users.push_back(*it); 203 } 204 } 205 } 206 207 // If no user pods are visible, fallback to single new user pod which will 208 // have guest session link. 209 bool show_guest; 210 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest); 211 bool show_users; 212 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_users); 213 show_guest &= !filtered_users.empty(); 214 bool show_new_user = true; 215 login_display_->set_parent_window(GetNativeWindow()); 216 login_display_->Init(filtered_users, show_guest, show_users, show_new_user); 217 host_->OnPreferencesChanged(); 218 } 219 220 void ExistingUserController::DoAutoEnrollment() { 221 do_auto_enrollment_ = true; 222 } 223 224 void ExistingUserController::ResumeLogin() { 225 // This means the user signed-in, then auto-enrollment used his credentials 226 // to enroll and succeeded. 227 resume_login_callback_.Run(); 228 resume_login_callback_.Reset(); 229 } 230 231 //////////////////////////////////////////////////////////////////////////////// 232 // ExistingUserController, content::NotificationObserver implementation: 233 // 234 235 void ExistingUserController::Observe( 236 int type, 237 const content::NotificationSource& source, 238 const content::NotificationDetails& details) { 239 if (type == chrome::NOTIFICATION_SESSION_STARTED) { 240 // Stop listening to any notification once session has started. 241 // Sign in screen objects are marked for deletion with DeleteSoon so 242 // make sure no object would be used after session has started. 243 // http://crbug.com/125276 244 registrar_.RemoveAll(); 245 return; 246 } 247 if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) { 248 DeviceSettingsChanged(); 249 return; 250 } 251 if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) { 252 // Possibly the user has authenticated against a proxy server and we might 253 // need the credentials for enrollment and other system requests from the 254 // main |g_browser_process| request context (see bug 255 // http://crosbug.com/24861). So we transfer any credentials to the global 256 // request context here. 257 // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent 258 // just after the UI is closed but before the new credentials were stored 259 // in the profile. Therefore we have to give it some time to make sure it 260 // has been updated before we copy it. 261 VLOG(1) << "Authentication was entered manually, possibly for proxyauth."; 262 scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter = 263 g_browser_process->system_request_context(); 264 Profile* signin_profile = ProfileHelper::GetSigninProfile(); 265 scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter = 266 signin_profile->GetRequestContext(); 267 DCHECK(browser_process_context_getter.get()); 268 DCHECK(signin_profile_context_getter.get()); 269 content::BrowserThread::PostDelayedTask( 270 content::BrowserThread::IO, FROM_HERE, 271 base::Bind(&TransferContextAuthenticationsOnIOThread, 272 signin_profile_context_getter, 273 browser_process_context_getter), 274 base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs)); 275 } 276 if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED) 277 return; 278 login_display_->OnUserImageChanged(*content::Details<User>(details).ptr()); 279 } 280 281 //////////////////////////////////////////////////////////////////////////////// 282 // ExistingUserController, private: 283 284 ExistingUserController::~ExistingUserController() { 285 LoginUtils::Get()->DelegateDeleted(this); 286 287 if (current_controller_ == this) { 288 current_controller_ = NULL; 289 } else { 290 NOTREACHED() << "More than one controller are alive."; 291 } 292 DCHECK(login_display_.get()); 293 } 294 295 //////////////////////////////////////////////////////////////////////////////// 296 // ExistingUserController, LoginDisplay::Delegate implementation: 297 // 298 299 void ExistingUserController::CancelPasswordChangedFlow() { 300 login_performer_.reset(NULL); 301 login_display_->SetUIEnabled(true); 302 StartPublicSessionAutoLoginTimer(); 303 } 304 305 void ExistingUserController::CreateAccount() { 306 content::RecordAction(content::UserMetricsAction("Login.CreateAccount")); 307 guest_mode_url_ = 308 google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL)); 309 LoginAsGuest(); 310 } 311 312 void ExistingUserController::CompleteLogin(const UserContext& user_context) { 313 login_display_->set_signin_completed(true); 314 if (!host_) { 315 // Complete login event was generated already from UI. Ignore notification. 316 return; 317 } 318 319 // Stop the auto-login timer when attempting login. 320 StopPublicSessionAutoLoginTimer(); 321 322 // Disable UI while loading user profile. 323 login_display_->SetUIEnabled(false); 324 325 if (!time_init_.is_null()) { 326 base::TimeDelta delta = base::Time::Now() - time_init_; 327 UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta); 328 time_init_ = base::Time(); // Reset to null. 329 } 330 331 host_->OnCompleteLogin(); 332 333 // Do an ownership check now to avoid auto-enrolling if the device has 334 // already been owned. 335 DeviceSettingsService::Get()->GetOwnershipStatusAsync( 336 base::Bind(&ExistingUserController::CompleteLoginInternal, 337 weak_factory_.GetWeakPtr(), 338 user_context)); 339 } 340 341 void ExistingUserController::CompleteLoginInternal( 342 const UserContext& user_context, 343 DeviceSettingsService::OwnershipStatus ownership_status) { 344 // Auto-enrollment must have made a decision by now. It's too late to enroll 345 // if the protocol isn't done at this point. 346 if (do_auto_enrollment_ && 347 ownership_status == DeviceSettingsService::OWNERSHIP_NONE) { 348 VLOG(1) << "Forcing auto-enrollment before completing login"; 349 // The only way to get out of the enrollment screen from now on is to either 350 // complete enrollment, or opt-out of it. So this controller shouldn't force 351 // enrollment again if it is reused for another sign-in. 352 do_auto_enrollment_ = false; 353 auto_enrollment_username_ = user_context.username; 354 resume_login_callback_ = base::Bind( 355 &ExistingUserController::PerformLogin, 356 weak_factory_.GetWeakPtr(), 357 user_context, LoginPerformer::AUTH_MODE_EXTENSION); 358 ShowEnrollmentScreen(true, user_context.username); 359 // Enable UI for the enrollment screen. SetUIEnabled(true) will post a 360 // request to show the sign-in screen again when invoked at the sign-in 361 // screen; invoke SetUIEnabled() after navigating to the enrollment screen. 362 login_display_->SetUIEnabled(true); 363 } else { 364 PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION); 365 } 366 } 367 368 base::string16 ExistingUserController::GetConnectedNetworkName() { 369 return network_state_helper_->GetCurrentNetworkName(); 370 } 371 372 bool ExistingUserController::IsSigninInProgress() const { 373 return is_login_in_progress_; 374 } 375 376 void ExistingUserController::Login(const UserContext& user_context) { 377 if ((user_context.username.empty() || user_context.password.empty()) && 378 user_context.auth_code.empty()) 379 return; 380 381 // Stop the auto-login timer when attempting login. 382 StopPublicSessionAutoLoginTimer(); 383 384 // Disable clicking on other windows. 385 login_display_->SetUIEnabled(false); 386 387 BootTimesLoader::Get()->RecordLoginAttempted(); 388 389 if (last_login_attempt_username_ != user_context.username) { 390 last_login_attempt_username_ = user_context.username; 391 num_login_attempts_ = 0; 392 // Also reset state variables, which are used to determine password change. 393 offline_failed_ = false; 394 online_succeeded_for_.clear(); 395 } 396 num_login_attempts_++; 397 PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL); 398 } 399 400 void ExistingUserController::PerformLogin( 401 const UserContext& user_context, 402 LoginPerformer::AuthorizationMode auth_mode) { 403 UserManager::Get()->GetUserFlow(last_login_attempt_username_)-> 404 set_host(host_); 405 406 // Disable UI while loading user profile. 407 login_display_->SetUIEnabled(false); 408 409 // Use the same LoginPerformer for subsequent login as it has state 410 // such as Authenticator instance. 411 if (!login_performer_.get() || num_login_attempts_ <= 1) { 412 LoginPerformer::Delegate* delegate = this; 413 if (login_performer_delegate_.get()) 414 delegate = login_performer_delegate_.get(); 415 // Only one instance of LoginPerformer should exist at a time. 416 login_performer_.reset(NULL); 417 login_performer_.reset(new LoginPerformer(delegate)); 418 } 419 420 is_login_in_progress_ = true; 421 if (gaia::ExtractDomainName(user_context.username) == 422 UserManager::kLocallyManagedUserDomain) { 423 login_performer_->LoginAsLocallyManagedUser( 424 UserContext(user_context.username, 425 user_context.password, 426 std::string())); // auth_code 427 } else { 428 login_performer_->PerformLogin(user_context, auth_mode); 429 } 430 SendAccessibilityAlert( 431 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN)); 432 } 433 434 void ExistingUserController::LoginAsRetailModeUser() { 435 // Stop the auto-login timer when attempting login. 436 StopPublicSessionAutoLoginTimer(); 437 438 // Disable clicking on other windows. 439 login_display_->SetUIEnabled(false); 440 // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once 441 // the enterprise policy wiring is done for retail mode. 442 443 // Only one instance of LoginPerformer should exist at a time. 444 login_performer_.reset(NULL); 445 login_performer_.reset(new LoginPerformer(this)); 446 is_login_in_progress_ = true; 447 login_performer_->LoginRetailMode(); 448 SendAccessibilityAlert( 449 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER)); 450 } 451 452 void ExistingUserController::LoginAsGuest() { 453 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn()) 454 return; 455 456 // Stop the auto-login timer when attempting login. 457 StopPublicSessionAutoLoginTimer(); 458 459 // Disable clicking on other windows. 460 login_display_->SetUIEnabled(false); 461 462 CrosSettingsProvider::TrustedStatus status = 463 cros_settings_->PrepareTrustedValues( 464 base::Bind(&ExistingUserController::LoginAsGuest, 465 weak_factory_.GetWeakPtr())); 466 // Must not proceed without signature verification. 467 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { 468 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1, 469 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); 470 // Reenable clicking on other windows and status area. 471 login_display_->SetUIEnabled(true); 472 StartPublicSessionAutoLoginTimer(); 473 display_email_.clear(); 474 return; 475 } else if (status != CrosSettingsProvider::TRUSTED) { 476 // Value of AllowNewUser setting is still not verified. 477 // Another attempt will be invoked after verification completion. 478 return; 479 } 480 481 bool allow_guest; 482 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest); 483 if (!allow_guest) { 484 // Disallowed. The UI should normally not show the guest pod but if for some 485 // reason this has been made available to the user here is the time to tell 486 // this nicely. 487 login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1, 488 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); 489 // Reenable clicking on other windows and status area. 490 login_display_->SetUIEnabled(true); 491 StartPublicSessionAutoLoginTimer(); 492 display_email_.clear(); 493 return; 494 } 495 496 // Only one instance of LoginPerformer should exist at a time. 497 login_performer_.reset(NULL); 498 login_performer_.reset(new LoginPerformer(this)); 499 is_login_in_progress_ = true; 500 login_performer_->LoginOffTheRecord(); 501 SendAccessibilityAlert( 502 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD)); 503 } 504 505 void ExistingUserController::MigrateUserData(const std::string& old_password) { 506 // LoginPerformer instance has state of the user so it should exist. 507 if (login_performer_.get()) 508 login_performer_->RecoverEncryptedData(old_password); 509 } 510 511 void ExistingUserController::LoginAsPublicAccount( 512 const std::string& username) { 513 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn()) 514 return; 515 516 // Stop the auto-login timer when attempting login. 517 StopPublicSessionAutoLoginTimer(); 518 519 // Disable clicking on other windows. 520 login_display_->SetUIEnabled(false); 521 522 CrosSettingsProvider::TrustedStatus status = 523 cros_settings_->PrepareTrustedValues( 524 base::Bind(&ExistingUserController::LoginAsPublicAccount, 525 weak_factory_.GetWeakPtr(), 526 username)); 527 // If device policy is permanently unavailable, logging into public accounts 528 // is not possible. 529 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { 530 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1, 531 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); 532 // Re-enable clicking on other windows. 533 login_display_->SetUIEnabled(true); 534 return; 535 } 536 537 // If device policy is not verified yet, this function will be called again 538 // when verification finishes. 539 if (status != CrosSettingsProvider::TRUSTED) 540 return; 541 542 // If there is no public account with the given |username|, logging in is not 543 // possible. 544 const User* user = UserManager::Get()->FindUser(username); 545 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) { 546 // Re-enable clicking on other windows. 547 login_display_->SetUIEnabled(true); 548 StartPublicSessionAutoLoginTimer(); 549 return; 550 } 551 552 // Only one instance of LoginPerformer should exist at a time. 553 login_performer_.reset(NULL); 554 login_performer_.reset(new LoginPerformer(this)); 555 is_login_in_progress_ = true; 556 login_performer_->LoginAsPublicAccount(username); 557 SendAccessibilityAlert( 558 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT)); 559 } 560 561 void ExistingUserController::LoginAsKioskApp(const std::string& app_id) { 562 host_->StartAppLaunch(app_id); 563 } 564 565 void ExistingUserController::OnSigninScreenReady() { 566 signin_screen_ready_ = true; 567 StartPublicSessionAutoLoginTimer(); 568 } 569 570 void ExistingUserController::OnUserSelected(const std::string& username) { 571 login_performer_.reset(NULL); 572 num_login_attempts_ = 0; 573 } 574 575 void ExistingUserController::OnStartEnterpriseEnrollment() { 576 DeviceSettingsService::Get()->GetOwnershipStatusAsync( 577 base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted, 578 weak_factory_.GetWeakPtr())); 579 } 580 581 void ExistingUserController::OnStartKioskEnableScreen() { 582 KioskAppManager::Get()->GetConsumerKioskModeStatus( 583 base::Bind(&ExistingUserController::OnConsumerKioskModeCheckCompleted, 584 weak_factory_.GetWeakPtr())); 585 } 586 587 void ExistingUserController::OnStartDeviceReset() { 588 ShowResetScreen(); 589 } 590 591 void ExistingUserController::OnStartKioskAutolaunchScreen() { 592 ShowKioskAutolaunchScreen(); 593 } 594 595 void ExistingUserController::ResyncUserData() { 596 // LoginPerformer instance has state of the user so it should exist. 597 if (login_performer_.get()) 598 login_performer_->ResyncEncryptedData(); 599 } 600 601 void ExistingUserController::SetDisplayEmail(const std::string& email) { 602 display_email_ = email; 603 } 604 605 void ExistingUserController::ShowWrongHWIDScreen() { 606 scoped_ptr<DictionaryValue> params; 607 host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass()); 608 login_display_->OnFadeOut(); 609 } 610 611 void ExistingUserController::Signout() { 612 NOTREACHED(); 613 } 614 615 void ExistingUserController::OnConsumerKioskModeCheckCompleted( 616 KioskAppManager::ConsumerKioskModeStatus status) { 617 if (status == KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE) 618 ShowKioskEnableScreen(); 619 } 620 621 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted( 622 DeviceSettingsService::OwnershipStatus status) { 623 if (status == DeviceSettingsService::OWNERSHIP_NONE) { 624 ShowEnrollmentScreen(false, std::string()); 625 } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) { 626 // On a device that is already owned we might want to allow users to 627 // re-enroll if the policy information is invalid. 628 CrosSettingsProvider::TrustedStatus trusted_status = 629 CrosSettings::Get()->PrepareTrustedValues( 630 base::Bind( 631 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted, 632 weak_factory_.GetWeakPtr(), status)); 633 if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { 634 ShowEnrollmentScreen(false, std::string()); 635 } 636 } else { 637 // OwnershipService::GetStatusAsync is supposed to return either 638 // OWNERSHIP_NONE or OWNERSHIP_TAKEN. 639 NOTREACHED(); 640 } 641 } 642 643 void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment, 644 const std::string& user) { 645 scoped_ptr<DictionaryValue> params; 646 if (is_auto_enrollment) { 647 params.reset(new DictionaryValue()); 648 params->SetBoolean("is_auto_enrollment", true); 649 params->SetString("user", user); 650 } 651 host_->StartWizard(WizardController::kEnrollmentScreenName, 652 params.Pass()); 653 login_display_->OnFadeOut(); 654 } 655 656 void ExistingUserController::ShowResetScreen() { 657 scoped_ptr<DictionaryValue> params; 658 host_->StartWizard(WizardController::kResetScreenName, params.Pass()); 659 login_display_->OnFadeOut(); 660 } 661 662 void ExistingUserController::ShowKioskEnableScreen() { 663 scoped_ptr<DictionaryValue> params; 664 host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass()); 665 login_display_->OnFadeOut(); 666 } 667 668 void ExistingUserController::ShowKioskAutolaunchScreen() { 669 scoped_ptr<DictionaryValue> params; 670 host_->StartWizard(WizardController::kKioskAutolaunchScreenName, 671 params.Pass()); 672 login_display_->OnFadeOut(); 673 } 674 675 void ExistingUserController::ShowTPMError() { 676 login_display_->SetUIEnabled(false); 677 login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR); 678 } 679 680 //////////////////////////////////////////////////////////////////////////////// 681 // ExistingUserController, LoginPerformer::Delegate implementation: 682 // 683 684 void ExistingUserController::OnLoginFailure(const LoginFailure& failure) { 685 is_login_in_progress_ = false; 686 offline_failed_ = true; 687 688 guest_mode_url_ = GURL::EmptyGURL(); 689 std::string error = failure.GetErrorString(); 690 691 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)-> 692 HandleLoginFailure(failure)) { 693 login_display_->SetUIEnabled(true); 694 return; 695 } 696 697 if (failure.reason() == LoginFailure::OWNER_REQUIRED) { 698 ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error); 699 content::BrowserThread::PostDelayedTask( 700 content::BrowserThread::UI, FROM_HERE, 701 base::Bind(&SessionManagerClient::StopSession, 702 base::Unretained(DBusThreadManager::Get()-> 703 GetSessionManagerClient())), 704 base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs)); 705 } else if (failure.reason() == LoginFailure::TPM_ERROR) { 706 ShowTPMError(); 707 } else if (!online_succeeded_for_.empty()) { 708 ShowGaiaPasswordChanged(online_succeeded_for_); 709 } else { 710 // Check networking after trying to login in case user is 711 // cached locally or the local admin account. 712 bool is_known_user = 713 UserManager::Get()->IsKnownUser(last_login_attempt_username_); 714 if (!network_state_helper_->IsConnected()) { 715 if (is_known_user) 716 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error); 717 else 718 ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error); 719 } else { 720 // TODO(nkostylev): Cleanup rest of ClientLogin related code. 721 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED && 722 failure.error().state() == 723 GoogleServiceAuthError::HOSTED_NOT_ALLOWED) { 724 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error); 725 } else { 726 if (!is_known_user) 727 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error); 728 else 729 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error); 730 } 731 } 732 // Reenable clicking on other windows and status area. 733 login_display_->SetUIEnabled(true); 734 login_display_->ClearAndEnablePassword(); 735 StartPublicSessionAutoLoginTimer(); 736 } 737 738 // Reset user flow to default, so that special flow will not affect next 739 // attempt. 740 UserManager::Get()->ResetUserFlow(last_login_attempt_username_); 741 742 if (login_status_consumer_) 743 login_status_consumer_->OnLoginFailure(failure); 744 745 // Clear the recorded displayed email so it won't affect any future attempts. 746 display_email_.clear(); 747 } 748 749 void ExistingUserController::OnLoginSuccess(const UserContext& user_context) { 750 is_login_in_progress_ = false; 751 offline_failed_ = false; 752 login_display_->set_signin_completed(true); 753 754 StopPublicSessionAutoLoginTimer(); 755 756 bool has_cookies = 757 login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION && 758 user_context.auth_code.empty(); 759 760 // Login performer will be gone so cache this value to use 761 // once profile is loaded. 762 password_changed_ = login_performer_->password_changed(); 763 764 // LoginPerformer instance will delete itself once online auth result is OK. 765 // In case of failure it'll bring up ScreenLock and ask for 766 // correct password/display error message. 767 // Even in case when following online,offline protocol and returning 768 // requests_pending = false, let LoginPerformer delete itself. 769 login_performer_->set_delegate(NULL); 770 ignore_result(login_performer_.release()); 771 772 // Will call OnProfilePrepared() in the end. 773 LoginUtils::Get()->PrepareProfile(user_context, 774 display_email_, 775 has_cookies, 776 false, // Start session for user. 777 this); 778 779 display_email_.clear(); 780 781 // Notify LoginDisplay to allow it provide visual feedback to user. 782 login_display_->OnLoginSuccess(user_context.username); 783 } 784 785 void ExistingUserController::OnProfilePrepared(Profile* profile) { 786 // Reenable clicking on other windows and status area. 787 login_display_->SetUIEnabled(true); 788 789 UserManager* user_manager = UserManager::Get(); 790 if (user_manager->IsCurrentUserNew() && 791 user_manager->IsLoggedInAsLocallyManagedUser()) { 792 // Supervised users should launch into empty desktop on first run. 793 CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch); 794 } 795 796 if (user_manager->IsCurrentUserNew() && 797 !user_manager->GetCurrentUserFlow()->ShouldSkipPostLoginScreens() && 798 !WizardController::default_controller()->skip_post_login_screens()) { 799 // Don't specify start URLs if the administrator has configured the start 800 // URLs via policy. 801 if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs())) 802 InitializeStartUrls(); 803 804 // Mark the device as registered., i.e. the second part of OOBE as 805 // completed. 806 if (!StartupUtils::IsDeviceRegistered()) 807 StartupUtils::MarkDeviceRegistered(); 808 809 if (CommandLine::ForCurrentProcess()->HasSwitch( 810 chromeos::switches::kOobeSkipPostLogin)) { 811 LoginUtils::Get()->DoBrowserLaunch(profile, host_); 812 host_ = NULL; 813 } else { 814 ActivateWizard(WizardController::kTermsOfServiceScreenName); 815 } 816 } else { 817 LoginUtils::Get()->DoBrowserLaunch(profile, host_); 818 host_ = NULL; 819 } 820 // Inform |login_status_consumer_| about successful login. 821 if (login_status_consumer_) 822 login_status_consumer_->OnLoginSuccess(UserContext()); 823 login_display_->OnFadeOut(); 824 } 825 826 void ExistingUserController::OnOffTheRecordLoginSuccess() { 827 is_login_in_progress_ = false; 828 offline_failed_ = false; 829 830 // Mark the device as registered., i.e. the second part of OOBE as completed. 831 if (!StartupUtils::IsDeviceRegistered()) 832 StartupUtils::MarkDeviceRegistered(); 833 834 LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_); 835 836 if (login_status_consumer_) 837 login_status_consumer_->OnOffTheRecordLoginSuccess(); 838 } 839 840 void ExistingUserController::OnPasswordChangeDetected() { 841 is_login_in_progress_ = false; 842 offline_failed_ = false; 843 844 // Must not proceed without signature verification. 845 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues( 846 base::Bind(&ExistingUserController::OnPasswordChangeDetected, 847 weak_factory_.GetWeakPtr()))) { 848 // Value of owner email is still not verified. 849 // Another attempt will be invoked after verification completion. 850 return; 851 } 852 853 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)-> 854 HandlePasswordChangeDetected()) { 855 return; 856 } 857 858 // True if user has already made an attempt to enter old password and failed. 859 bool show_invalid_old_password_error = 860 login_performer_->password_changed_callback_count() > 1; 861 862 // Note: We allow owner using "full sync" mode which will recreate 863 // cryptohome and deal with owner private key being lost. This also allows 864 // us to recover from a lost owner password/homedir. 865 // TODO(gspencer): We shouldn't have to erase stateful data when 866 // doing this. See http://crosbug.com/9115 http://crosbug.com/7792 867 login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error); 868 869 if (login_status_consumer_) 870 login_status_consumer_->OnPasswordChangeDetected(); 871 872 display_email_.clear(); 873 } 874 875 void ExistingUserController::WhiteListCheckFailed(const std::string& email) { 876 is_login_in_progress_ = false; 877 offline_failed_ = false; 878 879 ShowError(IDS_LOGIN_ERROR_WHITELIST, email); 880 881 // Reenable clicking on other windows and status area. 882 login_display_->SetUIEnabled(true); 883 login_display_->ShowSigninUI(email); 884 885 if (login_status_consumer_) { 886 login_status_consumer_->OnLoginFailure(LoginFailure( 887 LoginFailure::WHITELIST_CHECK_FAILED)); 888 } 889 890 display_email_.clear(); 891 892 StartPublicSessionAutoLoginTimer(); 893 } 894 895 void ExistingUserController::PolicyLoadFailed() { 896 ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, ""); 897 898 // Reenable clicking on other windows and status area. 899 is_login_in_progress_ = false; 900 offline_failed_ = false; 901 login_display_->SetUIEnabled(true); 902 903 display_email_.clear(); 904 905 // Policy load failure stops login attempts -- restart the timer. 906 StartPublicSessionAutoLoginTimer(); 907 } 908 909 void ExistingUserController::OnOnlineChecked(const std::string& username, 910 bool success) { 911 if (success && last_login_attempt_username_ == username) { 912 online_succeeded_for_ = username; 913 // Wait for login attempt to end, if it hasn't yet. 914 if (offline_failed_ && !is_login_in_progress_) 915 ShowGaiaPasswordChanged(username); 916 } 917 } 918 919 //////////////////////////////////////////////////////////////////////////////// 920 // ExistingUserController, private: 921 922 void ExistingUserController::DeviceSettingsChanged() { 923 if (host_ != NULL) { 924 // Signed settings or user list changed. Notify views and update them. 925 UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers()); 926 ConfigurePublicSessionAutoLogin(); 927 return; 928 } 929 } 930 931 void ExistingUserController::ActivateWizard(const std::string& screen_name) { 932 scoped_ptr<DictionaryValue> params; 933 host_->StartWizard(screen_name, params.Pass()); 934 } 935 936 void ExistingUserController::ConfigurePublicSessionAutoLogin() { 937 std::string auto_login_account_id; 938 cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId, 939 &auto_login_account_id); 940 const std::vector<policy::DeviceLocalAccount> device_local_accounts = 941 policy::GetDeviceLocalAccounts(cros_settings_); 942 943 public_session_auto_login_username_.clear(); 944 for (std::vector<policy::DeviceLocalAccount>::const_iterator 945 it = device_local_accounts.begin(); 946 it != device_local_accounts.end(); ++it) { 947 if (it->account_id == auto_login_account_id) { 948 public_session_auto_login_username_ = it->user_id; 949 break; 950 } 951 } 952 953 const User* user = 954 UserManager::Get()->FindUser(public_session_auto_login_username_); 955 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) 956 public_session_auto_login_username_.clear(); 957 958 if (!cros_settings_->GetInteger( 959 kAccountsPrefDeviceLocalAccountAutoLoginDelay, 960 &public_session_auto_login_delay_)) { 961 public_session_auto_login_delay_ = 0; 962 } 963 964 if (!public_session_auto_login_username_.empty()) 965 StartPublicSessionAutoLoginTimer(); 966 else 967 StopPublicSessionAutoLoginTimer(); 968 } 969 970 void ExistingUserController::ResetPublicSessionAutoLoginTimer() { 971 // Only restart the auto-login timer if it's already running. 972 if (auto_login_timer_ && auto_login_timer_->IsRunning()) { 973 StopPublicSessionAutoLoginTimer(); 974 StartPublicSessionAutoLoginTimer(); 975 } 976 } 977 978 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() { 979 CHECK(signin_screen_ready_ && 980 !is_login_in_progress_ && 981 !public_session_auto_login_username_.empty()); 982 LoginAsPublicAccount(public_session_auto_login_username_); 983 } 984 985 void ExistingUserController::StopPublicSessionAutoLoginTimer() { 986 if (auto_login_timer_) 987 auto_login_timer_->Stop(); 988 } 989 990 void ExistingUserController::StartPublicSessionAutoLoginTimer() { 991 if (!signin_screen_ready_ || 992 is_login_in_progress_ || 993 public_session_auto_login_username_.empty()) { 994 return; 995 } 996 997 // Start the auto-login timer. 998 if (!auto_login_timer_) 999 auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>); 1000 1001 auto_login_timer_->Start( 1002 FROM_HERE, 1003 base::TimeDelta::FromMilliseconds( 1004 public_session_auto_login_delay_), 1005 base::Bind( 1006 &ExistingUserController::OnPublicSessionAutoLoginTimerFire, 1007 weak_factory_.GetWeakPtr())); 1008 } 1009 1010 gfx::NativeWindow ExistingUserController::GetNativeWindow() const { 1011 return host_->GetNativeWindow(); 1012 } 1013 1014 void ExistingUserController::InitializeStartUrls() const { 1015 std::vector<std::string> start_urls; 1016 1017 const base::ListValue *urls; 1018 bool can_show_getstarted_guide = 1019 UserManager::Get()->IsLoggedInAsRegularUser(); 1020 if (UserManager::Get()->IsLoggedInAsDemoUser()) { 1021 if (CrosSettings::Get()->GetList(kStartUpUrls, &urls)) { 1022 // The retail mode user will get start URLs from a special policy if it is 1023 // set. 1024 for (base::ListValue::const_iterator it = urls->begin(); 1025 it != urls->end(); ++it) { 1026 std::string url; 1027 if ((*it)->GetAsString(&url)) 1028 start_urls.push_back(url); 1029 } 1030 } 1031 can_show_getstarted_guide = false; 1032 // Skip the default first-run behavior for public accounts. 1033 } else if (!UserManager::Get()->IsLoggedInAsPublicAccount()) { 1034 if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) { 1035 const char* url = kChromeVoxTutorialURLPattern; 1036 PrefService* prefs = g_browser_process->local_state(); 1037 const std::string current_locale = 1038 StringToLowerASCII(prefs->GetString(prefs::kApplicationLocale)); 1039 std::string vox_url = base::StringPrintf(url, current_locale.c_str()); 1040 start_urls.push_back(vox_url); 1041 can_show_getstarted_guide = false; 1042 } 1043 } 1044 1045 ServicesCustomizationDocument* customization = 1046 ServicesCustomizationDocument::GetInstance(); 1047 if (!ServicesCustomizationDocument::WasApplied() && 1048 customization->IsReady()) { 1049 // Since we don't use OEM start URL anymore, just mark as applied. 1050 customization->ApplyCustomization(); 1051 } 1052 1053 // Only show getting started guide for a new user. 1054 const bool should_show_getstarted_guide = 1055 UserManager::Get()->IsCurrentUserNew(); 1056 1057 if (can_show_getstarted_guide && should_show_getstarted_guide) { 1058 // Don't open default Chrome window if we're going to launch the first-run 1059 // app. Because we dont' want the first-run app to be hidden in the 1060 // background. 1061 CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch); 1062 first_run::MaybeLaunchDialogAfterSessionStart(); 1063 } else { 1064 for (size_t i = 0; i < start_urls.size(); ++i) { 1065 CommandLine::ForCurrentProcess()->AppendArg(start_urls[i]); 1066 } 1067 } 1068 } 1069 1070 void ExistingUserController::ShowError(int error_id, 1071 const std::string& details) { 1072 // TODO(dpolukhin): show detailed error info. |details| string contains 1073 // low level error info that is not localized and even is not user friendly. 1074 // For now just ignore it because error_text contains all required information 1075 // for end users, developers can see details string in Chrome logs. 1076 VLOG(1) << details; 1077 HelpAppLauncher::HelpTopic help_topic_id; 1078 bool is_offline = !network_state_helper_->IsConnected(); 1079 switch (login_performer_->error().state()) { 1080 case GoogleServiceAuthError::CONNECTION_FAILED: 1081 help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE; 1082 break; 1083 case GoogleServiceAuthError::ACCOUNT_DISABLED: 1084 help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED; 1085 break; 1086 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED: 1087 help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT; 1088 break; 1089 default: 1090 help_topic_id = is_offline ? 1091 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE : 1092 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT; 1093 break; 1094 } 1095 1096 login_display_->ShowError(error_id, num_login_attempts_, help_topic_id); 1097 } 1098 1099 void ExistingUserController::ShowGaiaPasswordChanged( 1100 const std::string& username) { 1101 // Invalidate OAuth token, since it can't be correct after password is 1102 // changed. 1103 UserManager::Get()->SaveUserOAuthStatus( 1104 username, 1105 User::OAUTH2_TOKEN_STATUS_INVALID); 1106 1107 login_display_->SetUIEnabled(true); 1108 login_display_->ShowGaiaPasswordChanged(username); 1109 } 1110 1111 void ExistingUserController::SendAccessibilityAlert( 1112 const std::string& alert_text) { 1113 AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text); 1114 SendControlAccessibilityNotification( 1115 ui::AccessibilityTypes::EVENT_VALUE_CHANGED, &event); 1116 } 1117 1118 } // namespace chromeos 1119