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