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