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