signin_screen_handler.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 "base/callback.h" 8#include "base/command_line.h" 9#include "base/logging.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/metrics/histogram.h" 12#include "base/prefs/pref_service.h" 13#include "base/string16.h" 14#include "base/string_util.h" 15#include "base/stringprintf.h" 16#include "base/utf_string_conversions.h" 17#include "chrome/browser/browser_process.h" 18#include "chrome/browser/browser_process_platform_part_chromeos.h" 19#include "chrome/browser/browser_shutdown.h" 20#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" 21#include "chrome/browser/chromeos/login/hwid_checker.h" 22#include "chrome/browser/chromeos/login/login_display_host_impl.h" 23#include "chrome/browser/chromeos/login/screen_locker.h" 24#include "chrome/browser/chromeos/login/user.h" 25#include "chrome/browser/chromeos/login/webui_login_display.h" 26#include "chrome/browser/chromeos/login/wizard_controller.h" 27#include "chrome/browser/chromeos/net/network_portal_detector.h" 28#include "chrome/browser/chromeos/profiles/profile_helper.h" 29#include "chrome/browser/chromeos/settings/cros_settings.h" 30#include "chrome/browser/io_thread.h" 31#include "chrome/browser/policy/browser_policy_connector.h" 32#include "chrome/browser/profiles/profile.h" 33#include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" 34#include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h" 35#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" 36#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 37#include "chrome/common/chrome_notification_types.h" 38#include "chrome/common/chrome_switches.h" 39#include "chrome/common/pref_names.h" 40#include "chrome/common/url_constants.h" 41#include "chromeos/chromeos_switches.h" 42#include "chromeos/dbus/dbus_thread_manager.h" 43#include "chromeos/dbus/power_manager_client.h" 44#include "chromeos/ime/input_method_manager.h" 45#include "chromeos/ime/xkeyboard.h" 46#include "chromeos/network/network_state.h" 47#include "chromeos/network/network_state_handler.h" 48#include "content/public/browser/render_view_host.h" 49#include "content/public/browser/web_contents.h" 50#include "google_apis/gaia/gaia_auth_util.h" 51#include "google_apis/gaia/gaia_switches.h" 52#include "google_apis/gaia/gaia_urls.h" 53#include "grit/chromium_strings.h" 54#include "grit/generated_resources.h" 55#include "third_party/cros_system_api/dbus/service_constants.h" 56#include "ui/base/l10n/l10n_util.h" 57 58#if defined(USE_AURA) 59#include "ash/shell.h" 60#include "ash/wm/session_state_controller.h" 61#endif 62 63using content::BrowserThread; 64using content::RenderViewHost; 65 66namespace { 67 68// User dictionary keys. 69const char kKeyUsername[] = "username"; 70const char kKeyDisplayName[] = "displayName"; 71const char kKeyEmailAddress[] = "emailAddress"; 72const char kKeyEnterpriseDomain[] = "enterpriseDomain"; 73const char kKeyPublicAccount[] = "publicAccount"; 74const char kKeyLocallyManagedUser[] = "locallyManagedUser"; 75const char kKeySignedIn[] = "signedIn"; 76const char kKeyCanRemove[] = "canRemove"; 77const char kKeyIsOwner[] = "isOwner"; 78const char kKeyOauthTokenStatus[] = "oauthTokenStatus"; 79 80// Max number of users to show. 81const size_t kMaxUsers = 18; 82 83// Timeout to delay first notification about offline state for a 84// current network. 85const int kOfflineTimeoutSec = 5; 86 87// Timeout used to prevent infinite connecting to a flaky network. 88const int kConnectingTimeoutSec = 60; 89 90// Type of the login screen UI that is currently presented to user. 91const char kSourceGaiaSignin[] = "gaia-signin"; 92const char kSourceAccountPicker[] = "account-picker"; 93 94// The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO 95// thread. 96void ClearDnsCache(IOThread* io_thread) { 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 98 if (browser_shutdown::IsTryingToQuit()) 99 return; 100 101 io_thread->ClearHostCache(); 102} 103 104} // namespace 105 106namespace chromeos { 107 108namespace { 109 110const char kNetworkStateOffline[] = "offline"; 111const char kNetworkStateOnline[] = "online"; 112const char kNetworkStateCaptivePortal[] = "behind captive portal"; 113const char kNetworkStateConnecting[] = "connecting"; 114const char kNetworkStateProxyAuthRequired[] = "proxy auth required"; 115 116const char kErrorReasonProxyAuthCancelled[] = "proxy auth cancelled"; 117const char kErrorReasonProxyAuthSupplied[] = "proxy auth supplied"; 118const char kErrorReasonProxyConnectionFailed[] = "proxy connection failed"; 119const char kErrorReasonProxyConfigChanged[] = "proxy config changed"; 120const char kErrorReasonLoadingTimeout[] = "loading timeout"; 121const char kErrorReasonPortalDetected[] = "portal detected"; 122const char kErrorReasonNetworkStateChanged[] = "network state changed"; 123const char kErrorReasonUpdate[] = "update"; 124const char kErrorReasonFrameError[] = "frame error"; 125 126const char* NetworkStateStatusString(NetworkStateInformer::State state) { 127 switch (state) { 128 case NetworkStateInformer::OFFLINE: 129 return kNetworkStateOffline; 130 case NetworkStateInformer::ONLINE: 131 return kNetworkStateOnline; 132 case NetworkStateInformer::CAPTIVE_PORTAL: 133 return kNetworkStateCaptivePortal; 134 case NetworkStateInformer::CONNECTING: 135 return kNetworkStateConnecting; 136 case NetworkStateInformer::PROXY_AUTH_REQUIRED: 137 return kNetworkStateProxyAuthRequired; 138 default: 139 NOTREACHED(); 140 return NULL; 141 } 142} 143 144const char* ErrorReasonString(ErrorScreenActor::ErrorReason reason) { 145 switch (reason) { 146 case ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED: 147 return kErrorReasonProxyAuthCancelled; 148 case ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED: 149 return kErrorReasonProxyAuthSupplied; 150 case ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED: 151 return kErrorReasonProxyConnectionFailed; 152 case ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED: 153 return kErrorReasonProxyConfigChanged; 154 case ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT: 155 return kErrorReasonLoadingTimeout; 156 case ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED: 157 return kErrorReasonPortalDetected; 158 case ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED: 159 return kErrorReasonNetworkStateChanged; 160 case ErrorScreenActor::ERROR_REASON_UPDATE: 161 return kErrorReasonUpdate; 162 case ErrorScreenActor::ERROR_REASON_FRAME_ERROR: 163 return kErrorReasonFrameError; 164 default: 165 NOTREACHED(); 166 return NULL; 167 } 168} 169 170// Updates params dictionary passed to the auth extension with related 171// preferences from CrosSettings. 172void UpdateAuthParamsFromSettings(DictionaryValue* params, 173 const CrosSettings* cros_settings) { 174 bool allow_new_user = true; 175 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user); 176 bool allow_guest = true; 177 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest); 178 // Account creation depends on Guest sign-in (http://crosbug.com/24570). 179 params->SetBoolean("createAccount", allow_new_user && allow_guest); 180 params->SetBoolean("guestSignin", allow_guest); 181} 182 183bool IsOnline(NetworkStateInformer::State state, 184 ErrorScreenActor::ErrorReason reason) { 185 return state == NetworkStateInformer::ONLINE && 186 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED && 187 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT; 188} 189 190bool IsUnderCaptivePortal(NetworkStateInformer::State state, 191 ErrorScreenActor::ErrorReason reason) { 192 return state == NetworkStateInformer::CAPTIVE_PORTAL || 193 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED; 194} 195 196bool IsProxyError(NetworkStateInformer::State state, 197 ErrorScreenActor::ErrorReason reason) { 198 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED || 199 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED || 200 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED; 201} 202 203bool IsSigninScreen(const OobeUI::Screen screen) { 204 return screen == OobeUI::SCREEN_GAIA_SIGNIN || 205 screen == OobeUI::SCREEN_ACCOUNT_PICKER; 206} 207 208bool IsSigninScreenError(ErrorScreen::ErrorState error_state) { 209 return error_state == ErrorScreen::ERROR_STATE_PORTAL || 210 error_state == ErrorScreen::ERROR_STATE_OFFLINE || 211 error_state == ErrorScreen::ERROR_STATE_PROXY || 212 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT; 213} 214 215// Returns network name by service path. 216std::string GetNetworkName(const std::string& service_path) { 217 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 218 GetNetworkState(service_path); 219 if (!network) 220 return std::string(); 221 return network->name(); 222} 223 224// Returns network unique id by service path. 225std::string GetNetworkUniqueId(const std::string& service_path) { 226 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 227 GetNetworkState(service_path); 228 if (!network) 229 return std::string(); 230 return network->guid(); 231} 232 233// Returns captive portal state for a network by its service path. 234NetworkPortalDetector::CaptivePortalState GetCaptivePortalState( 235 const std::string& service_path) { 236 NetworkPortalDetector* detector = NetworkPortalDetector::GetInstance(); 237 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 238 GetNetworkState(service_path); 239 if (!detector || !network) 240 return NetworkPortalDetector::CaptivePortalState(); 241 return detector->GetCaptivePortalState(network); 242} 243 244void RecordDiscrepancyWithShill( 245 const NetworkState* network, 246 const NetworkPortalDetector::CaptivePortalStatus status) { 247 if (network->connection_state() == flimflam::kStateOnline) { 248 UMA_HISTOGRAM_ENUMERATION( 249 "CaptivePortal.OOBE.DiscrepancyWithShill_Online", 250 status, 251 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 252 } else if (network->connection_state() == flimflam::kStatePortal) { 253 UMA_HISTOGRAM_ENUMERATION( 254 "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool", 255 status, 256 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 257 } else { 258 UMA_HISTOGRAM_ENUMERATION( 259 "CaptivePortal.OOBE.DiscrepancyWithShill_Offline", 260 status, 261 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 262 } 263} 264 265// Record state and descripancies with shill (e.g. shill thinks that 266// network is online but NetworkPortalDetector claims that it's behind 267// portal) for the network identified by |service_path|. 268void RecordNetworkPortalDetectorStats(const std::string& service_path) { 269 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 270 GetNetworkState(service_path); 271 if (!network) 272 return; 273 NetworkPortalDetector::CaptivePortalState state = 274 GetCaptivePortalState(service_path); 275 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN) 276 return; 277 278 UMA_HISTOGRAM_ENUMERATION("CaptivePortal.OOBE.DetectionResult", 279 state.status, 280 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 281 282 switch (state.status) { 283 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN: 284 NOTREACHED(); 285 break; 286 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE: 287 if (network->connection_state() == flimflam::kStateOnline || 288 network->connection_state() == flimflam::kStatePortal) 289 RecordDiscrepancyWithShill(network, state.status); 290 break; 291 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE: 292 if (network->connection_state() != flimflam::kStateOnline) 293 RecordDiscrepancyWithShill(network, state.status); 294 break; 295 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL: 296 if (network->connection_state() != flimflam::kStatePortal) 297 RecordDiscrepancyWithShill(network, state.status); 298 break; 299 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED: 300 if (network->connection_state() != flimflam::kStateOnline) 301 RecordDiscrepancyWithShill(network, state.status); 302 break; 303 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 304 NOTREACHED(); 305 break; 306 } 307} 308 309} // namespace 310 311// SigninScreenHandler implementation ------------------------------------------ 312 313SigninScreenHandler::SigninScreenHandler( 314 const scoped_refptr<NetworkStateInformer>& network_state_informer, 315 ErrorScreenActor* error_screen_actor) 316 : ui_state_(UI_STATE_UNKNOWN), 317 frame_state_(FRAME_STATE_UNKNOWN), 318 frame_error_(net::OK), 319 delegate_(NULL), 320 native_window_delegate_(NULL), 321 show_on_init_(false), 322 oobe_ui_(false), 323 focus_stolen_(false), 324 gaia_silent_load_(false), 325 is_account_picker_showing_first_time_(false), 326 dns_cleared_(false), 327 dns_clear_task_running_(false), 328 cookies_cleared_(false), 329 network_state_informer_(network_state_informer), 330 weak_factory_(this), 331 webui_visible_(false), 332 preferences_changed_delayed_(false), 333 error_screen_actor_(error_screen_actor), 334 is_first_update_state_call_(true), 335 offline_login_active_(false), 336 last_network_state_(NetworkStateInformer::UNKNOWN), 337 has_pending_auth_ui_(false) { 338 DCHECK(network_state_informer_); 339 DCHECK(error_screen_actor_); 340 network_state_informer_->AddObserver(this); 341 CrosSettings::Get()->AddSettingsObserver(kAccountsPrefAllowNewUser, this); 342 CrosSettings::Get()->AddSettingsObserver(kAccountsPrefAllowGuest, this); 343 344 registrar_.Add(this, 345 chrome::NOTIFICATION_AUTH_NEEDED, 346 content::NotificationService::AllSources()); 347 registrar_.Add(this, 348 chrome::NOTIFICATION_AUTH_SUPPLIED, 349 content::NotificationService::AllSources()); 350 registrar_.Add(this, 351 chrome::NOTIFICATION_AUTH_CANCELLED, 352 content::NotificationService::AllSources()); 353} 354 355SigninScreenHandler::~SigninScreenHandler() { 356 weak_factory_.InvalidateWeakPtrs(); 357 SystemKeyEventListener* key_event_listener = 358 SystemKeyEventListener::GetInstance(); 359 if (key_event_listener) 360 key_event_listener->RemoveCapsLockObserver(this); 361 if (delegate_) 362 delegate_->SetWebUIHandler(NULL); 363 network_state_informer_->RemoveObserver(this); 364 CrosSettings::Get()->RemoveSettingsObserver(kAccountsPrefAllowNewUser, this); 365 CrosSettings::Get()->RemoveSettingsObserver(kAccountsPrefAllowGuest, this); 366} 367 368void SigninScreenHandler::DeclareLocalizedValues( 369 LocalizedValuesBuilder* builder) { 370 builder->Add("signinScreenTitle", IDS_SIGNIN_SCREEN_TITLE); 371 builder->Add("signinScreenPasswordChanged", 372 IDS_SIGNIN_SCREEN_PASSWORD_CHANGED); 373 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT); 374 builder->Add("podMenuButtonAccessibleName", 375 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME); 376 builder->Add("podMenuRemoveItemAccessibleName", 377 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME); 378 builder->Add("passwordFieldAccessibleName", 379 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME); 380 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER); 381 builder->Add("signinButton", IDS_LOGIN_BUTTON); 382 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON); 383 builder->Add("addUser", IDS_ADD_USER_BUTTON); 384 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON); 385 builder->Add("cancel", IDS_CANCEL); 386 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT); 387 builder->Add("createAccount", IDS_CREATE_ACCOUNT_HTML); 388 builder->Add("guestSignin", IDS_BROWSE_WITHOUT_SIGNING_IN_HTML); 389 builder->Add("createLocallyManagedUser", 390 IDS_CREATE_LOCALLY_MANAGED_USER_HTML); 391 builder->Add("createManagedUserFeatureName", 392 IDS_CREATE_LOCALLY_MANAGED_USER_FEATURE_NAME); 393 builder->Add("createManagedUserNoManagerText", 394 IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT); 395 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML); 396 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER); 397 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER); 398 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE); 399 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT); 400 builder->Add("errorTpmFailureRebootButton", 401 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON); 402 builder->Add( 403 "disabledAddUserTooltip", 404 g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ? 405 IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE : 406 IDS_DISABLED_ADD_USER_TOOLTIP); 407 408 // Strings used by password changed dialog. 409 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE); 410 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC); 411 builder->AddF("passwordChangedMoreInfo", 412 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO, 413 IDS_SHORT_PRODUCT_OS_NAME); 414 415 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT); 416 builder->Add("oldPasswordIncorrect", 417 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD); 418 builder->Add("passwordChangedCantRemember", 419 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER); 420 builder->Add("passwordChangedBackButton", 421 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON); 422 builder->Add("passwordChangedsOkButton", IDS_OK); 423 builder->Add("passwordChangedProceedAnyway", 424 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY); 425 builder->Add("proceedAnywayButton", 426 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON); 427 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT); 428 builder->Add("publicAccountReminder", 429 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER); 430 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER); 431 builder->Add("publicAccountEnterAccessibleName", 432 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME); 433 434 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) 435 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE); 436} 437 438void SigninScreenHandler::Show(bool oobe_ui) { 439 CHECK(delegate_); 440 oobe_ui_ = oobe_ui; 441 if (!page_is_ready()) { 442 show_on_init_ = true; 443 return; 444 } 445 446 if (oobe_ui) { 447 // Shows new user sign-in for OOBE. 448 HandleShowAddUser(NULL); 449 } else { 450 // Populates account picker. Animation is turned off for now until we 451 // figure out how to make it fast enough. 452 SendUserList(false); 453 454 // Reset Caps Lock state when login screen is shown. 455 input_method::InputMethodManager::Get()->GetXKeyboard()-> 456 SetCapsLockEnabled(false); 457 458 DictionaryValue params; 459 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent()); 460 UpdateUIState(UI_STATE_ACCOUNT_PICKER, ¶ms); 461 } 462} 463 464void SigninScreenHandler::ShowRetailModeLoginSpinner() { 465 CallJS("showLoginSpinner"); 466} 467 468void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) { 469 delegate_ = delegate; 470 if (delegate_) 471 delegate_->SetWebUIHandler(this); 472} 473 474void SigninScreenHandler::SetNativeWindowDelegate( 475 NativeWindowDelegate* native_window_delegate) { 476 native_window_delegate_ = native_window_delegate; 477} 478 479void SigninScreenHandler::OnNetworkReady() { 480 MaybePreloadAuthExtension(); 481} 482 483void SigninScreenHandler::UpdateState(NetworkStateInformer::State state, 484 ErrorScreenActor::ErrorReason reason) { 485 UpdateStateInternal(state, reason, false); 486} 487 488// SigninScreenHandler, private: ----------------------------------------------- 489 490void SigninScreenHandler::UpdateUIState(UIState ui_state, 491 DictionaryValue* params) { 492 switch (ui_state) { 493 case UI_STATE_GAIA_SIGNIN: 494 ui_state_ = UI_STATE_GAIA_SIGNIN; 495 ShowScreen(OobeUI::kScreenGaiaSignin, params); 496 break; 497 case UI_STATE_ACCOUNT_PICKER: 498 ui_state_ = UI_STATE_ACCOUNT_PICKER; 499 ShowScreen(OobeUI::kScreenAccountPicker, params); 500 break; 501 case UI_STATE_LOCALLY_MANAGED_USER_CREATION: 502 ui_state_ = UI_STATE_LOCALLY_MANAGED_USER_CREATION; 503 ShowScreen(OobeUI::kScreenManagedUserCreationDialog, params); 504 break; 505 default: 506 NOTREACHED(); 507 break; 508 } 509} 510 511// TODO (ygorshenin@): split this method into small parts. 512void SigninScreenHandler::UpdateStateInternal( 513 NetworkStateInformer::State state, 514 ErrorScreenActor::ErrorReason reason, 515 bool force_update) { 516 // Do nothing once user has signed in or sign in is in progress. 517 // TODO(ygorshenin): We will end up here when processing network state 518 // notification but no ShowSigninScreen() was called so delegate_ will be 519 // NULL. Network state processing logic does not belong here. 520 if (delegate_ && 521 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) { 522 return; 523 } 524 525 const std::string service_path = 526 network_state_informer_->last_network_service_path(); 527 const std::string network_id = 528 GetNetworkUniqueId(service_path); 529 530 // Skip "update" notification about OFFLINE state from 531 // NetworkStateInformer if previous notification already was 532 // delayed. 533 if (state == NetworkStateInformer::OFFLINE && 534 reason == ErrorScreenActor::ERROR_REASON_UPDATE && 535 !update_state_closure_.IsCancelled()) { 536 return; 537 } 538 539 // TODO (ygorshenin@): switch log level to INFO once signin screen 540 // will be tested well. 541 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): " 542 << "state=" << NetworkStateStatusString(state) << ", " 543 << "network_id=" << network_id << ", " 544 << "reason=" << ErrorReasonString(reason) << ", " 545 << "force_update=" << force_update; 546 update_state_closure_.Cancel(); 547 548 // Delay UpdateStateInternal() call in the following cases: 549 // 1. this is the first call and it's about offline state of the 550 // current network. This can happen because device is just powered 551 // up and network stack isn't ready now. 552 // 2. proxy auth ui is displayed. UpdateStateCall() is delayed to 553 // prevent screen change behind proxy auth ui. 554 if ((state == NetworkStateInformer::OFFLINE && is_first_update_state_call_) || 555 has_pending_auth_ui_) { 556 is_first_update_state_call_ = false; 557 update_state_closure_.Reset( 558 base::Bind( 559 &SigninScreenHandler::UpdateStateInternal, 560 weak_factory_.GetWeakPtr(), state, reason, force_update)); 561 base::MessageLoop::current()->PostDelayedTask( 562 FROM_HERE, 563 update_state_closure_.callback(), 564 base::TimeDelta::FromSeconds(kOfflineTimeoutSec)); 565 return; 566 } 567 is_first_update_state_call_ = false; 568 569 // Don't show or hide error screen if we're in connecting state. 570 if (state == NetworkStateInformer::CONNECTING && !force_update) { 571 if (connecting_closure_.IsCancelled()) { 572 // First notification about CONNECTING state. 573 connecting_closure_.Reset( 574 base::Bind(&SigninScreenHandler::UpdateStateInternal, 575 weak_factory_.GetWeakPtr(), state, reason, true)); 576 base::MessageLoop::current()->PostDelayedTask( 577 FROM_HERE, 578 connecting_closure_.callback(), 579 base::TimeDelta::FromSeconds(kConnectingTimeoutSec)); 580 } 581 return; 582 } 583 connecting_closure_.Cancel(); 584 585 const bool is_online = IsOnline(state, reason); 586 const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason); 587 const bool is_gaia_loading_timeout = 588 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 589 const bool is_gaia_error = frame_error_ != net::OK && 590 frame_error_ != net::ERR_NETWORK_CHANGED; 591 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError(); 592 const bool error_screen_should_overlay = 593 !offline_login_active_ && IsGaiaVisible(); 594 const bool from_not_online_to_online_transition = 595 is_online && last_network_state_ != NetworkStateInformer::ONLINE; 596 last_network_state_ = state; 597 598 if (is_online || !is_under_captive_portal) 599 error_screen_actor_->HideCaptivePortal(); 600 601 // Hide offline message (if needed) and return if current screen is 602 // not a Gaia frame. 603 if (!is_gaia_signin) { 604 if (!IsSigninScreenHiddenByError()) 605 HideOfflineMessage(state, reason); 606 return; 607 } 608 609 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state. 610 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED && 611 from_not_online_to_online_transition) { 612 // Schedules a immediate retry. 613 LOG(WARNING) << "Retry page load since network has been changed."; 614 ReloadGaiaScreen(); 615 } 616 617 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED && 618 error_screen_should_overlay) { 619 // Schedules a immediate retry. 620 LOG(WARNING) << "Retry page load since proxy settings has been changed."; 621 ReloadGaiaScreen(); 622 } 623 624 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR) { 625 LOG(WARNING) << "Retry page load due to reason: " 626 << ErrorReasonString(reason); 627 ReloadGaiaScreen(); 628 } 629 630 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) && 631 !offline_login_active_) { 632 SetupAndShowOfflineMessage(state, reason); 633 } else { 634 HideOfflineMessage(state, reason); 635 } 636} 637 638void SigninScreenHandler::SetupAndShowOfflineMessage( 639 NetworkStateInformer:: State state, 640 ErrorScreenActor::ErrorReason reason) { 641 const std::string service_path = 642 network_state_informer_->last_network_service_path(); 643 const std::string network_id = GetNetworkUniqueId(service_path); 644 const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason); 645 const bool is_proxy_error = IsProxyError(state, reason); 646 const bool is_gaia_loading_timeout = 647 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 648 649 LOG(WARNING) << "Offline message is displayed"; 650 651 // Record portal detection stats only if we're going to show or 652 // change state of the error screen. 653 RecordNetworkPortalDetectorStats(service_path); 654 655 if (is_proxy_error) { 656 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY, 657 std::string()); 658 } else if (is_under_captive_portal) { 659 // Do not bother a user with obsessive captive portal showing. This 660 // check makes captive portal being shown only once: either when error 661 // screen is shown for the first time or when switching from another 662 // error screen (offline, proxy). 663 if (IsGaiaVisible() || 664 (error_screen_actor_->error_state() != 665 ErrorScreen::ERROR_STATE_PORTAL)) { 666 error_screen_actor_->FixCaptivePortal(); 667 } 668 const std::string network_name = GetNetworkName(service_path); 669 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, 670 network_name); 671 } else if (is_gaia_loading_timeout) { 672 error_screen_actor_->SetErrorState( 673 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string()); 674 } else { 675 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE, 676 std::string()); 677 } 678 679 const bool guest_signin_allowed = IsGuestSigninAllowed() && 680 IsSigninScreenError(error_screen_actor_->error_state()); 681 error_screen_actor_->AllowGuestSignin(guest_signin_allowed); 682 683 const bool offline_login_allowed = IsOfflineLoginAllowed() && 684 IsSigninScreenError(error_screen_actor_->error_state()) && 685 error_screen_actor_->error_state() != 686 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT; 687 error_screen_actor_->AllowOfflineLogin(offline_login_allowed); 688 689 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) { 690 DictionaryValue params; 691 const std::string connection_type = 692 network_state_informer_->last_network_type(); 693 params.SetString("lastNetworkType", connection_type); 694 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN); 695 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, ¶ms); 696 } 697} 698 699void SigninScreenHandler::HideOfflineMessage( 700 NetworkStateInformer::State state, 701 ErrorScreenActor::ErrorReason reason) { 702 if (!IsSigninScreenHiddenByError()) 703 return; 704 705 LOG(WARNING) << "Offline message is hidden"; 706 error_screen_actor_->Hide(); 707 708 // Forces a reload for Gaia screen on hiding error message. 709 if (IsGaiaVisible() || IsGaiaHiddenByError()) 710 ReloadGaiaScreen(); 711} 712 713void SigninScreenHandler::ReloadGaiaScreen() { 714 if (frame_state_ == FRAME_STATE_LOADING) 715 return; 716 NetworkStateInformer::State state = network_state_informer_->state(); 717 if (state != NetworkStateInformer::ONLINE) { 718 LOG(WARNING) << "Skipping reload of auth extension frame since " 719 << "network state=" << NetworkStateStatusString(state); 720 return; 721 } 722 LOG(WARNING) << "Reload auth extension frame."; 723 frame_state_ = FRAME_STATE_LOADING; 724 CallJS("login.GaiaSigninScreen.doReload"); 725} 726 727void SigninScreenHandler::Initialize() { 728 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed), 729 // don't do anything, just return. 730 if (!delegate_) 731 return; 732 733 // Register for Caps Lock state change notifications; 734 SystemKeyEventListener* key_event_listener = 735 SystemKeyEventListener::GetInstance(); 736 if (key_event_listener) 737 key_event_listener->AddCapsLockObserver(this); 738 739 if (show_on_init_) { 740 show_on_init_ = false; 741 Show(oobe_ui_); 742 } 743} 744 745gfx::NativeWindow SigninScreenHandler::GetNativeWindow() { 746 if (native_window_delegate_) 747 return native_window_delegate_->GetNativeWindow(); 748 return NULL; 749} 750 751void SigninScreenHandler::RegisterMessages() { 752 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser); 753 AddCallback("completeLogin", &SigninScreenHandler::HandleCompleteLogin); 754 AddCallback("completeAuthentication", 755 &SigninScreenHandler::HandleCompleteAuthentication); 756 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers); 757 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser); 758 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito); 759 AddCallback("showLocallyManagedUserCreationScreen", 760 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen); 761 AddCallback("launchPublicAccount", 762 &SigninScreenHandler::HandleLaunchPublicAccount); 763 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin); 764 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem); 765 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser); 766 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem); 767 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper); 768 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser); 769 AddCallback("toggleEnrollmentScreen", 770 &SigninScreenHandler::HandleToggleEnrollmentScreen); 771 AddCallback("toggleResetScreen", 772 &SigninScreenHandler::HandleToggleResetScreen); 773 AddCallback("launchHelpApp", &SigninScreenHandler::HandleLaunchHelpApp); 774 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount); 775 AddCallback("accountPickerReady", 776 &SigninScreenHandler::HandleAccountPickerReady); 777 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady); 778 AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady); 779 AddCallback("demoWebuiReady", &SigninScreenHandler::HandleDemoWebuiReady); 780 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser); 781 AddCallback("userImagesLoaded", &SigninScreenHandler::HandleUserImagesLoaded); 782 AddCallback("networkErrorShown", 783 &SigninScreenHandler::HandleNetworkErrorShown); 784 AddCallback("openProxySettings", 785 &SigninScreenHandler::HandleOpenProxySettings); 786 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible); 787 AddCallback("cancelPasswordChangedFlow", 788 &SigninScreenHandler::HandleCancelPasswordChangedFlow); 789 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData); 790 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData); 791 AddCallback("loginUIStateChanged", 792 &SigninScreenHandler::HandleLoginUIStateChanged); 793 AddCallback("unlockOnLoginSuccess", 794 &SigninScreenHandler::HandleUnlockOnLoginSuccess); 795 AddCallback("frameLoadingCompleted", 796 &SigninScreenHandler::HandleFrameLoadingCompleted); 797 AddCallback("showLoadingTimeoutError", 798 &SigninScreenHandler::HandleShowLoadingTimeoutError); 799 AddCallback("updateOfflineLogin", 800 &SigninScreenHandler::HandleUpdateOfflineLogin); 801} 802 803void SigninScreenHandler::HandleGetUsers() { 804 SendUserList(false); 805} 806 807void SigninScreenHandler::ClearAndEnablePassword() { 808 CallJS("cr.ui.Oobe.resetSigninUI", false); 809} 810 811void SigninScreenHandler::ClearUserPodPassword() { 812 CallJS("cr.ui.Oobe.clearUserPodPassword"); 813} 814 815void SigninScreenHandler::RefocusCurrentPod() { 816 CallJS("cr.ui.Oobe.refocusCurrentPod"); 817} 818 819void SigninScreenHandler::OnLoginSuccess(const std::string& username) { 820 CallJS("cr.ui.Oobe.onLoginSuccess", username); 821} 822 823void SigninScreenHandler::OnUserRemoved(const std::string& username) { 824 SendUserList(false); 825} 826 827void SigninScreenHandler::OnUserImageChanged(const User& user) { 828 if (page_is_ready()) 829 CallJS("login.AccountPickerScreen.updateUserImage", user.email()); 830} 831 832void SigninScreenHandler::OnPreferencesChanged() { 833 // Make sure that one of the login UI is fully functional now, otherwise 834 // preferences update would be picked up next time it will be shown. 835 if (!webui_visible_) { 836 LOG(WARNING) << "Login UI is not active - postponed prefs change."; 837 preferences_changed_delayed_ = true; 838 return; 839 } 840 841 if (delegate_ && !delegate_->IsShowUsers()) { 842 HandleShowAddUser(NULL); 843 } else { 844 SendUserList(false); 845 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL); 846 } 847 preferences_changed_delayed_ = false; 848} 849 850void SigninScreenHandler::ResetSigninScreenHandlerDelegate() { 851 SetDelegate(NULL); 852} 853 854void SigninScreenHandler::ShowError(int login_attempts, 855 const std::string& error_text, 856 const std::string& help_link_text, 857 HelpAppLauncher::HelpTopic help_topic_id) { 858 CallJS("cr.ui.Oobe.showSignInError", login_attempts, error_text, 859 help_link_text, static_cast<int>(help_topic_id)); 860} 861 862void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) { 863 switch (error_id) { 864 case LoginDisplay::TPM_ERROR: 865 CallJS("cr.ui.Oobe.showTpmError"); 866 break; 867 default: 868 NOTREACHED() << "Unknown sign in error"; 869 break; 870 } 871} 872 873void SigninScreenHandler::ShowSigninUI(const std::string& email) { 874 CallJS("cr.ui.Oobe.showSigninUI", email); 875} 876 877void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) { 878 email_ = username; 879 password_changed_for_.insert(email_); 880 CallJS("cr.ui.Oobe.showSigninUI", email_); 881 CallJS("login.AccountPickerScreen.updateUserGaiaNeeded", email_); 882} 883 884void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) { 885 CallJS("cr.ui.Oobe.showPasswordChangedScreen", show_password_error); 886} 887 888void SigninScreenHandler::ShowSigninScreenForCreds( 889 const std::string& username, 890 const std::string& password) { 891 VLOG(2) << "ShowSigninScreenForCreds " << username << " " << password; 892 893 test_user_ = username; 894 test_pass_ = password; 895 HandleShowAddUser(NULL); 896} 897 898void SigninScreenHandler::SetGaiaUrlForTesting(const GURL& gaia_url) { 899 gaia_url_for_test_ = gaia_url; 900} 901 902void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) { 903 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 904 cookies_cleared_ = true; 905 on_clear_callback.Run(); 906} 907 908void SigninScreenHandler::OnCapsLockChange(bool enabled) { 909 if (page_is_ready()) 910 CallJS("login.AccountPickerScreen.setCapsLockState", enabled); 911} 912 913void SigninScreenHandler::Observe(int type, 914 const content::NotificationSource& source, 915 const content::NotificationDetails& details) { 916 switch (type) { 917 case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: { 918 UpdateAuthExtension(); 919 UpdateAddButtonStatus(); 920 break; 921 } 922 case chrome::NOTIFICATION_AUTH_NEEDED: { 923 has_pending_auth_ui_ = true; 924 break; 925 } 926 case chrome::NOTIFICATION_AUTH_SUPPLIED: 927 has_pending_auth_ui_ = false; 928 if (IsSigninScreenHiddenByError()) { 929 // Hide error screen and reload auth extension. 930 HideOfflineMessage(network_state_informer_->state(), 931 ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED); 932 } else if (ui_state_ == UI_STATE_GAIA_SIGNIN) { 933 // Reload auth extension as proxy credentials are supplied. 934 ReloadGaiaScreen(); 935 } 936 break; 937 case chrome::NOTIFICATION_AUTH_CANCELLED: { 938 // Don't reload auth extension if proxy auth dialog was cancelled. 939 has_pending_auth_ui_ = false; 940 break; 941 } 942 default: 943 NOTREACHED() << "Unexpected notification " << type; 944 } 945} 946 947void SigninScreenHandler::OnDnsCleared() { 948 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 949 dns_clear_task_running_ = false; 950 dns_cleared_ = true; 951 ShowSigninScreenIfReady(); 952} 953 954void SigninScreenHandler::ShowSigninScreenIfReady() { 955 if (!dns_cleared_ || !cookies_cleared_ || !delegate_) 956 return; 957 958 std::string active_network = 959 network_state_informer_->active_network_service_path(); 960 if (gaia_silent_load_ && 961 (!network_state_informer_->is_online() || 962 gaia_silent_load_network_ != active_network)) { 963 // Network has changed. Force Gaia reload. 964 gaia_silent_load_ = false; 965 // Gaia page will be realoded, so focus isn't stolen anymore. 966 focus_stolen_ = false; 967 } 968 969 // Note that LoadAuthExtension clears |email_|. 970 if (email_.empty()) 971 delegate_->LoadSigninWallpaper(); 972 else 973 delegate_->LoadWallpaper(email_); 974 975 LoadAuthExtension(!gaia_silent_load_, false, false); 976 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL); 977 978 if (gaia_silent_load_) { 979 // The variable is assigned to false because silently loaded Gaia page was 980 // used. 981 gaia_silent_load_ = false; 982 if (focus_stolen_) 983 HandleLoginWebuiReady(); 984 } 985 986 UpdateState(network_state_informer_->state(), 987 ErrorScreenActor::ERROR_REASON_UPDATE); 988} 989 990 991void SigninScreenHandler::UpdateAuthParams(DictionaryValue* params) { 992 UpdateAuthParamsFromSettings(params, CrosSettings::Get()); 993 994 // TODO(nkostylev): Allow locally managed user creation only if: 995 // 1. Enterprise managed device > is allowed by policy. 996 // 2. Consumer device > owner exists. 997 // g_browser_process->browser_policy_connector()->IsEnterpriseManaged() 998 // const UserList& users = delegate_->GetUsers(); 999 // bool single_user = users.size() == 1; 1000 // chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner); 1001 1002 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 1003 bool managed_users_enabled = 1004 command_line->HasSwitch(::switches::kEnableManagedUsers); 1005 bool managed_users_can_create = false; 1006 if (managed_users_enabled) 1007 managed_users_can_create = delegate_->GetUsers().size() > 0; 1008 params->SetBoolean("managedUsersEnabled", managed_users_enabled); 1009 params->SetBoolean("managedUsersCanCreate", managed_users_can_create); 1010} 1011 1012void SigninScreenHandler::LoadAuthExtension( 1013 bool force, bool silent_load, bool offline) { 1014 DictionaryValue params; 1015 1016 params.SetBoolean("forceReload", force); 1017 params.SetBoolean("silentLoad", silent_load); 1018 params.SetBoolean("isLocal", offline); 1019 params.SetBoolean("passwordChanged", 1020 !email_.empty() && password_changed_for_.count(email_)); 1021 if (delegate_) 1022 params.SetBoolean("isShowUsers", delegate_->IsShowUsers()); 1023 params.SetBoolean("useOffline", offline); 1024 params.SetString("email", email_); 1025 email_.clear(); 1026 1027 UpdateAuthParams(¶ms); 1028 1029 if (!offline) { 1030 const std::string app_locale = g_browser_process->GetApplicationLocale(); 1031 if (!app_locale.empty()) 1032 params.SetString("hl", app_locale); 1033 } else { 1034 base::DictionaryValue *localized_strings = new base::DictionaryValue(); 1035 localized_strings->SetString("stringEmail", 1036 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMAIL)); 1037 localized_strings->SetString("stringPassword", 1038 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_PASSWORD)); 1039 localized_strings->SetString("stringSignIn", 1040 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_SIGNIN)); 1041 localized_strings->SetString("stringEmptyEmail", 1042 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_EMAIL)); 1043 localized_strings->SetString("stringEmptyPassword", 1044 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_PASSWORD)); 1045 localized_strings->SetString("stringError", 1046 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_ERROR)); 1047 params.Set("localizedStrings", localized_strings); 1048 } 1049 1050 const GURL gaia_url = gaia_url_for_test_.is_empty() ? 1051 GaiaUrls::GetInstance()->gaia_url() : 1052 gaia_url_for_test_; 1053 params.SetString("gaiaUrl", gaia_url.spec()); 1054 1055 // Test automation data: 1056 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 1057 if (command_line->HasSwitch(switches::kAuthExtensionPath)) { 1058 if (!test_user_.empty()) { 1059 params.SetString("test_email", test_user_); 1060 test_user_.clear(); 1061 } 1062 if (!test_pass_.empty()) { 1063 params.SetString("test_password", test_pass_); 1064 test_pass_.clear(); 1065 } 1066 } 1067 CallJS("login.GaiaSigninScreen.loadAuthExtension", params); 1068} 1069 1070void SigninScreenHandler::UpdateAuthExtension() { 1071 DictionaryValue params; 1072 UpdateAuthParams(¶ms); 1073 CallJS("login.GaiaSigninScreen.updateAuthExtension", params); 1074} 1075 1076void SigninScreenHandler::UpdateAddButtonStatus() { 1077 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus", 1078 AllWhitelistedUsersPresent()); 1079} 1080 1081void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email, 1082 const std::string& password) { 1083 if (!delegate_) 1084 return; 1085 const std::string sanitized_email = gaia::SanitizeEmail(typed_email); 1086 delegate_->SetDisplayEmail(sanitized_email); 1087 delegate_->CompleteLogin(UserContext(sanitized_email, 1088 password, 1089 std::string())); // auth_code 1090} 1091 1092void SigninScreenHandler::HandleCompleteAuthentication( 1093 const std::string& email, 1094 const std::string& password, 1095 const std::string& auth_code) { 1096 if (!delegate_) 1097 return; 1098 const std::string sanitized_email = gaia::SanitizeEmail(email); 1099 delegate_->SetDisplayEmail(sanitized_email); 1100 delegate_->CompleteLogin(UserContext(sanitized_email, password, auth_code)); 1101} 1102 1103void SigninScreenHandler::HandleAuthenticateUser(const std::string& username, 1104 const std::string& password) { 1105 if (!delegate_) 1106 return; 1107 delegate_->Login(UserContext(gaia::SanitizeEmail(username), 1108 password, 1109 std::string())); // auth_code 1110} 1111 1112void SigninScreenHandler::HandleLaunchDemoUser() { 1113 if (delegate_) 1114 delegate_->LoginAsRetailModeUser(); 1115} 1116 1117void SigninScreenHandler::HandleLaunchIncognito() { 1118 if (delegate_) 1119 delegate_->LoginAsGuest(); 1120} 1121 1122void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() { 1123 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 1124 if (!command_line->HasSwitch(::switches::kEnableManagedUsers)) 1125 return; 1126 scoped_ptr<DictionaryValue> params(new DictionaryValue()); 1127 LoginDisplayHostImpl::default_host()-> 1128 StartWizard(WizardController::kLocallyManagedUserCreationScreenName, 1129 params.Pass()); 1130} 1131 1132void SigninScreenHandler::HandleLaunchPublicAccount( 1133 const std::string& username) { 1134 if (delegate_) 1135 delegate_->LoginAsPublicAccount(username); 1136} 1137 1138void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) { 1139 if (!delegate_ || delegate_->IsShowUsers()) { 1140 NOTREACHED(); 1141 return; 1142 } 1143 if (!args->GetString(0, &email_)) 1144 email_.clear(); 1145 // Load auth extension. Parameters are: force reload, do not load extension in 1146 // background, use offline version. 1147 LoadAuthExtension(true, false, true); 1148 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL); 1149} 1150 1151void SigninScreenHandler::HandleShutdownSystem() { 1152 ash::Shell::GetInstance()->session_state_controller()->RequestShutdown(); 1153} 1154 1155void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) { 1156 if (delegate_) 1157 delegate_->LoadWallpaper(email); 1158} 1159 1160void SigninScreenHandler::HandleRebootSystem() { 1161 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 1162} 1163 1164void SigninScreenHandler::HandleRemoveUser(const std::string& email) { 1165 if (!delegate_) 1166 return; 1167 delegate_->RemoveUser(email); 1168 UpdateAddButtonStatus(); 1169} 1170 1171void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) { 1172 email_.clear(); 1173 // |args| can be null if it's OOBE. 1174 if (args) 1175 args->GetString(0, &email_); 1176 is_account_picker_showing_first_time_ = false; 1177 1178 if (gaia_silent_load_ && email_.empty()) { 1179 dns_cleared_ = true; 1180 cookies_cleared_ = true; 1181 ShowSigninScreenIfReady(); 1182 } else { 1183 StartClearingDnsCache(); 1184 StartClearingCookies(base::Bind( 1185 &SigninScreenHandler::ShowSigninScreenIfReady, 1186 weak_factory_.GetWeakPtr())); 1187 } 1188} 1189 1190void SigninScreenHandler::HandleToggleEnrollmentScreen() { 1191 if (delegate_) 1192 delegate_->ShowEnterpriseEnrollmentScreen(); 1193} 1194 1195void SigninScreenHandler::HandleToggleResetScreen() { 1196 if (delegate_ && 1197 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) { 1198 delegate_->ShowResetScreen(); 1199 } 1200} 1201 1202void SigninScreenHandler::HandleLaunchHelpApp(double help_topic_id) { 1203 if (!delegate_) 1204 return; 1205 if (!help_app_.get()) 1206 help_app_ = new HelpAppLauncher(GetNativeWindow()); 1207 help_app_->ShowHelpTopic( 1208 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id)); 1209} 1210 1211void SigninScreenHandler::FillUserDictionary(User* user, 1212 bool is_owner, 1213 DictionaryValue* user_dict) { 1214 const std::string& email = user->email(); 1215 bool is_public_account = 1216 user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT; 1217 bool is_locally_managed_user = 1218 user->GetType() == User::USER_TYPE_LOCALLY_MANAGED; 1219 bool signed_in = user == UserManager::Get()->GetLoggedInUser(); 1220 1221 user_dict->SetString(kKeyUsername, email); 1222 user_dict->SetString(kKeyEmailAddress, user->display_email()); 1223 user_dict->SetString(kKeyDisplayName, user->GetDisplayName()); 1224 user_dict->SetBoolean(kKeyPublicAccount, is_public_account); 1225 user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user); 1226 user_dict->SetInteger(kKeyOauthTokenStatus, user->oauth_token_status()); 1227 user_dict->SetBoolean(kKeySignedIn, signed_in); 1228 user_dict->SetBoolean(kKeyIsOwner, is_owner); 1229 1230 if (is_public_account) { 1231 policy::BrowserPolicyConnector* policy_connector = 1232 g_browser_process->browser_policy_connector(); 1233 1234 if (policy_connector->IsEnterpriseManaged()) { 1235 user_dict->SetString(kKeyEnterpriseDomain, 1236 policy_connector->GetEnterpriseDomain()); 1237 } 1238 } 1239} 1240 1241void SigninScreenHandler::SendUserList(bool animated) { 1242 if (!delegate_) 1243 return; 1244 1245 size_t max_non_owner_users = kMaxUsers - 1; 1246 size_t non_owner_count = 0; 1247 1248 ListValue users_list; 1249 const UserList& users = delegate_->GetUsers(); 1250 1251 // TODO(nkostylev): Show optional intro dialog about multi-profiles feature 1252 // based on user preferences. http://crbug.com/230862 1253 1254 // TODO(nkostylev): Move to a separate method in UserManager. 1255 // http://crbug.com/230852 1256 bool is_signin_to_add = LoginDisplayHostImpl::default_host() && 1257 UserManager::Get()->IsUserLoggedIn(); 1258 1259 bool single_user = users.size() == 1; 1260 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 1261 const std::string& email = (*it)->email(); 1262 if (is_signin_to_add && (*it)->is_logged_in()) { 1263 // Skip all users that are already signed in. 1264 continue; 1265 } 1266 1267 std::string owner; 1268 chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner); 1269 bool is_owner = (email == owner); 1270 1271 if (non_owner_count < max_non_owner_users || is_owner) { 1272 DictionaryValue* user_dict = new DictionaryValue(); 1273 FillUserDictionary(*it, is_owner, user_dict); 1274 bool is_public_account = 1275 ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT); 1276 bool signed_in = *it == UserManager::Get()->GetLoggedInUser(); 1277 // Single user check here is necessary because owner info might not be 1278 // available when running into login screen on first boot. 1279 // See http://crosbug.com/12723 1280 user_dict->SetBoolean(kKeyCanRemove, 1281 !single_user && 1282 !email.empty() && 1283 !is_owner && 1284 !is_public_account && 1285 !signed_in && 1286 !is_signin_to_add); 1287 1288 users_list.Append(user_dict); 1289 if (!is_owner) 1290 ++non_owner_count; 1291 } 1292 } 1293 1294 CallJS("login.AccountPickerScreen.loadUsers", users_list, animated, 1295 delegate_->IsShowGuest()); 1296} 1297 1298void SigninScreenHandler::HandleAccountPickerReady() { 1299 LOG(INFO) << "Login WebUI >> AccountPickerReady"; 1300 1301 if (delegate_ && !ScreenLocker::default_screen_locker() && 1302 !chromeos::IsMachineHWIDCorrect() && 1303 !oobe_ui_) { 1304 delegate_->ShowWrongHWIDScreen(); 1305 return; 1306 } 1307 1308 PrefService* prefs = g_browser_process->local_state(); 1309 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) { 1310 prefs->SetBoolean(prefs::kFactoryResetRequested, false); 1311 prefs->CommitPendingWrite(); 1312 HandleToggleResetScreen(); 1313 return; 1314 } 1315 1316 is_account_picker_showing_first_time_ = true; 1317 MaybePreloadAuthExtension(); 1318 1319 if (ScreenLocker::default_screen_locker()) { 1320 content::NotificationService::current()->Notify( 1321 chrome::NOTIFICATION_LOCK_WEBUI_READY, 1322 content::NotificationService::AllSources(), 1323 content::NotificationService::NoDetails()); 1324 } 1325 1326 if (delegate_) 1327 delegate_->OnSigninScreenReady(); 1328} 1329 1330void SigninScreenHandler::HandleWallpaperReady() { 1331 if (ScreenLocker::default_screen_locker()) { 1332 content::NotificationService::current()->Notify( 1333 chrome::NOTIFICATION_LOCK_BACKGROUND_DISPLAYED, 1334 content::NotificationService::AllSources(), 1335 content::NotificationService::NoDetails()); 1336 } 1337} 1338 1339void SigninScreenHandler::HandleLoginWebuiReady() { 1340 if (focus_stolen_) { 1341 // Set focus to the Gaia page. 1342 // TODO(altimofeev): temporary solution, until focus parameters are 1343 // implemented on the Gaia side. 1344 // Do this only once. Any subsequent call would relod GAIA frame. 1345 focus_stolen_ = false; 1346 const char code[] = "gWindowOnLoad();"; 1347 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost(); 1348 rvh->ExecuteJavascriptInWebFrame( 1349 ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"), 1350 ASCIIToUTF16(code)); 1351 } 1352 if (!gaia_silent_load_) { 1353 content::NotificationService::current()->Notify( 1354 chrome::NOTIFICATION_LOGIN_WEBUI_LOADED, 1355 content::NotificationService::AllSources(), 1356 content::NotificationService::NoDetails()); 1357 } else { 1358 focus_stolen_ = true; 1359 // Prevent focus stealing by the Gaia page. 1360 // TODO(altimofeev): temporary solution, until focus parameters are 1361 // implemented on the Gaia side. 1362 const char code[] = "var gWindowOnLoad = window.onload; " 1363 "window.onload=function() {};"; 1364 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost(); 1365 rvh->ExecuteJavascriptInWebFrame( 1366 ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"), 1367 ASCIIToUTF16(code)); 1368 // As we could miss and window.onload could already be called, restore 1369 // focus to current pod (see crbug/175243). 1370 RefocusCurrentPod(); 1371 } 1372 HandleFrameLoadingCompleted(0); 1373} 1374 1375void SigninScreenHandler::HandleDemoWebuiReady() { 1376 content::NotificationService::current()->Notify( 1377 chrome::NOTIFICATION_DEMO_WEBUI_LOADED, 1378 content::NotificationService::AllSources(), 1379 content::NotificationService::NoDetails()); 1380} 1381 1382void SigninScreenHandler::HandleSignOutUser() { 1383 if (delegate_) 1384 delegate_->Signout(); 1385} 1386 1387void SigninScreenHandler::HandleUserImagesLoaded() { 1388 content::NotificationService::current()->Notify( 1389 chrome::NOTIFICATION_LOGIN_USER_IMAGES_LOADED, 1390 content::NotificationService::AllSources(), 1391 content::NotificationService::NoDetails()); 1392} 1393 1394void SigninScreenHandler::HandleNetworkErrorShown() { 1395 content::NotificationService::current()->Notify( 1396 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, 1397 content::NotificationService::AllSources(), 1398 content::NotificationService::NoDetails()); 1399} 1400 1401void SigninScreenHandler::HandleCreateAccount() { 1402 if (delegate_) 1403 delegate_->CreateAccount(); 1404} 1405 1406void SigninScreenHandler::HandleOpenProxySettings() { 1407 LoginDisplayHostImpl::default_host()->OpenProxySettings(); 1408} 1409 1410void SigninScreenHandler::HandleLoginVisible(const std::string& source) { 1411 LOG(INFO) << "Login WebUI >> LoginVisible, source: " << source << ", " 1412 << "webui_visible_: " << webui_visible_; 1413 if (!webui_visible_) { 1414 // There might be multiple messages from OOBE UI so send notifications after 1415 // the first one only. 1416 content::NotificationService::current()->Notify( 1417 chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE, 1418 content::NotificationService::AllSources(), 1419 content::NotificationService::NoDetails()); 1420 } 1421 webui_visible_ = true; 1422 if (preferences_changed_delayed_) 1423 OnPreferencesChanged(); 1424} 1425 1426void SigninScreenHandler::HandleCancelPasswordChangedFlow() { 1427 StartClearingCookies(base::Bind( 1428 &SigninScreenHandler::CancelPasswordChangedFlowInternal, 1429 weak_factory_.GetWeakPtr())); 1430} 1431 1432void SigninScreenHandler::HandleMigrateUserData( 1433 const std::string& old_password) { 1434 if (delegate_) 1435 delegate_->MigrateUserData(old_password); 1436} 1437 1438void SigninScreenHandler::HandleResyncUserData() { 1439 if (delegate_) 1440 delegate_->ResyncUserData(); 1441} 1442 1443void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source, 1444 bool new_value) { 1445 LOG(INFO) << "Login WebUI >> active: " << new_value << ", " 1446 << "source: " << source; 1447 1448 if (source == kSourceGaiaSignin) { 1449 ui_state_ = UI_STATE_GAIA_SIGNIN; 1450 } else if (source == kSourceAccountPicker) { 1451 ui_state_ = UI_STATE_ACCOUNT_PICKER; 1452 } else { 1453 NOTREACHED(); 1454 return; 1455 } 1456} 1457 1458void SigninScreenHandler::HandleUnlockOnLoginSuccess() { 1459 DCHECK(UserManager::Get()->IsUserLoggedIn()); 1460 if (ScreenLocker::default_screen_locker()) 1461 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess(); 1462} 1463 1464void SigninScreenHandler::HandleFrameLoadingCompleted(int status) { 1465 frame_error_ = static_cast<net::Error>(-status); 1466 if (frame_error_ == net::OK) { 1467 LOG(INFO) << "Gaia frame is loaded"; 1468 frame_state_ = FRAME_STATE_LOADED; 1469 } else { 1470 LOG(WARNING) << "Gaia frame error: " << frame_error_; 1471 frame_state_ = FRAME_STATE_ERROR; 1472 } 1473 if (network_state_informer_->state() != NetworkStateInformer::ONLINE) 1474 return; 1475 if (frame_state_ == FRAME_STATE_LOADED) { 1476 UpdateState(network_state_informer_->state(), 1477 ErrorScreenActor::ERROR_REASON_UPDATE); 1478 } else if (frame_state_ == FRAME_STATE_ERROR) { 1479 UpdateState(network_state_informer_->state(), 1480 ErrorScreenActor::ERROR_REASON_FRAME_ERROR); 1481 } 1482} 1483 1484void SigninScreenHandler::HandleShowLoadingTimeoutError() { 1485 UpdateState(network_state_informer_->state(), 1486 ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT); 1487} 1488 1489void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) { 1490 offline_login_active_ = offline_login_active; 1491} 1492 1493void SigninScreenHandler::StartClearingDnsCache() { 1494 if (dns_clear_task_running_ || !g_browser_process->io_thread()) 1495 return; 1496 1497 dns_cleared_ = false; 1498 BrowserThread::PostTaskAndReply( 1499 BrowserThread::IO, FROM_HERE, 1500 base::Bind(&ClearDnsCache, g_browser_process->io_thread()), 1501 base::Bind(&SigninScreenHandler::OnDnsCleared, 1502 weak_factory_.GetWeakPtr())); 1503 dns_clear_task_running_ = true; 1504} 1505 1506void SigninScreenHandler::StartClearingCookies( 1507 const base::Closure& on_clear_callback) { 1508 cookies_cleared_ = false; 1509 ProfileHelper* profile_helper = 1510 g_browser_process->platform_part()->profile_helper(); 1511 LOG_ASSERT( 1512 Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile()); 1513 profile_helper->ClearSigninProfile(base::Bind( 1514 &SigninScreenHandler::OnCookiesCleared, 1515 weak_factory_.GetWeakPtr(), on_clear_callback)); 1516} 1517 1518void SigninScreenHandler::MaybePreloadAuthExtension() { 1519 // Fetching of the extension is not started before account picker page is 1520 // loaded because it can affect the loading speed. Also if cookies clearing 1521 // was initiated or |dns_clear_task_running_| then auth extension showing has 1522 // already been initiated and preloading is senseless. 1523 // Do not load the extension for the screen locker, see crosbug.com/25018. 1524 if (is_account_picker_showing_first_time_ && 1525 !gaia_silent_load_ && 1526 !ScreenLocker::default_screen_locker() && 1527 !cookies_cleared_ && 1528 !dns_clear_task_running_ && 1529 network_state_informer_->is_online()) { 1530 gaia_silent_load_ = true; 1531 gaia_silent_load_network_ = 1532 network_state_informer_->active_network_service_path(); 1533 LoadAuthExtension(true, true, false); 1534 } 1535} 1536 1537bool SigninScreenHandler::AllWhitelistedUsersPresent() { 1538 CrosSettings* cros_settings = CrosSettings::Get(); 1539 bool allow_new_user = false; 1540 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user); 1541 if (allow_new_user) 1542 return false; 1543 UserManager* user_manager = UserManager::Get(); 1544 const UserList& users = user_manager->GetUsers(); 1545 if (!delegate_ || users.size() > kMaxUsers) { 1546 return false; 1547 } 1548 const base::ListValue* whitelist = NULL; 1549 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist) 1550 return false; 1551 for (size_t i = 0; i < whitelist->GetSize(); ++i) { 1552 std::string whitelisted_user; 1553 // NB: Wildcards in the whitelist are also detected as not present here. 1554 if (!whitelist->GetString(i, &whitelisted_user) || 1555 !user_manager->IsKnownUser(whitelisted_user)) { 1556 return false; 1557 } 1558 } 1559 return true; 1560} 1561 1562void SigninScreenHandler::CancelPasswordChangedFlowInternal() { 1563 if (delegate_) { 1564 Show(oobe_ui_); 1565 delegate_->CancelPasswordChangedFlow(); 1566 } 1567} 1568 1569OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const { 1570 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN; 1571 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController()); 1572 if (oobe_ui) 1573 screen = oobe_ui->current_screen(); 1574 return screen; 1575} 1576 1577bool SigninScreenHandler::IsGaiaVisible() const { 1578 return IsSigninScreen(GetCurrentScreen()) && 1579 ui_state_ == UI_STATE_GAIA_SIGNIN; 1580} 1581 1582bool SigninScreenHandler::IsGaiaHiddenByError() const { 1583 return IsSigninScreenHiddenByError() && 1584 ui_state_ == UI_STATE_GAIA_SIGNIN; 1585} 1586 1587bool SigninScreenHandler::IsSigninScreenHiddenByError() const { 1588 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) && 1589 (IsSigninScreen(error_screen_actor_->parent_screen())); 1590} 1591 1592bool SigninScreenHandler::IsGuestSigninAllowed() const { 1593 CrosSettings* cros_settings = CrosSettings::Get(); 1594 if (!cros_settings) 1595 return false; 1596 bool allow_guest; 1597 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest); 1598 return allow_guest; 1599} 1600 1601bool SigninScreenHandler::IsOfflineLoginAllowed() const { 1602 CrosSettings* cros_settings = CrosSettings::Get(); 1603 if (!cros_settings) 1604 return false; 1605 1606 // Offline login is allowed only when user pods are hidden. 1607 bool show_pods; 1608 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods); 1609 return !show_pods; 1610} 1611 1612} // namespace chromeos 1613