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