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 <algorithm>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/command_line.h"
     12 #include "base/debug/trace_event.h"
     13 #include "base/location.h"
     14 #include "base/logging.h"
     15 #include "base/metrics/histogram.h"
     16 #include "base/prefs/pref_registry_simple.h"
     17 #include "base/prefs/pref_service.h"
     18 #include "base/prefs/scoped_user_pref_update.h"
     19 #include "base/strings/string16.h"
     20 #include "base/strings/string_util.h"
     21 #include "base/strings/stringprintf.h"
     22 #include "base/strings/utf_string_conversions.h"
     23 #include "base/sys_info.h"
     24 #include "chrome/browser/browser_process.h"
     25 #include "chrome/browser/browser_process_platform_part_chromeos.h"
     26 #include "chrome/browser/browser_shutdown.h"
     27 #include "chrome/browser/chrome_notification_types.h"
     28 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
     29 #include "chrome/browser/chromeos/boot_times_loader.h"
     30 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     31 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
     32 #include "chrome/browser/chromeos/login/auth/key.h"
     33 #include "chrome/browser/chromeos/login/auth/user_context.h"
     34 #include "chrome/browser/chromeos/login/hwid_checker.h"
     35 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
     36 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
     37 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
     38 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
     39 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
     40 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
     41 #include "chrome/browser/chromeos/login/users/user.h"
     42 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
     43 #include "chrome/browser/chromeos/login/wizard_controller.h"
     44 #include "chrome/browser/chromeos/net/network_portal_detector.h"
     45 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
     46 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     47 #include "chrome/browser/chromeos/settings/cros_settings.h"
     48 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
     49 #include "chrome/browser/io_thread.h"
     50 #include "chrome/browser/profiles/profile.h"
     51 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h"
     52 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
     53 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
     54 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
     55 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
     56 #include "chrome/common/chrome_switches.h"
     57 #include "chrome/common/pref_names.h"
     58 #include "chrome/common/url_constants.h"
     59 #include "chromeos/chromeos_switches.h"
     60 #include "chromeos/dbus/dbus_thread_manager.h"
     61 #include "chromeos/dbus/power_manager_client.h"
     62 #include "chromeos/ime/ime_keyboard.h"
     63 #include "chromeos/ime/input_method_manager.h"
     64 #include "chromeos/network/network_state.h"
     65 #include "chromeos/network/network_state_handler.h"
     66 #include "content/public/browser/render_frame_host.h"
     67 #include "content/public/browser/web_contents.h"
     68 #include "google_apis/gaia/gaia_auth_util.h"
     69 #include "grit/chromium_strings.h"
     70 #include "grit/generated_resources.h"
     71 #include "net/url_request/url_request_context_getter.h"
     72 #include "third_party/cros_system_api/dbus/service_constants.h"
     73 #include "ui/base/webui/web_ui_util.h"
     74 #include "ui/gfx/image/image.h"
     75 #include "ui/gfx/image/image_skia.h"
     76 
     77 #if defined(USE_AURA)
     78 #include "ash/shell.h"
     79 #include "ash/wm/lock_state_controller.h"
     80 #endif
     81 
     82 using content::BrowserThread;
     83 
     84 namespace {
     85 
     86 // Max number of users to show.
     87 const size_t kMaxUsers = 18;
     88 
     89 // Timeout to delay first notification about offline state for a
     90 // current network.
     91 const int kOfflineTimeoutSec = 5;
     92 
     93 // Timeout used to prevent infinite connecting to a flaky network.
     94 const int kConnectingTimeoutSec = 60;
     95 
     96 // Type of the login screen UI that is currently presented to user.
     97 const char kSourceGaiaSignin[] = "gaia-signin";
     98 const char kSourceAccountPicker[] = "account-picker";
     99 
    100 static bool Contains(const std::vector<std::string>& container,
    101                      const std::string& value) {
    102   return std::find(container.begin(), container.end(), value) !=
    103          container.end();
    104 }
    105 
    106 }  // namespace
    107 
    108 namespace chromeos {
    109 
    110 namespace {
    111 
    112 bool IsOnline(NetworkStateInformer::State state,
    113               ErrorScreenActor::ErrorReason reason) {
    114   return state == NetworkStateInformer::ONLINE &&
    115       reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
    116       reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
    117 }
    118 
    119 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
    120                            ErrorScreenActor::ErrorReason reason) {
    121   return state == NetworkStateInformer::CAPTIVE_PORTAL ||
    122       reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
    123 }
    124 
    125 bool IsProxyError(NetworkStateInformer::State state,
    126                   ErrorScreenActor::ErrorReason reason,
    127                   net::Error frame_error) {
    128   return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
    129       reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
    130       reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
    131       (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
    132        (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
    133         frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
    134 }
    135 
    136 bool IsSigninScreen(const OobeUI::Screen screen) {
    137   return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
    138       screen == OobeUI::SCREEN_ACCOUNT_PICKER;
    139 }
    140 
    141 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
    142   return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
    143       error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
    144       error_state == ErrorScreen::ERROR_STATE_PROXY ||
    145       error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
    146 }
    147 
    148 // Returns network name by service path.
    149 std::string GetNetworkName(const std::string& service_path) {
    150   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
    151       GetNetworkState(service_path);
    152   if (!network)
    153     return std::string();
    154   return network->name();
    155 }
    156 
    157 static bool SetUserInputMethodImpl(
    158     const std::string& username,
    159     chromeos::input_method::InputMethodManager* manager) {
    160   PrefService* const local_state = g_browser_process->local_state();
    161 
    162   const base::DictionaryValue* users_lru_input_methods =
    163       local_state->GetDictionary(prefs::kUsersLRUInputMethod);
    164 
    165   if (users_lru_input_methods == NULL) {
    166     DLOG(WARNING) << "SetUserInputMethod('" << username
    167                   << "'): no kUsersLRUInputMethod";
    168     return false;
    169   }
    170 
    171   std::string input_method;
    172 
    173   if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
    174                                                               &input_method)) {
    175     DVLOG(0) << "SetUserInputMethod('" << username
    176                << "'): no input method for this user";
    177     return false;
    178   }
    179 
    180   if (input_method.empty())
    181     return false;
    182 
    183   if (!manager->IsLoginKeyboard(input_method)) {
    184     LOG(WARNING) << "SetUserInputMethod('" << username
    185                  << "'): stored user LRU input method '" << input_method
    186                  << "' is no longer Full Latin Keyboard Language"
    187                  << " (entry dropped). Use hardware default instead.";
    188 
    189     DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
    190 
    191     base::DictionaryValue* const users_lru_input_methods = updater.Get();
    192     if (users_lru_input_methods != NULL) {
    193       users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
    194     }
    195     return false;
    196   }
    197 
    198   if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
    199     if (!manager->EnableInputMethod(input_method)) {
    200       DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
    201                   << "'): user input method '" << input_method
    202                   << "' is not enabled and enabling failed (ignored!).";
    203     }
    204   }
    205   manager->ChangeInputMethod(input_method);
    206 
    207   return true;
    208 }
    209 
    210 }  // namespace
    211 
    212 // LoginScreenContext implementation ------------------------------------------
    213 
    214 LoginScreenContext::LoginScreenContext() {
    215   Init();
    216 }
    217 
    218 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
    219   Init();
    220 
    221   if (!args || args->GetSize() == 0)
    222     return;
    223   std::string email;
    224   if (args->GetString(0, &email))
    225     email_ = email;
    226 }
    227 
    228 void LoginScreenContext::Init() {
    229   oobe_ui_ = false;
    230 }
    231 
    232 // SigninScreenHandler implementation ------------------------------------------
    233 
    234 SigninScreenHandler::SigninScreenHandler(
    235     const scoped_refptr<NetworkStateInformer>& network_state_informer,
    236     ErrorScreenActor* error_screen_actor,
    237     CoreOobeActor* core_oobe_actor,
    238     GaiaScreenHandler* gaia_screen_handler)
    239     : ui_state_(UI_STATE_UNKNOWN),
    240       delegate_(NULL),
    241       native_window_delegate_(NULL),
    242       show_on_init_(false),
    243       oobe_ui_(false),
    244       is_account_picker_showing_first_time_(false),
    245       network_state_informer_(network_state_informer),
    246       webui_visible_(false),
    247       preferences_changed_delayed_(false),
    248       error_screen_actor_(error_screen_actor),
    249       core_oobe_actor_(core_oobe_actor),
    250       is_first_update_state_call_(true),
    251       offline_login_active_(false),
    252       last_network_state_(NetworkStateInformer::UNKNOWN),
    253       has_pending_auth_ui_(false),
    254       caps_lock_enabled_(chromeos::input_method::InputMethodManager::Get()
    255                              ->GetImeKeyboard()
    256                              ->CapsLockIsEnabled()),
    257       gaia_screen_handler_(gaia_screen_handler),
    258       weak_factory_(this) {
    259   DCHECK(network_state_informer_.get());
    260   DCHECK(error_screen_actor_);
    261   DCHECK(core_oobe_actor_);
    262   DCHECK(gaia_screen_handler_);
    263   gaia_screen_handler_->SetSigninScreenHandler(this);
    264   network_state_informer_->AddObserver(this);
    265 
    266   registrar_.Add(this,
    267                  chrome::NOTIFICATION_AUTH_NEEDED,
    268                  content::NotificationService::AllSources());
    269   registrar_.Add(this,
    270                  chrome::NOTIFICATION_AUTH_SUPPLIED,
    271                  content::NotificationService::AllSources());
    272   registrar_.Add(this,
    273                  chrome::NOTIFICATION_AUTH_CANCELLED,
    274                  content::NotificationService::AllSources());
    275 
    276   chromeos::input_method::ImeKeyboard* keyboard =
    277       chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
    278   if (keyboard)
    279     keyboard->AddObserver(this);
    280 }
    281 
    282 SigninScreenHandler::~SigninScreenHandler() {
    283   chromeos::input_method::ImeKeyboard* keyboard =
    284       chromeos::input_method::InputMethodManager::Get()->GetImeKeyboard();
    285   if (keyboard)
    286     keyboard->RemoveObserver(this);
    287   weak_factory_.InvalidateWeakPtrs();
    288   if (delegate_)
    289     delegate_->SetWebUIHandler(NULL);
    290   network_state_informer_->RemoveObserver(this);
    291   ScreenlockBridge::Get()->SetLockHandler(NULL);
    292 }
    293 
    294 void SigninScreenHandler::DeclareLocalizedValues(
    295     LocalizedValuesBuilder* builder) {
    296   builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
    297   builder->Add("podMenuButtonAccessibleName",
    298                IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
    299   builder->Add("podMenuRemoveItemAccessibleName",
    300                IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
    301   builder->Add("passwordFieldAccessibleName",
    302                IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
    303   builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
    304   builder->Add("signinButton", IDS_LOGIN_BUTTON);
    305   builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON);
    306   builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
    307   builder->Add("addUser", IDS_ADD_USER_BUTTON);
    308   builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
    309   builder->Add("cancel", IDS_CANCEL);
    310   builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
    311   builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
    312   builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
    313   builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
    314   builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
    315   builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
    316   builder->Add("errorTpmFailureRebootButton",
    317                IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
    318 
    319   policy::BrowserPolicyConnectorChromeOS* connector =
    320       g_browser_process->platform_part()->browser_policy_connector_chromeos();
    321   builder->Add("disabledAddUserTooltip",
    322                connector->IsEnterpriseManaged()
    323                    ? IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE
    324                    : IDS_DISABLED_ADD_USER_TOOLTIP);
    325 
    326   builder->Add("supervisedUserExpiredTokenWarning",
    327                IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
    328   builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
    329 
    330   // Multi-profiles related strings.
    331   builder->Add("multiProfilesRestrictedPolicyTitle",
    332                IDS_MULTI_PROFILES_RESTRICTED_POLICY_TITLE);
    333   builder->Add("multiProfilesNotAllowedPolicyMsg",
    334                IDS_MULTI_PROFILES_NOT_ALLOWED_POLICY_MSG);
    335   builder->Add("multiProfilesPrimaryOnlyPolicyMsg",
    336                IDS_MULTI_PROFILES_PRIMARY_ONLY_POLICY_MSG);
    337   builder->Add("multiProfilesOwnerPrimaryOnlyMsg",
    338                IDS_MULTI_PROFILES_OWNER_PRIMARY_ONLY_MSG);
    339 
    340   // Strings used by password changed dialog.
    341   builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
    342   builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
    343   builder->AddF("passwordChangedMoreInfo",
    344                 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
    345                 IDS_SHORT_PRODUCT_OS_NAME);
    346 
    347   builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
    348   builder->Add("oldPasswordIncorrect",
    349                IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
    350   builder->Add("passwordChangedCantRemember",
    351                IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
    352   builder->Add("passwordChangedBackButton",
    353                IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
    354   builder->Add("passwordChangedsOkButton", IDS_OK);
    355   builder->Add("passwordChangedProceedAnyway",
    356                IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
    357   builder->Add("proceedAnywayButton",
    358                IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
    359   builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
    360   builder->Add("publicAccountReminder",
    361                IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
    362   builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
    363   builder->Add("publicAccountEnterAccessibleName",
    364                IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
    365   builder->Add("removeUserWarningText",
    366                base::string16());
    367   builder->AddF("removeSupervisedUserWarningText",
    368                IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING,
    369                base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
    370   builder->Add("removeUserWarningButtonTitle",
    371                IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
    372 
    373   builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
    374 
    375   builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
    376   builder->Add("confirmPasswordLabel", IDS_LOGIN_CONFIRM_PASSWORD_LABEL);
    377   builder->Add("confirmPasswordConfirmButton",
    378                IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
    379   builder->Add("confirmPasswordText", IDS_LOGIN_CONFIRM_PASSWORD_TEXT);
    380   builder->Add("confirmPasswordErrorText",
    381                IDS_LOGIN_CONFIRM_PASSWORD_ERROR_TEXT);
    382   builder->Add("easyUnlockTooltip",
    383                IDS_LOGIN_EASY_UNLOCK_TOOLTIP);
    384 
    385   builder->Add("fatalEnrollmentError",
    386                IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR);
    387   builder->Add("insecureURLEnrollmentError",
    388                IDS_ENTERPRISE_ENROLLMENT_AUTH_INSECURE_URL_ERROR);
    389 
    390   if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
    391     builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
    392 
    393   builder->Add("runType", CommandLine::ForCurrentProcess()->HasSwitch(
    394       switches::kFirstExecAfterBoot) ?  "firstExecAfterBoot" :
    395                                         "notFirstExecAfterBoot");
    396 }
    397 
    398 void SigninScreenHandler::Show(const LoginScreenContext& context) {
    399   CHECK(delegate_);
    400 
    401   // Just initialize internal fields from context and call ShowImpl().
    402   oobe_ui_ = context.oobe_ui();
    403   gaia_screen_handler_->PopulateEmail(context.email());
    404   ShowImpl();
    405 }
    406 
    407 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
    408   CallJS("showLoginSpinner");
    409 }
    410 
    411 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
    412   delegate_ = delegate;
    413   if (delegate_)
    414     delegate_->SetWebUIHandler(this);
    415   else
    416     auto_enrollment_progress_subscription_.reset();
    417 }
    418 
    419 void SigninScreenHandler::SetNativeWindowDelegate(
    420     NativeWindowDelegate* native_window_delegate) {
    421   native_window_delegate_ = native_window_delegate;
    422 }
    423 
    424 void SigninScreenHandler::OnNetworkReady() {
    425   LOG(WARNING) << "OnNetworkReady() call.";
    426   DCHECK(gaia_screen_handler_);
    427   gaia_screen_handler_->MaybePreloadAuthExtension();
    428 }
    429 
    430 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
    431   UpdateStateInternal(reason, false);
    432 }
    433 
    434 // SigninScreenHandler, private: -----------------------------------------------
    435 
    436 void SigninScreenHandler::ShowImpl() {
    437   if (!page_is_ready()) {
    438     show_on_init_ = true;
    439     return;
    440   }
    441 
    442   if (oobe_ui_) {
    443     // Shows new user sign-in for OOBE.
    444     OnShowAddUser();
    445   } else {
    446     // Populates account picker. Animation is turned off for now until we
    447     // figure out how to make it fast enough.
    448     delegate_->HandleGetUsers();
    449 
    450     // Reset Caps Lock state when login screen is shown.
    451     input_method::InputMethodManager::Get()
    452         ->GetImeKeyboard()
    453         ->SetCapsLockEnabled(false);
    454 
    455     base::DictionaryValue params;
    456     params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
    457     UpdateUIState(UI_STATE_ACCOUNT_PICKER, &params);
    458   }
    459 }
    460 
    461 void SigninScreenHandler::UpdateUIState(UIState ui_state,
    462                                         base::DictionaryValue* params) {
    463   switch (ui_state) {
    464     case UI_STATE_GAIA_SIGNIN:
    465       ui_state_ = UI_STATE_GAIA_SIGNIN;
    466       ShowScreen(OobeUI::kScreenGaiaSignin, params);
    467       break;
    468     case UI_STATE_ACCOUNT_PICKER:
    469       ui_state_ = UI_STATE_ACCOUNT_PICKER;
    470       ShowScreen(OobeUI::kScreenAccountPicker, params);
    471       break;
    472     default:
    473       NOTREACHED();
    474       break;
    475   }
    476 }
    477 
    478 // TODO (ygorshenin@): split this method into small parts.
    479 // TODO (ygorshenin@): move this logic to GaiaScreenHandler.
    480 void SigninScreenHandler::UpdateStateInternal(
    481     ErrorScreenActor::ErrorReason reason,
    482     bool force_update) {
    483   // Do nothing once user has signed in or sign in is in progress.
    484   // TODO(ygorshenin): We will end up here when processing network state
    485   // notification but no ShowSigninScreen() was called so delegate_ will be
    486   // NULL. Network state processing logic does not belong here.
    487   if (delegate_ &&
    488       (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
    489     return;
    490   }
    491 
    492   NetworkStateInformer::State state = network_state_informer_->state();
    493   const std::string network_path = network_state_informer_->network_path();
    494   const std::string network_name = GetNetworkName(network_path);
    495 
    496   // Skip "update" notification about OFFLINE state from
    497   // NetworkStateInformer if previous notification already was
    498   // delayed.
    499   if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
    500       !force_update && !update_state_closure_.IsCancelled()) {
    501     return;
    502   }
    503 
    504   // TODO (ygorshenin@): switch log level to INFO once signin screen
    505   // will be tested well.
    506   LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
    507                << "state=" << NetworkStateInformer::StatusString(state) << ", "
    508                << "network_name=" << network_name << ", "
    509                << "reason=" << ErrorScreenActor::ErrorReasonString(reason)
    510                << ", force_update=" << force_update;
    511   update_state_closure_.Cancel();
    512 
    513   if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
    514       has_pending_auth_ui_) {
    515     update_state_closure_.Reset(
    516         base::Bind(&SigninScreenHandler::UpdateStateInternal,
    517                    weak_factory_.GetWeakPtr(),
    518                    reason,
    519                    true));
    520     base::MessageLoop::current()->PostDelayedTask(
    521         FROM_HERE,
    522         update_state_closure_.callback(),
    523         base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
    524     return;
    525   }
    526 
    527   // Don't show or hide error screen if we're in connecting state.
    528   if (state == NetworkStateInformer::CONNECTING && !force_update) {
    529     if (connecting_closure_.IsCancelled()) {
    530       // First notification about CONNECTING state.
    531       connecting_closure_.Reset(
    532           base::Bind(&SigninScreenHandler::UpdateStateInternal,
    533                      weak_factory_.GetWeakPtr(),
    534                      reason,
    535                      true));
    536       base::MessageLoop::current()->PostDelayedTask(
    537           FROM_HERE,
    538           connecting_closure_.callback(),
    539           base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
    540     }
    541     return;
    542   }
    543   connecting_closure_.Cancel();
    544 
    545   const bool is_online = IsOnline(state, reason);
    546   const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
    547   const bool is_gaia_loading_timeout =
    548       (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
    549   const bool is_gaia_error =
    550       FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED;
    551   const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError();
    552   const bool error_screen_should_overlay =
    553       !offline_login_active_ && IsGaiaVisible();
    554   const bool from_not_online_to_online_transition =
    555       is_online && last_network_state_ != NetworkStateInformer::ONLINE;
    556   last_network_state_ = state;
    557 
    558   if (is_online || !is_behind_captive_portal)
    559     error_screen_actor_->HideCaptivePortal();
    560 
    561   // Hide offline message (if needed) and return if current screen is
    562   // not a Gaia frame.
    563   if (!is_gaia_signin) {
    564     if (!IsSigninScreenHiddenByError())
    565       HideOfflineMessage(state, reason);
    566     return;
    567   }
    568 
    569   // Reload frame if network state is changed from {!ONLINE} -> ONLINE state.
    570   if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED &&
    571       from_not_online_to_online_transition) {
    572     // Schedules a immediate retry.
    573     LOG(WARNING) << "Retry page load since network has been changed.";
    574     ReloadGaiaScreen();
    575   }
    576 
    577   if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED &&
    578       error_screen_should_overlay) {
    579     // Schedules a immediate retry.
    580     LOG(WARNING) << "Retry page load since proxy settings has been changed.";
    581     ReloadGaiaScreen();
    582   }
    583 
    584   if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
    585       !IsProxyError(state, reason, FrameError())) {
    586     LOG(WARNING) << "Retry page load due to reason: "
    587                  << ErrorScreenActor::ErrorReasonString(reason);
    588     ReloadGaiaScreen();
    589   }
    590 
    591   if ((!is_online || is_gaia_loading_timeout || is_gaia_error) &&
    592       !offline_login_active_) {
    593     SetupAndShowOfflineMessage(state, reason);
    594   } else {
    595     HideOfflineMessage(state, reason);
    596   }
    597 }
    598 
    599 void SigninScreenHandler::SetupAndShowOfflineMessage(
    600     NetworkStateInformer:: State state,
    601     ErrorScreenActor::ErrorReason reason) {
    602   const std::string network_path = network_state_informer_->network_path();
    603   const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
    604   const bool is_proxy_error = IsProxyError(state, reason, FrameError());
    605   const bool is_gaia_loading_timeout =
    606       (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
    607 
    608   if (is_proxy_error) {
    609     error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
    610                                        std::string());
    611   } else if (is_behind_captive_portal) {
    612     // Do not bother a user with obsessive captive portal showing. This
    613     // check makes captive portal being shown only once: either when error
    614     // screen is shown for the first time or when switching from another
    615     // error screen (offline, proxy).
    616     if (IsGaiaVisible() ||
    617         (error_screen_actor_->error_state() !=
    618          ErrorScreen::ERROR_STATE_PORTAL)) {
    619       error_screen_actor_->FixCaptivePortal();
    620     }
    621     const std::string network_name = GetNetworkName(network_path);
    622     error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
    623                                        network_name);
    624   } else if (is_gaia_loading_timeout) {
    625     error_screen_actor_->SetErrorState(
    626         ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string());
    627   } else {
    628     error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
    629                                        std::string());
    630   }
    631 
    632   const bool guest_signin_allowed = IsGuestSigninAllowed() &&
    633       IsSigninScreenError(error_screen_actor_->error_state());
    634   error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
    635 
    636   const bool offline_login_allowed = IsOfflineLoginAllowed() &&
    637       IsSigninScreenError(error_screen_actor_->error_state()) &&
    638       error_screen_actor_->error_state() !=
    639       ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
    640   error_screen_actor_->AllowOfflineLogin(offline_login_allowed);
    641 
    642   if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
    643     base::DictionaryValue params;
    644     const std::string network_type = network_state_informer_->network_type();
    645     params.SetString("lastNetworkType", network_type);
    646     error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
    647     error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, &params);
    648   }
    649 }
    650 
    651 void SigninScreenHandler::HideOfflineMessage(
    652     NetworkStateInformer::State state,
    653     ErrorScreenActor::ErrorReason reason) {
    654   if (!IsSigninScreenHiddenByError())
    655     return;
    656 
    657   error_screen_actor_->Hide();
    658 
    659   // Forces a reload for Gaia screen on hiding error message.
    660   if (IsGaiaVisible() || IsGaiaHiddenByError())
    661     ReloadGaiaScreen();
    662 }
    663 
    664 void SigninScreenHandler::ReloadGaiaScreen() {
    665   gaia_screen_handler_->ReloadGaia();
    666 }
    667 
    668 void SigninScreenHandler::Initialize() {
    669   // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
    670   // don't do anything, just return.
    671   if (!delegate_)
    672     return;
    673 
    674   if (show_on_init_) {
    675     show_on_init_ = false;
    676     ShowImpl();
    677   }
    678 }
    679 
    680 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
    681   if (native_window_delegate_)
    682     return native_window_delegate_->GetNativeWindow();
    683   return NULL;
    684 }
    685 
    686 void SigninScreenHandler::RegisterMessages() {
    687   AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
    688   AddCallback("attemptUnlock", &SigninScreenHandler::HandleAttemptUnlock);
    689   AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
    690   AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
    691   AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
    692   AddCallback("showLocallyManagedUserCreationScreen",
    693               &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen);
    694   AddCallback("launchPublicAccount",
    695               &SigninScreenHandler::HandleLaunchPublicAccount);
    696   AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
    697   AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
    698   AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
    699   AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
    700   AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
    701   AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
    702   AddCallback("toggleEnrollmentScreen",
    703               &SigninScreenHandler::HandleToggleEnrollmentScreen);
    704   AddCallback("toggleKioskEnableScreen",
    705               &SigninScreenHandler::HandleToggleKioskEnableScreen);
    706   AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
    707   AddCallback("accountPickerReady",
    708               &SigninScreenHandler::HandleAccountPickerReady);
    709   AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
    710   AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
    711   AddCallback("openProxySettings",
    712               &SigninScreenHandler::HandleOpenProxySettings);
    713   AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
    714   AddCallback("cancelPasswordChangedFlow",
    715               &SigninScreenHandler::HandleCancelPasswordChangedFlow);
    716   AddCallback("cancelUserAdding",
    717               &SigninScreenHandler::HandleCancelUserAdding);
    718   AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
    719   AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
    720   AddCallback("loginUIStateChanged",
    721               &SigninScreenHandler::HandleLoginUIStateChanged);
    722   AddCallback("unlockOnLoginSuccess",
    723               &SigninScreenHandler::HandleUnlockOnLoginSuccess);
    724   AddCallback("showLoadingTimeoutError",
    725               &SigninScreenHandler::HandleShowLoadingTimeoutError);
    726   AddCallback("updateOfflineLogin",
    727               &SigninScreenHandler::HandleUpdateOfflineLogin);
    728   AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
    729   AddCallback("retrieveAuthenticatedUserEmail",
    730               &SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail);
    731 
    732   // This message is sent by the kiosk app menu, but is handled here
    733   // so we can tell the delegate to launch the app.
    734   AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
    735 }
    736 
    737 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
    738   registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
    739 }
    740 
    741 void SigninScreenHandler::HandleGetUsers() {
    742   if (delegate_)
    743     delegate_->HandleGetUsers();
    744 }
    745 
    746 void SigninScreenHandler::ClearAndEnablePassword() {
    747   core_oobe_actor_->ResetSignInUI(false);
    748 }
    749 
    750 void SigninScreenHandler::ClearUserPodPassword() {
    751   core_oobe_actor_->ClearUserPodPassword();
    752 }
    753 
    754 void SigninScreenHandler::RefocusCurrentPod() {
    755   core_oobe_actor_->RefocusCurrentPod();
    756 }
    757 
    758 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
    759   CallJS("login.AccountPickerScreen.removeUser", username);
    760   if (delegate_->GetUsers().empty())
    761     OnShowAddUser();
    762 }
    763 
    764 void SigninScreenHandler::OnUserImageChanged(const User& user) {
    765   if (page_is_ready())
    766     CallJS("login.AccountPickerScreen.updateUserImage", user.email());
    767 }
    768 
    769 void SigninScreenHandler::OnPreferencesChanged() {
    770   // Make sure that one of the login UI is fully functional now, otherwise
    771   // preferences update would be picked up next time it will be shown.
    772   if (!webui_visible_) {
    773     LOG(WARNING) << "Login UI is not active - postponed prefs change.";
    774     preferences_changed_delayed_ = true;
    775     return;
    776   }
    777 
    778   if (delegate_ && !delegate_->IsShowUsers()) {
    779     HandleShowAddUser(NULL);
    780   } else {
    781     if (delegate_)
    782       delegate_->HandleGetUsers();
    783     UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
    784   }
    785   preferences_changed_delayed_ = false;
    786 }
    787 
    788 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
    789   SetDelegate(NULL);
    790 }
    791 
    792 void SigninScreenHandler::ShowError(int login_attempts,
    793                                     const std::string& error_text,
    794                                     const std::string& help_link_text,
    795                                     HelpAppLauncher::HelpTopic help_topic_id) {
    796   core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
    797                                     help_topic_id);
    798 }
    799 
    800 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
    801   switch (error_id) {
    802     case LoginDisplay::TPM_ERROR:
    803       core_oobe_actor_->ShowTpmError();
    804       break;
    805     default:
    806       NOTREACHED() << "Unknown sign in error";
    807       break;
    808   }
    809 }
    810 
    811 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
    812   core_oobe_actor_->ShowSignInUI(email);
    813 }
    814 
    815 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
    816   gaia_screen_handler_->PasswordChangedFor(username);
    817   gaia_screen_handler_->PopulateEmail(username);
    818   core_oobe_actor_->ShowSignInUI(username);
    819   CallJS("login.setAuthType",
    820          username,
    821          static_cast<int>(ONLINE_SIGN_IN),
    822          base::StringValue(""));
    823 }
    824 
    825 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
    826   core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
    827 }
    828 
    829 void SigninScreenHandler::ShowSigninScreenForCreds(
    830     const std::string& username,
    831     const std::string& password) {
    832   DCHECK(gaia_screen_handler_);
    833   gaia_screen_handler_->ShowSigninScreenForCreds(username, password);
    834 }
    835 
    836 void SigninScreenHandler::Observe(int type,
    837                                   const content::NotificationSource& source,
    838                                   const content::NotificationDetails& details) {
    839   switch (type) {
    840     case chrome::NOTIFICATION_AUTH_NEEDED: {
    841       has_pending_auth_ui_ = true;
    842       break;
    843     }
    844     case chrome::NOTIFICATION_AUTH_SUPPLIED:
    845       has_pending_auth_ui_ = false;
    846       // Reload auth extension as proxy credentials are supplied.
    847       if (!IsSigninScreenHiddenByError() && ui_state_ == UI_STATE_GAIA_SIGNIN)
    848         ReloadGaiaScreen();
    849       update_state_closure_.Cancel();
    850       break;
    851     case chrome::NOTIFICATION_AUTH_CANCELLED: {
    852       // Don't reload auth extension if proxy auth dialog was cancelled.
    853       has_pending_auth_ui_ = false;
    854       update_state_closure_.Cancel();
    855       break;
    856     }
    857     default:
    858       NOTREACHED() << "Unexpected notification " << type;
    859   }
    860 }
    861 
    862 void SigninScreenHandler::ShowBannerMessage(const std::string& message) {
    863   CallJS("login.AccountPickerScreen.showBannerMessage", message);
    864 }
    865 
    866 void SigninScreenHandler::ShowUserPodCustomIcon(
    867     const std::string& username,
    868     const gfx::Image& icon) {
    869   gfx::ImageSkia icon_skia = icon.AsImageSkia();
    870   base::DictionaryValue icon_representations;
    871   icon_representations.SetString(
    872       "scale1x",
    873       webui::GetBitmapDataUrl(icon_skia.GetRepresentation(1.0f).sk_bitmap()));
    874   icon_representations.SetString(
    875       "scale2x",
    876       webui::GetBitmapDataUrl(icon_skia.GetRepresentation(2.0f).sk_bitmap()));
    877   CallJS("login.AccountPickerScreen.showUserPodCustomIcon",
    878       username, icon_representations);
    879 
    880   // TODO(tengs): Move this code once we move unlocking to native code.
    881   if (ScreenLocker::default_screen_locker()) {
    882     UserManager* user_manager = UserManager::Get();
    883     const User* user = user_manager->FindUser(username);
    884     if (!user)
    885       return;
    886     PrefService* profile_prefs =
    887         user_manager->GetProfileByUser(user)->GetPrefs();
    888     if (profile_prefs->GetBoolean(prefs::kEasyUnlockShowTutorial)) {
    889       CallJS("login.AccountPickerScreen.showEasyUnlockBubble");
    890       profile_prefs->SetBoolean(prefs::kEasyUnlockShowTutorial, false);
    891     }
    892   }
    893 }
    894 
    895 void SigninScreenHandler::HideUserPodCustomIcon(const std::string& username) {
    896   CallJS("login.AccountPickerScreen.hideUserPodCustomIcon", username);
    897 }
    898 
    899 void SigninScreenHandler::EnableInput() {
    900   // Only for lock screen at the moment.
    901   ScreenLocker::default_screen_locker()->EnableInput();
    902 }
    903 
    904 void SigninScreenHandler::SetAuthType(
    905     const std::string& username,
    906     ScreenlockBridge::LockHandler::AuthType auth_type,
    907     const std::string& initial_value) {
    908   delegate_->SetAuthType(username, auth_type);
    909 
    910   CallJS("login.AccountPickerScreen.setAuthType",
    911          username,
    912          static_cast<int>(auth_type),
    913          base::StringValue(initial_value));
    914 }
    915 
    916 ScreenlockBridge::LockHandler::AuthType SigninScreenHandler::GetAuthType(
    917     const std::string& username) const {
    918   return delegate_->GetAuthType(username);
    919 }
    920 
    921 void SigninScreenHandler::Unlock(const std::string& user_email) {
    922   DCHECK(ScreenLocker::default_screen_locker());
    923   ScreenLocker::Hide();
    924 }
    925 
    926 bool SigninScreenHandler::ShouldLoadGaia() const {
    927   // Fetching of the extension is not started before account picker page is
    928   // loaded because it can affect the loading speed.
    929   // Do not load the extension for the screen locker, see crosbug.com/25018.
    930   return !ScreenLocker::default_screen_locker() &&
    931          is_account_picker_showing_first_time_;
    932 }
    933 
    934 // Update keyboard layout to least recently used by the user.
    935 void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
    936   UserManager* user_manager = UserManager::Get();
    937   if (user_manager->IsUserLoggedIn()) {
    938     // We are on sign-in screen inside user session (adding new user to
    939     // the session or on lock screen), don't switch input methods in this case.
    940     // TODO(dpolukhin): adding user and sign-in should be consistent
    941     // crbug.com/292774
    942     return;
    943   }
    944 
    945   chromeos::input_method::InputMethodManager* const manager =
    946       chromeos::input_method::InputMethodManager::Get();
    947 
    948   const bool succeed = SetUserInputMethodImpl(username, manager);
    949 
    950   // This is also a case when LRU layout is set only for a few local users,
    951   // thus others need to be switched to default locale.
    952   // Otherwise they will end up using another user's locale to log in.
    953   if (!succeed) {
    954     DVLOG(0) << "SetUserInputMethod('" << username
    955                << "'): failed to set user layout. Switching to default.";
    956 
    957     manager->SetInputMethodLoginDefault();
    958   }
    959 }
    960 
    961 
    962 void SigninScreenHandler::UserSettingsChanged() {
    963   DCHECK(gaia_screen_handler_);
    964   GaiaContext context;
    965   if (delegate_)
    966     context.has_users = !delegate_->GetUsers().empty();
    967   gaia_screen_handler_->UpdateGaia(context);
    968   UpdateAddButtonStatus();
    969 }
    970 
    971 void SigninScreenHandler::UpdateAddButtonStatus() {
    972   CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
    973          AllWhitelistedUsersPresent());
    974 }
    975 
    976 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
    977                                                  const std::string& password) {
    978   if (!delegate_)
    979     return;
    980   UserContext user_context(username);
    981   user_context.SetKey(Key(password));
    982   delegate_->Login(user_context);
    983 }
    984 
    985 void SigninScreenHandler::HandleAttemptUnlock(const std::string& username) {
    986   DCHECK(ScreenLocker::default_screen_locker());
    987 
    988   const User* unlock_user = NULL;
    989   const UserList& users = delegate_->GetUsers();
    990   for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
    991     if ((*it)->email() == username) {
    992       unlock_user = *it;
    993       break;
    994     }
    995   }
    996   if (!unlock_user)
    997     return;
    998 
    999   Profile* profile = UserManager::Get()->GetProfileByUser(unlock_user);
   1000   extensions::ScreenlockPrivateEventRouter* router =
   1001       extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
   1002           profile);
   1003   router->OnAuthAttempted(GetAuthType(username), "");
   1004 }
   1005 
   1006 void SigninScreenHandler::HandleLaunchDemoUser() {
   1007   if (delegate_)
   1008     delegate_->LoginAsRetailModeUser();
   1009 }
   1010 
   1011 void SigninScreenHandler::HandleLaunchIncognito() {
   1012   if (delegate_)
   1013     delegate_->LoginAsGuest();
   1014 }
   1015 
   1016 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
   1017   if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
   1018     LOG(ERROR) << "Managed users not allowed.";
   1019     return;
   1020   }
   1021   scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
   1022   LoginDisplayHostImpl::default_host()->
   1023       StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
   1024       params.Pass());
   1025 }
   1026 
   1027 void SigninScreenHandler::HandleLaunchPublicAccount(
   1028     const std::string& username) {
   1029   if (delegate_)
   1030     delegate_->LoginAsPublicAccount(username);
   1031 }
   1032 
   1033 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
   1034   if (!delegate_ || delegate_->IsShowUsers()) {
   1035     NOTREACHED();
   1036     return;
   1037   }
   1038   std::string email;
   1039   args->GetString(0, &email);
   1040 
   1041   gaia_screen_handler_->PopulateEmail(email);
   1042   // Load auth extension. Parameters are: force reload, do not load extension in
   1043   // background, use offline version.
   1044   gaia_screen_handler_->LoadAuthExtension(true, false, true);
   1045   UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
   1046 }
   1047 
   1048 void SigninScreenHandler::HandleShutdownSystem() {
   1049   ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
   1050 }
   1051 
   1052 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
   1053   if (delegate_)
   1054     delegate_->LoadWallpaper(email);
   1055 }
   1056 
   1057 void SigninScreenHandler::HandleRebootSystem() {
   1058   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
   1059 }
   1060 
   1061 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
   1062   if (!delegate_)
   1063     return;
   1064   delegate_->RemoveUser(email);
   1065   UpdateAddButtonStatus();
   1066 }
   1067 
   1068 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
   1069   TRACE_EVENT_ASYNC_STEP_INTO0("ui",
   1070                                "ShowLoginWebUI",
   1071                                LoginDisplayHostImpl::kShowLoginWebUIid,
   1072                                "ShowAddUser");
   1073   std::string email;
   1074   // |args| can be null if it's OOBE.
   1075   if (args)
   1076     args->GetString(0, &email);
   1077   gaia_screen_handler_->PopulateEmail(email);
   1078   OnShowAddUser();
   1079 }
   1080 
   1081 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
   1082   if (delegate_)
   1083     delegate_->ShowEnterpriseEnrollmentScreen();
   1084 }
   1085 
   1086 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
   1087   policy::BrowserPolicyConnectorChromeOS* connector =
   1088       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1089   if (delegate_ &&
   1090       !auto_enrollment_progress_subscription_ &&
   1091       !connector->IsEnterpriseManaged() &&
   1092       LoginDisplayHostImpl::default_host()) {
   1093     AutoEnrollmentController* auto_enrollment_controller =
   1094         LoginDisplayHostImpl::default_host()->GetAutoEnrollmentController();
   1095     auto_enrollment_progress_subscription_ =
   1096         auto_enrollment_controller->RegisterProgressCallback(
   1097             base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
   1098                        weak_factory_.GetWeakPtr()));
   1099     ContinueKioskEnableFlow(auto_enrollment_controller->state());
   1100   }
   1101 }
   1102 
   1103 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
   1104   policy::BrowserPolicyConnectorChromeOS* connector =
   1105       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   1106   if (delegate_ && !connector->IsEnterpriseManaged())
   1107     delegate_->ShowKioskAutolaunchScreen();
   1108 }
   1109 
   1110 void SigninScreenHandler::LoadUsers(const base::ListValue& users_list,
   1111                                     bool animated,
   1112                                     bool showGuest) {
   1113   CallJS("login.AccountPickerScreen.loadUsers",
   1114          users_list,
   1115          animated,
   1116          delegate_->IsShowGuest());
   1117 }
   1118 
   1119 void SigninScreenHandler::HandleAccountPickerReady() {
   1120   VLOG(0) << "Login WebUI >> AccountPickerReady";
   1121 
   1122   if (delegate_ && !ScreenLocker::default_screen_locker() &&
   1123       !chromeos::IsMachineHWIDCorrect() &&
   1124       !oobe_ui_) {
   1125     delegate_->ShowWrongHWIDScreen();
   1126     return;
   1127   }
   1128 
   1129   PrefService* prefs = g_browser_process->local_state();
   1130   if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
   1131     if (core_oobe_actor_) {
   1132       core_oobe_actor_->ShowDeviceResetScreen();
   1133       return;
   1134     }
   1135   }
   1136 
   1137   is_account_picker_showing_first_time_ = true;
   1138   gaia_screen_handler_->MaybePreloadAuthExtension();
   1139 
   1140   if (ScreenLocker::default_screen_locker()) {
   1141     ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
   1142     ScreenlockBridge::Get()->SetLockHandler(this);
   1143   }
   1144 
   1145   if (delegate_)
   1146     delegate_->OnSigninScreenReady();
   1147 }
   1148 
   1149 void SigninScreenHandler::HandleWallpaperReady() {
   1150   if (ScreenLocker::default_screen_locker()) {
   1151     ScreenLocker::default_screen_locker()->delegate()->
   1152         OnLockBackgroundDisplayed();
   1153   }
   1154 }
   1155 
   1156 void SigninScreenHandler::HandleSignOutUser() {
   1157   if (delegate_)
   1158     delegate_->Signout();
   1159 }
   1160 
   1161 void SigninScreenHandler::HandleCreateAccount() {
   1162   if (delegate_)
   1163     delegate_->CreateAccount();
   1164 }
   1165 
   1166 void SigninScreenHandler::HandleOpenProxySettings() {
   1167   LoginDisplayHostImpl::default_host()->OpenProxySettings();
   1168 }
   1169 
   1170 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
   1171   LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
   1172                << "webui_visible_: " << webui_visible_;
   1173   if (!webui_visible_) {
   1174     // There might be multiple messages from OOBE UI so send notifications after
   1175     // the first one only.
   1176     content::NotificationService::current()->Notify(
   1177         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
   1178         content::NotificationService::AllSources(),
   1179         content::NotificationService::NoDetails());
   1180     TRACE_EVENT_ASYNC_END0(
   1181         "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
   1182   }
   1183   webui_visible_ = true;
   1184   if (preferences_changed_delayed_)
   1185     OnPreferencesChanged();
   1186 }
   1187 
   1188 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
   1189   gaia_screen_handler_->StartClearingCookies(
   1190       base::Bind(&SigninScreenHandler::CancelPasswordChangedFlowInternal,
   1191                  weak_factory_.GetWeakPtr()));
   1192 }
   1193 
   1194 void SigninScreenHandler::HandleCancelUserAdding() {
   1195   if (delegate_)
   1196     delegate_->CancelUserAdding();
   1197 }
   1198 
   1199 void SigninScreenHandler::HandleMigrateUserData(
   1200     const std::string& old_password) {
   1201   if (delegate_)
   1202     delegate_->MigrateUserData(old_password);
   1203 }
   1204 
   1205 void SigninScreenHandler::HandleResyncUserData() {
   1206   if (delegate_)
   1207     delegate_->ResyncUserData();
   1208 }
   1209 
   1210 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
   1211                                                     bool new_value) {
   1212   VLOG(0) << "Login WebUI >> active: " << new_value << ", "
   1213             << "source: " << source;
   1214 
   1215   if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
   1216       KioskAppManager::Get()->IsAutoLaunchRequested()) {
   1217     VLOG(0) << "Showing auto-launch warning";
   1218     // On slow devices, the wallpaper animation is not shown initially, so we
   1219     // must explicitly load the wallpaper. This is also the case for the
   1220     // account-picker and gaia-signin UI states.
   1221     delegate_->LoadSigninWallpaper();
   1222     HandleToggleKioskAutolaunchScreen();
   1223     return;
   1224   }
   1225 
   1226   if (source == kSourceGaiaSignin) {
   1227     ui_state_ = UI_STATE_GAIA_SIGNIN;
   1228   } else if (source == kSourceAccountPicker) {
   1229     ui_state_ = UI_STATE_ACCOUNT_PICKER;
   1230   } else {
   1231     NOTREACHED();
   1232     return;
   1233   }
   1234 }
   1235 
   1236 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
   1237   DCHECK(UserManager::Get()->IsUserLoggedIn());
   1238   if (ScreenLocker::default_screen_locker())
   1239     ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
   1240 }
   1241 
   1242 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
   1243   UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
   1244 }
   1245 
   1246 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
   1247   offline_login_active_ = offline_login_active;
   1248 }
   1249 
   1250 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
   1251   SetUserInputMethod(user_id);
   1252   WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
   1253 }
   1254 
   1255 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
   1256     double attempt_token) {
   1257   email_retriever_.reset(new AuthenticatedUserEmailRetriever(
   1258       base::Bind(&SigninScreenHandler::CallJS<double, std::string>,
   1259                  base::Unretained(this),
   1260                  "login.GaiaSigninScreen.setAuthenticatedUserEmail",
   1261                  attempt_token),
   1262       Profile::FromWebUI(web_ui())->GetRequestContext()));
   1263 }
   1264 
   1265 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id,
   1266                                                bool diagnostic_mode) {
   1267   delegate_->LoginAsKioskApp(app_id, diagnostic_mode);
   1268 }
   1269 
   1270 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
   1271   CrosSettings* cros_settings = CrosSettings::Get();
   1272   bool allow_new_user = false;
   1273   cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
   1274   if (allow_new_user)
   1275     return false;
   1276   UserManager* user_manager = UserManager::Get();
   1277   const UserList& users = user_manager->GetUsers();
   1278   if (!delegate_ || users.size() > kMaxUsers) {
   1279     return false;
   1280   }
   1281   const base::ListValue* whitelist = NULL;
   1282   if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
   1283     return false;
   1284   for (size_t i = 0; i < whitelist->GetSize(); ++i) {
   1285     std::string whitelisted_user;
   1286     // NB: Wildcards in the whitelist are also detected as not present here.
   1287     if (!whitelist->GetString(i, &whitelisted_user) ||
   1288         !user_manager->IsKnownUser(whitelisted_user)) {
   1289       return false;
   1290     }
   1291   }
   1292   return true;
   1293 }
   1294 
   1295 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
   1296   if (delegate_) {
   1297     ShowImpl();
   1298     delegate_->CancelPasswordChangedFlow();
   1299   }
   1300 }
   1301 
   1302 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
   1303   OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
   1304   OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
   1305   if (oobe_ui)
   1306     screen = oobe_ui->current_screen();
   1307   return screen;
   1308 }
   1309 
   1310 bool SigninScreenHandler::IsGaiaVisible() const {
   1311   return IsSigninScreen(GetCurrentScreen()) &&
   1312       ui_state_ == UI_STATE_GAIA_SIGNIN;
   1313 }
   1314 
   1315 bool SigninScreenHandler::IsGaiaHiddenByError() const {
   1316   return IsSigninScreenHiddenByError() &&
   1317       ui_state_ == UI_STATE_GAIA_SIGNIN;
   1318 }
   1319 
   1320 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
   1321   return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
   1322       (IsSigninScreen(error_screen_actor_->parent_screen()));
   1323 }
   1324 
   1325 bool SigninScreenHandler::IsGuestSigninAllowed() const {
   1326   CrosSettings* cros_settings = CrosSettings::Get();
   1327   if (!cros_settings)
   1328     return false;
   1329   bool allow_guest;
   1330   cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
   1331   return allow_guest;
   1332 }
   1333 
   1334 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
   1335   CrosSettings* cros_settings = CrosSettings::Get();
   1336   if (!cros_settings)
   1337     return false;
   1338 
   1339   // Offline login is allowed only when user pods are hidden.
   1340   bool show_pods;
   1341   cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
   1342   return !show_pods;
   1343 }
   1344 
   1345 void SigninScreenHandler::ContinueKioskEnableFlow(
   1346     policy::AutoEnrollmentState state) {
   1347   // Do not proceed with kiosk enable when auto enroll will be enforced.
   1348   // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
   1349   switch (state) {
   1350     case policy::AUTO_ENROLLMENT_STATE_IDLE:
   1351     case policy::AUTO_ENROLLMENT_STATE_PENDING:
   1352     case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
   1353       // Wait for the next callback.
   1354       return;
   1355     case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
   1356       // Auto-enrollment is on.
   1357       LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
   1358                       "going to be enforced.";
   1359       if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
   1360         kiosk_enable_flow_aborted_callback_for_test_.Run();
   1361       break;
   1362     case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
   1363     case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
   1364       // Auto-enrollment not applicable.
   1365       if (delegate_)
   1366         delegate_->ShowKioskEnableScreen();
   1367       break;
   1368   }
   1369   auto_enrollment_progress_subscription_.reset();
   1370 }
   1371 
   1372 void SigninScreenHandler::OnShowAddUser() {
   1373   is_account_picker_showing_first_time_ = false;
   1374   DCHECK(gaia_screen_handler_);
   1375   gaia_screen_handler_->ShowGaia();
   1376 }
   1377 
   1378 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
   1379   DCHECK(gaia_screen_handler_);
   1380   return gaia_screen_handler_->frame_state();
   1381 }
   1382 
   1383 net::Error SigninScreenHandler::FrameError() const {
   1384   DCHECK(gaia_screen_handler_);
   1385   return gaia_screen_handler_->frame_error();
   1386 }
   1387 
   1388 void SigninScreenHandler::OnCapsLockChanged(bool enabled) {
   1389   caps_lock_enabled_ = enabled;
   1390   if (page_is_ready())
   1391     CallJS("login.AccountPickerScreen.setCapsLockState", caps_lock_enabled_);
   1392 }
   1393 
   1394 }  // namespace chromeos
   1395