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