Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 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/network_screen_handler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/memory/weak_ptr.h"
     10 #include "base/prefs/pref_service.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
     15 #include "chrome/browser/chromeos/base/locale_util.h"
     16 #include "chrome/browser/chromeos/customization_document.h"
     17 #include "chrome/browser/chromeos/idle_detector.h"
     18 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
     19 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
     20 #include "chrome/browser/chromeos/system/input_device_settings.h"
     21 #include "chrome/browser/chromeos/system/timezone_util.h"
     22 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
     23 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
     24 #include "chrome/common/pref_names.h"
     25 #include "chrome/grit/generated_resources.h"
     26 #include "chromeos/ime/extension_ime_util.h"
     27 #include "chromeos/network/network_handler.h"
     28 #include "chromeos/network/network_state_handler.h"
     29 #include "ui/base/l10n/l10n_util.h"
     30 #include "ui/gfx/rect.h"
     31 #include "ui/views/layout/fill_layout.h"
     32 #include "ui/views/widget/widget.h"
     33 
     34 namespace {
     35 
     36 const char kJsScreenPath[] = "login.NetworkScreen";
     37 
     38 // JS API callbacks names.
     39 const char kJsApiNetworkOnExit[] = "networkOnExit";
     40 const char kJsApiNetworkOnLanguageChanged[] = "networkOnLanguageChanged";
     41 const char kJsApiNetworkOnInputMethodChanged[] = "networkOnInputMethodChanged";
     42 const char kJsApiNetworkOnTimezoneChanged[] = "networkOnTimezoneChanged";
     43 
     44 // For "UI Language" drop-down menu at OOBE screen we need to decide which
     45 // entry to mark "selected". If user has just selected "requested_locale",
     46 // but "loaded_locale" was actually loaded, we mark original user choice
     47 // "selected" only if loaded_locale is a backup for "requested_locale".
     48 std::string CalculateSelectedLanguage(const std::string& requested_locale,
     49                                       const std::string& loaded_locale) {
     50   std::string resolved_locale;
     51   if (!l10n_util::CheckAndResolveLocale(requested_locale, &resolved_locale))
     52     return loaded_locale;
     53 
     54   if (resolved_locale == loaded_locale)
     55     return requested_locale;
     56 
     57   return loaded_locale;
     58 }
     59 
     60 }  // namespace
     61 
     62 namespace chromeos {
     63 
     64 // NetworkScreenHandler, public: -----------------------------------------------
     65 
     66 NetworkScreenHandler::NetworkScreenHandler(CoreOobeActor* core_oobe_actor)
     67     : BaseScreenHandler(kJsScreenPath),
     68       screen_(NULL),
     69       core_oobe_actor_(core_oobe_actor),
     70       is_continue_enabled_(false),
     71       show_on_init_(false),
     72       weak_ptr_factory_(this) {
     73   DCHECK(core_oobe_actor_);
     74 
     75   input_method::InputMethodManager* manager =
     76       input_method::InputMethodManager::Get();
     77   manager->AddObserver(this);
     78 }
     79 
     80 NetworkScreenHandler::~NetworkScreenHandler() {
     81   if (screen_)
     82     screen_->OnActorDestroyed(this);
     83 
     84   input_method::InputMethodManager* manager =
     85       input_method::InputMethodManager::Get();
     86   manager->RemoveObserver(this);
     87 }
     88 
     89 // NetworkScreenHandler, NetworkScreenActor implementation: --------------------
     90 
     91 void NetworkScreenHandler::SetDelegate(NetworkScreenActor::Delegate* screen) {
     92   screen_ = screen;
     93 }
     94 
     95 void NetworkScreenHandler::PrepareToShow() {
     96 }
     97 
     98 void NetworkScreenHandler::Show() {
     99   if (!page_is_ready()) {
    100     show_on_init_ = true;
    101     return;
    102   }
    103 
    104   // Here we should handle default locales, for which we do not have UI
    105   // resources. This would load fallback, but properly show "selected" locale
    106   // in the UI.
    107   if (selected_language_code_.empty()) {
    108     const StartupCustomizationDocument* startup_manifest =
    109         StartupCustomizationDocument::GetInstance();
    110     HandleOnLanguageChanged(startup_manifest->initial_locale_default());
    111   }
    112 
    113   PrefService* prefs = g_browser_process->local_state();
    114   if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
    115     if (core_oobe_actor_)
    116       core_oobe_actor_->ShowDeviceResetScreen();
    117     return;
    118   }
    119 
    120   // Make sure all our network technologies are turned on. On OOBE, the user
    121   // should be able to select any of the available networks on the device.
    122   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
    123   handler->SetTechnologyEnabled(NetworkTypePattern::NonVirtual(),
    124                                 true,
    125                                 chromeos::network_handler::ErrorCallback());
    126   ShowScreen(OobeUI::kScreenOobeNetwork, NULL);
    127   core_oobe_actor_->InitDemoModeDetection();
    128 }
    129 
    130 void NetworkScreenHandler::Hide() {
    131 }
    132 
    133 void NetworkScreenHandler::ShowError(const base::string16& message) {
    134   CallJS("showError", message);
    135 }
    136 
    137 void NetworkScreenHandler::ClearErrors() {
    138   if (page_is_ready())
    139     core_oobe_actor_->ClearErrors();
    140 }
    141 
    142 void NetworkScreenHandler::ShowConnectingStatus(
    143     bool connecting,
    144     const base::string16& network_id) {
    145 }
    146 
    147 void NetworkScreenHandler::EnableContinue(bool enabled) {
    148   is_continue_enabled_ = enabled;
    149   if (page_is_ready())
    150     CallJS("enableContinueButton", enabled);
    151 }
    152 
    153 // NetworkScreenHandler, BaseScreenHandler implementation: --------------------
    154 
    155 void NetworkScreenHandler::DeclareLocalizedValues(
    156     LocalizedValuesBuilder* builder) {
    157   if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation())
    158     builder->Add("networkScreenGreeting", IDS_REMORA_CONFIRM_MESSAGE);
    159   else
    160     builder->Add("networkScreenGreeting", IDS_WELCOME_SCREEN_GREETING);
    161 
    162   builder->Add("networkScreenTitle", IDS_WELCOME_SCREEN_TITLE);
    163   builder->Add("networkScreenAccessibleTitle",
    164                IDS_NETWORK_SCREEN_ACCESSIBLE_TITLE);
    165   builder->Add("selectLanguage", IDS_LANGUAGE_SELECTION_SELECT);
    166   builder->Add("selectKeyboard", IDS_KEYBOARD_SELECTION_SELECT);
    167   builder->Add("selectNetwork", IDS_NETWORK_SELECTION_SELECT);
    168   builder->Add("selectTimezone", IDS_OPTIONS_SETTINGS_TIMEZONE_DESCRIPTION);
    169   builder->Add("proxySettings", IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON);
    170   builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
    171 }
    172 
    173 void NetworkScreenHandler::GetAdditionalParameters(
    174     base::DictionaryValue* dict) {
    175   const std::string application_locale =
    176       g_browser_process->GetApplicationLocale();
    177   const std::string selected_language = selected_language_code_.empty() ?
    178       application_locale : selected_language_code_;
    179   const std::string selected_input_method =
    180       input_method::InputMethodManager::Get()
    181           ->GetActiveIMEState()
    182           ->GetCurrentInputMethod()
    183           .id();
    184 
    185   dict->Set("languageList",
    186             GetUILanguageList(NULL, selected_language).release());
    187   dict->Set("inputMethodsList",
    188             GetAndActivateLoginKeyboardLayouts(
    189                 application_locale, selected_input_method).release());
    190   dict->Set("timezoneList", GetTimezoneList());
    191 }
    192 
    193 void NetworkScreenHandler::Initialize() {
    194   EnableContinue(is_continue_enabled_);
    195   if (show_on_init_) {
    196     show_on_init_ = false;
    197     Show();
    198   }
    199 
    200   timezone_subscription_ = CrosSettings::Get()->AddSettingsObserver(
    201       kSystemTimezone,
    202       base::Bind(&NetworkScreenHandler::OnSystemTimezoneChanged,
    203                  base::Unretained(this)));
    204   OnSystemTimezoneChanged();
    205 }
    206 
    207 // NetworkScreenHandler, WebUIMessageHandler implementation: -------------------
    208 
    209 void NetworkScreenHandler::RegisterMessages() {
    210   AddCallback(kJsApiNetworkOnExit, &NetworkScreenHandler::HandleOnExit);
    211   AddCallback(kJsApiNetworkOnLanguageChanged,
    212               &NetworkScreenHandler::HandleOnLanguageChanged);
    213   AddCallback(kJsApiNetworkOnInputMethodChanged,
    214               &NetworkScreenHandler::HandleOnInputMethodChanged);
    215   AddCallback(kJsApiNetworkOnTimezoneChanged,
    216               &NetworkScreenHandler::HandleOnTimezoneChanged);
    217 }
    218 
    219 
    220 // NetworkScreenHandler, private: ----------------------------------------------
    221 
    222 void NetworkScreenHandler::HandleOnExit() {
    223   core_oobe_actor_->StopDemoModeDetection();
    224   ClearErrors();
    225   if (screen_)
    226     screen_->OnContinuePressed();
    227 }
    228 
    229 struct NetworkScreenHandlerOnLanguageChangedCallbackData {
    230   explicit NetworkScreenHandlerOnLanguageChangedCallbackData(
    231       const base::WeakPtr<NetworkScreenHandler>& handler)
    232       : handler(handler) {}
    233 
    234   base::WeakPtr<NetworkScreenHandler> handler;
    235 
    236   // Block UI while resource bundle is being reloaded.
    237   chromeos::InputEventsBlocker input_events_blocker;
    238 };
    239 
    240 // static
    241 void NetworkScreenHandler::OnLanguageChangedCallback(
    242     scoped_ptr<NetworkScreenHandlerOnLanguageChangedCallbackData> context,
    243     const std::string& requested_locale,
    244     const std::string& loaded_locale,
    245     const bool success) {
    246   if (!context || !context->handler)
    247     return;
    248 
    249   NetworkScreenHandler* const self = context->handler.get();
    250 
    251   if (success) {
    252     if (requested_locale == loaded_locale) {
    253       self->selected_language_code_ = requested_locale;
    254     } else {
    255       self->selected_language_code_ =
    256           CalculateSelectedLanguage(requested_locale, loaded_locale);
    257     }
    258   } else {
    259     self->selected_language_code_ = loaded_locale;
    260   }
    261 
    262   self->ReloadLocalizedContent();
    263 
    264   // We still do not have device owner, so owner settings are not applied.
    265   // But Guest session can be started before owner is created, so we need to
    266   // save locale settings directly here.
    267   g_browser_process->local_state()->SetString(prefs::kApplicationLocale,
    268                                               self->selected_language_code_);
    269 
    270   AccessibilityManager::Get()->OnLocaleChanged();
    271 }
    272 
    273 void NetworkScreenHandler::HandleOnLanguageChanged(const std::string& locale) {
    274   const std::string app_locale = g_browser_process->GetApplicationLocale();
    275   if (app_locale == locale)
    276     return;
    277 
    278   base::WeakPtr<NetworkScreenHandler> weak_self =
    279       weak_ptr_factory_.GetWeakPtr();
    280   scoped_ptr<NetworkScreenHandlerOnLanguageChangedCallbackData> callback_data(
    281       new NetworkScreenHandlerOnLanguageChangedCallbackData(weak_self));
    282   scoped_ptr<locale_util::SwitchLanguageCallback> callback(
    283       new locale_util::SwitchLanguageCallback(
    284           base::Bind(&NetworkScreenHandler::OnLanguageChangedCallback,
    285                      base::Passed(callback_data.Pass()))));
    286   locale_util::SwitchLanguage(locale,
    287                               true /* enableLocaleKeyboardLayouts */,
    288                               true /* login_layouts_only */,
    289                               callback.Pass());
    290 }
    291 
    292 void NetworkScreenHandler::HandleOnInputMethodChanged(const std::string& id) {
    293   input_method::InputMethodManager::Get()
    294       ->GetActiveIMEState()
    295       ->ChangeInputMethod(id, false /* show_message */);
    296 }
    297 
    298 void NetworkScreenHandler::HandleOnTimezoneChanged(
    299     const std::string& timezone_id) {
    300   std::string current_timezone_id;
    301   CrosSettings::Get()->GetString(kSystemTimezone, &current_timezone_id);
    302   if (current_timezone_id == timezone_id)
    303     return;
    304 
    305   CrosSettings::Get()->SetString(kSystemTimezone, timezone_id);
    306 }
    307 
    308 void NetworkScreenHandler::OnSystemTimezoneChanged() {
    309   std::string current_timezone_id;
    310   CrosSettings::Get()->GetString(kSystemTimezone, &current_timezone_id);
    311   CallJS("setTimezone", current_timezone_id);
    312 }
    313 
    314 void NetworkScreenHandler::InputMethodChanged(
    315     input_method::InputMethodManager* manager, bool show_message) {
    316   CallJS("setInputMethod",
    317          manager->GetActiveIMEState()->GetCurrentInputMethod().id());
    318 }
    319 
    320 void NetworkScreenHandler::ReloadLocalizedContent() {
    321   base::DictionaryValue localized_strings;
    322   static_cast<OobeUI*>(web_ui()->GetController())
    323       ->GetLocalizedStrings(&localized_strings);
    324   core_oobe_actor_->ReloadContent(localized_strings);
    325 
    326   // Buttons are recreated, updated "Continue" button state.
    327   EnableContinue(is_continue_enabled_);
    328 }
    329 
    330 // static
    331 base::ListValue* NetworkScreenHandler::GetTimezoneList() {
    332   std::string current_timezone_id;
    333   CrosSettings::Get()->GetString(kSystemTimezone, &current_timezone_id);
    334 
    335   scoped_ptr<base::ListValue> timezone_list(new base::ListValue);
    336   scoped_ptr<base::ListValue> timezones = system::GetTimezoneList().Pass();
    337   for (size_t i = 0; i < timezones->GetSize(); ++i) {
    338     const base::ListValue* timezone = NULL;
    339     CHECK(timezones->GetList(i, &timezone));
    340 
    341     std::string timezone_id;
    342     CHECK(timezone->GetString(0, &timezone_id));
    343 
    344     std::string timezone_name;
    345     CHECK(timezone->GetString(1, &timezone_name));
    346 
    347     scoped_ptr<base::DictionaryValue> timezone_option(
    348         new base::DictionaryValue);
    349     timezone_option->SetString("value", timezone_id);
    350     timezone_option->SetString("title", timezone_name);
    351     timezone_option->SetBoolean("selected", timezone_id == current_timezone_id);
    352     timezone_list->Append(timezone_option.release());
    353   }
    354 
    355   return timezone_list.release();
    356 }
    357 
    358 }  // namespace chromeos
    359