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