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