Upstream version 11.40.277.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 "ash/shell.h"
11 #include "ash/wm/lock_state_controller.h"
12 #include "base/bind.h"
13 #include "base/debug/trace_event.h"
14 #include "base/location.h"
15 #include "base/logging.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_registry_simple.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/prefs/scoped_user_pref_update.h"
20 #include "base/strings/string16.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/sys_info.h"
25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/browser_process_platform_part_chromeos.h"
27 #include "chrome/browser/browser_shutdown.h"
28 #include "chrome/browser/chrome_notification_types.h"
29 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
30 #include "chrome/browser/chromeos/boot_times_loader.h"
31 #include "chrome/browser/chromeos/input_method/input_method_util.h"
32 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
33 #include "chrome/browser/chromeos/login/error_screens_histogram_helper.h"
34 #include "chrome/browser/chromeos/login/hwid_checker.h"
35 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
36 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
37 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
38 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
39 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
40 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
41 #include "chrome/browser/chromeos/login/wizard_controller.h"
42 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
43 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
44 #include "chrome/browser/chromeos/policy/device_local_account.h"
45 #include "chrome/browser/chromeos/profiles/profile_helper.h"
46 #include "chrome/browser/chromeos/settings/cros_settings.h"
47 #include "chrome/browser/io_thread.h"
48 #include "chrome/browser/profiles/profile.h"
49 #include "chrome/browser/signin/easy_unlock_service.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 "third_party/cros_system_api/dbus/service_constants.h"
76 #include "ui/base/webui/web_ui_util.h"
77
78 #if !defined(USE_ATHENA)
79 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
80 #endif
81
82 namespace {
83
84 // Max number of users to show.
85 const size_t kMaxUsers = 18;
86
87 // Timeout to delay first notification about offline state for a
88 // current network.
89 const int kOfflineTimeoutSec = 5;
90
91 // Timeout used to prevent infinite connecting to a flaky network.
92 const int kConnectingTimeoutSec = 60;
93
94 // Type of the login screen UI that is currently presented to user.
95 const char kSourceGaiaSignin[] = "gaia-signin";
96 const char kSourceAccountPicker[] = "account-picker";
97
98 static bool Contains(const std::vector<std::string>& container,
99                      const std::string& value) {
100   return std::find(container.begin(), container.end(), value) !=
101          container.end();
102 }
103
104 class CallOnReturn {
105  public:
106   explicit CallOnReturn(const base::Closure& callback)
107       : callback_(callback), call_scheduled_(false) {}
108
109   ~CallOnReturn() {
110     if (call_scheduled_ && !callback_.is_null())
111       callback_.Run();
112   }
113
114   void ScheduleCall() { call_scheduled_ = true; }
115
116  private:
117   base::Closure callback_;
118   bool call_scheduled_;
119
120   DISALLOW_COPY_AND_ASSIGN(CallOnReturn);
121 };
122
123 }  // namespace
124
125 namespace chromeos {
126
127 namespace {
128
129 bool IsOnline(NetworkStateInformer::State state,
130               ErrorScreenActor::ErrorReason reason) {
131   return state == NetworkStateInformer::ONLINE &&
132       reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
133       reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
134 }
135
136 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
137                            ErrorScreenActor::ErrorReason reason) {
138   return state == NetworkStateInformer::CAPTIVE_PORTAL ||
139       reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
140 }
141
142 bool IsProxyError(NetworkStateInformer::State state,
143                   ErrorScreenActor::ErrorReason reason,
144                   net::Error frame_error) {
145   return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
146       reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
147       reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
148       (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
149        (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
150         frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
151 }
152
153 bool IsSigninScreen(const OobeUI::Screen screen) {
154   return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
155       screen == OobeUI::SCREEN_ACCOUNT_PICKER;
156 }
157
158 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
159   return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
160       error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
161       error_state == ErrorScreen::ERROR_STATE_PROXY ||
162       error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
163 }
164
165 // Returns network name by service path.
166 std::string GetNetworkName(const std::string& service_path) {
167   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
168       GetNetworkState(service_path);
169   if (!network)
170     return std::string();
171   return network->name();
172 }
173
174 static bool SetUserInputMethodImpl(
175     const std::string& username,
176     const std::string& user_input_method,
177     input_method::InputMethodManager::State* ime_state) {
178   if (!chromeos::input_method::InputMethodManager::Get()->IsLoginKeyboard(
179           user_input_method)) {
180     LOG(WARNING) << "SetUserInputMethod('" << username
181                  << "'): stored user LRU input method '" << user_input_method
182                  << "' is no longer Full Latin Keyboard Language"
183                  << " (entry dropped). Use hardware default instead.";
184
185     PrefService* const local_state = g_browser_process->local_state();
186     DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
187
188     base::DictionaryValue* const users_lru_input_methods = updater.Get();
189     if (users_lru_input_methods != NULL) {
190       users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
191     }
192     return false;
193   }
194
195   if (!Contains(ime_state->GetActiveInputMethodIds(), user_input_method)) {
196     if (!ime_state->EnableInputMethod(user_input_method)) {
197       DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
198                   << "'): user input method '" << user_input_method
199                   << "' is not enabled and enabling failed (ignored!).";
200     }
201   }
202   ime_state->ChangeInputMethod(user_input_method, false /* show_message */);
203
204   return true;
205 }
206
207 }  // namespace
208
209 // LoginScreenContext implementation ------------------------------------------
210
211 LoginScreenContext::LoginScreenContext() {
212   Init();
213 }
214
215 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
216   Init();
217
218   if (!args || args->GetSize() == 0)
219     return;
220   std::string email;
221   if (args->GetString(0, &email))
222     email_ = email;
223 }
224
225 void LoginScreenContext::Init() {
226   oobe_ui_ = false;
227 }
228
229 // SigninScreenHandler implementation ------------------------------------------
230
231 SigninScreenHandler::SigninScreenHandler(
232     const scoped_refptr<NetworkStateInformer>& network_state_informer,
233     ErrorScreenActor* error_screen_actor,
234     CoreOobeActor* core_oobe_actor,
235     GaiaScreenHandler* gaia_screen_handler)
236     : ui_state_(UI_STATE_UNKNOWN),
237       delegate_(NULL),
238       native_window_delegate_(NULL),
239       show_on_init_(false),
240       oobe_ui_(false),
241       is_account_picker_showing_first_time_(false),
242       network_state_informer_(network_state_informer),
243       webui_visible_(false),
244       preferences_changed_delayed_(false),
245       error_screen_actor_(error_screen_actor),
246       core_oobe_actor_(core_oobe_actor),
247       is_first_update_state_call_(true),
248       offline_login_active_(false),
249       last_network_state_(NetworkStateInformer::UNKNOWN),
250       has_pending_auth_ui_(false),
251       caps_lock_enabled_(chromeos::input_method::InputMethodManager::Get()
252                              ->GetImeKeyboard()
253                              ->CapsLockIsEnabled()),
254       gaia_screen_handler_(gaia_screen_handler),
255       oobe_ui_observer_added_(false),
256       histogram_helper_(new ErrorScreensHistogramHelper("Signin")),
257       weak_factory_(this) {
258   DCHECK(network_state_informer_.get());
259   DCHECK(error_screen_actor_);
260   DCHECK(core_oobe_actor_);
261   DCHECK(gaia_screen_handler_);
262   gaia_screen_handler_->SetSigninScreenHandler(this);
263   network_state_informer_->AddObserver(this);
264
265   registrar_.Add(this,
266                  chrome::NOTIFICATION_AUTH_NEEDED,
267                  content::NotificationService::AllSources());
268   registrar_.Add(this,
269                  chrome::NOTIFICATION_AUTH_SUPPLIED,
270                  content::NotificationService::AllSources());
271   registrar_.Add(this,
272                  chrome::NOTIFICATION_AUTH_CANCELLED,
273                  content::NotificationService::AllSources());
274
275   chromeos::input_method::ImeKeyboard* keyboard =
276       chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
277   if (keyboard)
278     keyboard->AddObserver(this);
279
280 #if !defined(USE_ATHENA)
281   max_mode_delegate_.reset(new TouchViewControllerDelegate());
282   max_mode_delegate_->AddObserver(this);
283 #endif
284
285   policy::ConsumerManagementService* consumer_management =
286       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
287           GetConsumerManagementService();
288   is_enrolling_consumer_management_ =
289       consumer_management &&
290       consumer_management->GetEnrollmentStage() ==
291           policy::ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED;
292 }
293
294 SigninScreenHandler::~SigninScreenHandler() {
295   OobeUI* oobe_ui = GetOobeUI();
296   if (oobe_ui && oobe_ui_observer_added_)
297     oobe_ui->RemoveObserver(this);
298   chromeos::input_method::ImeKeyboard* keyboard =
299       chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
300   if (keyboard)
301     keyboard->RemoveObserver(this);
302   weak_factory_.InvalidateWeakPtrs();
303   if (delegate_)
304     delegate_->SetWebUIHandler(NULL);
305   network_state_informer_->RemoveObserver(this);
306   if (max_mode_delegate_) {
307     max_mode_delegate_->RemoveObserver(this);
308     max_mode_delegate_.reset(NULL);
309   }
310   ScreenlockBridge::Get()->SetLockHandler(NULL);
311   ScreenlockBridge::Get()->SetFocusedUser("");
312 }
313
314 void SigninScreenHandler::DeclareLocalizedValues(
315     LocalizedValuesBuilder* builder) {
316   builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
317   builder->Add("podMenuButtonAccessibleName",
318                IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
319   builder->Add("podMenuRemoveItemAccessibleName",
320                IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
321   builder->Add("passwordFieldAccessibleName",
322                IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
323   builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
324   builder->Add("signinButton", IDS_LOGIN_BUTTON);
325   builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON);
326   builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
327   builder->Add("addUser", IDS_ADD_USER_BUTTON);
328   builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
329   builder->Add("cancel", IDS_CANCEL);
330   builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
331   builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
332   builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
333   builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
334   builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
335   builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
336   builder->Add("errorTpmFailureRebootButton",
337                IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
338
339   policy::BrowserPolicyConnectorChromeOS* connector =
340       g_browser_process->platform_part()->browser_policy_connector_chromeos();
341   builder->Add("disabledAddUserTooltip",
342                connector->IsEnterpriseManaged()
343                    ? IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE
344                    : IDS_DISABLED_ADD_USER_TOOLTIP);
345
346   builder->Add("supervisedUserExpiredTokenWarning",
347                IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
348   builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
349
350   // Multi-profiles related strings.
351   builder->Add("multiProfilesRestrictedPolicyTitle",
352                IDS_MULTI_PROFILES_RESTRICTED_POLICY_TITLE);
353   builder->Add("multiProfilesNotAllowedPolicyMsg",
354                IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG);
355   builder->Add("multiProfilesPrimaryOnlyPolicyMsg",
356                IDS_MULTI_PROFILES_PRIMARY_ONLY_POLICY_MSG);
357   builder->Add("multiProfilesOwnerPrimaryOnlyMsg",
358                IDS_MULTI_PROFILES_OWNER_PRIMARY_ONLY_MSG);
359
360   // Strings used by password changed dialog.
361   builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
362   builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
363   builder->AddF("passwordChangedMoreInfo",
364                 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
365                 IDS_SHORT_PRODUCT_OS_NAME);
366
367   builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
368   builder->Add("oldPasswordIncorrect",
369                IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
370   builder->Add("passwordChangedCantRemember",
371                IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
372   builder->Add("passwordChangedBackButton",
373                IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
374   builder->Add("passwordChangedsOkButton", IDS_OK);
375   builder->Add("passwordChangedProceedAnyway",
376                IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
377   builder->Add("proceedAnywayButton",
378                IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
379   builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
380   builder->Add("publicAccountReminder",
381                IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
382   builder->Add("publicSessionLanguageAndInput",
383                IDS_LOGIN_PUBLIC_SESSION_LANGUAGE_AND_INPUT);
384   builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
385   builder->Add("publicAccountEnterAccessibleName",
386                IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
387   builder->Add("publicSessionSelectLanguage", IDS_LANGUAGE_SELECTION_SELECT);
388   builder->Add("publicSessionSelectKeyboard", IDS_KEYBOARD_SELECTION_SELECT);
389   builder->Add("removeUserWarningText",
390                base::string16());
391   builder->AddF("removeSupervisedUserWarningText",
392                IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING,
393                base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
394   builder->Add("removeUserWarningButtonTitle",
395                IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
396
397   builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
398
399   builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
400   builder->Add("confirmPasswordLabel", IDS_LOGIN_CONFIRM_PASSWORD_LABEL);
401   builder->Add("confirmPasswordConfirmButton",
402                IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
403   builder->Add("confirmPasswordText", IDS_LOGIN_CONFIRM_PASSWORD_TEXT);
404   builder->Add("confirmPasswordErrorText",
405                IDS_LOGIN_CONFIRM_PASSWORD_ERROR_TEXT);
406
407   builder->Add("fatalEnrollmentError",
408                IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR);
409   builder->Add("insecureURLEnrollmentError",
410                IDS_ENTERPRISE_ENROLLMENT_AUTH_INSECURE_URL_ERROR);
411
412   if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
413     builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
414 }
415
416 void SigninScreenHandler::Show(const LoginScreenContext& context) {
417   CHECK(delegate_);
418
419   // Just initialize internal fields from context and call ShowImpl().
420   oobe_ui_ = context.oobe_ui();
421
422   std::string email;
423   if (is_enrolling_consumer_management_) {
424     // We don't check if the value of the owner e-mail is trusted because it is
425     // only used to pre-fill the e-mail field in Gaia sign-in page and a cached
426     // value is sufficient.
427     CrosSettings::Get()->GetString(kDeviceOwner, &email);
428   } else {
429     email = context.email();
430   }
431   gaia_screen_handler_->PopulateEmail(email);
432   ShowImpl();
433   histogram_helper_->OnScreenShow();
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     histogram_helper_->OnErrorShow(error_screen_actor_->error_state());
692   }
693 }
694
695 void SigninScreenHandler::HideOfflineMessage(
696     NetworkStateInformer::State state,
697     ErrorScreenActor::ErrorReason reason) {
698   if (!IsSigninScreenHiddenByError())
699     return;
700
701   error_screen_actor_->Hide();
702   histogram_helper_->OnErrorHide();
703
704   // Forces a reload for Gaia screen on hiding error message.
705   if (IsGaiaVisible() || IsGaiaHiddenByError())
706     ReloadGaia(false);
707 }
708
709 void SigninScreenHandler::ReloadGaia(bool force_reload) {
710   gaia_screen_handler_->ReloadGaia(force_reload);
711 }
712
713 void SigninScreenHandler::Initialize() {
714   // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
715   // don't do anything, just return.
716   if (!delegate_)
717     return;
718
719   if (show_on_init_) {
720     show_on_init_ = false;
721     ShowImpl();
722   }
723 }
724
725 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
726   if (native_window_delegate_)
727     return native_window_delegate_->GetNativeWindow();
728   return NULL;
729 }
730
731 void SigninScreenHandler::RegisterMessages() {
732   AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
733   AddCallback("attemptUnlock", &SigninScreenHandler::HandleAttemptUnlock);
734   AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
735   AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
736   AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
737   AddCallback("showSupervisedUserCreationScreen",
738               &SigninScreenHandler::HandleShowSupervisedUserCreationScreen);
739   AddCallback("launchPublicSession",
740               &SigninScreenHandler::HandleLaunchPublicSession);
741   AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
742   AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
743   AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
744   AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
745   AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
746   AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
747   AddCallback("toggleEnrollmentScreen",
748               &SigninScreenHandler::HandleToggleEnrollmentScreen);
749   AddCallback("switchToEmbeddedSignin",
750               &SigninScreenHandler::HandleSwitchToEmbeddedSignin);
751   AddCallback("toggleKioskEnableScreen",
752               &SigninScreenHandler::HandleToggleKioskEnableScreen);
753   AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
754   AddCallback("accountPickerReady",
755               &SigninScreenHandler::HandleAccountPickerReady);
756   AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
757   AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
758   AddCallback("openProxySettings",
759               &SigninScreenHandler::HandleOpenProxySettings);
760   AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
761   AddCallback("cancelPasswordChangedFlow",
762               &SigninScreenHandler::HandleCancelPasswordChangedFlow);
763   AddCallback("cancelUserAdding",
764               &SigninScreenHandler::HandleCancelUserAdding);
765   AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
766   AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
767   AddCallback("loginUIStateChanged",
768               &SigninScreenHandler::HandleLoginUIStateChanged);
769   AddCallback("unlockOnLoginSuccess",
770               &SigninScreenHandler::HandleUnlockOnLoginSuccess);
771   AddCallback("showLoadingTimeoutError",
772               &SigninScreenHandler::HandleShowLoadingTimeoutError);
773   AddCallback("updateOfflineLogin",
774               &SigninScreenHandler::HandleUpdateOfflineLogin);
775   AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
776   AddCallback("hardlockPod", &SigninScreenHandler::HandleHardlockPod);
777   AddCallback("getPublicSessionKeyboardLayouts",
778               &SigninScreenHandler::HandleGetPublicSessionKeyboardLayouts);
779   AddCallback("cancelConsumerManagementEnrollment",
780               &SigninScreenHandler::HandleCancelConsumerManagementEnrollment);
781   AddCallback("getTouchViewState",
782               &SigninScreenHandler::HandleGetTouchViewState);
783
784
785   // This message is sent by the kiosk app menu, but is handled here
786   // so we can tell the delegate to launch the app.
787   AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
788 }
789
790 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
791   registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
792 }
793
794 void SigninScreenHandler::OnCurrentScreenChanged(OobeUI::Screen current_screen,
795                                                  OobeUI::Screen new_screen) {
796   if (new_screen == OobeUI::SCREEN_ACCOUNT_PICKER) {
797     // Restore active IME state if returning to user pod row screen.
798     input_method::InputMethodManager::Get()->SetState(ime_state_);
799   }
800 }
801
802 std::string SigninScreenHandler::GetUserLRUInputMethod(
803     const std::string& username) const {
804   PrefService* const local_state = g_browser_process->local_state();
805   const base::DictionaryValue* users_lru_input_methods =
806       local_state->GetDictionary(prefs::kUsersLRUInputMethod);
807
808   if (users_lru_input_methods == NULL) {
809     DLOG(WARNING) << "GetUserLRUInputMethod('" << username
810                   << "'): no kUsersLRUInputMethod";
811     return std::string();
812   }
813
814   std::string input_method;
815
816   if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
817                                                               &input_method)) {
818     DVLOG(0) << "GetUserLRUInputMethod('" << username
819              << "'): no input method for this user";
820     return std::string();
821   }
822
823   return input_method;
824 }
825
826 void SigninScreenHandler::HandleGetUsers() {
827   if (delegate_)
828     delegate_->HandleGetUsers();
829 }
830
831 void SigninScreenHandler::ClearAndEnablePassword() {
832   core_oobe_actor_->ResetSignInUI(false);
833 }
834
835 void SigninScreenHandler::ClearUserPodPassword() {
836   core_oobe_actor_->ClearUserPodPassword();
837 }
838
839 void SigninScreenHandler::RefocusCurrentPod() {
840   core_oobe_actor_->RefocusCurrentPod();
841 }
842
843 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
844   CallJS("login.AccountPickerScreen.removeUser", username);
845   if (delegate_->GetUsers().empty())
846     OnShowAddUser();
847 }
848
849 void SigninScreenHandler::OnUserImageChanged(const user_manager::User& user) {
850   if (page_is_ready())
851     CallJS("login.AccountPickerScreen.updateUserImage", user.email());
852 }
853
854 void SigninScreenHandler::OnPreferencesChanged() {
855   // Make sure that one of the login UI is fully functional now, otherwise
856   // preferences update would be picked up next time it will be shown.
857   if (!webui_visible_) {
858     LOG(WARNING) << "Login UI is not active - postponed prefs change.";
859     preferences_changed_delayed_ = true;
860     return;
861   }
862
863   if (delegate_ && !delegate_->IsShowUsers()) {
864     HandleShowAddUser(NULL);
865   } else {
866     if (delegate_)
867       delegate_->HandleGetUsers();
868     UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
869   }
870   preferences_changed_delayed_ = false;
871 }
872
873 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
874   SetDelegate(NULL);
875 }
876
877 void SigninScreenHandler::ShowError(int login_attempts,
878                                     const std::string& error_text,
879                                     const std::string& help_link_text,
880                                     HelpAppLauncher::HelpTopic help_topic_id) {
881   core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
882                                     help_topic_id);
883 }
884
885 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
886   switch (error_id) {
887     case LoginDisplay::TPM_ERROR:
888       core_oobe_actor_->ShowTpmError();
889       break;
890     default:
891       NOTREACHED() << "Unknown sign in error";
892       break;
893   }
894 }
895
896 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
897   core_oobe_actor_->ShowSignInUI(email);
898 }
899
900 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
901   gaia_screen_handler_->PasswordChangedFor(username);
902   gaia_screen_handler_->PopulateEmail(username);
903   core_oobe_actor_->ShowSignInUI(username);
904   CallJS("login.setAuthType",
905          username,
906          static_cast<int>(ONLINE_SIGN_IN),
907          base::StringValue(""));
908 }
909
910 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
911   core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
912 }
913
914 void SigninScreenHandler::ShowSigninScreenForCreds(
915     const std::string& username,
916     const std::string& password) {
917   DCHECK(gaia_screen_handler_);
918   gaia_screen_handler_->ShowSigninScreenForCreds(username, password);
919 }
920
921 void SigninScreenHandler::SetPublicSessionDisplayName(
922       const std::string& user_id,
923       const std::string& display_name) {
924   CallJS("login.AccountPickerScreen.setPublicSessionDisplayName",
925          user_id,
926          display_name);
927 }
928
929 void SigninScreenHandler::SetPublicSessionLocales(
930     const std::string& user_id,
931     scoped_ptr<base::ListValue> locales,
932     const std::string& default_locale,
933     bool multipleRecommendedLocales) {
934   CallJS("login.AccountPickerScreen.setPublicSessionLocales",
935          user_id,
936          *locales,
937          default_locale,
938          multipleRecommendedLocales);
939 }
940
941 void SigninScreenHandler::Observe(int type,
942                                   const content::NotificationSource& source,
943                                   const content::NotificationDetails& details) {
944   switch (type) {
945     case chrome::NOTIFICATION_AUTH_NEEDED: {
946       has_pending_auth_ui_ = true;
947       break;
948     }
949     case chrome::NOTIFICATION_AUTH_SUPPLIED:
950       has_pending_auth_ui_ = false;
951       // Reload auth extension as proxy credentials are supplied.
952       if (!IsSigninScreenHiddenByError() && ui_state_ == UI_STATE_GAIA_SIGNIN)
953         ReloadGaia(true);
954       update_state_closure_.Cancel();
955       break;
956     case chrome::NOTIFICATION_AUTH_CANCELLED: {
957       // Don't reload auth extension if proxy auth dialog was cancelled.
958       has_pending_auth_ui_ = false;
959       update_state_closure_.Cancel();
960       break;
961     }
962     default:
963       NOTREACHED() << "Unexpected notification " << type;
964   }
965 }
966
967 void SigninScreenHandler::ShowBannerMessage(const base::string16& message) {
968   CallJS("login.AccountPickerScreen.showBannerMessage", message);
969 }
970
971 void SigninScreenHandler::ShowUserPodCustomIcon(
972     const std::string& username,
973     const ScreenlockBridge::UserPodCustomIconOptions& icon_options) {
974   scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
975   if (!icon || icon->empty())
976     return;
977   CallJS("login.AccountPickerScreen.showUserPodCustomIcon", username, *icon);
978 }
979
980 void SigninScreenHandler::HideUserPodCustomIcon(const std::string& username) {
981   CallJS("login.AccountPickerScreen.hideUserPodCustomIcon", username);
982 }
983
984 void SigninScreenHandler::EnableInput() {
985   // Only for lock screen at the moment.
986   ScreenLocker::default_screen_locker()->EnableInput();
987 }
988
989 void SigninScreenHandler::SetAuthType(
990     const std::string& username,
991     ScreenlockBridge::LockHandler::AuthType auth_type,
992     const base::string16& initial_value) {
993   if (delegate_->GetAuthType(username) ==
994           ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
995     return;
996
997   delegate_->SetAuthType(username, auth_type);
998
999   CallJS("login.AccountPickerScreen.setAuthType",
1000          username,
1001          static_cast<int>(auth_type),
1002          base::StringValue(initial_value));
1003 }
1004
1005 ScreenlockBridge::LockHandler::AuthType SigninScreenHandler::GetAuthType(
1006     const std::string& username) const {
1007   return delegate_->GetAuthType(username);
1008 }
1009
1010 void SigninScreenHandler::Unlock(const std::string& user_email) {
1011   DCHECK(ScreenLocker::default_screen_locker());
1012   ScreenLocker::Hide();
1013 }
1014
1015 void SigninScreenHandler::AttemptEasySignin(const std::string& user_email,
1016                                             const std::string& secret,
1017                                             const std::string& key_label) {
1018   DCHECK(!ScreenLocker::default_screen_locker());
1019   if (!delegate_)
1020     return;
1021
1022   UserContext user_context(user_email);
1023   user_context.SetAuthFlow(UserContext::AUTH_FLOW_EASY_UNLOCK);
1024   user_context.SetKey(Key(secret));
1025   user_context.GetKey()->SetLabel(key_label);
1026
1027   delegate_->Login(user_context, SigninSpecifics());
1028 }
1029
1030 void SigninScreenHandler::OnMaximizeModeStarted() {
1031   CallJS("login.AccountPickerScreen.setTouchViewState", true);
1032 }
1033
1034 void SigninScreenHandler::OnMaximizeModeEnded() {
1035   CallJS("login.AccountPickerScreen.setTouchViewState", false);
1036 }
1037
1038 bool SigninScreenHandler::ShouldLoadGaia() const {
1039   // Fetching of the extension is not started before account picker page is
1040   // loaded because it can affect the loading speed.
1041   // Do not load the extension for the screen locker, see crosbug.com/25018.
1042   return !ScreenLocker::default_screen_locker() &&
1043          is_account_picker_showing_first_time_;
1044 }
1045
1046 // Update keyboard layout to least recently used by the user.
1047 void SigninScreenHandler::SetUserInputMethod(
1048     const std::string& username,
1049     input_method::InputMethodManager::State* ime_state) {
1050   bool succeed = false;
1051
1052   const std::string input_method = GetUserLRUInputMethod(username);
1053
1054   if (!input_method.empty())
1055     succeed = SetUserInputMethodImpl(username, input_method, ime_state);
1056
1057   // This is also a case when LRU layout is set only for a few local users,
1058   // thus others need to be switched to default locale.
1059   // Otherwise they will end up using another user's locale to log in.
1060   if (!succeed) {
1061     DVLOG(0) << "SetUserInputMethod('" << username
1062                << "'): failed to set user layout. Switching to default.";
1063
1064     ime_state->SetInputMethodLoginDefault();
1065   }
1066 }
1067
1068
1069 void SigninScreenHandler::UserSettingsChanged() {
1070   DCHECK(gaia_screen_handler_);
1071   GaiaContext context;
1072   if (delegate_)
1073     context.has_users = !delegate_->GetUsers().empty();
1074   gaia_screen_handler_->UpdateGaia(context);
1075   UpdateAddButtonStatus();
1076 }
1077
1078 void SigninScreenHandler::UpdateAddButtonStatus() {
1079   CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1080          AllWhitelistedUsersPresent());
1081 }
1082
1083 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
1084                                                  const std::string& password) {
1085   if (!delegate_)
1086     return;
1087   UserContext user_context(username);
1088   user_context.SetKey(Key(password));
1089   delegate_->Login(user_context, SigninSpecifics());
1090 }
1091
1092 void SigninScreenHandler::HandleAttemptUnlock(const std::string& username) {
1093   EasyUnlockService* service = GetEasyUnlockServiceForUser(username);
1094   if (!service)
1095     return;
1096   service->AttemptAuth(username);
1097 }
1098
1099 void SigninScreenHandler::HandleLaunchDemoUser() {
1100   UserContext context(user_manager::USER_TYPE_RETAIL_MODE, std::string());
1101   if (delegate_)
1102     delegate_->Login(context, SigninSpecifics());
1103 }
1104
1105 void SigninScreenHandler::HandleLaunchIncognito() {
1106   UserContext context(user_manager::USER_TYPE_GUEST, std::string());
1107   if (delegate_)
1108     delegate_->Login(context, SigninSpecifics());
1109 }
1110
1111 void SigninScreenHandler::HandleShowSupervisedUserCreationScreen() {
1112   if (!user_manager::UserManager::Get()->AreSupervisedUsersAllowed()) {
1113     LOG(ERROR) << "Managed users not allowed.";
1114     return;
1115   }
1116   scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
1117   LoginDisplayHostImpl::default_host()->
1118       StartWizard(WizardController::kSupervisedUserCreationScreenName,
1119       params.Pass());
1120 }
1121
1122 void SigninScreenHandler::HandleLaunchPublicSession(
1123     const std::string& user_id,
1124     const std::string& locale,
1125     const std::string& input_method) {
1126   if (!delegate_)
1127     return;
1128
1129   UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT, user_id);
1130   context.SetPublicSessionLocale(locale),
1131   context.SetPublicSessionInputMethod(input_method);
1132   delegate_->Login(context, SigninSpecifics());
1133 }
1134
1135 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
1136   if (!delegate_ || delegate_->IsShowUsers()) {
1137     NOTREACHED();
1138     return;
1139   }
1140   std::string email;
1141   args->GetString(0, &email);
1142
1143   gaia_screen_handler_->PopulateEmail(email);
1144   // Load auth extension. Parameters are: force reload, do not load extension in
1145   // background, use offline version.
1146   gaia_screen_handler_->LoadAuthExtension(true, false, true);
1147   UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
1148 }
1149
1150 void SigninScreenHandler::HandleShutdownSystem() {
1151 #if defined(USE_ATHENA)
1152   chromeos::DBusThreadManager::Get()->
1153       GetPowerManagerClient()->RequestShutdown();
1154 #else
1155   ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1156 #endif
1157 }
1158
1159 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1160   if (delegate_)
1161     delegate_->LoadWallpaper(email);
1162 }
1163
1164 void SigninScreenHandler::HandleRebootSystem() {
1165   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1166 }
1167
1168 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1169   if (!delegate_)
1170     return;
1171   delegate_->RemoveUser(email);
1172   UpdateAddButtonStatus();
1173 }
1174
1175 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
1176   TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1177                                "ShowLoginWebUI",
1178                                LoginDisplayHostImpl::kShowLoginWebUIid,
1179                                "ShowAddUser");
1180   std::string email;
1181   // |args| can be null if it's OOBE.
1182   if (args)
1183     args->GetString(0, &email);
1184   gaia_screen_handler_->PopulateEmail(email);
1185   OnShowAddUser();
1186 }
1187
1188 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1189   if (delegate_)
1190     delegate_->ShowEnterpriseEnrollmentScreen();
1191 }
1192
1193 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
1194   policy::BrowserPolicyConnectorChromeOS* connector =
1195       g_browser_process->platform_part()->browser_policy_connector_chromeos();
1196   if (delegate_ &&
1197       !auto_enrollment_progress_subscription_ &&
1198       !connector->IsEnterpriseManaged() &&
1199       LoginDisplayHostImpl::default_host()) {
1200     AutoEnrollmentController* auto_enrollment_controller =
1201         LoginDisplayHostImpl::default_host()->GetAutoEnrollmentController();
1202     auto_enrollment_progress_subscription_ =
1203         auto_enrollment_controller->RegisterProgressCallback(
1204             base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1205                        weak_factory_.GetWeakPtr()));
1206     ContinueKioskEnableFlow(auto_enrollment_controller->state());
1207   }
1208 }
1209
1210 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
1211   policy::BrowserPolicyConnectorChromeOS* connector =
1212       g_browser_process->platform_part()->browser_policy_connector_chromeos();
1213   if (delegate_ && !connector->IsEnterpriseManaged())
1214     delegate_->ShowKioskAutolaunchScreen();
1215 }
1216
1217 void SigninScreenHandler::LoadUsers(const base::ListValue& users_list,
1218                                     bool showGuest) {
1219   CallJS("login.AccountPickerScreen.loadUsers",
1220          users_list,
1221          delegate_->IsShowGuest());
1222 }
1223
1224 void SigninScreenHandler::HandleAccountPickerReady() {
1225   VLOG(0) << "Login WebUI >> AccountPickerReady";
1226
1227   if (delegate_ && !ScreenLocker::default_screen_locker() &&
1228       !chromeos::IsMachineHWIDCorrect() &&
1229       !oobe_ui_) {
1230     delegate_->ShowWrongHWIDScreen();
1231     return;
1232   }
1233
1234   PrefService* prefs = g_browser_process->local_state();
1235   if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1236     if (core_oobe_actor_) {
1237       core_oobe_actor_->ShowDeviceResetScreen();
1238       return;
1239     }
1240   }
1241
1242   is_account_picker_showing_first_time_ = true;
1243   gaia_screen_handler_->MaybePreloadAuthExtension();
1244
1245   ScreenlockBridge::Get()->SetLockHandler(this);
1246   if (ScreenLocker::default_screen_locker()) {
1247     ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1248   }
1249
1250   if (delegate_)
1251     delegate_->OnSigninScreenReady();
1252 }
1253
1254 void SigninScreenHandler::HandleWallpaperReady() {
1255   if (ScreenLocker::default_screen_locker()) {
1256     ScreenLocker::default_screen_locker()->delegate()->
1257         OnLockBackgroundDisplayed();
1258   }
1259 }
1260
1261 void SigninScreenHandler::HandleSignOutUser() {
1262   if (delegate_)
1263     delegate_->Signout();
1264 }
1265
1266 void SigninScreenHandler::HandleCreateAccount() {
1267   if (delegate_)
1268     delegate_->CreateAccount();
1269 }
1270
1271 void SigninScreenHandler::HandleOpenProxySettings() {
1272   LoginDisplayHostImpl::default_host()->OpenProxySettings();
1273 }
1274
1275 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1276   VLOG(1) << "Login WebUI >> loginVisible, src: " << source << ", "
1277           << "webui_visible_: " << webui_visible_;
1278   if (!webui_visible_) {
1279     // There might be multiple messages from OOBE UI so send notifications after
1280     // the first one only.
1281     content::NotificationService::current()->Notify(
1282         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1283         content::NotificationService::AllSources(),
1284         content::NotificationService::NoDetails());
1285     TRACE_EVENT_ASYNC_END0(
1286         "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1287   }
1288   webui_visible_ = true;
1289   if (preferences_changed_delayed_)
1290     OnPreferencesChanged();
1291 }
1292
1293 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1294   gaia_screen_handler_->StartClearingCookies(
1295       base::Bind(&SigninScreenHandler::CancelPasswordChangedFlowInternal,
1296                  weak_factory_.GetWeakPtr()));
1297 }
1298
1299 void SigninScreenHandler::HandleCancelUserAdding() {
1300   if (delegate_)
1301     delegate_->CancelUserAdding();
1302 }
1303
1304 void SigninScreenHandler::HandleMigrateUserData(
1305     const std::string& old_password) {
1306   if (delegate_)
1307     delegate_->MigrateUserData(old_password);
1308 }
1309
1310 void SigninScreenHandler::HandleResyncUserData() {
1311   if (delegate_)
1312     delegate_->ResyncUserData();
1313 }
1314
1315 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1316                                                     bool new_value) {
1317   VLOG(0) << "Login WebUI >> active: " << new_value << ", "
1318             << "source: " << source;
1319
1320   if (source == "gaia-signin" && !new_value)
1321     gaia_screen_handler_->CancelEmbeddedSignin();
1322
1323   if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1324       KioskAppManager::Get()->IsAutoLaunchRequested()) {
1325     VLOG(0) << "Showing auto-launch warning";
1326     // On slow devices, the wallpaper animation is not shown initially, so we
1327     // must explicitly load the wallpaper. This is also the case for the
1328     // account-picker and gaia-signin UI states.
1329     delegate_->LoadSigninWallpaper();
1330     HandleToggleKioskAutolaunchScreen();
1331     return;
1332   }
1333
1334   if (source == kSourceGaiaSignin) {
1335     ui_state_ = UI_STATE_GAIA_SIGNIN;
1336   } else if (source == kSourceAccountPicker) {
1337     ui_state_ = UI_STATE_ACCOUNT_PICKER;
1338   } else {
1339     NOTREACHED();
1340     return;
1341   }
1342 }
1343
1344 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1345   DCHECK(user_manager::UserManager::Get()->IsUserLoggedIn());
1346   if (ScreenLocker::default_screen_locker())
1347     ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1348 }
1349
1350 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1351   UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1352 }
1353
1354 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1355   offline_login_active_ = offline_login_active;
1356 }
1357
1358 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1359   SetUserInputMethod(user_id, ime_state_.get());
1360 #if !defined(USE_ATHENA)
1361   // TODO(dpolukhin):  crbug.com/408734.
1362   WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
1363 #endif
1364   ScreenlockBridge::Get()->SetFocusedUser(user_id);
1365   if (!test_focus_pod_callback_.is_null())
1366     test_focus_pod_callback_.Run();
1367 }
1368
1369 void SigninScreenHandler::HandleHardlockPod(const std::string& user_id) {
1370   SetAuthType(user_id,
1371               ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
1372               base::string16());
1373   EasyUnlockService* service = GetEasyUnlockServiceForUser(user_id);
1374   if (!service)
1375     return;
1376   service->SetHardlockState(EasyUnlockScreenlockStateHandler::USER_HARDLOCK);
1377 }
1378
1379 void SigninScreenHandler::HandleGetPublicSessionKeyboardLayouts(
1380     const std::string& user_id,
1381     const std::string& locale) {
1382   GetKeyboardLayoutsForLocale(
1383       base::Bind(&SigninScreenHandler::SendPublicSessionKeyboardLayouts,
1384                  weak_factory_.GetWeakPtr(),
1385                  user_id,
1386                  locale),
1387       locale);
1388 }
1389
1390 void SigninScreenHandler::SendPublicSessionKeyboardLayouts(
1391     const std::string& user_id,
1392     const std::string& locale,
1393     scoped_ptr<base::ListValue> keyboard_layouts) {
1394   CallJS("login.AccountPickerScreen.setPublicSessionKeyboardLayouts",
1395          user_id,
1396          locale,
1397          *keyboard_layouts);
1398 }
1399
1400 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id,
1401                                                bool diagnostic_mode) {
1402   UserContext context(user_manager::USER_TYPE_KIOSK_APP, app_id);
1403   SigninSpecifics specifics;
1404   specifics.kiosk_diagnostic_mode = diagnostic_mode;
1405   if (delegate_)
1406     delegate_->Login(context, specifics);
1407 }
1408
1409 void SigninScreenHandler::HandleCancelConsumerManagementEnrollment() {
1410   policy::ConsumerManagementService* consumer_management =
1411       g_browser_process->platform_part()->browser_policy_connector_chromeos()->
1412           GetConsumerManagementService();
1413   CHECK(consumer_management);
1414   consumer_management->SetEnrollmentStage(
1415       policy::ConsumerManagementService::ENROLLMENT_STAGE_CANCELED);
1416   is_enrolling_consumer_management_ = false;
1417   ShowImpl();
1418 }
1419
1420 void SigninScreenHandler::HandleGetTouchViewState() {
1421 #if defined(USE_ATHENA)
1422   // Login UI should treat athena builds as if it's TouchView mode.
1423   CallJS("login.AccountPickerScreen.setTouchViewState", true);
1424 #else
1425   if (max_mode_delegate_) {
1426     CallJS("login.AccountPickerScreen.setTouchViewState",
1427            max_mode_delegate_->IsMaximizeModeEnabled());
1428   }
1429 #endif
1430 }
1431
1432 void SigninScreenHandler::HandleSwitchToEmbeddedSignin() {
1433   gaia_screen_handler_->SwitchToEmbeddedSignin();
1434 }
1435
1436 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1437   CrosSettings* cros_settings = CrosSettings::Get();
1438   bool allow_new_user = false;
1439   cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1440   if (allow_new_user)
1441     return false;
1442   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
1443   const user_manager::UserList& users = user_manager->GetUsers();
1444   if (!delegate_ || users.size() > kMaxUsers) {
1445     return false;
1446   }
1447   const base::ListValue* whitelist = NULL;
1448   if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1449     return false;
1450   for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1451     std::string whitelisted_user;
1452     // NB: Wildcards in the whitelist are also detected as not present here.
1453     if (!whitelist->GetString(i, &whitelisted_user) ||
1454         !user_manager->IsKnownUser(whitelisted_user)) {
1455       return false;
1456     }
1457   }
1458   return true;
1459 }
1460
1461 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1462   if (delegate_) {
1463     ShowImpl();
1464     delegate_->CancelPasswordChangedFlow();
1465   }
1466 }
1467
1468 OobeUI* SigninScreenHandler::GetOobeUI() const {
1469   return static_cast<OobeUI*>(web_ui()->GetController());
1470 }
1471
1472 EasyUnlockService* SigninScreenHandler::GetEasyUnlockServiceForUser(
1473       const std::string& username) const {
1474   if (!ScreenLocker::default_screen_locker() &&
1475       GetOobeUI()->display_type() != OobeUI::kLoginDisplay)
1476     return NULL;
1477
1478   const user_manager::User* unlock_user = NULL;
1479   const user_manager::UserList& users = delegate_->GetUsers();
1480   for (user_manager::UserList::const_iterator it = users.begin();
1481        it != users.end();
1482        ++it) {
1483     if ((*it)->email() == username) {
1484       unlock_user = *it;
1485       break;
1486     }
1487   }
1488   if (!unlock_user)
1489     return NULL;
1490
1491   ProfileHelper* profile_helper = ProfileHelper::Get();
1492   Profile* profile = profile_helper->GetProfileByUser(unlock_user);
1493
1494   // The user profile should exists if and only if this is lock screen.
1495   DCHECK_NE(!profile, !ScreenLocker::default_screen_locker());
1496
1497   if (!profile)
1498     profile = profile_helper->GetSigninProfile();
1499
1500   return EasyUnlockService::Get(profile);
1501 }
1502
1503 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1504   OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1505   OobeUI* oobe_ui = GetOobeUI();
1506   if (oobe_ui)
1507     screen = oobe_ui->current_screen();
1508   return screen;
1509 }
1510
1511 bool SigninScreenHandler::IsGaiaVisible() const {
1512   return IsSigninScreen(GetCurrentScreen()) &&
1513       ui_state_ == UI_STATE_GAIA_SIGNIN;
1514 }
1515
1516 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1517   return IsSigninScreenHiddenByError() &&
1518       ui_state_ == UI_STATE_GAIA_SIGNIN;
1519 }
1520
1521 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1522   return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1523       (IsSigninScreen(error_screen_actor_->parent_screen()));
1524 }
1525
1526 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1527   CrosSettings* cros_settings = CrosSettings::Get();
1528   if (!cros_settings)
1529     return false;
1530   bool allow_guest;
1531   cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1532   return allow_guest;
1533 }
1534
1535 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1536   CrosSettings* cros_settings = CrosSettings::Get();
1537   if (!cros_settings)
1538     return false;
1539
1540   // Offline login is allowed only when user pods are hidden.
1541   bool show_pods;
1542   cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1543   return !show_pods;
1544 }
1545
1546 void SigninScreenHandler::ContinueKioskEnableFlow(
1547     policy::AutoEnrollmentState state) {
1548   // Do not proceed with kiosk enable when auto enroll will be enforced.
1549   // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1550   switch (state) {
1551     case policy::AUTO_ENROLLMENT_STATE_IDLE:
1552     case policy::AUTO_ENROLLMENT_STATE_PENDING:
1553     case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
1554       // Wait for the next callback.
1555       return;
1556     case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
1557       // Auto-enrollment is on.
1558       LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1559                       "going to be enforced.";
1560       if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1561         kiosk_enable_flow_aborted_callback_for_test_.Run();
1562       break;
1563     case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
1564     case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
1565       // Auto-enrollment not applicable.
1566       if (delegate_)
1567         delegate_->ShowKioskEnableScreen();
1568       break;
1569   }
1570   auto_enrollment_progress_subscription_.reset();
1571 }
1572
1573 void SigninScreenHandler::OnShowAddUser() {
1574   is_account_picker_showing_first_time_ = false;
1575   DCHECK(gaia_screen_handler_);
1576   gaia_screen_handler_->ShowGaia(is_enrolling_consumer_management_);
1577 }
1578
1579 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
1580   DCHECK(gaia_screen_handler_);
1581   return gaia_screen_handler_->frame_state();
1582 }
1583
1584 net::Error SigninScreenHandler::FrameError() const {
1585   DCHECK(gaia_screen_handler_);
1586   return gaia_screen_handler_->frame_error();
1587 }
1588
1589 void SigninScreenHandler::OnCapsLockChanged(bool enabled) {
1590   caps_lock_enabled_ = enabled;
1591   if (page_is_ready())
1592     CallJS("login.AccountPickerScreen.setCapsLockState", caps_lock_enabled_);
1593 }
1594
1595 }  // namespace chromeos