Home | History | Annotate | Download | only in login
      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 
     70 using content::BrowserThread;
     71 using content::RenderViewHost;
     72 
     73 namespace {
     74 
     75 // User dictionary keys.
     76 const char kKeyUsername[] = "username";
     77 const char kKeyDisplayName[] = "displayName";
     78 const char kKeyEmailAddress[] = "emailAddress";
     79 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
     80 const char kKeyPublicAccount[] = "publicAccount";
     81 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
     82 const char kKeySignedIn[] = "signedIn";
     83 const char kKeyCanRemove[] = "canRemove";
     84 const char kKeyIsOwner[] = "isOwner";
     85 const char kKeyOauthTokenStatus[] = "oauthTokenStatus";
     86 
     87 // Max number of users to show.
     88 const size_t kMaxUsers = 18;
     89 
     90 // Timeout to delay first notification about offline state for a
     91 // current network.
     92 const int kOfflineTimeoutSec = 5;
     93 
     94 // Timeout used to prevent infinite connecting to a flaky network.
     95 const int kConnectingTimeoutSec = 60;
     96 
     97 // Type of the login screen UI that is currently presented to user.
     98 const char kSourceGaiaSignin[] = "gaia-signin";
     99 const char kSourceAccountPicker[] = "account-picker";
    100 
    101 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
    102 // thread.
    103 void ClearDnsCache(IOThread* io_thread) {
    104   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    105   if (browser_shutdown::IsTryingToQuit())
    106     return;
    107 
    108   io_thread->ClearHostCache();
    109 }
    110 
    111 static 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 
    119 namespace chromeos {
    120 
    121 namespace {
    122 
    123 const char kNetworkStateOffline[] = "offline";
    124 const char kNetworkStateOnline[] = "online";
    125 const char kNetworkStateCaptivePortal[] = "behind captive portal";
    126 const char kNetworkStateConnecting[] = "connecting";
    127 const char kNetworkStateProxyAuthRequired[] = "proxy auth required";
    128 
    129 const char kErrorReasonProxyAuthCancelled[] = "proxy auth cancelled";
    130 const char kErrorReasonProxyAuthSupplied[] = "proxy auth supplied";
    131 const char kErrorReasonProxyConnectionFailed[] = "proxy connection failed";
    132 const char kErrorReasonProxyConfigChanged[] = "proxy config changed";
    133 const char kErrorReasonLoadingTimeout[] = "loading timeout";
    134 const char kErrorReasonPortalDetected[] = "portal detected";
    135 const char kErrorReasonNetworkStateChanged[] = "network state changed";
    136 const char kErrorReasonUpdate[] = "update";
    137 const char kErrorReasonFrameError[] = "frame error";
    138 
    139 const 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 
    157 const 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.
    185 void 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 
    196 bool 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 
    203 bool IsUnderCaptivePortal(NetworkStateInformer::State state,
    204                           ErrorScreenActor::ErrorReason reason) {
    205   return state == NetworkStateInformer::CAPTIVE_PORTAL ||
    206       reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
    207 }
    208 
    209 bool 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 
    220 bool IsSigninScreen(const OobeUI::Screen screen) {
    221   return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
    222       screen == OobeUI::SCREEN_ACCOUNT_PICKER;
    223 }
    224 
    225 bool 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.
    233 std::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.
    242 NetworkPortalDetector::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 
    252 void 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|.
    276 void 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 
    317 static 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 
    374 SigninScreenHandler::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 
    420 SigninScreenHandler::~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 
    433 void 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 
    507 void 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 
    533 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
    534   CallJS("showLoginSpinner");
    535 }
    536 
    537 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
    538   delegate_ = delegate;
    539   if (delegate_)
    540     delegate_->SetWebUIHandler(this);
    541 }
    542 
    543 void SigninScreenHandler::SetNativeWindowDelegate(
    544     NativeWindowDelegate* native_window_delegate) {
    545   native_window_delegate_ = native_window_delegate;
    546 }
    547 
    548 void SigninScreenHandler::OnNetworkReady() {
    549   MaybePreloadAuthExtension();
    550 }
    551 
    552 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
    553   UpdateStateInternal(reason, false);
    554 }
    555 
    556 // SigninScreenHandler, private: -----------------------------------------------
    557 
    558 void 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.
    576 void 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 
    693 void 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 
    749 void 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 
    762 void 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 
    776 void 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 
    794 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
    795   if (native_window_delegate_)
    796     return native_window_delegate_->GetNativeWindow();
    797   return NULL;
    798 }
    799 
    800 void 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 
    854 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
    855   registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
    856 }
    857 
    858 void SigninScreenHandler::HandleGetUsers() {
    859   SendUserList(false);
    860 }
    861 
    862 void SigninScreenHandler::ClearAndEnablePassword() {
    863   core_oobe_actor_->ResetSignInUI(false);
    864 }
    865 
    866 void SigninScreenHandler::ClearUserPodPassword() {
    867   core_oobe_actor_->ClearUserPodPassword();
    868 }
    869 
    870 void SigninScreenHandler::RefocusCurrentPod() {
    871   core_oobe_actor_->RefocusCurrentPod();
    872 }
    873 
    874 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
    875   core_oobe_actor_->OnLoginSuccess(username);
    876 }
    877 
    878 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
    879   SendUserList(false);
    880 }
    881 
    882 void SigninScreenHandler::OnUserImageChanged(const User& user) {
    883   if (page_is_ready())
    884     CallJS("login.AccountPickerScreen.updateUserImage", user.email());
    885 }
    886 
    887 void 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 
    905 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
    906   SetDelegate(NULL);
    907 }
    908 
    909 void SigninScreenHandler::ShowError(int login_attempts,
    910                                     const std::string& error_text,
    911                                     const std::string& help_link_text,
    912                                     HelpAppLauncher::HelpTopic help_topic_id) {
    913   core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
    914                                     help_topic_id);
    915 }
    916 
    917 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
    918   switch (error_id) {
    919     case LoginDisplay::TPM_ERROR:
    920       core_oobe_actor_->ShowTpmError();
    921       break;
    922     default:
    923       NOTREACHED() << "Unknown sign in error";
    924       break;
    925   }
    926 }
    927 
    928 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
    929 
    930 }
    931 
    932 void 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 
    939 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
    940   core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
    941 }
    942 
    943 void 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 
    962 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
    963   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    964   cookies_cleared_ = true;
    965   on_clear_callback.Run();
    966 }
    967 
    968 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
    969   if (page_is_ready())
    970     CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
    971 }
    972 
    973 void 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 
   1007 void 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.
   1015 void 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 
   1032 void 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 
   1071 void 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 
   1107 void 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 
   1156 void SigninScreenHandler::UpdateAuthExtension() {
   1157   DictionaryValue params;
   1158   UpdateAuthParams(&params);
   1159   CallJS("login.GaiaSigninScreen.updateAuthExtension", params);
   1160 }
   1161 
   1162 void SigninScreenHandler::UpdateAddButtonStatus() {
   1163   CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
   1164          AllWhitelistedUsersPresent());
   1165 }
   1166 
   1167 void 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 
   1187 void 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 
   1198 void 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 
   1207 void SigninScreenHandler::HandleLaunchDemoUser() {
   1208   if (delegate_)
   1209     delegate_->LoginAsRetailModeUser();
   1210 }
   1211 
   1212 void SigninScreenHandler::HandleLaunchIncognito() {
   1213   if (delegate_)
   1214     delegate_->LoginAsGuest();
   1215 }
   1216 
   1217 void 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 
   1228 void SigninScreenHandler::HandleLaunchPublicAccount(
   1229     const std::string& username) {
   1230   if (delegate_)
   1231     delegate_->LoginAsPublicAccount(username);
   1232 }
   1233 
   1234 void 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 
   1247 void SigninScreenHandler::HandleShutdownSystem() {
   1248   ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
   1249 }
   1250 
   1251 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
   1252   if (delegate_)
   1253     delegate_->LoadWallpaper(email);
   1254 }
   1255 
   1256 void SigninScreenHandler::HandleRebootSystem() {
   1257   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
   1258 }
   1259 
   1260 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
   1261   if (!delegate_)
   1262     return;
   1263   delegate_->RemoveUser(email);
   1264   UpdateAddButtonStatus();
   1265 }
   1266 
   1267 void 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 
   1286 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
   1287   if (delegate_)
   1288     delegate_->ShowEnterpriseEnrollmentScreen();
   1289 }
   1290 
   1291 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
   1292   if (delegate_ &&
   1293       !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
   1294     delegate_->ShowKioskEnableScreen();
   1295   }
   1296 }
   1297 
   1298 void SigninScreenHandler::HandleToggleResetScreen() {
   1299   if (delegate_ &&
   1300       !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
   1301     delegate_->ShowResetScreen();
   1302   }
   1303 }
   1304 
   1305 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
   1306   if (delegate_ &&
   1307       !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
   1308     delegate_->ShowKioskAutolaunchScreen();
   1309   }
   1310 }
   1311 
   1312 void 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 
   1321 void 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 
   1350 void 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 
   1403 void 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 
   1435 void 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 
   1444 void 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 
   1483 void SigninScreenHandler::HandleSignOutUser() {
   1484   if (delegate_)
   1485     delegate_->Signout();
   1486 }
   1487 
   1488 void SigninScreenHandler::HandleNetworkErrorShown() {
   1489   content::NotificationService::current()->Notify(
   1490       chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
   1491       content::NotificationService::AllSources(),
   1492       content::NotificationService::NoDetails());
   1493 }
   1494 
   1495 void SigninScreenHandler::HandleCreateAccount() {
   1496   if (delegate_)
   1497     delegate_->CreateAccount();
   1498 }
   1499 
   1500 void SigninScreenHandler::HandleOpenProxySettings() {
   1501   LoginDisplayHostImpl::default_host()->OpenProxySettings();
   1502 }
   1503 
   1504 void 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 
   1522 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
   1523   StartClearingCookies(base::Bind(
   1524       &SigninScreenHandler::CancelPasswordChangedFlowInternal,
   1525       weak_factory_.GetWeakPtr()));
   1526 }
   1527 
   1528 void SigninScreenHandler::HandleCancelUserAdding() {
   1529   if (delegate_)
   1530     delegate_->CancelUserAdding();
   1531 }
   1532 
   1533 void SigninScreenHandler::HandleMigrateUserData(
   1534     const std::string& old_password) {
   1535   if (delegate_)
   1536     delegate_->MigrateUserData(old_password);
   1537 }
   1538 
   1539 void SigninScreenHandler::HandleResyncUserData() {
   1540   if (delegate_)
   1541     delegate_->ResyncUserData();
   1542 }
   1543 
   1544 void 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 
   1566 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
   1567   DCHECK(UserManager::Get()->IsUserLoggedIn());
   1568   if (ScreenLocker::default_screen_locker())
   1569     ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
   1570 }
   1571 
   1572 void 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 
   1595 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
   1596   UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
   1597 }
   1598 
   1599 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
   1600   offline_login_active_ = offline_login_active;
   1601 }
   1602 
   1603 void 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 
   1616 void 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 
   1628 void 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 
   1646 bool 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 
   1671 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
   1672   if (delegate_) {
   1673     Show(oobe_ui_);
   1674     delegate_->CancelPasswordChangedFlow();
   1675   }
   1676 }
   1677 
   1678 OobeUI::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 
   1686 bool SigninScreenHandler::IsGaiaVisible() const {
   1687   return IsSigninScreen(GetCurrentScreen()) &&
   1688       ui_state_ == UI_STATE_GAIA_SIGNIN;
   1689 }
   1690 
   1691 bool SigninScreenHandler::IsGaiaHiddenByError() const {
   1692   return IsSigninScreenHiddenByError() &&
   1693       ui_state_ == UI_STATE_GAIA_SIGNIN;
   1694 }
   1695 
   1696 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
   1697   return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
   1698       (IsSigninScreen(error_screen_actor_->parent_screen()));
   1699 }
   1700 
   1701 bool 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 
   1710 bool 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 
   1721 void 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