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