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