Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2011 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/options/core_options_handler.h"
      6 
      7 #include "base/json/json_reader.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/string16.h"
     10 #include "base/string_number_conversions.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/google/google_util.h"
     15 #include "chrome/browser/metrics/user_metrics.h"
     16 #include "chrome/browser/prefs/pref_service.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/common/pref_names.h"
     19 #include "chrome/common/url_constants.h"
     20 #include "content/common/notification_details.h"
     21 #include "content/common/notification_type.h"
     22 #include "googleurl/src/gurl.h"
     23 #include "grit/chromium_strings.h"
     24 #include "grit/generated_resources.h"
     25 #include "grit/locale_settings.h"
     26 #include "grit/theme_resources.h"
     27 #include "ui/base/l10n/l10n_util.h"
     28 
     29 CoreOptionsHandler::CoreOptionsHandler()
     30     : handlers_host_(NULL) {
     31 }
     32 
     33 CoreOptionsHandler::~CoreOptionsHandler() {}
     34 
     35 void CoreOptionsHandler::Initialize() {
     36   clear_plugin_lso_data_enabled_.Init(prefs::kClearPluginLSODataEnabled,
     37                                       g_browser_process->local_state(),
     38                                       this);
     39   UpdateClearPluginLSOData();
     40 }
     41 
     42 void CoreOptionsHandler::GetLocalizedValues(
     43     DictionaryValue* localized_strings) {
     44   DCHECK(localized_strings);
     45   // Main
     46   localized_strings->SetString("title",
     47       l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
     48 
     49   // Managed prefs
     50   localized_strings->SetString("managedPrefsBannerText",
     51       l10n_util::GetStringUTF16(IDS_OPTIONS_MANAGED_PREFS));
     52 
     53   // Search
     54   RegisterTitle(localized_strings, "searchPage", IDS_OPTIONS_SEARCH_PAGE_TITLE);
     55   localized_strings->SetString("searchPlaceholder",
     56       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PLACEHOLDER));
     57   localized_strings->SetString("searchPageNoMatches",
     58       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
     59   localized_strings->SetString("searchPageHelpLabel",
     60       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_LABEL));
     61   localized_strings->SetString("searchPageHelpTitle",
     62       l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_TITLE,
     63           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
     64   localized_strings->SetString("searchPageHelpURL",
     65       google_util::AppendGoogleLocaleParam(
     66           GURL(chrome::kChromeHelpURL)).spec());
     67 
     68   // Common
     69   localized_strings->SetString("ok",
     70       l10n_util::GetStringUTF16(IDS_OK));
     71   localized_strings->SetString("cancel",
     72       l10n_util::GetStringUTF16(IDS_CANCEL));
     73   localized_strings->SetString("learnMore",
     74       l10n_util::GetStringUTF16(IDS_LEARN_MORE));
     75   localized_strings->SetString("close",
     76       l10n_util::GetStringUTF16(IDS_CLOSE));
     77 }
     78 
     79 void CoreOptionsHandler::Uninitialize() {
     80   std::string last_pref;
     81   for (PreferenceCallbackMap::const_iterator iter = pref_callback_map_.begin();
     82        iter != pref_callback_map_.end();
     83        ++iter) {
     84     if (last_pref != iter->first) {
     85       StopObservingPref(iter->first);
     86       last_pref = iter->first;
     87     }
     88   }
     89 }
     90 
     91 WebUIMessageHandler* CoreOptionsHandler::Attach(WebUI* web_ui) {
     92   WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
     93   DCHECK(web_ui_);
     94   registrar_.Init(web_ui_->GetProfile()->GetPrefs());
     95   return result;
     96 }
     97 
     98 void CoreOptionsHandler::Observe(NotificationType type,
     99                                  const NotificationSource& source,
    100                                  const NotificationDetails& details) {
    101   if (type == NotificationType::PREF_CHANGED)
    102     NotifyPrefChanged(Details<std::string>(details).ptr());
    103 }
    104 
    105 void CoreOptionsHandler::RegisterMessages() {
    106   web_ui_->RegisterMessageCallback("coreOptionsInitialize",
    107       NewCallback(this, &CoreOptionsHandler::HandleInitialize));
    108   web_ui_->RegisterMessageCallback("fetchPrefs",
    109       NewCallback(this, &CoreOptionsHandler::HandleFetchPrefs));
    110   web_ui_->RegisterMessageCallback("observePrefs",
    111       NewCallback(this, &CoreOptionsHandler::HandleObservePrefs));
    112   web_ui_->RegisterMessageCallback("setBooleanPref",
    113       NewCallback(this, &CoreOptionsHandler::HandleSetBooleanPref));
    114   web_ui_->RegisterMessageCallback("setIntegerPref",
    115       NewCallback(this, &CoreOptionsHandler::HandleSetIntegerPref));
    116   web_ui_->RegisterMessageCallback("setDoublePref",
    117       NewCallback(this, &CoreOptionsHandler::HandleSetDoublePref));
    118   web_ui_->RegisterMessageCallback("setStringPref",
    119       NewCallback(this, &CoreOptionsHandler::HandleSetStringPref));
    120   web_ui_->RegisterMessageCallback("setListPref",
    121       NewCallback(this, &CoreOptionsHandler::HandleSetListPref));
    122   web_ui_->RegisterMessageCallback("clearPref",
    123       NewCallback(this, &CoreOptionsHandler::HandleClearPref));
    124   web_ui_->RegisterMessageCallback("coreOptionsUserMetricsAction",
    125       NewCallback(this, &CoreOptionsHandler::HandleUserMetricsAction));
    126 }
    127 
    128 void CoreOptionsHandler::HandleInitialize(const ListValue* args) {
    129   DCHECK(handlers_host_);
    130   handlers_host_->InitializeHandlers();
    131 }
    132 
    133 Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
    134   PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
    135 
    136   const PrefService::Preference* pref =
    137       pref_service->FindPreference(pref_name.c_str());
    138 
    139   Value* return_value;
    140   if (pref) {
    141     DictionaryValue* dict = new DictionaryValue;
    142     dict->Set("value", pref->GetValue()->DeepCopy());
    143     dict->SetBoolean("managed", pref->IsManaged());
    144     return_value = dict;
    145   } else {
    146     return_value = Value::CreateNullValue();
    147   }
    148   return return_value;
    149 }
    150 
    151 void CoreOptionsHandler::ObservePref(const std::string& pref_name) {
    152   registrar_.Add(pref_name.c_str(), this);
    153 }
    154 
    155 void CoreOptionsHandler::SetPref(const std::string& pref_name,
    156                                  const Value* value,
    157                                  const std::string& metric) {
    158   PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
    159 
    160   switch (value->GetType()) {
    161     case Value::TYPE_BOOLEAN:
    162     case Value::TYPE_INTEGER:
    163     case Value::TYPE_DOUBLE:
    164     case Value::TYPE_STRING:
    165       pref_service->Set(pref_name.c_str(), *value);
    166       break;
    167 
    168     default:
    169       NOTREACHED();
    170       return;
    171   }
    172 
    173   pref_service->ScheduleSavePersistentPrefs();
    174   ProcessUserMetric(value, metric);
    175 }
    176 
    177 void CoreOptionsHandler::ClearPref(const std::string& pref_name,
    178                                    const std::string& metric) {
    179   PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
    180   pref_service->ClearPref(pref_name.c_str());
    181   pref_service->ScheduleSavePersistentPrefs();
    182 
    183   if (!metric.empty())
    184     UserMetricsRecordAction(UserMetricsAction(metric.c_str()));
    185 }
    186 
    187 void CoreOptionsHandler::ProcessUserMetric(const Value* value,
    188                                            const std::string& metric) {
    189   if (metric.empty())
    190     return;
    191 
    192   std::string metric_string = metric;
    193   if (value->IsType(Value::TYPE_BOOLEAN)) {
    194     bool bool_value;
    195     CHECK(value->GetAsBoolean(&bool_value));
    196     metric_string += bool_value ? "_Enable" : "_Disable";
    197   }
    198 
    199   UserMetricsRecordAction(UserMetricsAction(metric_string.c_str()));
    200 }
    201 
    202 void CoreOptionsHandler::StopObservingPref(const std::string& path) {
    203   registrar_.Remove(path.c_str(), this);
    204 }
    205 
    206 void CoreOptionsHandler::HandleFetchPrefs(const ListValue* args) {
    207   // First param is name of callback function, so, there needs to be at least
    208   // one more element for the actual preference identifier.
    209   DCHECK_GE(static_cast<int>(args->GetSize()), 2);
    210 
    211   // Get callback JS function name.
    212   Value* callback;
    213   if (!args->Get(0, &callback) || !callback->IsType(Value::TYPE_STRING))
    214     return;
    215 
    216   string16 callback_function;
    217   if (!callback->GetAsString(&callback_function))
    218     return;
    219 
    220   // Get the list of name for prefs to build the response dictionary.
    221   DictionaryValue result_value;
    222   Value* list_member;
    223 
    224   for (size_t i = 1; i < args->GetSize(); i++) {
    225     if (!args->Get(i, &list_member))
    226       break;
    227 
    228     if (!list_member->IsType(Value::TYPE_STRING))
    229       continue;
    230 
    231     std::string pref_name;
    232     if (!list_member->GetAsString(&pref_name))
    233       continue;
    234 
    235     result_value.Set(pref_name.c_str(), FetchPref(pref_name));
    236   }
    237   web_ui_->CallJavascriptFunction(UTF16ToASCII(callback_function),
    238                                   result_value);
    239 }
    240 
    241 void CoreOptionsHandler::HandleObservePrefs(const ListValue* args) {
    242   // First param is name is JS callback function name, the rest are pref
    243   // identifiers that we are observing.
    244   DCHECK_GE(static_cast<int>(args->GetSize()), 2);
    245 
    246   // Get preference change callback function name.
    247   string16 callback_func_name;
    248   if (!args->GetString(0, &callback_func_name))
    249     return;
    250 
    251   // Get all other parameters - pref identifiers.
    252   for (size_t i = 1; i < args->GetSize(); i++) {
    253     Value* list_member;
    254     if (!args->Get(i, &list_member))
    255       break;
    256 
    257     // Just ignore bad pref identifiers for now.
    258     std::string pref_name;
    259     if (!list_member->IsType(Value::TYPE_STRING) ||
    260         !list_member->GetAsString(&pref_name))
    261       continue;
    262 
    263     if (pref_callback_map_.find(pref_name) == pref_callback_map_.end())
    264       ObservePref(pref_name);
    265 
    266     pref_callback_map_.insert(
    267         PreferenceCallbackMap::value_type(pref_name,
    268                                           UTF16ToWideHack(callback_func_name)));
    269   }
    270 }
    271 
    272 void CoreOptionsHandler::HandleSetBooleanPref(const ListValue* args) {
    273   HandleSetPref(args, Value::TYPE_BOOLEAN);
    274 }
    275 
    276 void CoreOptionsHandler::HandleSetIntegerPref(const ListValue* args) {
    277   HandleSetPref(args, Value::TYPE_INTEGER);
    278 }
    279 
    280 void CoreOptionsHandler::HandleSetDoublePref(const ListValue* args) {
    281   HandleSetPref(args, Value::TYPE_DOUBLE);
    282 }
    283 
    284 void CoreOptionsHandler::HandleSetStringPref(const ListValue* args) {
    285   HandleSetPref(args, Value::TYPE_STRING);
    286 }
    287 
    288 void CoreOptionsHandler::HandleSetListPref(const ListValue* args) {
    289   HandleSetPref(args, Value::TYPE_LIST);
    290 }
    291 
    292 void CoreOptionsHandler::HandleSetPref(const ListValue* args,
    293                                        Value::ValueType type) {
    294   DCHECK_GT(static_cast<int>(args->GetSize()), 1);
    295 
    296   std::string pref_name;
    297   if (!args->GetString(0, &pref_name))
    298     return;
    299 
    300   Value* value;
    301   if (!args->Get(1, &value))
    302     return;
    303 
    304   scoped_ptr<Value> temp_value;
    305 
    306   // In JS all numbers are doubles.
    307   if (type == Value::TYPE_INTEGER) {
    308     double double_value;
    309     CHECK(value->GetAsDouble(&double_value));
    310     temp_value.reset(Value::CreateIntegerValue(static_cast<int>(double_value)));
    311     value = temp_value.get();
    312 
    313   // In case we have a List pref we got a JSON string.
    314   } else if (type == Value::TYPE_LIST) {
    315     std::string json_string;
    316     CHECK(value->GetAsString(&json_string));
    317     temp_value.reset(
    318         base::JSONReader().JsonToValue(json_string,
    319                                        false,  // no check_root
    320                                        false));  // no trailing comma
    321     value = temp_value.get();
    322   }
    323 
    324   CHECK_EQ(type, value->GetType());
    325 
    326   std::string metric;
    327   if (args->GetSize() > 2)
    328     args->GetString(2, &metric);
    329 
    330   SetPref(pref_name, value, metric);
    331 }
    332 
    333 void CoreOptionsHandler::HandleClearPref(const ListValue* args) {
    334   DCHECK_GT(static_cast<int>(args->GetSize()), 0);
    335 
    336   std::string pref_name;
    337   if (!args->GetString(0, &pref_name))
    338     return;
    339 
    340   std::string metric;
    341   if (args->GetSize() > 1)
    342     args->GetString(1, &metric);
    343 
    344   ClearPref(pref_name, metric);
    345 }
    346 
    347 void CoreOptionsHandler::HandleUserMetricsAction(const ListValue* args) {
    348   std::string metric = UTF16ToUTF8(ExtractStringValue(args));
    349   if (!metric.empty())
    350     UserMetricsRecordAction(UserMetricsAction(metric.c_str()));
    351 }
    352 
    353 void CoreOptionsHandler::UpdateClearPluginLSOData() {
    354   scoped_ptr<Value> enabled(
    355       Value::CreateBooleanValue(clear_plugin_lso_data_enabled_.GetValue()));
    356   web_ui_->CallJavascriptFunction(
    357       "OptionsPage.setClearPluginLSODataEnabled", *enabled);
    358 }
    359 
    360 void CoreOptionsHandler::NotifyPrefChanged(const std::string* pref_name) {
    361   if (*pref_name == prefs::kClearPluginLSODataEnabled) {
    362     // This preference is stored in Local State, not in the user preferences.
    363     UpdateClearPluginLSOData();
    364     return;
    365   }
    366 
    367   PrefService* pref_service = web_ui_->GetProfile()->GetPrefs();
    368   const PrefService::Preference* pref =
    369       pref_service->FindPreference(pref_name->c_str());
    370   if (pref) {
    371     for (PreferenceCallbackMap::const_iterator iter =
    372         pref_callback_map_.find(*pref_name);
    373         iter != pref_callback_map_.end(); ++iter) {
    374       const std::wstring& callback_function = iter->second;
    375       ListValue result_value;
    376       result_value.Append(Value::CreateStringValue(pref_name->c_str()));
    377 
    378       DictionaryValue* dict = new DictionaryValue;
    379       dict->Set("value", pref->GetValue()->DeepCopy());
    380       dict->SetBoolean("managed", pref->IsManaged());
    381       result_value.Append(dict);
    382 
    383       web_ui_->CallJavascriptFunction(WideToASCII(callback_function),
    384                                       result_value);
    385     }
    386   }
    387 }
    388