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