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