Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / chromeos / login / signin_screen_handler.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/scoped_user_pref_update.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "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"
69
70 #if defined(USE_AURA)
71 #include "ash/shell.h"
72 #include "ash/wm/lock_state_controller.h"
73 #endif
74
75 using content::BrowserThread;
76 using content::RenderViewHost;
77
78 namespace {
79
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";
93
94 // Max number of users to show.
95 const size_t kMaxUsers = 18;
96
97 // Timeout to delay first notification about offline state for a
98 // current network.
99 const int kOfflineTimeoutSec = 5;
100
101 // Timeout used to prevent infinite connecting to a flaky network.
102 const int kConnectingTimeoutSec = 60;
103
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";
107
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;
114
115   io_thread->ClearHostCache();
116 }
117
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();
122 }
123
124 }  // namespace
125
126 namespace chromeos {
127
128 namespace {
129
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;
135 }
136
137 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
138                            ErrorScreenActor::ErrorReason reason) {
139   return state == NetworkStateInformer::CAPTIVE_PORTAL ||
140       reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
141 }
142
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));
152 }
153
154 bool IsSigninScreen(const OobeUI::Screen screen) {
155   return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
156       screen == OobeUI::SCREEN_ACCOUNT_PICKER;
157 }
158
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;
164 }
165
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();
173 }
174
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();
179
180   const base::DictionaryValue* users_lru_input_methods =
181       local_state->GetDictionary(prefs::kUsersLRUInputMethod);
182
183   if (users_lru_input_methods == NULL) {
184     DLOG(WARNING) << "SetUserInputMethod('" << username
185                   << "'): no kUsersLRUInputMethod";
186     return false;
187   }
188
189   std::string input_method;
190
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;
196   }
197
198   if (input_method.empty())
199     return false;
200
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.";
206
207     DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
208
209     base::DictionaryValue* const users_lru_input_methods = updater.Get();
210     if (users_lru_input_methods != NULL) {
211       users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
212     }
213     return false;
214   }
215
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!).";
221     }
222   }
223   manager->ChangeInputMethod(input_method);
224
225   return true;
226 }
227
228 void RecordSAMLScrapingVerificationResultInHistogram(bool success) {
229   UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.Scraping.VerificationResult", success);
230 }
231
232 }  // namespace
233
234 // LoginScreenContext implementation ------------------------------------------
235
236 LoginScreenContext::LoginScreenContext() {
237   Init();
238 }
239
240 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
241   Init();
242
243   if (!args || args->GetSize() == 0)
244     return;
245   std::string email;
246   if (args->GetString(0, &email))
247     email_ = email;
248 }
249
250 void LoginScreenContext::Init() {
251   oobe_ui_ = false;
252 }
253
254 // SigninScreenHandler implementation ------------------------------------------
255
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)));
300
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());
310 }
311
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);
321 }
322
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);
347
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);
354
355   builder->Add("supervisedUserExpiredTokenWarning",
356                IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
357   builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
358
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);
366
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);
373
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);
397
398   builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
399
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);
407
408   if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
409     builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
410
411   builder->Add("runType", CommandLine::ForCurrentProcess()->HasSwitch(
412       switches::kFirstExecAfterBoot) ?  "firstExecAfterBoot" :
413                                         "notFirstExecAfterBoot");
414 }
415
416 void SigninScreenHandler::Show(const LoginScreenContext& context) {
417   CHECK(delegate_);
418
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();
426 }
427
428 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
429   CallJS("showLoginSpinner");
430 }
431
432 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
433   delegate_ = delegate;
434   if (delegate_)
435     delegate_->SetWebUIHandler(this);
436 }
437
438 void SigninScreenHandler::SetNativeWindowDelegate(
439     NativeWindowDelegate* native_window_delegate) {
440   native_window_delegate_ = native_window_delegate;
441 }
442
443 void SigninScreenHandler::OnNetworkReady() {
444   LOG(WARNING) << "OnNetworkReady() call.";
445   MaybePreloadAuthExtension();
446 }
447
448 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
449   UpdateStateInternal(reason, false);
450 }
451
452 // SigninScreenHandler, private: -----------------------------------------------
453
454 void SigninScreenHandler::ShowImpl() {
455   if (!page_is_ready()) {
456     show_on_init_ = true;
457     return;
458   }
459
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);
467
468     // Reset Caps Lock state when login screen is shown.
469     input_method::InputMethodManager::Get()->GetXKeyboard()->
470         SetCapsLockEnabled(false);
471
472     base::DictionaryValue params;
473     params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
474     UpdateUIState(UI_STATE_ACCOUNT_PICKER, &params);
475   }
476 }
477
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;
492   }
493 }
494
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;
507   }
508
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);
512
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;
519   }
520
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();
529
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;
542   }
543
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));
557     }
558     return;
559   }
560   connecting_closure_.Cancel();
561
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;
574
575   if (is_online || !is_behind_captive_portal)
576     error_screen_actor_->HideCaptivePortal();
577
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;
584   }
585
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();
592   }
593
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();
599   }
600
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();
606   }
607
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);
613   }
614 }
615
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);
624
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();
637     }
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());
647   }
648
649   const bool guest_signin_allowed = IsGuestSigninAllowed() &&
650       IsSigninScreenError(error_screen_actor_->error_state());
651   error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
652
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);
658
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);
665   }
666 }
667
668 void SigninScreenHandler::HideOfflineMessage(
669     NetworkStateInformer::State state,
670     ErrorScreenActor::ErrorReason reason) {
671   if (!IsSigninScreenHiddenByError())
672     return;
673
674   error_screen_actor_->Hide();
675
676   // Forces a reload for Gaia screen on hiding error message.
677   if (IsGaiaVisible() || IsGaiaHiddenByError())
678     ReloadGaiaScreen();
679 }
680
681 void SigninScreenHandler::ReloadGaiaScreen() {
682   gaia_screen_handler_->ReloadGaia();
683 }
684
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;
690
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);
696
697   if (show_on_init_) {
698     show_on_init_ = false;
699     ShowImpl();
700   }
701 }
702
703 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
704   if (native_window_delegate_)
705     return native_window_delegate_->GetNativeWindow();
706   return NULL;
707 }
708
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);
769
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);
773 }
774
775 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
776   registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
777 }
778
779 void SigninScreenHandler::HandleGetUsers() {
780   SendUserList(false);
781 }
782
783 void SigninScreenHandler::ClearAndEnablePassword() {
784   core_oobe_actor_->ResetSignInUI(false);
785 }
786
787 void SigninScreenHandler::ClearUserPodPassword() {
788   core_oobe_actor_->ClearUserPodPassword();
789 }
790
791 void SigninScreenHandler::RefocusCurrentPod() {
792   core_oobe_actor_->RefocusCurrentPod();
793 }
794
795 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
796   core_oobe_actor_->OnLoginSuccess(username);
797 }
798
799 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
800   CallJS("login.AccountPickerScreen.removeUser", username);
801 }
802
803 void SigninScreenHandler::OnUserImageChanged(const User& user) {
804   if (page_is_ready())
805     CallJS("login.AccountPickerScreen.updateUserImage", user.email());
806 }
807
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;
815   }
816
817   if (delegate_ && !delegate_->IsShowUsers()) {
818     HandleShowAddUser(NULL);
819   } else {
820     SendUserList(false);
821     UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
822   }
823   preferences_changed_delayed_ = false;
824 }
825
826 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
827   SetDelegate(NULL);
828 }
829
830 void SigninScreenHandler::ShowBannerMessage(const std::string& message) {
831   CallJS("login.AccountPickerScreen.showBannerMessage", message);
832 }
833
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);
840 }
841
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);
848 }
849
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;
858   }
859 }
860
861 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
862   core_oobe_actor_->ShowSignInUI(email);
863 }
864
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_);
870 }
871
872 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
873   core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
874 }
875
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();
881
882   test_user_ = username;
883   test_pass_ = password;
884   test_expects_complete_login_ = true;
885
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);
893 }
894
895 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
896   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
897   cookies_cleared_ = true;
898   on_clear_callback.Run();
899 }
900
901 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
902   if (page_is_ready())
903     CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
904 }
905
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;
913     }
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();
923       }
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;
929     }
930     default:
931       NOTREACHED() << "Unexpected notification " << type;
932   }
933 }
934
935 void SigninScreenHandler::OnDnsCleared() {
936   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
937   dns_clear_task_running_ = false;
938   dns_cleared_ = true;
939   ShowSigninScreenIfReady();
940 }
941
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;
951   }
952
953   chromeos::input_method::InputMethodManager* const manager =
954       chromeos::input_method::InputMethodManager::Get();
955
956   const bool succeed = SetUserInputMethodImpl(username, manager);
957
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.";
964
965     manager->SetInputMethodLoginDefault();
966   }
967 }
968
969 void SigninScreenHandler::ShowSigninScreenIfReady() {
970   LOG(WARNING) << "ShowSigninScreenIfReady() call.";
971
972   if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
973     return;
974
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;
983   }
984
985   // Note that LoadAuthExtension clears |email_|.
986   if (email_.empty())
987     delegate_->LoadSigninWallpaper();
988   else
989     delegate_->LoadWallpaper(email_);
990
991   // Set Least Recently Used input method for the user.
992   if (!email_.empty())
993     SetUserInputMethod(email_);
994
995   LoadAuthExtension(!gaia_silent_load_, false, false);
996   UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
997
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();
1004   }
1005
1006   UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
1007 }
1008
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_;
1022
1023   email_.clear();
1024
1025   DCHECK(gaia_screen_handler_);
1026   gaia_screen_handler_->LoadGaia(context);
1027 }
1028
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();
1036 }
1037
1038 void SigninScreenHandler::UpdateAddButtonStatus() {
1039   CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1040          AllWhitelistedUsersPresent());
1041 }
1042
1043 void SigninScreenHandler::HandleUsingSAMLAPI() {
1044   SetSAMLPrincipalsAPIUsed(true);
1045 }
1046
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();
1055 }
1056
1057 void SigninScreenHandler::HandleScrapedPasswordVerificationFailed() {
1058   RecordSAMLScrapingVerificationResultInHistogram(false);
1059 }
1060
1061 void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email,
1062                                               const std::string& password,
1063                                               bool using_saml) {
1064   if (!delegate_)
1065     return;
1066
1067   if (using_saml && !using_saml_api_)
1068     RecordSAMLScrapingVerificationResultInHistogram(true);
1069
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));
1080
1081   if (test_expects_complete_login_) {
1082     VLOG(2) << "Complete test login for " << typed_email
1083             << ", requested=" << test_user_;
1084
1085     test_expects_complete_login_ = false;
1086     test_user_.clear();
1087     test_pass_.clear();
1088   }
1089 }
1090
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));
1100 }
1101
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
1109 }
1110
1111 void SigninScreenHandler::HandleLaunchDemoUser() {
1112   if (delegate_)
1113     delegate_->LoginAsRetailModeUser();
1114 }
1115
1116 void SigninScreenHandler::HandleLaunchIncognito() {
1117   if (delegate_)
1118     delegate_->LoginAsGuest();
1119 }
1120
1121 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
1122   if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
1123     LOG(ERROR) << "Managed users not allowed.";
1124     return;
1125   }
1126   scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
1127   LoginDisplayHostImpl::default_host()->
1128       StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
1129       params.Pass());
1130 }
1131
1132 void SigninScreenHandler::HandleLaunchPublicAccount(
1133     const std::string& username) {
1134   if (delegate_)
1135     delegate_->LoginAsPublicAccount(username);
1136 }
1137
1138 void 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
1151 void SigninScreenHandler::HandleShutdownSystem() {
1152   ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1153 }
1154
1155 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1156   if (delegate_)
1157     delegate_->LoadWallpaper(email);
1158 }
1159
1160 void SigninScreenHandler::HandleRebootSystem() {
1161   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1162 }
1163
1164 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1165   if (!delegate_)
1166     return;
1167   delegate_->RemoveUser(email);
1168   UpdateAddButtonStatus();
1169 }
1170
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);
1181 }
1182
1183 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1184   if (delegate_)
1185     delegate_->ShowEnterpriseEnrollmentScreen();
1186 }
1187
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;
1195
1196     LoginDisplayHostImpl::default_host()->GetAutoEnrollmentCheckResult(
1197         base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1198                    weak_factory_.GetWeakPtr()));
1199   }
1200 }
1201
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();
1207 }
1208
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();
1214 }
1215
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));
1223 }
1224
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();
1235
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);
1248
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);
1257
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);
1270   }
1271
1272   if (is_public_account) {
1273     policy::BrowserPolicyConnectorChromeOS* policy_connector =
1274         g_browser_process->platform_part()->browser_policy_connector_chromeos();
1275
1276     if (policy_connector->IsEnterpriseManaged()) {
1277       user_dict->SetString(kKeyEnterpriseDomain,
1278                            policy_connector->GetEnterpriseDomain());
1279     }
1280   }
1281 }
1282
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");
1291
1292   base::ListValue users_list;
1293   const UserList& users = delegate_->GetUsers();
1294
1295   // TODO(nkostylev): Move to a separate method in UserManager.
1296   // http://crbug.com/230852
1297   bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
1298       UserManager::Get()->IsUserLoggedIn();
1299
1300   bool single_user = users.size() == 1;
1301   std::string owner;
1302   chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
1303   bool has_owner = owner.size() > 0;
1304   size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers;
1305   size_t non_owner_count = 0;
1306
1307   for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1308     const std::string& email = (*it)->email();
1309     bool is_owner = (email == owner);
1310     bool is_public_account =
1311         ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
1312
1313     if (is_public_account || non_owner_count < max_non_owner_users ||
1314         is_owner) {
1315       base::DictionaryValue* user_dict = new base::DictionaryValue();
1316       FillUserDictionary(*it, is_owner, is_signin_to_add, user_dict);
1317       bool signed_in = (*it)->is_logged_in();
1318       // Single user check here is necessary because owner info might not be
1319       // available when running into login screen on first boot.
1320       // See http://crosbug.com/12723
1321       bool can_remove_user = !single_user && !email.empty() && !is_owner &&
1322           !is_public_account && !signed_in && !is_signin_to_add;
1323       user_dict->SetBoolean(kKeyCanRemove, can_remove_user);
1324
1325       if (!is_owner)
1326         ++non_owner_count;
1327
1328       users_list.Append(user_dict);
1329     }
1330   }
1331   while (users_list.GetSize() > kMaxUsers)
1332     users_list.Remove(kMaxUsers, NULL);
1333
1334   CallJS("login.AccountPickerScreen.loadUsers", users_list, animated,
1335          delegate_->IsShowGuest());
1336 }
1337
1338 void SigninScreenHandler::HandleAccountPickerReady() {
1339   VLOG(0) << "Login WebUI >> AccountPickerReady";
1340
1341   if (delegate_ && !ScreenLocker::default_screen_locker() &&
1342       !chromeos::IsMachineHWIDCorrect() &&
1343       !oobe_ui_) {
1344     delegate_->ShowWrongHWIDScreen();
1345     return;
1346   }
1347
1348   PrefService* prefs = g_browser_process->local_state();
1349   if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1350     prefs->SetBoolean(prefs::kFactoryResetRequested, false);
1351     prefs->CommitPendingWrite();
1352     HandleToggleResetScreen();
1353     return;
1354   }
1355
1356   is_account_picker_showing_first_time_ = true;
1357   MaybePreloadAuthExtension();
1358
1359   if (ScreenLocker::default_screen_locker())
1360     ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1361
1362   if (delegate_)
1363     delegate_->OnSigninScreenReady();
1364 }
1365
1366 void SigninScreenHandler::HandleWallpaperReady() {
1367   if (ScreenLocker::default_screen_locker()) {
1368     ScreenLocker::default_screen_locker()->delegate()->
1369         OnLockBackgroundDisplayed();
1370   }
1371 }
1372
1373 void SigninScreenHandler::HandleLoginWebuiReady() {
1374   if (focus_stolen_) {
1375     // Set focus to the Gaia page.
1376     // TODO(altimofeev): temporary solution, until focus parameters are
1377     // implemented on the Gaia side.
1378     // Do this only once. Any subsequent call would relod GAIA frame.
1379     focus_stolen_ = false;
1380     const char code[] = "gWindowOnLoad();";
1381     RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1382     rvh->ExecuteJavascriptInWebFrame(
1383         base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1384         base::ASCIIToUTF16(code));
1385   }
1386   if (!gaia_silent_load_) {
1387     content::NotificationService::current()->Notify(
1388         chrome::NOTIFICATION_LOGIN_WEBUI_LOADED,
1389         content::NotificationService::AllSources(),
1390         content::NotificationService::NoDetails());
1391   } else {
1392     focus_stolen_ = true;
1393     // Prevent focus stealing by the Gaia page.
1394     // TODO(altimofeev): temporary solution, until focus parameters are
1395     // implemented on the Gaia side.
1396     const char code[] = "var gWindowOnLoad = window.onload; "
1397                         "window.onload=function() {};";
1398     RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1399     rvh->ExecuteJavascriptInWebFrame(
1400         base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1401         base::ASCIIToUTF16(code));
1402     // As we could miss and window.onload could already be called, restore
1403     // focus to current pod (see crbug/175243).
1404     RefocusCurrentPod();
1405   }
1406   DCHECK(gaia_screen_handler_);
1407   gaia_screen_handler_->HandleFrameLoadingCompleted(0);
1408
1409   if (test_expects_complete_login_)
1410     SubmitLoginFormForTest();
1411 }
1412
1413 void SigninScreenHandler::HandleSignOutUser() {
1414   if (delegate_)
1415     delegate_->Signout();
1416 }
1417
1418 void SigninScreenHandler::HandleNetworkErrorShown() {
1419   content::NotificationService::current()->Notify(
1420       chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
1421       content::NotificationService::AllSources(),
1422       content::NotificationService::NoDetails());
1423 }
1424
1425 void SigninScreenHandler::HandleCreateAccount() {
1426   if (delegate_)
1427     delegate_->CreateAccount();
1428 }
1429
1430 void SigninScreenHandler::HandleOpenProxySettings() {
1431   LoginDisplayHostImpl::default_host()->OpenProxySettings();
1432 }
1433
1434 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1435   LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
1436                << "webui_visible_: " << webui_visible_;
1437   if (!webui_visible_) {
1438     // There might be multiple messages from OOBE UI so send notifications after
1439     // the first one only.
1440     content::NotificationService::current()->Notify(
1441         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1442         content::NotificationService::AllSources(),
1443         content::NotificationService::NoDetails());
1444     TRACE_EVENT_ASYNC_END0(
1445         "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1446   }
1447   webui_visible_ = true;
1448   if (preferences_changed_delayed_)
1449     OnPreferencesChanged();
1450 }
1451
1452 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1453   StartClearingCookies(base::Bind(
1454       &SigninScreenHandler::CancelPasswordChangedFlowInternal,
1455       weak_factory_.GetWeakPtr()));
1456 }
1457
1458 void SigninScreenHandler::HandleCancelUserAdding() {
1459   if (delegate_)
1460     delegate_->CancelUserAdding();
1461 }
1462
1463 void SigninScreenHandler::HandleMigrateUserData(
1464     const std::string& old_password) {
1465   if (delegate_)
1466     delegate_->MigrateUserData(old_password);
1467 }
1468
1469 void SigninScreenHandler::HandleResyncUserData() {
1470   if (delegate_)
1471     delegate_->ResyncUserData();
1472 }
1473
1474 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1475                                                     bool new_value) {
1476   VLOG(0) << "Login WebUI >> active: " << new_value << ", "
1477             << "source: " << source;
1478
1479   if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1480       KioskAppManager::Get()->IsAutoLaunchRequested()) {
1481     VLOG(0) << "Showing auto-launch warning";
1482     // On slow devices, the wallpaper animation is not shown initially, so we
1483     // must explicitly load the wallpaper. This is also the case for the
1484     // account-picker and gaia-signin UI states.
1485     delegate_->LoadSigninWallpaper();
1486     HandleToggleKioskAutolaunchScreen();
1487     return;
1488   }
1489
1490   if (source == kSourceGaiaSignin) {
1491     ui_state_ = UI_STATE_GAIA_SIGNIN;
1492   } else if (source == kSourceAccountPicker) {
1493     ui_state_ = UI_STATE_ACCOUNT_PICKER;
1494   } else {
1495     NOTREACHED();
1496     return;
1497   }
1498 }
1499
1500 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1501   DCHECK(UserManager::Get()->IsUserLoggedIn());
1502   if (ScreenLocker::default_screen_locker())
1503     ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1504 }
1505
1506 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1507   UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1508 }
1509
1510 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1511   offline_login_active_ = offline_login_active;
1512 }
1513
1514 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1515   SetUserInputMethod(user_id);
1516   WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
1517 }
1518
1519 void SigninScreenHandler::HandleCustomButtonClicked(
1520     const std::string& username) {
1521   if (user_pod_button_callback_map_.find(username)
1522       == user_pod_button_callback_map_.end()) {
1523     LOG(WARNING) << "User pod custom button clicked but no callback found";
1524     return;
1525   }
1526   user_pod_button_callback_map_[username].Run();
1527 }
1528
1529 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
1530     double attempt_token) {
1531   email_retriever_.reset(new AuthenticatedUserEmailRetriever(
1532       base::Bind(&SigninScreenHandler::CallJS<double, std::string>,
1533                  base::Unretained(this),
1534                  "login.GaiaSigninScreen.setAuthenticatedUserEmail",
1535                  attempt_token),
1536       Profile::FromWebUI(web_ui())->GetRequestContext()));
1537 }
1538
1539 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id,
1540                                                bool diagnostic_mode) {
1541   delegate_->LoginAsKioskApp(app_id, diagnostic_mode);
1542 }
1543
1544 void SigninScreenHandler::StartClearingDnsCache() {
1545   if (dns_clear_task_running_ || !g_browser_process->io_thread())
1546     return;
1547
1548   dns_cleared_ = false;
1549   BrowserThread::PostTaskAndReply(
1550       BrowserThread::IO, FROM_HERE,
1551       base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
1552       base::Bind(&SigninScreenHandler::OnDnsCleared,
1553                  weak_factory_.GetWeakPtr()));
1554   dns_clear_task_running_ = true;
1555 }
1556
1557 void SigninScreenHandler::StartClearingCookies(
1558     const base::Closure& on_clear_callback) {
1559   cookies_cleared_ = false;
1560   ProfileHelper* profile_helper =
1561       g_browser_process->platform_part()->profile_helper();
1562   LOG_ASSERT(
1563       Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile());
1564   profile_helper->ClearSigninProfile(base::Bind(
1565       &SigninScreenHandler::OnCookiesCleared,
1566       weak_factory_.GetWeakPtr(), on_clear_callback));
1567 }
1568
1569 void SigninScreenHandler::MaybePreloadAuthExtension() {
1570   LOG(WARNING) << "MaybePreloadAuthExtension() call.";
1571
1572   // Fetching of the extension is not started before account picker page is
1573   // loaded because it can affect the loading speed. Also if cookies clearing
1574   // was initiated or |dns_clear_task_running_| then auth extension showing has
1575   // already been initiated and preloading is senseless.
1576   // Do not load the extension for the screen locker, see crosbug.com/25018.
1577   if (is_account_picker_showing_first_time_ &&
1578       !gaia_silent_load_ &&
1579       !ScreenLocker::default_screen_locker() &&
1580       !cookies_cleared_ &&
1581       !dns_clear_task_running_ &&
1582       network_state_informer_->state() == NetworkStateInformer::ONLINE) {
1583     gaia_silent_load_ = true;
1584     gaia_silent_load_network_ = network_state_informer_->network_path();
1585     LoadAuthExtension(true, true, false);
1586   }
1587 }
1588
1589 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1590   CrosSettings* cros_settings = CrosSettings::Get();
1591   bool allow_new_user = false;
1592   cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1593   if (allow_new_user)
1594     return false;
1595   UserManager* user_manager = UserManager::Get();
1596   const UserList& users = user_manager->GetUsers();
1597   if (!delegate_ || users.size() > kMaxUsers) {
1598     return false;
1599   }
1600   const base::ListValue* whitelist = NULL;
1601   if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1602     return false;
1603   for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1604     std::string whitelisted_user;
1605     // NB: Wildcards in the whitelist are also detected as not present here.
1606     if (!whitelist->GetString(i, &whitelisted_user) ||
1607         !user_manager->IsKnownUser(whitelisted_user)) {
1608       return false;
1609     }
1610   }
1611   return true;
1612 }
1613
1614 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1615   if (delegate_) {
1616     ShowImpl();
1617     delegate_->CancelPasswordChangedFlow();
1618   }
1619 }
1620
1621 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1622   OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1623   OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
1624   if (oobe_ui)
1625     screen = oobe_ui->current_screen();
1626   return screen;
1627 }
1628
1629 bool SigninScreenHandler::IsGaiaVisible() const {
1630   return IsSigninScreen(GetCurrentScreen()) &&
1631       ui_state_ == UI_STATE_GAIA_SIGNIN;
1632 }
1633
1634 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1635   return IsSigninScreenHiddenByError() &&
1636       ui_state_ == UI_STATE_GAIA_SIGNIN;
1637 }
1638
1639 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1640   return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1641       (IsSigninScreen(error_screen_actor_->parent_screen()));
1642 }
1643
1644 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1645   CrosSettings* cros_settings = CrosSettings::Get();
1646   if (!cros_settings)
1647     return false;
1648   bool allow_guest;
1649   cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1650   return allow_guest;
1651 }
1652
1653 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1654   CrosSettings* cros_settings = CrosSettings::Get();
1655   if (!cros_settings)
1656     return false;
1657
1658   // Offline login is allowed only when user pods are hidden.
1659   bool show_pods;
1660   cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1661   return !show_pods;
1662 }
1663
1664 void SigninScreenHandler::SubmitLoginFormForTest() {
1665   VLOG(2) << "Submit login form for test, user=" << test_user_;
1666
1667   std::string code;
1668   code += "document.getElementById('Email').value = '" + test_user_ + "';";
1669   code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
1670   code += "document.getElementById('signIn').click();";
1671
1672   RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1673   rvh->ExecuteJavascriptInWebFrame(
1674       base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1675       base::ASCIIToUTF16(code));
1676
1677   // Test properties are cleared in HandleCompleteLogin because the form
1678   // submission might fail and login will not be attempted after reloading
1679   // if they are cleared here.
1680 }
1681
1682 void SigninScreenHandler::ContinueKioskEnableFlow(bool should_auto_enroll) {
1683   wait_for_auto_enrollment_check_ = false;
1684
1685   // Do not proceed with kiosk enable when auto enroll will be enforced.
1686   // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1687   if (should_auto_enroll) {
1688     LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1689                     "going to be enforced.";
1690
1691     if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1692       kiosk_enable_flow_aborted_callback_for_test_.Run();
1693     return;
1694   }
1695
1696   if (delegate_)
1697     delegate_->ShowKioskEnableScreen();
1698 }
1699
1700 void SigninScreenHandler::OnShowAddUser(const std::string& email) {
1701   email_ = email;
1702   is_account_picker_showing_first_time_ = false;
1703
1704   if (gaia_silent_load_ && email_.empty()) {
1705     dns_cleared_ = true;
1706     cookies_cleared_ = true;
1707     ShowSigninScreenIfReady();
1708   } else {
1709     StartClearingDnsCache();
1710     StartClearingCookies(base::Bind(
1711         &SigninScreenHandler::ShowSigninScreenIfReady,
1712         weak_factory_.GetWeakPtr()));
1713   }
1714 }
1715
1716 void SigninScreenHandler::SetSAMLPrincipalsAPIUsed(bool api_used) {
1717   using_saml_api_ = api_used;
1718   UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.APIUsed", api_used);
1719 }
1720
1721 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
1722   DCHECK(gaia_screen_handler_);
1723   return gaia_screen_handler_->frame_state();
1724 }
1725
1726 net::Error SigninScreenHandler::FrameError() const {
1727   DCHECK(gaia_screen_handler_);
1728   return gaia_screen_handler_->frame_error();
1729 }
1730
1731 }  // namespace chromeos