Home | History | Annotate | Download | only in options
      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/options/font_settings_handler.h"
      6 
      7 #include <string>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/i18n/rtl.h"
     13 #include "base/prefs/pref_service.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/strings/string_util.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "base/values.h"
     18 #include "chrome/browser/browser_process.h"
     19 #include "chrome/browser/character_encoding.h"
     20 #include "chrome/browser/chrome_notification_types.h"
     21 #include "chrome/browser/extensions/extension_service.h"
     22 #include "chrome/browser/extensions/extension_tab_util.h"
     23 #include "chrome/browser/profiles/profile.h"
     24 #include "chrome/browser/ui/browser_finder.h"
     25 #include "chrome/browser/ui/webui/options/font_settings_utils.h"
     26 #include "chrome/common/extensions/extension_constants.h"
     27 #include "chrome/common/pref_names.h"
     28 #include "content/public/browser/font_list_async.h"
     29 #include "content/public/browser/notification_details.h"
     30 #include "content/public/browser/notification_service.h"
     31 #include "content/public/browser/web_ui.h"
     32 #include "extensions/browser/extension_system.h"
     33 #include "extensions/common/extension.h"
     34 #include "grit/chromium_strings.h"
     35 #include "grit/generated_resources.h"
     36 #include "ui/base/l10n/l10n_util.h"
     37 #include "url/gurl.h"
     38 
     39 #if defined(OS_WIN)
     40 #include "ui/gfx/font.h"
     41 #include "ui/gfx/platform_font_win.h"
     42 #endif
     43 
     44 namespace {
     45 
     46 // Returns the localized name of a font so that settings can find it within the
     47 // list of system fonts. On Windows, the list of system fonts has names only
     48 // for the system locale, but the pref value may be in the English name.
     49 std::string MaybeGetLocalizedFontName(const std::string& font_name) {
     50 #if defined(OS_WIN)
     51   gfx::Font font(font_name, 12);  // dummy font size
     52   return static_cast<gfx::PlatformFontWin*>(font.platform_font())->
     53       GetLocalizedFontName();
     54 #else
     55   return font_name;
     56 #endif
     57 }
     58 
     59 const char kAdvancedFontSettingsExtensionId[] =
     60     "caclkomlalccbpcdllchkeecicepbmbm";
     61 
     62 }  // namespace
     63 
     64 
     65 namespace options {
     66 
     67 FontSettingsHandler::FontSettingsHandler() {
     68 }
     69 
     70 FontSettingsHandler::~FontSettingsHandler() {
     71 }
     72 
     73 void FontSettingsHandler::GetLocalizedValues(
     74     base::DictionaryValue* localized_strings) {
     75   DCHECK(localized_strings);
     76 
     77   static OptionsStringResource resources[] = {
     78     { "fontSettingsStandard",
     79       IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_STANDARD_LABEL },
     80     { "fontSettingsSerif",
     81       IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SERIF_LABEL },
     82     { "fontSettingsSansSerif",
     83       IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_SANS_SERIF_LABEL },
     84     { "fontSettingsFixedWidth",
     85       IDS_FONT_LANGUAGE_SETTING_FONT_SELECTOR_FIXED_WIDTH_LABEL },
     86     { "fontSettingsMinimumSize",
     87       IDS_FONT_LANGUAGE_SETTING_MINIMUM_FONT_SIZE_TITLE },
     88     { "fontSettingsEncoding",
     89       IDS_FONT_LANGUAGE_SETTING_FONT_SUB_DIALOG_ENCODING_TITLE },
     90     { "fontSettingsSizeTiny",
     91       IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_TINY },
     92     { "fontSettingsSizeHuge",
     93       IDS_FONT_LANGUAGE_SETTING_FONT_SIZE_HUGE },
     94     { "fontSettingsLoremIpsum",
     95       IDS_FONT_LANGUAGE_SETTING_LOREM_IPSUM },
     96     { "advancedFontSettingsOptions",
     97       IDS_FONT_LANGUAGE_SETTING_ADVANCED_FONT_SETTINGS_OPTIONS }
     98   };
     99 
    100   RegisterStrings(localized_strings, resources, arraysize(resources));
    101   RegisterTitle(localized_strings, "fontSettingsPage",
    102                 IDS_FONT_LANGUAGE_SETTING_FONT_TAB_TITLE);
    103   localized_strings->SetString("fontSettingsPlaceholder",
    104       l10n_util::GetStringUTF16(
    105           IDS_FONT_LANGUAGE_SETTING_PLACEHOLDER));
    106 
    107   GURL install_url(extension_urls::GetWebstoreItemDetailURLPrefix());
    108   localized_strings->SetString("advancedFontSettingsInstall",
    109       l10n_util::GetStringFUTF16(
    110           IDS_FONT_LANGUAGE_SETTING_ADVANCED_FONT_SETTINGS_INSTALL,
    111           base::UTF8ToUTF16(
    112               install_url.Resolve(kAdvancedFontSettingsExtensionId).spec())));
    113 }
    114 
    115 void FontSettingsHandler::InitializeHandler() {
    116   registrar_.Add(this,
    117                  chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
    118                  content::NotificationService::AllSources());
    119   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
    120                  content::NotificationService::AllSources());
    121 }
    122 
    123 void FontSettingsHandler::InitializePage() {
    124   DCHECK(web_ui());
    125   SetUpStandardFontSample();
    126   SetUpSerifFontSample();
    127   SetUpSansSerifFontSample();
    128   SetUpFixedFontSample();
    129   SetUpMinimumFontSample();
    130   NotifyAdvancedFontSettingsAvailability();
    131 }
    132 
    133 void FontSettingsHandler::RegisterMessages() {
    134   // Perform validation for saved fonts.
    135   PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
    136   FontSettingsUtilities::ValidateSavedFonts(pref_service);
    137 
    138   // Register for preferences that we need to observe manually.
    139   font_encoding_.Init(prefs::kDefaultCharset, pref_service);
    140 
    141   standard_font_.Init(prefs::kWebKitStandardFontFamily,
    142                       pref_service,
    143                       base::Bind(&FontSettingsHandler::SetUpStandardFontSample,
    144                                  base::Unretained(this)));
    145   serif_font_.Init(prefs::kWebKitSerifFontFamily,
    146                    pref_service,
    147                    base::Bind(&FontSettingsHandler::SetUpSerifFontSample,
    148                               base::Unretained(this)));
    149   sans_serif_font_.Init(
    150       prefs::kWebKitSansSerifFontFamily,
    151       pref_service,
    152       base::Bind(&FontSettingsHandler::SetUpSansSerifFontSample,
    153                  base::Unretained(this)));
    154 
    155   base::Closure callback = base::Bind(
    156       &FontSettingsHandler::SetUpFixedFontSample, base::Unretained(this));
    157 
    158   fixed_font_.Init(prefs::kWebKitFixedFontFamily, pref_service, callback);
    159   default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize,
    160                                 pref_service, callback);
    161   default_font_size_.Init(
    162       prefs::kWebKitDefaultFontSize,
    163       pref_service,
    164       base::Bind(&FontSettingsHandler::OnWebKitDefaultFontSizeChanged,
    165                  base::Unretained(this)));
    166   minimum_font_size_.Init(
    167       prefs::kWebKitMinimumFontSize,
    168       pref_service,
    169       base::Bind(&FontSettingsHandler::SetUpMinimumFontSample,
    170                  base::Unretained(this)));
    171 
    172   web_ui()->RegisterMessageCallback("fetchFontsData",
    173       base::Bind(&FontSettingsHandler::HandleFetchFontsData,
    174                  base::Unretained(this)));
    175   web_ui()->RegisterMessageCallback("openAdvancedFontSettingsOptions",
    176       base::Bind(&FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions,
    177                  base::Unretained(this)));
    178 }
    179 
    180 void FontSettingsHandler::Observe(int type,
    181                                   const content::NotificationSource& source,
    182                                   const content::NotificationDetails& details) {
    183   DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED ||
    184          type == chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED);
    185   NotifyAdvancedFontSettingsAvailability();
    186 }
    187 
    188 void FontSettingsHandler::HandleFetchFontsData(const base::ListValue* args) {
    189   content::GetFontListAsync(
    190       base::Bind(&FontSettingsHandler::FontsListHasLoaded,
    191                  base::Unretained(this)));
    192 }
    193 
    194 void FontSettingsHandler::FontsListHasLoaded(
    195     scoped_ptr<base::ListValue> list) {
    196   // Selects the directionality for the fonts in the given list.
    197   for (size_t i = 0; i < list->GetSize(); i++) {
    198     base::ListValue* font;
    199     bool has_font = list->GetList(i, &font);
    200     DCHECK(has_font);
    201     base::string16 value;
    202     bool has_value = font->GetString(1, &value);
    203     DCHECK(has_value);
    204     bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(value);
    205     font->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
    206   }
    207 
    208   base::ListValue encoding_list;
    209   const std::vector<CharacterEncoding::EncodingInfo>* encodings;
    210   PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
    211   encodings = CharacterEncoding::GetCurrentDisplayEncodings(
    212       g_browser_process->GetApplicationLocale(),
    213       pref_service->GetString(prefs::kStaticEncodings),
    214       pref_service->GetString(prefs::kRecentlySelectedEncoding));
    215   DCHECK(encodings);
    216   DCHECK(!encodings->empty());
    217 
    218   std::vector<CharacterEncoding::EncodingInfo>::const_iterator it;
    219   for (it = encodings->begin(); it != encodings->end(); ++it) {
    220     base::ListValue* option = new base::ListValue();
    221     if (it->encoding_id) {
    222       int cmd_id = it->encoding_id;
    223       std::string encoding =
    224       CharacterEncoding::GetCanonicalEncodingNameByCommandId(cmd_id);
    225       base::string16 name = it->encoding_display_name;
    226       bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(name);
    227       option->Append(new base::StringValue(encoding));
    228       option->Append(new base::StringValue(name));
    229       option->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
    230     } else {
    231       // Add empty name/value to indicate a separator item.
    232       option->Append(new base::StringValue(std::string()));
    233       option->Append(new base::StringValue(std::string()));
    234     }
    235     encoding_list.Append(option);
    236   }
    237 
    238   base::ListValue selected_values;
    239   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    240       standard_font_.GetValue())));
    241   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    242       serif_font_.GetValue())));
    243   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    244       sans_serif_font_.GetValue())));
    245   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    246       fixed_font_.GetValue())));
    247   selected_values.Append(new base::StringValue(font_encoding_.GetValue()));
    248 
    249   web_ui()->CallJavascriptFunction("FontSettings.setFontsData",
    250                                    *list.get(), encoding_list,
    251                                    selected_values);
    252 }
    253 
    254 void FontSettingsHandler::SetUpStandardFontSample() {
    255   base::StringValue font_value(standard_font_.GetValue());
    256   base::FundamentalValue size_value(default_font_size_.GetValue());
    257   web_ui()->CallJavascriptFunction(
    258       "FontSettings.setUpStandardFontSample", font_value, size_value);
    259 }
    260 
    261 void FontSettingsHandler::SetUpSerifFontSample() {
    262   base::StringValue font_value(serif_font_.GetValue());
    263   base::FundamentalValue size_value(default_font_size_.GetValue());
    264   web_ui()->CallJavascriptFunction(
    265       "FontSettings.setUpSerifFontSample", font_value, size_value);
    266 }
    267 
    268 void FontSettingsHandler::SetUpSansSerifFontSample() {
    269   base::StringValue font_value(sans_serif_font_.GetValue());
    270   base::FundamentalValue size_value(default_font_size_.GetValue());
    271   web_ui()->CallJavascriptFunction(
    272       "FontSettings.setUpSansSerifFontSample", font_value, size_value);
    273 }
    274 
    275 void FontSettingsHandler::SetUpFixedFontSample() {
    276   base::StringValue font_value(fixed_font_.GetValue());
    277   base::FundamentalValue size_value(default_fixed_font_size_.GetValue());
    278   web_ui()->CallJavascriptFunction(
    279       "FontSettings.setUpFixedFontSample", font_value, size_value);
    280 }
    281 
    282 void FontSettingsHandler::SetUpMinimumFontSample() {
    283   base::FundamentalValue size_value(minimum_font_size_.GetValue());
    284   web_ui()->CallJavascriptFunction("FontSettings.setUpMinimumFontSample",
    285                                    size_value);
    286 }
    287 
    288 const extensions::Extension*
    289 FontSettingsHandler::GetAdvancedFontSettingsExtension() {
    290   Profile* profile = Profile::FromWebUI(web_ui());
    291   ExtensionService* service =
    292       extensions::ExtensionSystem::Get(profile)->extension_service();
    293   if (!service->IsExtensionEnabled(kAdvancedFontSettingsExtensionId))
    294     return NULL;
    295   return service->GetInstalledExtension(kAdvancedFontSettingsExtensionId);
    296 }
    297 
    298 void FontSettingsHandler::NotifyAdvancedFontSettingsAvailability() {
    299   web_ui()->CallJavascriptFunction(
    300       "FontSettings.notifyAdvancedFontSettingsAvailability",
    301       base::FundamentalValue(GetAdvancedFontSettingsExtension() != NULL));
    302 }
    303 
    304 void FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions(
    305     const base::ListValue* args) {
    306   const extensions::Extension* extension = GetAdvancedFontSettingsExtension();
    307   if (!extension)
    308     return;
    309   extensions::ExtensionTabUtil::OpenOptionsPage(extension,
    310       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
    311 }
    312 
    313 void FontSettingsHandler::OnWebKitDefaultFontSizeChanged() {
    314   SetUpStandardFontSample();
    315   SetUpSerifFontSample();
    316   SetUpSansSerifFontSample();
    317 }
    318 
    319 }  // namespace options
    320