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