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