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