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