1 // Copyright (c) 2013 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/ui/webui/chromeos/login/signin_screen_handler.h" 6 7 #include <algorithm> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/command_line.h" 12 #include "base/debug/trace_event.h" 13 #include "base/location.h" 14 #include "base/logging.h" 15 #include "base/metrics/histogram.h" 16 #include "base/prefs/pref_registry_simple.h" 17 #include "base/prefs/pref_service.h" 18 #include "base/prefs/scoped_user_pref_update.h" 19 #include "base/strings/string16.h" 20 #include "base/strings/string_util.h" 21 #include "base/strings/stringprintf.h" 22 #include "base/strings/utf_string_conversions.h" 23 #include "base/sys_info.h" 24 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/browser_process_platform_part_chromeos.h" 26 #include "chrome/browser/browser_shutdown.h" 27 #include "chrome/browser/chrome_notification_types.h" 28 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 29 #include "chrome/browser/chromeos/boot_times_loader.h" 30 #include "chrome/browser/chromeos/input_method/input_method_util.h" 31 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" 32 #include "chrome/browser/chromeos/login/auth/key.h" 33 #include "chrome/browser/chromeos/login/auth/user_context.h" 34 #include "chrome/browser/chromeos/login/hwid_checker.h" 35 #include "chrome/browser/chromeos/login/lock/screen_locker.h" 36 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h" 37 #include "chrome/browser/chromeos/login/ui/login_display_host.h" 38 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" 39 #include "chrome/browser/chromeos/login/ui/webui_login_display.h" 40 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" 41 #include "chrome/browser/chromeos/login/users/user.h" 42 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" 43 #include "chrome/browser/chromeos/login/wizard_controller.h" 44 #include "chrome/browser/chromeos/net/network_portal_detector.h" 45 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 46 #include "chrome/browser/chromeos/profiles/profile_helper.h" 47 #include "chrome/browser/chromeos/settings/cros_settings.h" 48 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h" 49 #include "chrome/browser/io_thread.h" 50 #include "chrome/browser/profiles/profile.h" 51 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h" 52 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" 53 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h" 54 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" 55 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 56 #include "chrome/common/chrome_switches.h" 57 #include "chrome/common/pref_names.h" 58 #include "chrome/common/url_constants.h" 59 #include "chromeos/chromeos_switches.h" 60 #include "chromeos/dbus/dbus_thread_manager.h" 61 #include "chromeos/dbus/power_manager_client.h" 62 #include "chromeos/ime/ime_keyboard.h" 63 #include "chromeos/ime/input_method_manager.h" 64 #include "chromeos/network/network_state.h" 65 #include "chromeos/network/network_state_handler.h" 66 #include "content/public/browser/render_frame_host.h" 67 #include "content/public/browser/web_contents.h" 68 #include "google_apis/gaia/gaia_auth_util.h" 69 #include "grit/chromium_strings.h" 70 #include "grit/generated_resources.h" 71 #include "net/url_request/url_request_context_getter.h" 72 #include "third_party/cros_system_api/dbus/service_constants.h" 73 #include "ui/base/webui/web_ui_util.h" 74 #include "ui/gfx/image/image.h" 75 #include "ui/gfx/image/image_skia.h" 76 77 #if defined(USE_AURA) 78 #include "ash/shell.h" 79 #include "ash/wm/lock_state_controller.h" 80 #endif 81 82 using content::BrowserThread; 83 84 namespace { 85 86 // Max number of users to show. 87 const size_t kMaxUsers = 18; 88 89 // Timeout to delay first notification about offline state for a 90 // current network. 91 const int kOfflineTimeoutSec = 5; 92 93 // Timeout used to prevent infinite connecting to a flaky network. 94 const int kConnectingTimeoutSec = 60; 95 96 // Type of the login screen UI that is currently presented to user. 97 const char kSourceGaiaSignin[] = "gaia-signin"; 98 const char kSourceAccountPicker[] = "account-picker"; 99 100 static bool Contains(const std::vector<std::string>& container, 101 const std::string& value) { 102 return std::find(container.begin(), container.end(), value) != 103 container.end(); 104 } 105 106 } // namespace 107 108 namespace chromeos { 109 110 namespace { 111 112 bool IsOnline(NetworkStateInformer::State state, 113 ErrorScreenActor::ErrorReason reason) { 114 return state == NetworkStateInformer::ONLINE && 115 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED && 116 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT; 117 } 118 119 bool IsBehindCaptivePortal(NetworkStateInformer::State state, 120 ErrorScreenActor::ErrorReason reason) { 121 return state == NetworkStateInformer::CAPTIVE_PORTAL || 122 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED; 123 } 124 125 bool IsProxyError(NetworkStateInformer::State state, 126 ErrorScreenActor::ErrorReason reason, 127 net::Error frame_error) { 128 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED || 129 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED || 130 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED || 131 (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR && 132 (frame_error == net::ERR_PROXY_CONNECTION_FAILED || 133 frame_error == net::ERR_TUNNEL_CONNECTION_FAILED)); 134 } 135 136 bool IsSigninScreen(const OobeUI::Screen screen) { 137 return screen == OobeUI::SCREEN_GAIA_SIGNIN || 138 screen == OobeUI::SCREEN_ACCOUNT_PICKER; 139 } 140 141 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) { 142 return error_state == ErrorScreen::ERROR_STATE_PORTAL || 143 error_state == ErrorScreen::ERROR_STATE_OFFLINE || 144 error_state == ErrorScreen::ERROR_STATE_PROXY || 145 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT; 146 } 147 148 // Returns network name by service path. 149 std::string GetNetworkName(const std::string& service_path) { 150 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 151 GetNetworkState(service_path); 152 if (!network) 153 return std::string(); 154 return network->name(); 155 } 156 157 static bool SetUserInputMethodImpl( 158 const std::string& username, 159 chromeos::input_method::InputMethodManager* manager) { 160 PrefService* const local_state = g_browser_process->local_state(); 161 162 const base::DictionaryValue* users_lru_input_methods = 163 local_state->GetDictionary(prefs::kUsersLRUInputMethod); 164 165 if (users_lru_input_methods == NULL) { 166 DLOG(WARNING) << "SetUserInputMethod('" << username 167 << "'): no kUsersLRUInputMethod"; 168 return false; 169 } 170 171 std::string input_method; 172 173 if (!users_lru_input_methods->GetStringWithoutPathExpansion(username, 174 &input_method)) { 175 DVLOG(0) << "SetUserInputMethod('" << username 176 << "'): no input method for this user"; 177 return false; 178 } 179 180 if (input_method.empty()) 181 return false; 182 183 if (!manager->IsLoginKeyboard(input_method)) { 184 LOG(WARNING) << "SetUserInputMethod('" << username 185 << "'): stored user LRU input method '" << input_method 186 << "' is no longer Full Latin Keyboard Language" 187 << " (entry dropped). Use hardware default instead."; 188 189 DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod); 190 191 base::DictionaryValue* const users_lru_input_methods = updater.Get(); 192 if (users_lru_input_methods != NULL) { 193 users_lru_input_methods->SetStringWithoutPathExpansion(username, ""); 194 } 195 return false; 196 } 197 198 if (!Contains(manager->GetActiveInputMethodIds(), input_method)) { 199 if (!manager->EnableInputMethod(input_method)) { 200 DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username 201 << "'): user input method '" << input_method 202 << "' is not enabled and enabling failed (ignored!)."; 203 } 204 } 205 manager->ChangeInputMethod(input_method); 206 207 return true; 208 } 209 210 } // namespace 211 212 // LoginScreenContext implementation ------------------------------------------ 213 214 LoginScreenContext::LoginScreenContext() { 215 Init(); 216 } 217 218 LoginScreenContext::LoginScreenContext(const base::ListValue* args) { 219 Init(); 220 221 if (!args || args->GetSize() == 0) 222 return; 223 std::string email; 224 if (args->GetString(0, &email)) 225 email_ = email; 226 } 227 228 void LoginScreenContext::Init() { 229 oobe_ui_ = false; 230 } 231 232 // SigninScreenHandler implementation ------------------------------------------ 233 234 SigninScreenHandler::SigninScreenHandler( 235 const scoped_refptr<NetworkStateInformer>& network_state_informer, 236 ErrorScreenActor* error_screen_actor, 237 CoreOobeActor* core_oobe_actor, 238 GaiaScreenHandler* gaia_screen_handler) 239 : ui_state_(UI_STATE_UNKNOWN), 240 delegate_(NULL), 241 native_window_delegate_(NULL), 242 show_on_init_(false), 243 oobe_ui_(false), 244 is_account_picker_showing_first_time_(false), 245 network_state_informer_(network_state_informer), 246 webui_visible_(false), 247 preferences_changed_delayed_(false), 248 error_screen_actor_(error_screen_actor), 249 core_oobe_actor_(core_oobe_actor), 250 is_first_update_state_call_(true), 251 offline_login_active_(false), 252 last_network_state_(NetworkStateInformer::UNKNOWN), 253 has_pending_auth_ui_(false), 254 caps_lock_enabled_(chromeos::input_method::InputMethodManager::Get() 255 ->GetImeKeyboard() 256 ->CapsLockIsEnabled()), 257 gaia_screen_handler_(gaia_screen_handler), 258 weak_factory_(this) { 259 DCHECK(network_state_informer_.get()); 260 DCHECK(error_screen_actor_); 261 DCHECK(core_oobe_actor_); 262 DCHECK(gaia_screen_handler_); 263 gaia_screen_handler_->SetSigninScreenHandler(this); 264 network_state_informer_->AddObserver(this); 265 266 registrar_.Add(this, 267 chrome::NOTIFICATION_AUTH_NEEDED, 268 content::NotificationService::AllSources()); 269 registrar_.Add(this, 270 chrome::NOTIFICATION_AUTH_SUPPLIED, 271 content::NotificationService::AllSources()); 272 registrar_.Add(this, 273 chrome::NOTIFICATION_AUTH_CANCELLED, 274 content::NotificationService::AllSources()); 275 276 chromeos::input_method::ImeKeyboard* keyboard = 277 chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard(); 278 if (keyboard) 279 keyboard->AddObserver(this); 280 } 281 282 SigninScreenHandler::~SigninScreenHandler() { 283 chromeos::input_method::ImeKeyboard* keyboard = 284 chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard(); 285 if (keyboard) 286 keyboard->RemoveObserver(this); 287 weak_factory_.InvalidateWeakPtrs(); 288 if (delegate_) 289 delegate_->SetWebUIHandler(NULL); 290 network_state_informer_->RemoveObserver(this); 291 ScreenlockBridge::Get()->SetLockHandler(NULL); 292 } 293 294 void SigninScreenHandler::DeclareLocalizedValues( 295 LocalizedValuesBuilder* builder) { 296 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT); 297 builder->Add("podMenuButtonAccessibleName", 298 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME); 299 builder->Add("podMenuRemoveItemAccessibleName", 300 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME); 301 builder->Add("passwordFieldAccessibleName", 302 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME); 303 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER); 304 builder->Add("signinButton", IDS_LOGIN_BUTTON); 305 builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON); 306 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON); 307 builder->Add("addUser", IDS_ADD_USER_BUTTON); 308 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON); 309 builder->Add("cancel", IDS_CANCEL); 310 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT); 311 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML); 312 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER); 313 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER); 314 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE); 315 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT); 316 builder->Add("errorTpmFailureRebootButton", 317 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON); 318 319 policy::BrowserPolicyConnectorChromeOS* connector = 320 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 321 builder->Add("disabledAddUserTooltip", 322 connector->IsEnterpriseManaged() 323 ? IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE 324 : IDS_DISABLED_ADD_USER_TOOLTIP); 325 326 builder->Add("supervisedUserExpiredTokenWarning", 327 IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING); 328 builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER); 329 330 // Multi-profiles related strings. 331 builder->Add("multiProfilesRestrictedPolicyTitle", 332 IDS_MULTI_PROFILES_RESTRICTED_POLICY_TITLE); 333 builder->Add("multiProfilesNotAllowedPolicyMsg", 334 IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG); 335 builder->Add("multiProfilesPrimaryOnlyPolicyMsg", 336 IDS_MULTI_PROFILES_PRIMARY_ONLY_POLICY_MSG); 337 builder->Add("multiProfilesOwnerPrimaryOnlyMsg", 338 IDS_MULTI_PROFILES_OWNER_PRIMARY_ONLY_MSG); 339 340 // Strings used by password changed dialog. 341 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE); 342 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC); 343 builder->AddF("passwordChangedMoreInfo", 344 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO, 345 IDS_SHORT_PRODUCT_OS_NAME); 346 347 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT); 348 builder->Add("oldPasswordIncorrect", 349 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD); 350 builder->Add("passwordChangedCantRemember", 351 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER); 352 builder->Add("passwordChangedBackButton", 353 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON); 354 builder->Add("passwordChangedsOkButton", IDS_OK); 355 builder->Add("passwordChangedProceedAnyway", 356 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY); 357 builder->Add("proceedAnywayButton", 358 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON); 359 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT); 360 builder->Add("publicAccountReminder", 361 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER); 362 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER); 363 builder->Add("publicAccountEnterAccessibleName", 364 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME); 365 builder->Add("removeUserWarningText", 366 base::string16()); 367 builder->AddF("removeSupervisedUserWarningText", 368 IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING, 369 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)); 370 builder->Add("removeUserWarningButtonTitle", 371 IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON); 372 373 builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE); 374 375 builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE); 376 builder->Add("confirmPasswordLabel", IDS_LOGIN_CONFIRM_PASSWORD_LABEL); 377 builder->Add("confirmPasswordConfirmButton", 378 IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON); 379 builder->Add("confirmPasswordText", IDS_LOGIN_CONFIRM_PASSWORD_TEXT); 380 builder->Add("confirmPasswordErrorText", 381 IDS_LOGIN_CONFIRM_PASSWORD_ERROR_TEXT); 382 builder->Add("easyUnlockTooltip", 383 IDS_LOGIN_EASY_UNLOCK_TOOLTIP); 384 385 builder->Add("fatalEnrollmentError", 386 IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR); 387 builder->Add("insecureURLEnrollmentError", 388 IDS_ENTERPRISE_ENROLLMENT_AUTH_INSECURE_URL_ERROR); 389 390 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) 391 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE); 392 393 builder->Add("runType", CommandLine::ForCurrentProcess()->HasSwitch( 394 switches::kFirstExecAfterBoot) ? "firstExecAfterBoot" : 395 "notFirstExecAfterBoot"); 396 } 397 398 void SigninScreenHandler::Show(const LoginScreenContext& context) { 399 CHECK(delegate_); 400 401 // Just initialize internal fields from context and call ShowImpl(). 402 oobe_ui_ = context.oobe_ui(); 403 gaia_screen_handler_->PopulateEmail(context.email()); 404 ShowImpl(); 405 } 406 407 void SigninScreenHandler::ShowRetailModeLoginSpinner() { 408 CallJS("showLoginSpinner"); 409 } 410 411 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) { 412 delegate_ = delegate; 413 if (delegate_) 414 delegate_->SetWebUIHandler(this); 415 else 416 auto_enrollment_progress_subscription_.reset(); 417 } 418 419 void SigninScreenHandler::SetNativeWindowDelegate( 420 NativeWindowDelegate* native_window_delegate) { 421 native_window_delegate_ = native_window_delegate; 422 } 423 424 void SigninScreenHandler::OnNetworkReady() { 425 LOG(WARNING) << "OnNetworkReady() call."; 426 DCHECK(gaia_screen_handler_); 427 gaia_screen_handler_->MaybePreloadAuthExtension(); 428 } 429 430 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) { 431 UpdateStateInternal(reason, false); 432 } 433 434 // SigninScreenHandler, private: ----------------------------------------------- 435 436 void SigninScreenHandler::ShowImpl() { 437 if (!page_is_ready()) { 438 show_on_init_ = true; 439 return; 440 } 441 442 if (oobe_ui_) { 443 // Shows new user sign-in for OOBE. 444 OnShowAddUser(); 445 } else { 446 // Populates account picker. Animation is turned off for now until we 447 // figure out how to make it fast enough. 448 delegate_->HandleGetUsers(); 449 450 // Reset Caps Lock state when login screen is shown. 451 input_method::InputMethodManager::Get() 452 ->GetImeKeyboard() 453 ->SetCapsLockEnabled(false); 454 455 base::DictionaryValue params; 456 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent()); 457 UpdateUIState(UI_STATE_ACCOUNT_PICKER, ¶ms); 458 } 459 } 460 461 void SigninScreenHandler::UpdateUIState(UIState ui_state, 462 base::DictionaryValue* params) { 463 switch (ui_state) { 464 case UI_STATE_GAIA_SIGNIN: 465 ui_state_ = UI_STATE_GAIA_SIGNIN; 466 ShowScreen(OobeUI::kScreenGaiaSignin, params); 467 break; 468 case UI_STATE_ACCOUNT_PICKER: 469 ui_state_ = UI_STATE_ACCOUNT_PICKER; 470 ShowScreen(OobeUI::kScreenAccountPicker, params); 471 break; 472 default: 473 NOTREACHED(); 474 break; 475 } 476 } 477 478 // TODO (ygorshenin@): split this method into small parts. 479 // TODO (ygorshenin@): move this logic to GaiaScreenHandler. 480 void SigninScreenHandler::UpdateStateInternal( 481 ErrorScreenActor::ErrorReason reason, 482 bool force_update) { 483 // Do nothing once user has signed in or sign in is in progress. 484 // TODO(ygorshenin): We will end up here when processing network state 485 // notification but no ShowSigninScreen() was called so delegate_ will be 486 // NULL. Network state processing logic does not belong here. 487 if (delegate_ && 488 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) { 489 return; 490 } 491 492 NetworkStateInformer::State state = network_state_informer_->state(); 493 const std::string network_path = network_state_informer_->network_path(); 494 const std::string network_name = GetNetworkName(network_path); 495 496 // Skip "update" notification about OFFLINE state from 497 // NetworkStateInformer if previous notification already was 498 // delayed. 499 if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) && 500 !force_update && !update_state_closure_.IsCancelled()) { 501 return; 502 } 503 504 // TODO (ygorshenin@): switch log level to INFO once signin screen 505 // will be tested well. 506 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): " 507 << "state=" << NetworkStateInformer::StatusString(state) << ", " 508 << "network_name=" << network_name << ", " 509 << "reason=" << ErrorScreenActor::ErrorReasonString(reason) 510 << ", force_update=" << force_update; 511 update_state_closure_.Cancel(); 512 513 if ((state == NetworkStateInformer::OFFLINE && !force_update) || 514 has_pending_auth_ui_) { 515 update_state_closure_.Reset( 516 base::Bind(&SigninScreenHandler::UpdateStateInternal, 517 weak_factory_.GetWeakPtr(), 518 reason, 519 true)); 520 base::MessageLoop::current()->PostDelayedTask( 521 FROM_HERE, 522 update_state_closure_.callback(), 523 base::TimeDelta::FromSeconds(kOfflineTimeoutSec)); 524 return; 525 } 526 527 // Don't show or hide error screen if we're in connecting state. 528 if (state == NetworkStateInformer::CONNECTING && !force_update) { 529 if (connecting_closure_.IsCancelled()) { 530 // First notification about CONNECTING state. 531 connecting_closure_.Reset( 532 base::Bind(&SigninScreenHandler::UpdateStateInternal, 533 weak_factory_.GetWeakPtr(), 534 reason, 535 true)); 536 base::MessageLoop::current()->PostDelayedTask( 537 FROM_HERE, 538 connecting_closure_.callback(), 539 base::TimeDelta::FromSeconds(kConnectingTimeoutSec)); 540 } 541 return; 542 } 543 connecting_closure_.Cancel(); 544 545 const bool is_online = IsOnline(state, reason); 546 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason); 547 const bool is_gaia_loading_timeout = 548 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 549 const bool is_gaia_error = 550 FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED; 551 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError(); 552 const bool error_screen_should_overlay = 553 !offline_login_active_ && IsGaiaVisible(); 554 const bool from_not_online_to_online_transition = 555 is_online && last_network_state_ != NetworkStateInformer::ONLINE; 556 last_network_state_ = state; 557 558 if (is_online || !is_behind_captive_portal) 559 error_screen_actor_->HideCaptivePortal(); 560 561 // Hide offline message (if needed) and return if current screen is 562 // not a Gaia frame. 563 if (!is_gaia_signin) { 564 if (!IsSigninScreenHiddenByError()) 565 HideOfflineMessage(state, reason); 566 return; 567 } 568 569 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state. 570 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED && 571 from_not_online_to_online_transition) { 572 // Schedules a immediate retry. 573 LOG(WARNING) << "Retry page load since network has been changed."; 574 ReloadGaiaScreen(); 575 } 576 577 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED && 578 error_screen_should_overlay) { 579 // Schedules a immediate retry. 580 LOG(WARNING) << "Retry page load since proxy settings has been changed."; 581 ReloadGaiaScreen(); 582 } 583 584 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR && 585 !IsProxyError(state, reason, FrameError())) { 586 LOG(WARNING) << "Retry page load due to reason: " 587 << ErrorScreenActor::ErrorReasonString(reason); 588 ReloadGaiaScreen(); 589 } 590 591 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) && 592 !offline_login_active_) { 593 SetupAndShowOfflineMessage(state, reason); 594 } else { 595 HideOfflineMessage(state, reason); 596 } 597 } 598 599 void SigninScreenHandler::SetupAndShowOfflineMessage( 600 NetworkStateInformer:: State state, 601 ErrorScreenActor::ErrorReason reason) { 602 const std::string network_path = network_state_informer_->network_path(); 603 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason); 604 const bool is_proxy_error = IsProxyError(state, reason, FrameError()); 605 const bool is_gaia_loading_timeout = 606 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 607 608 if (is_proxy_error) { 609 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY, 610 std::string()); 611 } else if (is_behind_captive_portal) { 612 // Do not bother a user with obsessive captive portal showing. This 613 // check makes captive portal being shown only once: either when error 614 // screen is shown for the first time or when switching from another 615 // error screen (offline, proxy). 616 if (IsGaiaVisible() || 617 (error_screen_actor_->error_state() != 618 ErrorScreen::ERROR_STATE_PORTAL)) { 619 error_screen_actor_->FixCaptivePortal(); 620 } 621 const std::string network_name = GetNetworkName(network_path); 622 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, 623 network_name); 624 } else if (is_gaia_loading_timeout) { 625 error_screen_actor_->SetErrorState( 626 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string()); 627 } else { 628 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE, 629 std::string()); 630 } 631 632 const bool guest_signin_allowed = IsGuestSigninAllowed() && 633 IsSigninScreenError(error_screen_actor_->error_state()); 634 error_screen_actor_->AllowGuestSignin(guest_signin_allowed); 635 636 const bool offline_login_allowed = IsOfflineLoginAllowed() && 637 IsSigninScreenError(error_screen_actor_->error_state()) && 638 error_screen_actor_->error_state() != 639 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT; 640 error_screen_actor_->AllowOfflineLogin(offline_login_allowed); 641 642 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) { 643 base::DictionaryValue params; 644 const std::string network_type = network_state_informer_->network_type(); 645 params.SetString("lastNetworkType", network_type); 646 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN); 647 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, ¶ms); 648 } 649 } 650 651 void SigninScreenHandler::HideOfflineMessage( 652 NetworkStateInformer::State state, 653 ErrorScreenActor::ErrorReason reason) { 654 if (!IsSigninScreenHiddenByError()) 655 return; 656 657 error_screen_actor_->Hide(); 658 659 // Forces a reload for Gaia screen on hiding error message. 660 if (IsGaiaVisible() || IsGaiaHiddenByError()) 661 ReloadGaiaScreen(); 662 } 663 664 void SigninScreenHandler::ReloadGaiaScreen() { 665 gaia_screen_handler_->ReloadGaia(); 666 } 667 668 void SigninScreenHandler::Initialize() { 669 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed), 670 // don't do anything, just return. 671 if (!delegate_) 672 return; 673 674 if (show_on_init_) { 675 show_on_init_ = false; 676 ShowImpl(); 677 } 678 } 679 680 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() { 681 if (native_window_delegate_) 682 return native_window_delegate_->GetNativeWindow(); 683 return NULL; 684 } 685 686 void SigninScreenHandler::RegisterMessages() { 687 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser); 688 AddCallback("attemptUnlock", &SigninScreenHandler::HandleAttemptUnlock); 689 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers); 690 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser); 691 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito); 692 AddCallback("showLocallyManagedUserCreationScreen", 693 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen); 694 AddCallback("launchPublicAccount", 695 &SigninScreenHandler::HandleLaunchPublicAccount); 696 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin); 697 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem); 698 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser); 699 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem); 700 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper); 701 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser); 702 AddCallback("toggleEnrollmentScreen", 703 &SigninScreenHandler::HandleToggleEnrollmentScreen); 704 AddCallback("toggleKioskEnableScreen", 705 &SigninScreenHandler::HandleToggleKioskEnableScreen); 706 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount); 707 AddCallback("accountPickerReady", 708 &SigninScreenHandler::HandleAccountPickerReady); 709 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady); 710 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser); 711 AddCallback("openProxySettings", 712 &SigninScreenHandler::HandleOpenProxySettings); 713 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible); 714 AddCallback("cancelPasswordChangedFlow", 715 &SigninScreenHandler::HandleCancelPasswordChangedFlow); 716 AddCallback("cancelUserAdding", 717 &SigninScreenHandler::HandleCancelUserAdding); 718 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData); 719 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData); 720 AddCallback("loginUIStateChanged", 721 &SigninScreenHandler::HandleLoginUIStateChanged); 722 AddCallback("unlockOnLoginSuccess", 723 &SigninScreenHandler::HandleUnlockOnLoginSuccess); 724 AddCallback("showLoadingTimeoutError", 725 &SigninScreenHandler::HandleShowLoadingTimeoutError); 726 AddCallback("updateOfflineLogin", 727 &SigninScreenHandler::HandleUpdateOfflineLogin); 728 AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod); 729 AddCallback("retrieveAuthenticatedUserEmail", 730 &SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail); 731 732 // This message is sent by the kiosk app menu, but is handled here 733 // so we can tell the delegate to launch the app. 734 AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp); 735 } 736 737 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) { 738 registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod); 739 } 740 741 void SigninScreenHandler::HandleGetUsers() { 742 if (delegate_) 743 delegate_->HandleGetUsers(); 744 } 745 746 void SigninScreenHandler::ClearAndEnablePassword() { 747 core_oobe_actor_->ResetSignInUI(false); 748 } 749 750 void SigninScreenHandler::ClearUserPodPassword() { 751 core_oobe_actor_->ClearUserPodPassword(); 752 } 753 754 void SigninScreenHandler::RefocusCurrentPod() { 755 core_oobe_actor_->RefocusCurrentPod(); 756 } 757 758 void SigninScreenHandler::OnUserRemoved(const std::string& username) { 759 CallJS("login.AccountPickerScreen.removeUser", username); 760 if (delegate_->GetUsers().empty()) 761 OnShowAddUser(); 762 } 763 764 void SigninScreenHandler::OnUserImageChanged(const User& user) { 765 if (page_is_ready()) 766 CallJS("login.AccountPickerScreen.updateUserImage", user.email()); 767 } 768 769 void SigninScreenHandler::OnPreferencesChanged() { 770 // Make sure that one of the login UI is fully functional now, otherwise 771 // preferences update would be picked up next time it will be shown. 772 if (!webui_visible_) { 773 LOG(WARNING) << "Login UI is not active - postponed prefs change."; 774 preferences_changed_delayed_ = true; 775 return; 776 } 777 778 if (delegate_ && !delegate_->IsShowUsers()) { 779 HandleShowAddUser(NULL); 780 } else { 781 if (delegate_) 782 delegate_->HandleGetUsers(); 783 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL); 784 } 785 preferences_changed_delayed_ = false; 786 } 787 788 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() { 789 SetDelegate(NULL); 790 } 791 792 void SigninScreenHandler::ShowError(int login_attempts, 793 const std::string& error_text, 794 const std::string& help_link_text, 795 HelpAppLauncher::HelpTopic help_topic_id) { 796 core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text, 797 help_topic_id); 798 } 799 800 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) { 801 switch (error_id) { 802 case LoginDisplay::TPM_ERROR: 803 core_oobe_actor_->ShowTpmError(); 804 break; 805 default: 806 NOTREACHED() << "Unknown sign in error"; 807 break; 808 } 809 } 810 811 void SigninScreenHandler::ShowSigninUI(const std::string& email) { 812 core_oobe_actor_->ShowSignInUI(email); 813 } 814 815 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) { 816 gaia_screen_handler_->PasswordChangedFor(username); 817 gaia_screen_handler_->PopulateEmail(username); 818 core_oobe_actor_->ShowSignInUI(username); 819 CallJS("login.setAuthType", 820 username, 821 static_cast<int>(ONLINE_SIGN_IN), 822 base::StringValue("")); 823 } 824 825 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) { 826 core_oobe_actor_->ShowPasswordChangedScreen(show_password_error); 827 } 828 829 void SigninScreenHandler::ShowSigninScreenForCreds( 830 const std::string& username, 831 const std::string& password) { 832 DCHECK(gaia_screen_handler_); 833 gaia_screen_handler_->ShowSigninScreenForCreds(username, password); 834 } 835 836 void SigninScreenHandler::Observe(int type, 837 const content::NotificationSource& source, 838 const content::NotificationDetails& details) { 839 switch (type) { 840 case chrome::NOTIFICATION_AUTH_NEEDED: { 841 has_pending_auth_ui_ = true; 842 break; 843 } 844 case chrome::NOTIFICATION_AUTH_SUPPLIED: 845 has_pending_auth_ui_ = false; 846 // Reload auth extension as proxy credentials are supplied. 847 if (!IsSigninScreenHiddenByError() && ui_state_ == UI_STATE_GAIA_SIGNIN) 848 ReloadGaiaScreen(); 849 update_state_closure_.Cancel(); 850 break; 851 case chrome::NOTIFICATION_AUTH_CANCELLED: { 852 // Don't reload auth extension if proxy auth dialog was cancelled. 853 has_pending_auth_ui_ = false; 854 update_state_closure_.Cancel(); 855 break; 856 } 857 default: 858 NOTREACHED() << "Unexpected notification " << type; 859 } 860 } 861 862 void SigninScreenHandler::ShowBannerMessage(const std::string& message) { 863 CallJS("login.AccountPickerScreen.showBannerMessage", message); 864 } 865 866 void SigninScreenHandler::ShowUserPodCustomIcon( 867 const std::string& username, 868 const gfx::Image& icon) { 869 gfx::ImageSkia icon_skia = icon.AsImageSkia(); 870 base::DictionaryValue icon_representations; 871 icon_representations.SetString( 872 "scale1x", 873 webui::GetBitmapDataUrl(icon_skia.GetRepresentation(1.0f).sk_bitmap())); 874 icon_representations.SetString( 875 "scale2x", 876 webui::GetBitmapDataUrl(icon_skia.GetRepresentation(2.0f).sk_bitmap())); 877 CallJS("login.AccountPickerScreen.showUserPodCustomIcon", 878 username, icon_representations); 879 880 // TODO(tengs): Move this code once we move unlocking to native code. 881 if (ScreenLocker::default_screen_locker()) { 882 UserManager* user_manager = UserManager::Get(); 883 const User* user = user_manager->FindUser(username); 884 if (!user) 885 return; 886 PrefService* profile_prefs = 887 user_manager->GetProfileByUser(user)->GetPrefs(); 888 if (profile_prefs->GetBoolean(prefs::kEasyUnlockShowTutorial)) { 889 CallJS("login.AccountPickerScreen.showEasyUnlockBubble"); 890 profile_prefs->SetBoolean(prefs::kEasyUnlockShowTutorial, false); 891 } 892 } 893 } 894 895 void SigninScreenHandler::HideUserPodCustomIcon(const std::string& username) { 896 CallJS("login.AccountPickerScreen.hideUserPodCustomIcon", username); 897 } 898 899 void SigninScreenHandler::EnableInput() { 900 // Only for lock screen at the moment. 901 ScreenLocker::default_screen_locker()->EnableInput(); 902 } 903 904 void SigninScreenHandler::SetAuthType( 905 const std::string& username, 906 ScreenlockBridge::LockHandler::AuthType auth_type, 907 const std::string& initial_value) { 908 delegate_->SetAuthType(username, auth_type); 909 910 CallJS("login.AccountPickerScreen.setAuthType", 911 username, 912 static_cast<int>(auth_type), 913 base::StringValue(initial_value)); 914 } 915 916 ScreenlockBridge::LockHandler::AuthType SigninScreenHandler::GetAuthType( 917 const std::string& username) const { 918 return delegate_->GetAuthType(username); 919 } 920 921 void SigninScreenHandler::Unlock(const std::string& user_email) { 922 DCHECK(ScreenLocker::default_screen_locker()); 923 ScreenLocker::Hide(); 924 } 925 926 bool SigninScreenHandler::ShouldLoadGaia() const { 927 // Fetching of the extension is not started before account picker page is 928 // loaded because it can affect the loading speed. 929 // Do not load the extension for the screen locker, see crosbug.com/25018. 930 return !ScreenLocker::default_screen_locker() && 931 is_account_picker_showing_first_time_; 932 } 933 934 // Update keyboard layout to least recently used by the user. 935 void SigninScreenHandler::SetUserInputMethod(const std::string& username) { 936 UserManager* user_manager = UserManager::Get(); 937 if (user_manager->IsUserLoggedIn()) { 938 // We are on sign-in screen inside user session (adding new user to 939 // the session or on lock screen), don't switch input methods in this case. 940 // TODO(dpolukhin): adding user and sign-in should be consistent 941 // crbug.com/292774 942 return; 943 } 944 945 chromeos::input_method::InputMethodManager* const manager = 946 chromeos::input_method::InputMethodManager::Get(); 947 948 const bool succeed = SetUserInputMethodImpl(username, manager); 949 950 // This is also a case when LRU layout is set only for a few local users, 951 // thus others need to be switched to default locale. 952 // Otherwise they will end up using another user's locale to log in. 953 if (!succeed) { 954 DVLOG(0) << "SetUserInputMethod('" << username 955 << "'): failed to set user layout. Switching to default."; 956 957 manager->SetInputMethodLoginDefault(); 958 } 959 } 960 961 962 void SigninScreenHandler::UserSettingsChanged() { 963 DCHECK(gaia_screen_handler_); 964 GaiaContext context; 965 if (delegate_) 966 context.has_users = !delegate_->GetUsers().empty(); 967 gaia_screen_handler_->UpdateGaia(context); 968 UpdateAddButtonStatus(); 969 } 970 971 void SigninScreenHandler::UpdateAddButtonStatus() { 972 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus", 973 AllWhitelistedUsersPresent()); 974 } 975 976 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username, 977 const std::string& password) { 978 if (!delegate_) 979 return; 980 UserContext user_context(username); 981 user_context.SetKey(Key(password)); 982 delegate_->Login(user_context); 983 } 984 985 void SigninScreenHandler::HandleAttemptUnlock(const std::string& username) { 986 DCHECK(ScreenLocker::default_screen_locker()); 987 988 const User* unlock_user = NULL; 989 const UserList& users = delegate_->GetUsers(); 990 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 991 if ((*it)->email() == username) { 992 unlock_user = *it; 993 break; 994 } 995 } 996 if (!unlock_user) 997 return; 998 999 Profile* profile = UserManager::Get()->GetProfileByUser(unlock_user); 1000 extensions::ScreenlockPrivateEventRouter* router = 1001 extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get( 1002 profile); 1003 router->OnAuthAttempted(GetAuthType(username), ""); 1004 } 1005 1006 void SigninScreenHandler::HandleLaunchDemoUser() { 1007 if (delegate_) 1008 delegate_->LoginAsRetailModeUser(); 1009 } 1010 1011 void SigninScreenHandler::HandleLaunchIncognito() { 1012 if (delegate_) 1013 delegate_->LoginAsGuest(); 1014 } 1015 1016 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() { 1017 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) { 1018 LOG(ERROR) << "Managed users not allowed."; 1019 return; 1020 } 1021 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue()); 1022 LoginDisplayHostImpl::default_host()-> 1023 StartWizard(WizardController::kLocallyManagedUserCreationScreenName, 1024 params.Pass()); 1025 } 1026 1027 void SigninScreenHandler::HandleLaunchPublicAccount( 1028 const std::string& username) { 1029 if (delegate_) 1030 delegate_->LoginAsPublicAccount(username); 1031 } 1032 1033 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) { 1034 if (!delegate_ || delegate_->IsShowUsers()) { 1035 NOTREACHED(); 1036 return; 1037 } 1038 std::string email; 1039 args->GetString(0, &email); 1040 1041 gaia_screen_handler_->PopulateEmail(email); 1042 // Load auth extension. Parameters are: force reload, do not load extension in 1043 // background, use offline version. 1044 gaia_screen_handler_->LoadAuthExtension(true, false, true); 1045 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL); 1046 } 1047 1048 void SigninScreenHandler::HandleShutdownSystem() { 1049 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown(); 1050 } 1051 1052 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) { 1053 if (delegate_) 1054 delegate_->LoadWallpaper(email); 1055 } 1056 1057 void SigninScreenHandler::HandleRebootSystem() { 1058 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 1059 } 1060 1061 void SigninScreenHandler::HandleRemoveUser(const std::string& email) { 1062 if (!delegate_) 1063 return; 1064 delegate_->RemoveUser(email); 1065 UpdateAddButtonStatus(); 1066 } 1067 1068 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) { 1069 TRACE_EVENT_ASYNC_STEP_INTO0("ui", 1070 "ShowLoginWebUI", 1071 LoginDisplayHostImpl::kShowLoginWebUIid, 1072 "ShowAddUser"); 1073 std::string email; 1074 // |args| can be null if it's OOBE. 1075 if (args) 1076 args->GetString(0, &email); 1077 gaia_screen_handler_->PopulateEmail(email); 1078 OnShowAddUser(); 1079 } 1080 1081 void SigninScreenHandler::HandleToggleEnrollmentScreen() { 1082 if (delegate_) 1083 delegate_->ShowEnterpriseEnrollmentScreen(); 1084 } 1085 1086 void SigninScreenHandler::HandleToggleKioskEnableScreen() { 1087 policy::BrowserPolicyConnectorChromeOS* connector = 1088 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 1089 if (delegate_ && 1090 !auto_enrollment_progress_subscription_ && 1091 !connector->IsEnterpriseManaged() && 1092 LoginDisplayHostImpl::default_host()) { 1093 AutoEnrollmentController* auto_enrollment_controller = 1094 LoginDisplayHostImpl::default_host()->GetAutoEnrollmentController(); 1095 auto_enrollment_progress_subscription_ = 1096 auto_enrollment_controller->RegisterProgressCallback( 1097 base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow, 1098 weak_factory_.GetWeakPtr())); 1099 ContinueKioskEnableFlow(auto_enrollment_controller->state()); 1100 } 1101 } 1102 1103 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() { 1104 policy::BrowserPolicyConnectorChromeOS* connector = 1105 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 1106 if (delegate_ && !connector->IsEnterpriseManaged()) 1107 delegate_->ShowKioskAutolaunchScreen(); 1108 } 1109 1110 void SigninScreenHandler::LoadUsers(const base::ListValue& users_list, 1111 bool animated, 1112 bool showGuest) { 1113 CallJS("login.AccountPickerScreen.loadUsers", 1114 users_list, 1115 animated, 1116 delegate_->IsShowGuest()); 1117 } 1118 1119 void SigninScreenHandler::HandleAccountPickerReady() { 1120 VLOG(0) << "Login WebUI >> AccountPickerReady"; 1121 1122 if (delegate_ && !ScreenLocker::default_screen_locker() && 1123 !chromeos::IsMachineHWIDCorrect() && 1124 !oobe_ui_) { 1125 delegate_->ShowWrongHWIDScreen(); 1126 return; 1127 } 1128 1129 PrefService* prefs = g_browser_process->local_state(); 1130 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) { 1131 if (core_oobe_actor_) { 1132 core_oobe_actor_->ShowDeviceResetScreen(); 1133 return; 1134 } 1135 } 1136 1137 is_account_picker_showing_first_time_ = true; 1138 gaia_screen_handler_->MaybePreloadAuthExtension(); 1139 1140 if (ScreenLocker::default_screen_locker()) { 1141 ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady(); 1142 ScreenlockBridge::Get()->SetLockHandler(this); 1143 } 1144 1145 if (delegate_) 1146 delegate_->OnSigninScreenReady(); 1147 } 1148 1149 void SigninScreenHandler::HandleWallpaperReady() { 1150 if (ScreenLocker::default_screen_locker()) { 1151 ScreenLocker::default_screen_locker()->delegate()-> 1152 OnLockBackgroundDisplayed(); 1153 } 1154 } 1155 1156 void SigninScreenHandler::HandleSignOutUser() { 1157 if (delegate_) 1158 delegate_->Signout(); 1159 } 1160 1161 void SigninScreenHandler::HandleCreateAccount() { 1162 if (delegate_) 1163 delegate_->CreateAccount(); 1164 } 1165 1166 void SigninScreenHandler::HandleOpenProxySettings() { 1167 LoginDisplayHostImpl::default_host()->OpenProxySettings(); 1168 } 1169 1170 void SigninScreenHandler::HandleLoginVisible(const std::string& source) { 1171 LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", " 1172 << "webui_visible_: " << webui_visible_; 1173 if (!webui_visible_) { 1174 // There might be multiple messages from OOBE UI so send notifications after 1175 // the first one only. 1176 content::NotificationService::current()->Notify( 1177 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, 1178 content::NotificationService::AllSources(), 1179 content::NotificationService::NoDetails()); 1180 TRACE_EVENT_ASYNC_END0( 1181 "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid); 1182 } 1183 webui_visible_ = true; 1184 if (preferences_changed_delayed_) 1185 OnPreferencesChanged(); 1186 } 1187 1188 void SigninScreenHandler::HandleCancelPasswordChangedFlow() { 1189 gaia_screen_handler_->StartClearingCookies( 1190 base::Bind(&SigninScreenHandler::CancelPasswordChangedFlowInternal, 1191 weak_factory_.GetWeakPtr())); 1192 } 1193 1194 void SigninScreenHandler::HandleCancelUserAdding() { 1195 if (delegate_) 1196 delegate_->CancelUserAdding(); 1197 } 1198 1199 void SigninScreenHandler::HandleMigrateUserData( 1200 const std::string& old_password) { 1201 if (delegate_) 1202 delegate_->MigrateUserData(old_password); 1203 } 1204 1205 void SigninScreenHandler::HandleResyncUserData() { 1206 if (delegate_) 1207 delegate_->ResyncUserData(); 1208 } 1209 1210 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source, 1211 bool new_value) { 1212 VLOG(0) << "Login WebUI >> active: " << new_value << ", " 1213 << "source: " << source; 1214 1215 if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() && 1216 KioskAppManager::Get()->IsAutoLaunchRequested()) { 1217 VLOG(0) << "Showing auto-launch warning"; 1218 // On slow devices, the wallpaper animation is not shown initially, so we 1219 // must explicitly load the wallpaper. This is also the case for the 1220 // account-picker and gaia-signin UI states. 1221 delegate_->LoadSigninWallpaper(); 1222 HandleToggleKioskAutolaunchScreen(); 1223 return; 1224 } 1225 1226 if (source == kSourceGaiaSignin) { 1227 ui_state_ = UI_STATE_GAIA_SIGNIN; 1228 } else if (source == kSourceAccountPicker) { 1229 ui_state_ = UI_STATE_ACCOUNT_PICKER; 1230 } else { 1231 NOTREACHED(); 1232 return; 1233 } 1234 } 1235 1236 void SigninScreenHandler::HandleUnlockOnLoginSuccess() { 1237 DCHECK(UserManager::Get()->IsUserLoggedIn()); 1238 if (ScreenLocker::default_screen_locker()) 1239 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess(); 1240 } 1241 1242 void SigninScreenHandler::HandleShowLoadingTimeoutError() { 1243 UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 1244 } 1245 1246 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) { 1247 offline_login_active_ = offline_login_active; 1248 } 1249 1250 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) { 1251 SetUserInputMethod(user_id); 1252 WallpaperManager::Get()->SetUserWallpaperDelayed(user_id); 1253 } 1254 1255 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail( 1256 double attempt_token) { 1257 email_retriever_.reset(new AuthenticatedUserEmailRetriever( 1258 base::Bind(&SigninScreenHandler::CallJS<double, std::string>, 1259 base::Unretained(this), 1260 "login.GaiaSigninScreen.setAuthenticatedUserEmail", 1261 attempt_token), 1262 Profile::FromWebUI(web_ui())->GetRequestContext())); 1263 } 1264 1265 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id, 1266 bool diagnostic_mode) { 1267 delegate_->LoginAsKioskApp(app_id, diagnostic_mode); 1268 } 1269 1270 bool SigninScreenHandler::AllWhitelistedUsersPresent() { 1271 CrosSettings* cros_settings = CrosSettings::Get(); 1272 bool allow_new_user = false; 1273 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user); 1274 if (allow_new_user) 1275 return false; 1276 UserManager* user_manager = UserManager::Get(); 1277 const UserList& users = user_manager->GetUsers(); 1278 if (!delegate_ || users.size() > kMaxUsers) { 1279 return false; 1280 } 1281 const base::ListValue* whitelist = NULL; 1282 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist) 1283 return false; 1284 for (size_t i = 0; i < whitelist->GetSize(); ++i) { 1285 std::string whitelisted_user; 1286 // NB: Wildcards in the whitelist are also detected as not present here. 1287 if (!whitelist->GetString(i, &whitelisted_user) || 1288 !user_manager->IsKnownUser(whitelisted_user)) { 1289 return false; 1290 } 1291 } 1292 return true; 1293 } 1294 1295 void SigninScreenHandler::CancelPasswordChangedFlowInternal() { 1296 if (delegate_) { 1297 ShowImpl(); 1298 delegate_->CancelPasswordChangedFlow(); 1299 } 1300 } 1301 1302 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const { 1303 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN; 1304 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController()); 1305 if (oobe_ui) 1306 screen = oobe_ui->current_screen(); 1307 return screen; 1308 } 1309 1310 bool SigninScreenHandler::IsGaiaVisible() const { 1311 return IsSigninScreen(GetCurrentScreen()) && 1312 ui_state_ == UI_STATE_GAIA_SIGNIN; 1313 } 1314 1315 bool SigninScreenHandler::IsGaiaHiddenByError() const { 1316 return IsSigninScreenHiddenByError() && 1317 ui_state_ == UI_STATE_GAIA_SIGNIN; 1318 } 1319 1320 bool SigninScreenHandler::IsSigninScreenHiddenByError() const { 1321 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) && 1322 (IsSigninScreen(error_screen_actor_->parent_screen())); 1323 } 1324 1325 bool SigninScreenHandler::IsGuestSigninAllowed() const { 1326 CrosSettings* cros_settings = CrosSettings::Get(); 1327 if (!cros_settings) 1328 return false; 1329 bool allow_guest; 1330 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest); 1331 return allow_guest; 1332 } 1333 1334 bool SigninScreenHandler::IsOfflineLoginAllowed() const { 1335 CrosSettings* cros_settings = CrosSettings::Get(); 1336 if (!cros_settings) 1337 return false; 1338 1339 // Offline login is allowed only when user pods are hidden. 1340 bool show_pods; 1341 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods); 1342 return !show_pods; 1343 } 1344 1345 void SigninScreenHandler::ContinueKioskEnableFlow( 1346 policy::AutoEnrollmentState state) { 1347 // Do not proceed with kiosk enable when auto enroll will be enforced. 1348 // TODO(xiyuan): Add an error UI feedkback so user knows what happens. 1349 switch (state) { 1350 case policy::AUTO_ENROLLMENT_STATE_IDLE: 1351 case policy::AUTO_ENROLLMENT_STATE_PENDING: 1352 case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR: 1353 // Wait for the next callback. 1354 return; 1355 case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT: 1356 // Auto-enrollment is on. 1357 LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is " 1358 "going to be enforced."; 1359 if (!kiosk_enable_flow_aborted_callback_for_test_.is_null()) 1360 kiosk_enable_flow_aborted_callback_for_test_.Run(); 1361 break; 1362 case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR: 1363 case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT: 1364 // Auto-enrollment not applicable. 1365 if (delegate_) 1366 delegate_->ShowKioskEnableScreen(); 1367 break; 1368 } 1369 auto_enrollment_progress_subscription_.reset(); 1370 } 1371 1372 void SigninScreenHandler::OnShowAddUser() { 1373 is_account_picker_showing_first_time_ = false; 1374 DCHECK(gaia_screen_handler_); 1375 gaia_screen_handler_->ShowGaia(); 1376 } 1377 1378 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const { 1379 DCHECK(gaia_screen_handler_); 1380 return gaia_screen_handler_->frame_state(); 1381 } 1382 1383 net::Error SigninScreenHandler::FrameError() const { 1384 DCHECK(gaia_screen_handler_); 1385 return gaia_screen_handler_->frame_error(); 1386 } 1387 1388 void SigninScreenHandler::OnCapsLockChanged(bool enabled) { 1389 caps_lock_enabled_ = enabled; 1390 if (page_is_ready()) 1391 CallJS("login.AccountPickerScreen.setCapsLockState", caps_lock_enabled_); 1392 } 1393 1394 } // namespace chromeos 1395