NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / login / signin_screen_handler.cc
blob7fac31827892359ca6a5fcec95d36fc6afc87723
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.
5 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/scoped_user_pref_update.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/browser_process_platform_part_chromeos.h"
25 #include "chrome/browser/browser_shutdown.h"
26 #include "chrome/browser/chrome_notification_types.h"
27 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
28 #include "chrome/browser/chromeos/boot_times_loader.h"
29 #include "chrome/browser/chromeos/input_method/input_method_util.h"
30 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
31 #include "chrome/browser/chromeos/login/hwid_checker.h"
32 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
33 #include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
34 #include "chrome/browser/chromeos/login/screen_locker.h"
35 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
36 #include "chrome/browser/chromeos/login/user.h"
37 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
38 #include "chrome/browser/chromeos/login/webui_login_display.h"
39 #include "chrome/browser/chromeos/login/wizard_controller.h"
40 #include "chrome/browser/chromeos/net/network_portal_detector.h"
41 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
42 #include "chrome/browser/chromeos/profiles/profile_helper.h"
43 #include "chrome/browser/chromeos/settings/cros_settings.h"
44 #include "chrome/browser/io_thread.h"
45 #include "chrome/browser/profiles/profile.h"
46 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h"
47 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
48 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
49 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
50 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
51 #include "chrome/common/chrome_switches.h"
52 #include "chrome/common/pref_names.h"
53 #include "chrome/common/url_constants.h"
54 #include "chromeos/chromeos_switches.h"
55 #include "chromeos/dbus/dbus_thread_manager.h"
56 #include "chromeos/dbus/power_manager_client.h"
57 #include "chromeos/ime/input_method_manager.h"
58 #include "chromeos/ime/xkeyboard.h"
59 #include "chromeos/network/network_state.h"
60 #include "chromeos/network/network_state_handler.h"
61 #include "content/public/browser/browser_thread.h"
62 #include "content/public/browser/render_view_host.h"
63 #include "content/public/browser/web_contents.h"
64 #include "google_apis/gaia/gaia_auth_util.h"
65 #include "grit/chromium_strings.h"
66 #include "grit/generated_resources.h"
67 #include "net/url_request/url_request_context_getter.h"
68 #include "third_party/cros_system_api/dbus/service_constants.h"
70 #if defined(USE_AURA)
71 #include "ash/shell.h"
72 #include "ash/wm/lock_state_controller.h"
73 #endif
75 using content::BrowserThread;
76 using content::RenderViewHost;
78 namespace {
80 // User dictionary keys.
81 const char kKeyUsername[] = "username";
82 const char kKeyDisplayName[] = "displayName";
83 const char kKeyEmailAddress[] = "emailAddress";
84 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
85 const char kKeyPublicAccount[] = "publicAccount";
86 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
87 const char kKeySignedIn[] = "signedIn";
88 const char kKeyCanRemove[] = "canRemove";
89 const char kKeyIsOwner[] = "isOwner";
90 const char kKeyForceOnlineSignin[] = "forceOnlineSignin";
91 const char kKeyMultiProfilesAllowed[] = "isMultiProfilesAllowed";
92 const char kKeyMultiProfilesPolicy[] = "multiProfilesPolicy";
94 // Max number of users to show.
95 const size_t kMaxUsers = 18;
97 // Timeout to delay first notification about offline state for a
98 // current network.
99 const int kOfflineTimeoutSec = 5;
101 // Timeout used to prevent infinite connecting to a flaky network.
102 const int kConnectingTimeoutSec = 60;
104 // Type of the login screen UI that is currently presented to user.
105 const char kSourceGaiaSignin[] = "gaia-signin";
106 const char kSourceAccountPicker[] = "account-picker";
108 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
109 // thread.
110 void ClearDnsCache(IOThread* io_thread) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
112 if (browser_shutdown::IsTryingToQuit())
113 return;
115 io_thread->ClearHostCache();
118 static bool Contains(const std::vector<std::string>& container,
119 const std::string& value) {
120 return std::find(container.begin(), container.end(), value) !=
121 container.end();
124 } // namespace
126 namespace chromeos {
128 namespace {
130 bool IsOnline(NetworkStateInformer::State state,
131 ErrorScreenActor::ErrorReason reason) {
132 return state == NetworkStateInformer::ONLINE &&
133 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
134 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
137 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
138 ErrorScreenActor::ErrorReason reason) {
139 return state == NetworkStateInformer::CAPTIVE_PORTAL ||
140 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
143 bool IsProxyError(NetworkStateInformer::State state,
144 ErrorScreenActor::ErrorReason reason,
145 net::Error frame_error) {
146 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
147 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
148 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
149 (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
150 (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
151 frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
154 bool IsSigninScreen(const OobeUI::Screen screen) {
155 return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
156 screen == OobeUI::SCREEN_ACCOUNT_PICKER;
159 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
160 return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
161 error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
162 error_state == ErrorScreen::ERROR_STATE_PROXY ||
163 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
166 // Returns network name by service path.
167 std::string GetNetworkName(const std::string& service_path) {
168 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
169 GetNetworkState(service_path);
170 if (!network)
171 return std::string();
172 return network->name();
175 static bool SetUserInputMethodImpl(
176 const std::string& username,
177 chromeos::input_method::InputMethodManager* manager) {
178 PrefService* const local_state = g_browser_process->local_state();
180 const base::DictionaryValue* users_lru_input_methods =
181 local_state->GetDictionary(prefs::kUsersLRUInputMethod);
183 if (users_lru_input_methods == NULL) {
184 DLOG(WARNING) << "SetUserInputMethod('" << username
185 << "'): no kUsersLRUInputMethod";
186 return false;
189 std::string input_method;
191 if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
192 &input_method)) {
193 DVLOG(0) << "SetUserInputMethod('" << username
194 << "'): no input method for this user";
195 return false;
198 if (input_method.empty())
199 return false;
201 if (!manager->IsLoginKeyboard(input_method)) {
202 LOG(WARNING) << "SetUserInputMethod('" << username
203 << "'): stored user LRU input method '" << input_method
204 << "' is no longer Full Latin Keyboard Language"
205 << " (entry dropped). Use hardware default instead.";
207 DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
209 base::DictionaryValue* const users_lru_input_methods = updater.Get();
210 if (users_lru_input_methods != NULL) {
211 users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
213 return false;
216 if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
217 if (!manager->EnableInputMethod(input_method)) {
218 DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
219 << "'): user input method '" << input_method
220 << "' is not enabled and enabling failed (ignored!).";
223 manager->ChangeInputMethod(input_method);
225 return true;
228 void RecordSAMLScrapingVerificationResultInHistogram(bool success) {
229 UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.Scraping.VerificationResult", success);
232 } // namespace
234 // LoginScreenContext implementation ------------------------------------------
236 LoginScreenContext::LoginScreenContext() {
237 Init();
240 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
241 Init();
243 if (!args || args->GetSize() == 0)
244 return;
245 std::string email;
246 if (args->GetString(0, &email))
247 email_ = email;
250 void LoginScreenContext::Init() {
251 oobe_ui_ = false;
254 // SigninScreenHandler implementation ------------------------------------------
256 SigninScreenHandler::SigninScreenHandler(
257 const scoped_refptr<NetworkStateInformer>& network_state_informer,
258 ErrorScreenActor* error_screen_actor,
259 CoreOobeActor* core_oobe_actor,
260 GaiaScreenHandler* gaia_screen_handler)
261 : ui_state_(UI_STATE_UNKNOWN),
262 delegate_(NULL),
263 native_window_delegate_(NULL),
264 show_on_init_(false),
265 oobe_ui_(false),
266 focus_stolen_(false),
267 gaia_silent_load_(false),
268 is_account_picker_showing_first_time_(false),
269 dns_cleared_(false),
270 dns_clear_task_running_(false),
271 cookies_cleared_(false),
272 network_state_informer_(network_state_informer),
273 using_saml_api_(false),
274 test_expects_complete_login_(false),
275 weak_factory_(this),
276 webui_visible_(false),
277 preferences_changed_delayed_(false),
278 error_screen_actor_(error_screen_actor),
279 core_oobe_actor_(core_oobe_actor),
280 is_first_update_state_call_(true),
281 offline_login_active_(false),
282 last_network_state_(NetworkStateInformer::UNKNOWN),
283 has_pending_auth_ui_(false),
284 wait_for_auto_enrollment_check_(false),
285 gaia_screen_handler_(gaia_screen_handler) {
286 DCHECK(network_state_informer_.get());
287 DCHECK(error_screen_actor_);
288 DCHECK(core_oobe_actor_);
289 DCHECK(gaia_screen_handler_);
290 gaia_screen_handler_->SetSigninScreenHandler(this);
291 network_state_informer_->AddObserver(this);
292 allow_new_user_subscription_ = CrosSettings::Get()->AddSettingsObserver(
293 kAccountsPrefAllowNewUser,
294 base::Bind(&SigninScreenHandler::UserSettingsChanged,
295 base::Unretained(this)));
296 allow_guest_subscription_ = CrosSettings::Get()->AddSettingsObserver(
297 kAccountsPrefAllowGuest,
298 base::Bind(&SigninScreenHandler::UserSettingsChanged,
299 base::Unretained(this)));
301 registrar_.Add(this,
302 chrome::NOTIFICATION_AUTH_NEEDED,
303 content::NotificationService::AllSources());
304 registrar_.Add(this,
305 chrome::NOTIFICATION_AUTH_SUPPLIED,
306 content::NotificationService::AllSources());
307 registrar_.Add(this,
308 chrome::NOTIFICATION_AUTH_CANCELLED,
309 content::NotificationService::AllSources());
312 SigninScreenHandler::~SigninScreenHandler() {
313 weak_factory_.InvalidateWeakPtrs();
314 SystemKeyEventListener* key_event_listener =
315 SystemKeyEventListener::GetInstance();
316 if (key_event_listener)
317 key_event_listener->RemoveCapsLockObserver(this);
318 if (delegate_)
319 delegate_->SetWebUIHandler(NULL);
320 network_state_informer_->RemoveObserver(this);
323 void SigninScreenHandler::DeclareLocalizedValues(
324 LocalizedValuesBuilder* builder) {
325 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
326 builder->Add("podMenuButtonAccessibleName",
327 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
328 builder->Add("podMenuRemoveItemAccessibleName",
329 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
330 builder->Add("passwordFieldAccessibleName",
331 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
332 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
333 builder->Add("signinButton", IDS_LOGIN_BUTTON);
334 builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON);
335 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
336 builder->Add("addUser", IDS_ADD_USER_BUTTON);
337 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
338 builder->Add("cancel", IDS_CANCEL);
339 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
340 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
341 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
342 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
343 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
344 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
345 builder->Add("errorTpmFailureRebootButton",
346 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
348 policy::BrowserPolicyConnectorChromeOS* connector =
349 g_browser_process->platform_part()->browser_policy_connector_chromeos();
350 builder->Add("disabledAddUserTooltip",
351 connector->IsEnterpriseManaged()
352 ? IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE
353 : IDS_DISABLED_ADD_USER_TOOLTIP);
355 builder->Add("supervisedUserExpiredTokenWarning",
356 IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
357 builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
359 // Multi-profiles related strings.
360 builder->Add("multiProfilesRestrictedPolicyTitle",
361 IDS_MULTI_PROFILES_RESTRICTED_POLICY_TITLE);
362 builder->Add("multiProfilesNotAllowedPolicyMsg",
363 IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG);
364 builder->Add("multiProfilesPrimaryOnlyPolicyMsg",
365 IDS_MULTI_PROFILES_PRIMARY_ONLY_POLICY_MSG);
367 // Strings used by password changed dialog.
368 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
369 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
370 builder->AddF("passwordChangedMoreInfo",
371 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
372 IDS_SHORT_PRODUCT_OS_NAME);
374 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
375 builder->Add("oldPasswordIncorrect",
376 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
377 builder->Add("passwordChangedCantRemember",
378 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
379 builder->Add("passwordChangedBackButton",
380 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
381 builder->Add("passwordChangedsOkButton", IDS_OK);
382 builder->Add("passwordChangedProceedAnyway",
383 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
384 builder->Add("proceedAnywayButton",
385 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
386 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
387 builder->Add("publicAccountReminder",
388 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
389 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
390 builder->Add("publicAccountEnterAccessibleName",
391 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
392 builder->AddF("removeUserWarningText",
393 IDS_LOGIN_POD_USER_REMOVE_WARNING,
394 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
395 builder->Add("removeUserWarningButtonTitle",
396 IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
398 builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
400 builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
401 builder->Add("confirmPasswordLabel", IDS_LOGIN_CONFIRM_PASSWORD_LABEL);
402 builder->Add("confirmPasswordConfirmButton",
403 IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
404 builder->Add("confirmPasswordText", IDS_LOGIN_CONFIRM_PASSWORD_TEXT);
405 builder->Add("confirmPasswordErrorText",
406 IDS_LOGIN_CONFIRM_PASSWORD_ERROR_TEXT);
408 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
409 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
411 builder->Add("runType", CommandLine::ForCurrentProcess()->HasSwitch(
412 switches::kFirstExecAfterBoot) ? "firstExecAfterBoot" :
413 "notFirstExecAfterBoot");
416 void SigninScreenHandler::Show(const LoginScreenContext& context) {
417 CHECK(delegate_);
419 // Just initialize internal fields from context and call ShowImpl().
420 oobe_ui_ = context.oobe_ui();
421 if (!context.email().empty())
422 email_ = context.email();
423 else
424 email_.clear();
425 ShowImpl();
428 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
429 CallJS("showLoginSpinner");
432 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
433 delegate_ = delegate;
434 if (delegate_)
435 delegate_->SetWebUIHandler(this);
438 void SigninScreenHandler::SetNativeWindowDelegate(
439 NativeWindowDelegate* native_window_delegate) {
440 native_window_delegate_ = native_window_delegate;
443 void SigninScreenHandler::OnNetworkReady() {
444 LOG(WARNING) << "OnNetworkReady() call.";
445 MaybePreloadAuthExtension();
448 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
449 UpdateStateInternal(reason, false);
452 // SigninScreenHandler, private: -----------------------------------------------
454 void SigninScreenHandler::ShowImpl() {
455 if (!page_is_ready()) {
456 show_on_init_ = true;
457 return;
460 if (oobe_ui_) {
461 // Shows new user sign-in for OOBE.
462 OnShowAddUser(email_);
463 } else {
464 // Populates account picker. Animation is turned off for now until we
465 // figure out how to make it fast enough.
466 SendUserList(false);
468 // Reset Caps Lock state when login screen is shown.
469 input_method::InputMethodManager::Get()->GetXKeyboard()->
470 SetCapsLockEnabled(false);
472 base::DictionaryValue params;
473 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
474 UpdateUIState(UI_STATE_ACCOUNT_PICKER, &params);
478 void SigninScreenHandler::UpdateUIState(UIState ui_state,
479 base::DictionaryValue* params) {
480 switch (ui_state) {
481 case UI_STATE_GAIA_SIGNIN:
482 ui_state_ = UI_STATE_GAIA_SIGNIN;
483 ShowScreen(OobeUI::kScreenGaiaSignin, params);
484 break;
485 case UI_STATE_ACCOUNT_PICKER:
486 ui_state_ = UI_STATE_ACCOUNT_PICKER;
487 ShowScreen(OobeUI::kScreenAccountPicker, params);
488 break;
489 default:
490 NOTREACHED();
491 break;
495 // TODO (ygorshenin@): split this method into small parts.
496 // TODO (ygorshenin@): move this logic to GaiaScreenHandler.
497 void SigninScreenHandler::UpdateStateInternal(
498 ErrorScreenActor::ErrorReason reason,
499 bool force_update) {
500 // Do nothing once user has signed in or sign in is in progress.
501 // TODO(ygorshenin): We will end up here when processing network state
502 // notification but no ShowSigninScreen() was called so delegate_ will be
503 // NULL. Network state processing logic does not belong here.
504 if (delegate_ &&
505 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
506 return;
509 NetworkStateInformer::State state = network_state_informer_->state();
510 const std::string network_path = network_state_informer_->network_path();
511 const std::string network_name = GetNetworkName(network_path);
513 // Skip "update" notification about OFFLINE state from
514 // NetworkStateInformer if previous notification already was
515 // delayed.
516 if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
517 !force_update && !update_state_closure_.IsCancelled()) {
518 return;
521 // TODO (ygorshenin@): switch log level to INFO once signin screen
522 // will be tested well.
523 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
524 << "state=" << NetworkStateInformer::StatusString(state) << ", "
525 << "network_name=" << network_name << ", "
526 << "reason=" << ErrorScreenActor::ErrorReasonString(reason)
527 << ", force_update=" << force_update;
528 update_state_closure_.Cancel();
530 if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
531 has_pending_auth_ui_) {
532 update_state_closure_.Reset(
533 base::Bind(&SigninScreenHandler::UpdateStateInternal,
534 weak_factory_.GetWeakPtr(),
535 reason,
536 true));
537 base::MessageLoop::current()->PostDelayedTask(
538 FROM_HERE,
539 update_state_closure_.callback(),
540 base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
541 return;
544 // Don't show or hide error screen if we're in connecting state.
545 if (state == NetworkStateInformer::CONNECTING && !force_update) {
546 if (connecting_closure_.IsCancelled()) {
547 // First notification about CONNECTING state.
548 connecting_closure_.Reset(
549 base::Bind(&SigninScreenHandler::UpdateStateInternal,
550 weak_factory_.GetWeakPtr(),
551 reason,
552 true));
553 base::MessageLoop::current()->PostDelayedTask(
554 FROM_HERE,
555 connecting_closure_.callback(),
556 base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
558 return;
560 connecting_closure_.Cancel();
562 const bool is_online = IsOnline(state, reason);
563 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
564 const bool is_gaia_loading_timeout =
565 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
566 const bool is_gaia_error =
567 FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED;
568 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError();
569 const bool error_screen_should_overlay =
570 !offline_login_active_ && IsGaiaVisible();
571 const bool from_not_online_to_online_transition =
572 is_online && last_network_state_ != NetworkStateInformer::ONLINE;
573 last_network_state_ = state;
575 if (is_online || !is_behind_captive_portal)
576 error_screen_actor_->HideCaptivePortal();
578 // Hide offline message (if needed) and return if current screen is
579 // not a Gaia frame.
580 if (!is_gaia_signin) {
581 if (!IsSigninScreenHiddenByError())
582 HideOfflineMessage(state, reason);
583 return;
586 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state.
587 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED &&
588 from_not_online_to_online_transition) {
589 // Schedules a immediate retry.
590 LOG(WARNING) << "Retry page load since network has been changed.";
591 ReloadGaiaScreen();
594 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED &&
595 error_screen_should_overlay) {
596 // Schedules a immediate retry.
597 LOG(WARNING) << "Retry page load since proxy settings has been changed.";
598 ReloadGaiaScreen();
601 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
602 !IsProxyError(state, reason, FrameError())) {
603 LOG(WARNING) << "Retry page load due to reason: "
604 << ErrorScreenActor::ErrorReasonString(reason);
605 ReloadGaiaScreen();
608 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) &&
609 !offline_login_active_) {
610 SetupAndShowOfflineMessage(state, reason);
611 } else {
612 HideOfflineMessage(state, reason);
616 void SigninScreenHandler::SetupAndShowOfflineMessage(
617 NetworkStateInformer:: State state,
618 ErrorScreenActor::ErrorReason reason) {
619 const std::string network_path = network_state_informer_->network_path();
620 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
621 const bool is_proxy_error = IsProxyError(state, reason, FrameError());
622 const bool is_gaia_loading_timeout =
623 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
625 if (is_proxy_error) {
626 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
627 std::string());
628 } else if (is_behind_captive_portal) {
629 // Do not bother a user with obsessive captive portal showing. This
630 // check makes captive portal being shown only once: either when error
631 // screen is shown for the first time or when switching from another
632 // error screen (offline, proxy).
633 if (IsGaiaVisible() ||
634 (error_screen_actor_->error_state() !=
635 ErrorScreen::ERROR_STATE_PORTAL)) {
636 error_screen_actor_->FixCaptivePortal();
638 const std::string network_name = GetNetworkName(network_path);
639 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
640 network_name);
641 } else if (is_gaia_loading_timeout) {
642 error_screen_actor_->SetErrorState(
643 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string());
644 } else {
645 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
646 std::string());
649 const bool guest_signin_allowed = IsGuestSigninAllowed() &&
650 IsSigninScreenError(error_screen_actor_->error_state());
651 error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
653 const bool offline_login_allowed = IsOfflineLoginAllowed() &&
654 IsSigninScreenError(error_screen_actor_->error_state()) &&
655 error_screen_actor_->error_state() !=
656 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
657 error_screen_actor_->AllowOfflineLogin(offline_login_allowed);
659 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
660 base::DictionaryValue params;
661 const std::string network_type = network_state_informer_->network_type();
662 params.SetString("lastNetworkType", network_type);
663 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
664 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, &params);
668 void SigninScreenHandler::HideOfflineMessage(
669 NetworkStateInformer::State state,
670 ErrorScreenActor::ErrorReason reason) {
671 if (!IsSigninScreenHiddenByError())
672 return;
674 error_screen_actor_->Hide();
676 // Forces a reload for Gaia screen on hiding error message.
677 if (IsGaiaVisible() || IsGaiaHiddenByError())
678 ReloadGaiaScreen();
681 void SigninScreenHandler::ReloadGaiaScreen() {
682 gaia_screen_handler_->ReloadGaia();
685 void SigninScreenHandler::Initialize() {
686 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
687 // don't do anything, just return.
688 if (!delegate_)
689 return;
691 // Register for Caps Lock state change notifications;
692 SystemKeyEventListener* key_event_listener =
693 SystemKeyEventListener::GetInstance();
694 if (key_event_listener)
695 key_event_listener->AddCapsLockObserver(this);
697 if (show_on_init_) {
698 show_on_init_ = false;
699 ShowImpl();
703 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
704 if (native_window_delegate_)
705 return native_window_delegate_->GetNativeWindow();
706 return NULL;
709 void SigninScreenHandler::RegisterMessages() {
710 AddCallback("usingSAMLAPI", &SigninScreenHandler::HandleUsingSAMLAPI);
711 AddCallback("scrapedPasswordCount",
712 &SigninScreenHandler::HandleScrapedPasswordCount);
713 AddCallback("scrapedPasswordVerificationFailed",
714 &SigninScreenHandler::HandleScrapedPasswordVerificationFailed);
715 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
716 AddCallback("completeLogin", &SigninScreenHandler::HandleCompleteLogin);
717 AddCallback("completeAuthentication",
718 &SigninScreenHandler::HandleCompleteAuthentication);
719 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
720 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
721 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
722 AddCallback("showLocallyManagedUserCreationScreen",
723 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen);
724 AddCallback("launchPublicAccount",
725 &SigninScreenHandler::HandleLaunchPublicAccount);
726 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
727 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
728 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
729 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
730 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
731 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
732 AddCallback("toggleEnrollmentScreen",
733 &SigninScreenHandler::HandleToggleEnrollmentScreen);
734 AddCallback("toggleKioskEnableScreen",
735 &SigninScreenHandler::HandleToggleKioskEnableScreen);
736 AddCallback("toggleResetScreen",
737 &SigninScreenHandler::HandleToggleResetScreen);
738 AddCallback("launchHelpApp", &SigninScreenHandler::HandleLaunchHelpApp);
739 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
740 AddCallback("accountPickerReady",
741 &SigninScreenHandler::HandleAccountPickerReady);
742 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
743 AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
744 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
745 AddCallback("networkErrorShown",
746 &SigninScreenHandler::HandleNetworkErrorShown);
747 AddCallback("openProxySettings",
748 &SigninScreenHandler::HandleOpenProxySettings);
749 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
750 AddCallback("cancelPasswordChangedFlow",
751 &SigninScreenHandler::HandleCancelPasswordChangedFlow);
752 AddCallback("cancelUserAdding",
753 &SigninScreenHandler::HandleCancelUserAdding);
754 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
755 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
756 AddCallback("loginUIStateChanged",
757 &SigninScreenHandler::HandleLoginUIStateChanged);
758 AddCallback("unlockOnLoginSuccess",
759 &SigninScreenHandler::HandleUnlockOnLoginSuccess);
760 AddCallback("showLoadingTimeoutError",
761 &SigninScreenHandler::HandleShowLoadingTimeoutError);
762 AddCallback("updateOfflineLogin",
763 &SigninScreenHandler::HandleUpdateOfflineLogin);
764 AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
765 AddCallback("customButtonClicked",
766 &SigninScreenHandler::HandleCustomButtonClicked);
767 AddCallback("retrieveAuthenticatedUserEmail",
768 &SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail);
770 // This message is sent by the kiosk app menu, but is handled here
771 // so we can tell the delegate to launch the app.
772 AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
775 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
776 registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
779 void SigninScreenHandler::HandleGetUsers() {
780 SendUserList(false);
783 void SigninScreenHandler::ClearAndEnablePassword() {
784 core_oobe_actor_->ResetSignInUI(false);
787 void SigninScreenHandler::ClearUserPodPassword() {
788 core_oobe_actor_->ClearUserPodPassword();
791 void SigninScreenHandler::RefocusCurrentPod() {
792 core_oobe_actor_->RefocusCurrentPod();
795 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
796 core_oobe_actor_->OnLoginSuccess(username);
799 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
800 CallJS("login.AccountPickerScreen.removeUser", username);
803 void SigninScreenHandler::OnUserImageChanged(const User& user) {
804 if (page_is_ready())
805 CallJS("login.AccountPickerScreen.updateUserImage", user.email());
808 void SigninScreenHandler::OnPreferencesChanged() {
809 // Make sure that one of the login UI is fully functional now, otherwise
810 // preferences update would be picked up next time it will be shown.
811 if (!webui_visible_) {
812 LOG(WARNING) << "Login UI is not active - postponed prefs change.";
813 preferences_changed_delayed_ = true;
814 return;
817 if (delegate_ && !delegate_->IsShowUsers()) {
818 HandleShowAddUser(NULL);
819 } else {
820 SendUserList(false);
821 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
823 preferences_changed_delayed_ = false;
826 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
827 SetDelegate(NULL);
830 void SigninScreenHandler::ShowBannerMessage(const std::string& message) {
831 CallJS("login.AccountPickerScreen.showBannerMessage", message);
834 void SigninScreenHandler::ShowUserPodButton(
835 const std::string& username,
836 const std::string& iconURL,
837 const base::Closure& click_callback) {
838 user_pod_button_callback_map_[username] = click_callback;
839 CallJS("login.AccountPickerScreen.showUserPodButton", username, iconURL);
842 void SigninScreenHandler::ShowError(int login_attempts,
843 const std::string& error_text,
844 const std::string& help_link_text,
845 HelpAppLauncher::HelpTopic help_topic_id) {
846 core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
847 help_topic_id);
850 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
851 switch (error_id) {
852 case LoginDisplay::TPM_ERROR:
853 core_oobe_actor_->ShowTpmError();
854 break;
855 default:
856 NOTREACHED() << "Unknown sign in error";
857 break;
861 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
862 core_oobe_actor_->ShowSignInUI(email);
865 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
866 email_ = username;
867 password_changed_for_.insert(email_);
868 core_oobe_actor_->ShowSignInUI(email_);
869 CallJS("login.AccountPickerScreen.forceOnlineSignin", email_);
872 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
873 core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
876 void SigninScreenHandler::ShowSigninScreenForCreds(
877 const std::string& username,
878 const std::string& password) {
879 VLOG(2) << "ShowSigninScreenForCreds for user " << username
880 << ", frame_state=" << FrameState();
882 test_user_ = username;
883 test_pass_ = password;
884 test_expects_complete_login_ = true;
886 // Submit login form for test if gaia is ready. If gaia is loading, login
887 // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
888 // reload gaia then follow the loading case.
889 if (FrameState() == GaiaScreenHandler::FRAME_STATE_LOADED)
890 SubmitLoginFormForTest();
891 else if (FrameState() != GaiaScreenHandler::FRAME_STATE_LOADING)
892 HandleShowAddUser(NULL);
895 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
896 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
897 cookies_cleared_ = true;
898 on_clear_callback.Run();
901 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
902 if (page_is_ready())
903 CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
906 void SigninScreenHandler::Observe(int type,
907 const content::NotificationSource& source,
908 const content::NotificationDetails& details) {
909 switch (type) {
910 case chrome::NOTIFICATION_AUTH_NEEDED: {
911 has_pending_auth_ui_ = true;
912 break;
914 case chrome::NOTIFICATION_AUTH_SUPPLIED:
915 has_pending_auth_ui_ = false;
916 if (IsSigninScreenHiddenByError()) {
917 // Hide error screen and reload auth extension.
918 HideOfflineMessage(network_state_informer_->state(),
919 ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED);
920 } else if (ui_state_ == UI_STATE_GAIA_SIGNIN) {
921 // Reload auth extension as proxy credentials are supplied.
922 ReloadGaiaScreen();
924 break;
925 case chrome::NOTIFICATION_AUTH_CANCELLED: {
926 // Don't reload auth extension if proxy auth dialog was cancelled.
927 has_pending_auth_ui_ = false;
928 break;
930 default:
931 NOTREACHED() << "Unexpected notification " << type;
935 void SigninScreenHandler::OnDnsCleared() {
936 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
937 dns_clear_task_running_ = false;
938 dns_cleared_ = true;
939 ShowSigninScreenIfReady();
942 // Update keyboard layout to least recently used by the user.
943 void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
944 UserManager* user_manager = UserManager::Get();
945 if (user_manager->IsUserLoggedIn()) {
946 // We are on sign-in screen inside user session (adding new user to
947 // the session or on lock screen), don't switch input methods in this case.
948 // TODO(dpolukhin): adding user and sign-in should be consistent
949 // crbug.com/292774
950 return;
953 chromeos::input_method::InputMethodManager* const manager =
954 chromeos::input_method::InputMethodManager::Get();
956 const bool succeed = SetUserInputMethodImpl(username, manager);
958 // This is also a case when LRU layout is set only for a few local users,
959 // thus others need to be switched to default locale.
960 // Otherwise they will end up using another user's locale to log in.
961 if (!succeed) {
962 DVLOG(0) << "SetUserInputMethod('" << username
963 << "'): failed to set user layout. Switching to default.";
965 manager->SetInputMethodDefault();
969 void SigninScreenHandler::ShowSigninScreenIfReady() {
970 LOG(WARNING) << "ShowSigninScreenIfReady() call.";
972 if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
973 return;
975 std::string active_network_path = network_state_informer_->network_path();
976 if (gaia_silent_load_ &&
977 (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
978 gaia_silent_load_network_ != active_network_path)) {
979 // Network has changed. Force Gaia reload.
980 gaia_silent_load_ = false;
981 // Gaia page will be realoded, so focus isn't stolen anymore.
982 focus_stolen_ = false;
985 // Note that LoadAuthExtension clears |email_|.
986 if (email_.empty())
987 delegate_->LoadSigninWallpaper();
988 else
989 delegate_->LoadWallpaper(email_);
991 // Set Least Recently Used input method for the user.
992 if (!email_.empty())
993 SetUserInputMethod(email_);
995 LoadAuthExtension(!gaia_silent_load_, false, false);
996 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
998 if (gaia_silent_load_) {
999 // The variable is assigned to false because silently loaded Gaia page was
1000 // used.
1001 gaia_silent_load_ = false;
1002 if (focus_stolen_)
1003 HandleLoginWebuiReady();
1006 UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
1009 void SigninScreenHandler::LoadAuthExtension(
1010 bool force, bool silent_load, bool offline) {
1011 GaiaContext context;
1012 context.force_reload = force;
1013 context.is_local = offline;
1014 context.password_changed =
1015 !email_.empty() && password_changed_for_.count(email_);
1016 if (delegate_)
1017 context.show_users = delegate_->IsShowUsers();
1018 context.use_offline = offline;
1019 if (delegate_)
1020 context.has_users = delegate_->GetUsers().size() != 0;
1021 context.email = email_;
1023 email_.clear();
1025 DCHECK(gaia_screen_handler_);
1026 gaia_screen_handler_->LoadGaia(context);
1029 void SigninScreenHandler::UserSettingsChanged() {
1030 DCHECK(gaia_screen_handler_);
1031 GaiaContext context;
1032 if (delegate_)
1033 context.has_users = delegate_->GetUsers().size() != 0;
1034 gaia_screen_handler_->UpdateGaia(context);
1035 UpdateAddButtonStatus();
1038 void SigninScreenHandler::UpdateAddButtonStatus() {
1039 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1040 AllWhitelistedUsersPresent());
1043 void SigninScreenHandler::HandleUsingSAMLAPI() {
1044 SetSAMLPrincipalsAPIUsed(true);
1047 void SigninScreenHandler::HandleScrapedPasswordCount(int password_count) {
1048 SetSAMLPrincipalsAPIUsed(false);
1049 // Use a histogram that has 11 buckets, one for each of the values in [0, 9]
1050 // and an overflow bucket at the end.
1051 UMA_HISTOGRAM_ENUMERATION(
1052 "ChromeOS.SAML.Scraping.PasswordCount", std::min(password_count, 10), 11);
1053 if (password_count == 0)
1054 HandleScrapedPasswordVerificationFailed();
1057 void SigninScreenHandler::HandleScrapedPasswordVerificationFailed() {
1058 RecordSAMLScrapingVerificationResultInHistogram(false);
1061 void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email,
1062 const std::string& password,
1063 bool using_saml) {
1064 if (!delegate_)
1065 return;
1067 if (using_saml && !using_saml_api_)
1068 RecordSAMLScrapingVerificationResultInHistogram(true);
1070 const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
1071 delegate_->SetDisplayEmail(sanitized_email);
1072 delegate_->CompleteLogin(UserContext(
1073 sanitized_email,
1074 password,
1075 std::string(), // auth_code
1076 std::string(), // username_hash
1077 true, // using_oauth
1078 using_saml ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
1079 : UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML));
1081 if (test_expects_complete_login_) {
1082 VLOG(2) << "Complete test login for " << typed_email
1083 << ", requested=" << test_user_;
1085 test_expects_complete_login_ = false;
1086 test_user_.clear();
1087 test_pass_.clear();
1091 void SigninScreenHandler::HandleCompleteAuthentication(
1092 const std::string& email,
1093 const std::string& password,
1094 const std::string& auth_code) {
1095 if (!delegate_)
1096 return;
1097 const std::string sanitized_email = gaia::SanitizeEmail(email);
1098 delegate_->SetDisplayEmail(sanitized_email);
1099 delegate_->CompleteLogin(UserContext(sanitized_email, password, auth_code));
1102 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
1103 const std::string& password) {
1104 if (!delegate_)
1105 return;
1106 delegate_->Login(UserContext(gaia::SanitizeEmail(username),
1107 password,
1108 std::string())); // auth_code
1111 void SigninScreenHandler::HandleLaunchDemoUser() {
1112 if (delegate_)
1113 delegate_->LoginAsRetailModeUser();
1116 void SigninScreenHandler::HandleLaunchIncognito() {
1117 if (delegate_)
1118 delegate_->LoginAsGuest();
1121 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
1122 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
1123 LOG(ERROR) << "Managed users not allowed.";
1124 return;
1126 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
1127 LoginDisplayHostImpl::default_host()->
1128 StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
1129 params.Pass());
1132 void SigninScreenHandler::HandleLaunchPublicAccount(
1133 const std::string& username) {
1134 if (delegate_)
1135 delegate_->LoginAsPublicAccount(username);
1138 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
1139 if (!delegate_ || delegate_->IsShowUsers()) {
1140 NOTREACHED();
1141 return;
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);
1151 void SigninScreenHandler::HandleShutdownSystem() {
1152 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1155 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1156 if (delegate_)
1157 delegate_->LoadWallpaper(email);
1160 void SigninScreenHandler::HandleRebootSystem() {
1161 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1164 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1165 if (!delegate_)
1166 return;
1167 delegate_->RemoveUser(email);
1168 UpdateAddButtonStatus();
1171 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
1172 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1173 "ShowLoginWebUI",
1174 LoginDisplayHostImpl::kShowLoginWebUIid,
1175 "ShowAddUser");
1176 std::string email;
1177 // |args| can be null if it's OOBE.
1178 if (args)
1179 args->GetString(0, &email);
1180 OnShowAddUser(email);
1183 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1184 if (delegate_)
1185 delegate_->ShowEnterpriseEnrollmentScreen();
1188 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
1189 policy::BrowserPolicyConnectorChromeOS* connector =
1190 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1191 if (delegate_ &&
1192 !wait_for_auto_enrollment_check_ &&
1193 !connector->IsEnterpriseManaged()) {
1194 wait_for_auto_enrollment_check_ = true;
1196 LoginDisplayHostImpl::default_host()->GetAutoEnrollmentCheckResult(
1197 base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1198 weak_factory_.GetWeakPtr()));
1202 void SigninScreenHandler::HandleToggleResetScreen() {
1203 policy::BrowserPolicyConnectorChromeOS* connector =
1204 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1205 if (delegate_ && !connector->IsEnterpriseManaged())
1206 delegate_->ShowResetScreen();
1209 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
1210 policy::BrowserPolicyConnectorChromeOS* connector =
1211 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1212 if (delegate_ && !connector->IsEnterpriseManaged())
1213 delegate_->ShowKioskAutolaunchScreen();
1216 void SigninScreenHandler::HandleLaunchHelpApp(double help_topic_id) {
1217 if (!delegate_)
1218 return;
1219 if (!help_app_.get())
1220 help_app_ = new HelpAppLauncher(GetNativeWindow());
1221 help_app_->ShowHelpTopic(
1222 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id));
1225 void SigninScreenHandler::FillUserDictionary(User* user,
1226 bool is_owner,
1227 bool is_signin_to_add,
1228 base::DictionaryValue* user_dict) {
1229 const std::string& email = user->email();
1230 const bool is_public_account =
1231 user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
1232 const bool is_locally_managed_user =
1233 user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
1234 const User::OAuthTokenStatus token_status = user->oauth_token_status();
1236 // Force online sign-in if at least one of the following is true:
1237 // * The flag to force online sign-in is set for the user.
1238 // * The user's oauth token is invalid.
1239 // * The user's oauth token status is unknown. This condition does not apply
1240 // to supervised users: A supervised user whose oauth token status is
1241 // unknown may still log in offline. The token will be invalidated inside
1242 // the session in case it has been revoked.
1243 const bool force_online_signin =
1244 user->force_online_signin() ||
1245 (token_status == User::OAUTH2_TOKEN_STATUS_INVALID) ||
1246 (!is_locally_managed_user &&
1247 token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN);
1249 user_dict->SetString(kKeyUsername, email);
1250 user_dict->SetString(kKeyEmailAddress, user->display_email());
1251 user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
1252 user_dict->SetBoolean(kKeyPublicAccount, is_public_account);
1253 user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user);
1254 user_dict->SetInteger(kKeyForceOnlineSignin, force_online_signin);
1255 user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
1256 user_dict->SetBoolean(kKeyIsOwner, is_owner);
1258 // Fill in multi-profiles related fields.
1259 if (is_signin_to_add) {
1260 MultiProfileUserController* multi_profile_user_controller =
1261 UserManager::Get()->GetMultiProfileUserController();
1262 std::string behavior = multi_profile_user_controller->
1263 GetCachedValue(user->email());
1264 user_dict->SetBoolean(kKeyMultiProfilesAllowed,
1265 multi_profile_user_controller->IsUserAllowedInSession(email) ==
1266 MultiProfileUserController::ALLOWED);
1267 user_dict->SetString(kKeyMultiProfilesPolicy, behavior);
1268 } else {
1269 user_dict->SetBoolean(kKeyMultiProfilesAllowed, true);
1272 if (is_public_account) {
1273 policy::BrowserPolicyConnectorChromeOS* policy_connector =
1274 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1276 if (policy_connector->IsEnterpriseManaged()) {
1277 user_dict->SetString(kKeyEnterpriseDomain,
1278 policy_connector->GetEnterpriseDomain());
1283 void SigninScreenHandler::SendUserList(bool animated) {
1284 if (!delegate_)
1285 return;
1286 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1287 "ShowLoginWebUI",
1288 LoginDisplayHostImpl::kShowLoginWebUIid,
1289 "SendUserList");
1290 BootTimesLoader::Get()->RecordCurrentStats("login-send-user-list");
1292 base::ListValue users_list;
1293 size_t first_non_public_account_index = 0;
1294 const UserList& users = delegate_->GetUsers();
1296 // TODO(nkostylev): Move to a separate method in UserManager.
1297 // http://crbug.com/230852
1298 bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
1299 UserManager::Get()->IsUserLoggedIn();
1301 bool single_user = users.size() == 1;
1302 std::string owner;
1303 chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
1304 bool has_owner = owner.size() > 0;
1305 // if public accounts available, that means there's no device owner
1306 size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers;
1307 size_t non_owner_count = 0;
1309 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1310 const std::string& email = (*it)->email();
1311 bool is_owner = (email == owner);
1312 bool is_public_account =
1313 ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
1315 if (is_public_account || non_owner_count < max_non_owner_users ||
1316 is_owner) {
1317 base::DictionaryValue* user_dict = new base::DictionaryValue();
1318 FillUserDictionary(*it, is_owner, is_signin_to_add, user_dict);
1319 bool signed_in = (*it)->is_logged_in();
1320 // Single user check here is necessary because owner info might not be
1321 // available when running into login screen on first boot.
1322 // See http://crosbug.com/12723
1323 bool can_remove_user = !single_user && !email.empty() && !is_owner &&
1324 !is_public_account && !signed_in && !is_signin_to_add;
1325 user_dict->SetBoolean(kKeyCanRemove, can_remove_user);
1327 if (!is_owner)
1328 ++non_owner_count;
1329 // public accounts come first in the list
1330 if (is_public_account) {
1331 users_list.Insert(first_non_public_account_index++, user_dict);
1332 } else {
1333 users_list.Append(user_dict);
1337 while (users_list.GetSize() > kMaxUsers)
1338 users_list.Remove(kMaxUsers, NULL);
1340 CallJS("login.AccountPickerScreen.loadUsers", users_list, animated,
1341 delegate_->IsShowGuest());
1344 void SigninScreenHandler::HandleAccountPickerReady() {
1345 VLOG(0) << "Login WebUI >> AccountPickerReady";
1347 if (delegate_ && !ScreenLocker::default_screen_locker() &&
1348 !chromeos::IsMachineHWIDCorrect() &&
1349 !oobe_ui_) {
1350 delegate_->ShowWrongHWIDScreen();
1351 return;
1354 PrefService* prefs = g_browser_process->local_state();
1355 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1356 prefs->SetBoolean(prefs::kFactoryResetRequested, false);
1357 prefs->CommitPendingWrite();
1358 HandleToggleResetScreen();
1359 return;
1362 is_account_picker_showing_first_time_ = true;
1363 MaybePreloadAuthExtension();
1365 if (ScreenLocker::default_screen_locker())
1366 ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1368 if (delegate_)
1369 delegate_->OnSigninScreenReady();
1372 void SigninScreenHandler::HandleWallpaperReady() {
1373 if (ScreenLocker::default_screen_locker()) {
1374 ScreenLocker::default_screen_locker()->delegate()->
1375 OnLockBackgroundDisplayed();
1379 void SigninScreenHandler::HandleLoginWebuiReady() {
1380 if (focus_stolen_) {
1381 // Set focus to the Gaia page.
1382 // TODO(altimofeev): temporary solution, until focus parameters are
1383 // implemented on the Gaia side.
1384 // Do this only once. Any subsequent call would relod GAIA frame.
1385 focus_stolen_ = false;
1386 const char code[] = "gWindowOnLoad();";
1387 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1388 rvh->ExecuteJavascriptInWebFrame(
1389 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1390 base::ASCIIToUTF16(code));
1392 if (!gaia_silent_load_) {
1393 content::NotificationService::current()->Notify(
1394 chrome::NOTIFICATION_LOGIN_WEBUI_LOADED,
1395 content::NotificationService::AllSources(),
1396 content::NotificationService::NoDetails());
1397 } else {
1398 focus_stolen_ = true;
1399 // Prevent focus stealing by the Gaia page.
1400 // TODO(altimofeev): temporary solution, until focus parameters are
1401 // implemented on the Gaia side.
1402 const char code[] = "var gWindowOnLoad = window.onload; "
1403 "window.onload=function() {};";
1404 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1405 rvh->ExecuteJavascriptInWebFrame(
1406 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1407 base::ASCIIToUTF16(code));
1408 // As we could miss and window.onload could already be called, restore
1409 // focus to current pod (see crbug/175243).
1410 RefocusCurrentPod();
1412 DCHECK(gaia_screen_handler_);
1413 gaia_screen_handler_->HandleFrameLoadingCompleted(0);
1415 if (test_expects_complete_login_)
1416 SubmitLoginFormForTest();
1419 void SigninScreenHandler::HandleSignOutUser() {
1420 if (delegate_)
1421 delegate_->Signout();
1424 void SigninScreenHandler::HandleNetworkErrorShown() {
1425 content::NotificationService::current()->Notify(
1426 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
1427 content::NotificationService::AllSources(),
1428 content::NotificationService::NoDetails());
1431 void SigninScreenHandler::HandleCreateAccount() {
1432 if (delegate_)
1433 delegate_->CreateAccount();
1436 void SigninScreenHandler::HandleOpenProxySettings() {
1437 LoginDisplayHostImpl::default_host()->OpenProxySettings();
1440 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1441 LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
1442 << "webui_visible_: " << webui_visible_;
1443 if (!webui_visible_) {
1444 // There might be multiple messages from OOBE UI so send notifications after
1445 // the first one only.
1446 content::NotificationService::current()->Notify(
1447 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1448 content::NotificationService::AllSources(),
1449 content::NotificationService::NoDetails());
1450 TRACE_EVENT_ASYNC_END0(
1451 "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1453 webui_visible_ = true;
1454 if (preferences_changed_delayed_)
1455 OnPreferencesChanged();
1458 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1459 StartClearingCookies(base::Bind(
1460 &SigninScreenHandler::CancelPasswordChangedFlowInternal,
1461 weak_factory_.GetWeakPtr()));
1464 void SigninScreenHandler::HandleCancelUserAdding() {
1465 if (delegate_)
1466 delegate_->CancelUserAdding();
1469 void SigninScreenHandler::HandleMigrateUserData(
1470 const std::string& old_password) {
1471 if (delegate_)
1472 delegate_->MigrateUserData(old_password);
1475 void SigninScreenHandler::HandleResyncUserData() {
1476 if (delegate_)
1477 delegate_->ResyncUserData();
1480 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1481 bool new_value) {
1482 VLOG(0) << "Login WebUI >> active: " << new_value << ", "
1483 << "source: " << source;
1485 if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1486 KioskAppManager::Get()->IsAutoLaunchRequested()) {
1487 VLOG(0) << "Showing auto-launch warning";
1488 // On slow devices, the wallpaper animation is not shown initially, so we
1489 // must explicitly load the wallpaper. This is also the case for the
1490 // account-picker and gaia-signin UI states.
1491 delegate_->LoadSigninWallpaper();
1492 HandleToggleKioskAutolaunchScreen();
1493 return;
1496 if (source == kSourceGaiaSignin) {
1497 ui_state_ = UI_STATE_GAIA_SIGNIN;
1498 } else if (source == kSourceAccountPicker) {
1499 ui_state_ = UI_STATE_ACCOUNT_PICKER;
1500 } else {
1501 NOTREACHED();
1502 return;
1506 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1507 DCHECK(UserManager::Get()->IsUserLoggedIn());
1508 if (ScreenLocker::default_screen_locker())
1509 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1512 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1513 UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1516 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1517 offline_login_active_ = offline_login_active;
1520 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1521 SetUserInputMethod(user_id);
1522 WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
1525 void SigninScreenHandler::HandleCustomButtonClicked(
1526 const std::string& username) {
1527 if (user_pod_button_callback_map_.find(username)
1528 == user_pod_button_callback_map_.end()) {
1529 LOG(WARNING) << "User pod custom button clicked but no callback found";
1530 return;
1532 user_pod_button_callback_map_[username].Run();
1535 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
1536 double attempt_token) {
1537 email_retriever_.reset(new AuthenticatedUserEmailRetriever(
1538 base::Bind(&SigninScreenHandler::CallJS<double, std::string>,
1539 base::Unretained(this),
1540 "login.GaiaSigninScreen.setAuthenticatedUserEmail",
1541 attempt_token),
1542 Profile::FromWebUI(web_ui())->GetRequestContext()));
1545 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id,
1546 bool diagnostic_mode) {
1547 delegate_->LoginAsKioskApp(app_id, diagnostic_mode);
1550 void SigninScreenHandler::StartClearingDnsCache() {
1551 if (dns_clear_task_running_ || !g_browser_process->io_thread())
1552 return;
1554 dns_cleared_ = false;
1555 BrowserThread::PostTaskAndReply(
1556 BrowserThread::IO, FROM_HERE,
1557 base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
1558 base::Bind(&SigninScreenHandler::OnDnsCleared,
1559 weak_factory_.GetWeakPtr()));
1560 dns_clear_task_running_ = true;
1563 void SigninScreenHandler::StartClearingCookies(
1564 const base::Closure& on_clear_callback) {
1565 cookies_cleared_ = false;
1566 ProfileHelper* profile_helper =
1567 g_browser_process->platform_part()->profile_helper();
1568 LOG_ASSERT(
1569 Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile());
1570 profile_helper->ClearSigninProfile(base::Bind(
1571 &SigninScreenHandler::OnCookiesCleared,
1572 weak_factory_.GetWeakPtr(), on_clear_callback));
1575 void SigninScreenHandler::MaybePreloadAuthExtension() {
1576 LOG(WARNING) << "MaybePreloadAuthExtension() call.";
1578 // Fetching of the extension is not started before account picker page is
1579 // loaded because it can affect the loading speed. Also if cookies clearing
1580 // was initiated or |dns_clear_task_running_| then auth extension showing has
1581 // already been initiated and preloading is senseless.
1582 // Do not load the extension for the screen locker, see crosbug.com/25018.
1583 if (is_account_picker_showing_first_time_ &&
1584 !gaia_silent_load_ &&
1585 !ScreenLocker::default_screen_locker() &&
1586 !cookies_cleared_ &&
1587 !dns_clear_task_running_ &&
1588 network_state_informer_->state() == NetworkStateInformer::ONLINE) {
1589 gaia_silent_load_ = true;
1590 gaia_silent_load_network_ = network_state_informer_->network_path();
1591 LoadAuthExtension(true, true, false);
1595 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1596 CrosSettings* cros_settings = CrosSettings::Get();
1597 bool allow_new_user = false;
1598 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1599 if (allow_new_user)
1600 return false;
1601 UserManager* user_manager = UserManager::Get();
1602 const UserList& users = user_manager->GetUsers();
1603 if (!delegate_ || users.size() > kMaxUsers) {
1604 return false;
1606 const base::ListValue* whitelist = NULL;
1607 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1608 return false;
1609 for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1610 std::string whitelisted_user;
1611 // NB: Wildcards in the whitelist are also detected as not present here.
1612 if (!whitelist->GetString(i, &whitelisted_user) ||
1613 !user_manager->IsKnownUser(whitelisted_user)) {
1614 return false;
1617 return true;
1620 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1621 if (delegate_) {
1622 ShowImpl();
1623 delegate_->CancelPasswordChangedFlow();
1627 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1628 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1629 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
1630 if (oobe_ui)
1631 screen = oobe_ui->current_screen();
1632 return screen;
1635 bool SigninScreenHandler::IsGaiaVisible() const {
1636 return IsSigninScreen(GetCurrentScreen()) &&
1637 ui_state_ == UI_STATE_GAIA_SIGNIN;
1640 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1641 return IsSigninScreenHiddenByError() &&
1642 ui_state_ == UI_STATE_GAIA_SIGNIN;
1645 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1646 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1647 (IsSigninScreen(error_screen_actor_->parent_screen()));
1650 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1651 CrosSettings* cros_settings = CrosSettings::Get();
1652 if (!cros_settings)
1653 return false;
1654 bool allow_guest;
1655 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1656 return allow_guest;
1659 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1660 CrosSettings* cros_settings = CrosSettings::Get();
1661 if (!cros_settings)
1662 return false;
1664 // Offline login is allowed only when user pods are hidden.
1665 bool show_pods;
1666 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1667 return !show_pods;
1670 void SigninScreenHandler::SubmitLoginFormForTest() {
1671 VLOG(2) << "Submit login form for test, user=" << test_user_;
1673 std::string code;
1674 code += "document.getElementById('Email').value = '" + test_user_ + "';";
1675 code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
1676 code += "document.getElementById('signIn').click();";
1678 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1679 rvh->ExecuteJavascriptInWebFrame(
1680 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1681 base::ASCIIToUTF16(code));
1683 // Test properties are cleared in HandleCompleteLogin because the form
1684 // submission might fail and login will not be attempted after reloading
1685 // if they are cleared here.
1688 void SigninScreenHandler::ContinueKioskEnableFlow(bool should_auto_enroll) {
1689 wait_for_auto_enrollment_check_ = false;
1691 // Do not proceed with kiosk enable when auto enroll will be enforced.
1692 // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1693 if (should_auto_enroll) {
1694 LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1695 "going to be enforced.";
1697 if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1698 kiosk_enable_flow_aborted_callback_for_test_.Run();
1699 return;
1702 if (delegate_)
1703 delegate_->ShowKioskEnableScreen();
1706 void SigninScreenHandler::OnShowAddUser(const std::string& email) {
1707 email_ = email;
1708 is_account_picker_showing_first_time_ = false;
1710 if (gaia_silent_load_ && email_.empty()) {
1711 dns_cleared_ = true;
1712 cookies_cleared_ = true;
1713 ShowSigninScreenIfReady();
1714 } else {
1715 StartClearingDnsCache();
1716 StartClearingCookies(base::Bind(
1717 &SigninScreenHandler::ShowSigninScreenIfReady,
1718 weak_factory_.GetWeakPtr()));
1722 void SigninScreenHandler::SetSAMLPrincipalsAPIUsed(bool api_used) {
1723 using_saml_api_ = api_used;
1724 UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.APIUsed", api_used);
1727 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
1728 DCHECK(gaia_screen_handler_);
1729 return gaia_screen_handler_->frame_state();
1732 net::Error SigninScreenHandler::FrameError() const {
1733 DCHECK(gaia_screen_handler_);
1734 return gaia_screen_handler_->frame_error();
1737 } // namespace chromeos