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/extensions/extension_service.h"
     21 #include "chrome/browser/extensions/extension_tab_util.h"
     22 #include "chrome/browser/profiles/profile.h"
     23 #include "chrome/browser/ui/browser_finder.h"
     24 #include "chrome/browser/ui/webui/options/font_settings_utils.h"
     25 #include "chrome/common/pref_names.h"
     26 #include "chrome/grit/generated_resources.h"
     27 #include "content/public/browser/font_list_async.h"
     28 #include "content/public/browser/notification_details.h"
     29 #include "content/public/browser/notification_service.h"
     30 #include "content/public/browser/web_ui.h"
     31 #include "extensions/browser/extension_registry.h"
     32 #include "extensions/browser/extension_system.h"
     33 #include "extensions/common/extension.h"
     34 #include "extensions/common/extension_urls.h"
     35 #include "ui/base/l10n/l10n_util.h"
     36 #include "url/gurl.h"
     37 
     38 #if defined(OS_WIN)
     39 #include "ui/gfx/font.h"
     40 #include "ui/gfx/platform_font_win.h"
     41 #endif
     42 
     43 namespace {
     44 
     45 // Returns the localized name of a font so that settings can find it within the
     46 // list of system fonts. On Windows, the list of system fonts has names only
     47 // for the system locale, but the pref value may be in the English name.
     48 std::string MaybeGetLocalizedFontName(const std::string& font_name) {
     49 #if defined(OS_WIN)
     50   gfx::Font font(font_name, 12);  // dummy font size
     51   return static_cast<gfx::PlatformFontWin*>(font.platform_font())->
     52       GetLocalizedFontName();
     53 #else
     54   return font_name;
     55 #endif
     56 }
     57 
     58 const char kAdvancedFontSettingsExtensionId[] =
     59     "caclkomlalccbpcdllchkeecicepbmbm";
     60 
     61 }  // namespace
     62 
     63 
     64 namespace options {
     65 
     66 FontSettingsHandler::FontSettingsHandler()
     67     : extension_registry_observer_(this) {
     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   Profile* profile = Profile::FromWebUI(web_ui());
    117   extension_registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
    118 }
    119 
    120 void FontSettingsHandler::InitializePage() {
    121   DCHECK(web_ui());
    122   SetUpStandardFontSample();
    123   SetUpSerifFontSample();
    124   SetUpSansSerifFontSample();
    125   SetUpFixedFontSample();
    126   SetUpMinimumFontSample();
    127   NotifyAdvancedFontSettingsAvailability();
    128 }
    129 
    130 void FontSettingsHandler::RegisterMessages() {
    131   // Perform validation for saved fonts.
    132   PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
    133   FontSettingsUtilities::ValidateSavedFonts(pref_service);
    134 
    135   // Register for preferences that we need to observe manually.
    136   font_encoding_.Init(prefs::kDefaultCharset, pref_service);
    137 
    138   standard_font_.Init(prefs::kWebKitStandardFontFamily,
    139                       pref_service,
    140                       base::Bind(&FontSettingsHandler::SetUpStandardFontSample,
    141                                  base::Unretained(this)));
    142   serif_font_.Init(prefs::kWebKitSerifFontFamily,
    143                    pref_service,
    144                    base::Bind(&FontSettingsHandler::SetUpSerifFontSample,
    145                               base::Unretained(this)));
    146   sans_serif_font_.Init(
    147       prefs::kWebKitSansSerifFontFamily,
    148       pref_service,
    149       base::Bind(&FontSettingsHandler::SetUpSansSerifFontSample,
    150                  base::Unretained(this)));
    151 
    152   base::Closure callback = base::Bind(
    153       &FontSettingsHandler::SetUpFixedFontSample, base::Unretained(this));
    154 
    155   fixed_font_.Init(prefs::kWebKitFixedFontFamily, pref_service, callback);
    156   default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize,
    157                                 pref_service, callback);
    158   default_font_size_.Init(
    159       prefs::kWebKitDefaultFontSize,
    160       pref_service,
    161       base::Bind(&FontSettingsHandler::OnWebKitDefaultFontSizeChanged,
    162                  base::Unretained(this)));
    163   minimum_font_size_.Init(
    164       prefs::kWebKitMinimumFontSize,
    165       pref_service,
    166       base::Bind(&FontSettingsHandler::SetUpMinimumFontSample,
    167                  base::Unretained(this)));
    168 
    169   web_ui()->RegisterMessageCallback("fetchFontsData",
    170       base::Bind(&FontSettingsHandler::HandleFetchFontsData,
    171                  base::Unretained(this)));
    172   web_ui()->RegisterMessageCallback("openAdvancedFontSettingsOptions",
    173       base::Bind(&FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions,
    174                  base::Unretained(this)));
    175 }
    176 
    177 void FontSettingsHandler::OnExtensionLoaded(
    178     content::BrowserContext* browser_context,
    179     const extensions::Extension* extension) {
    180   NotifyAdvancedFontSettingsAvailability();
    181 }
    182 
    183 void FontSettingsHandler::OnExtensionUnloaded(
    184     content::BrowserContext* browser_context,
    185     const extensions::Extension* extension,
    186     extensions::UnloadedExtensionInfo::Reason reason) {
    187   NotifyAdvancedFontSettingsAvailability();
    188 }
    189 
    190 void FontSettingsHandler::HandleFetchFontsData(const base::ListValue* args) {
    191   content::GetFontListAsync(
    192       base::Bind(&FontSettingsHandler::FontsListHasLoaded,
    193                  base::Unretained(this)));
    194 }
    195 
    196 void FontSettingsHandler::FontsListHasLoaded(
    197     scoped_ptr<base::ListValue> list) {
    198   // Selects the directionality for the fonts in the given list.
    199   for (size_t i = 0; i < list->GetSize(); i++) {
    200     base::ListValue* font;
    201     bool has_font = list->GetList(i, &font);
    202     DCHECK(has_font);
    203     base::string16 value;
    204     bool has_value = font->GetString(1, &value);
    205     DCHECK(has_value);
    206     bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(value);
    207     font->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
    208   }
    209 
    210   base::ListValue encoding_list;
    211   const std::vector<CharacterEncoding::EncodingInfo>* encodings;
    212   PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
    213   encodings = CharacterEncoding::GetCurrentDisplayEncodings(
    214       g_browser_process->GetApplicationLocale(),
    215       pref_service->GetString(prefs::kStaticEncodings),
    216       pref_service->GetString(prefs::kRecentlySelectedEncoding));
    217   DCHECK(encodings);
    218   DCHECK(!encodings->empty());
    219 
    220   std::vector<CharacterEncoding::EncodingInfo>::const_iterator it;
    221   for (it = encodings->begin(); it != encodings->end(); ++it) {
    222     base::ListValue* option = new base::ListValue();
    223     if (it->encoding_id) {
    224       int cmd_id = it->encoding_id;
    225       std::string encoding =
    226       CharacterEncoding::GetCanonicalEncodingNameByCommandId(cmd_id);
    227       base::string16 name = it->encoding_display_name;
    228       bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(name);
    229       option->Append(new base::StringValue(encoding));
    230       option->Append(new base::StringValue(name));
    231       option->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
    232     } else {
    233       // Add empty name/value to indicate a separator item.
    234       option->Append(new base::StringValue(std::string()));
    235       option->Append(new base::StringValue(std::string()));
    236     }
    237     encoding_list.Append(option);
    238   }
    239 
    240   base::ListValue selected_values;
    241   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    242       standard_font_.GetValue())));
    243   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    244       serif_font_.GetValue())));
    245   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    246       sans_serif_font_.GetValue())));
    247   selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
    248       fixed_font_.GetValue())));
    249   selected_values.Append(new base::StringValue(font_encoding_.GetValue()));
    250 
    251   web_ui()->CallJavascriptFunction("FontSettings.setFontsData",
    252                                    *list.get(), encoding_list,
    253                                    selected_values);
    254 }
    255 
    256 void FontSettingsHandler::SetUpStandardFontSample() {
    257   base::StringValue font_value(standard_font_.GetValue());
    258   base::FundamentalValue size_value(default_font_size_.GetValue());
    259   web_ui()->CallJavascriptFunction(
    260       "FontSettings.setUpStandardFontSample", font_value, size_value);
    261 }
    262 
    263 void FontSettingsHandler::SetUpSerifFontSample() {
    264   base::StringValue font_value(serif_font_.GetValue());
    265   base::FundamentalValue size_value(default_font_size_.GetValue());
    266   web_ui()->CallJavascriptFunction(
    267       "FontSettings.setUpSerifFontSample", font_value, size_value);
    268 }
    269 
    270 void FontSettingsHandler::SetUpSansSerifFontSample() {
    271   base::StringValue font_value(sans_serif_font_.GetValue());
    272   base::FundamentalValue size_value(default_font_size_.GetValue());
    273   web_ui()->CallJavascriptFunction(
    274       "FontSettings.setUpSansSerifFontSample", font_value, size_value);
    275 }
    276 
    277 void FontSettingsHandler::SetUpFixedFontSample() {
    278   base::StringValue font_value(fixed_font_.GetValue());
    279   base::FundamentalValue size_value(default_fixed_font_size_.GetValue());
    280   web_ui()->CallJavascriptFunction(
    281       "FontSettings.setUpFixedFontSample", font_value, size_value);
    282 }
    283 
    284 void FontSettingsHandler::SetUpMinimumFontSample() {
    285   base::FundamentalValue size_value(minimum_font_size_.GetValue());
    286   web_ui()->CallJavascriptFunction("FontSettings.setUpMinimumFontSample",
    287                                    size_value);
    288 }
    289 
    290 const extensions::Extension*
    291 FontSettingsHandler::GetAdvancedFontSettingsExtension() {
    292   Profile* profile = Profile::FromWebUI(web_ui());
    293   ExtensionService* service =
    294       extensions::ExtensionSystem::Get(profile)->extension_service();
    295   if (!service->IsExtensionEnabled(kAdvancedFontSettingsExtensionId))
    296     return NULL;
    297   return service->GetInstalledExtension(kAdvancedFontSettingsExtensionId);
    298 }
    299 
    300 void FontSettingsHandler::NotifyAdvancedFontSettingsAvailability() {
    301   web_ui()->CallJavascriptFunction(
    302       "FontSettings.notifyAdvancedFontSettingsAvailability",
    303       base::FundamentalValue(GetAdvancedFontSettingsExtension() != NULL));
    304 }
    305 
    306 void FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions(
    307     const base::ListValue* args) {
    308   const extensions::Extension* extension = GetAdvancedFontSettingsExtension();
    309   if (!extension)
    310     return;
    311   extensions::ExtensionTabUtil::OpenOptionsPage(extension,
    312       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
    313 }
    314 
    315 void FontSettingsHandler::OnWebKitDefaultFontSizeChanged() {
    316   SetUpStandardFontSample();
    317   SetUpSerifFontSample();
    318   SetUpSansSerifFontSample();
    319 }
    320 
    321 }  // namespace options
    322