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