font_settings_handler.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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,
116                 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
117                 content::NotificationService::AllSources());
118  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
119                 content::NotificationService::AllSources());
120}
121
122void FontSettingsHandler::InitializePage() {
123  DCHECK(web_ui());
124  SetUpStandardFontSample();
125  SetUpSerifFontSample();
126  SetUpSansSerifFontSample();
127  SetUpFixedFontSample();
128  SetUpMinimumFontSample();
129  NotifyAdvancedFontSettingsAvailability();
130}
131
132void FontSettingsHandler::RegisterMessages() {
133  // Perform validation for saved fonts.
134  PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
135  FontSettingsUtilities::ValidateSavedFonts(pref_service);
136
137  // Register for preferences that we need to observe manually.
138  font_encoding_.Init(prefs::kDefaultCharset, pref_service);
139
140  standard_font_.Init(prefs::kWebKitStandardFontFamily,
141                      pref_service,
142                      base::Bind(&FontSettingsHandler::SetUpStandardFontSample,
143                                 base::Unretained(this)));
144  serif_font_.Init(prefs::kWebKitSerifFontFamily,
145                   pref_service,
146                   base::Bind(&FontSettingsHandler::SetUpSerifFontSample,
147                              base::Unretained(this)));
148  sans_serif_font_.Init(
149      prefs::kWebKitSansSerifFontFamily,
150      pref_service,
151      base::Bind(&FontSettingsHandler::SetUpSansSerifFontSample,
152                 base::Unretained(this)));
153
154  base::Closure callback = base::Bind(
155      &FontSettingsHandler::SetUpFixedFontSample, base::Unretained(this));
156
157  fixed_font_.Init(prefs::kWebKitFixedFontFamily, pref_service, callback);
158  default_fixed_font_size_.Init(prefs::kWebKitDefaultFixedFontSize,
159                                pref_service, callback);
160  default_font_size_.Init(
161      prefs::kWebKitDefaultFontSize,
162      pref_service,
163      base::Bind(&FontSettingsHandler::OnWebKitDefaultFontSizeChanged,
164                 base::Unretained(this)));
165  minimum_font_size_.Init(
166      prefs::kWebKitMinimumFontSize,
167      pref_service,
168      base::Bind(&FontSettingsHandler::SetUpMinimumFontSample,
169                 base::Unretained(this)));
170
171  web_ui()->RegisterMessageCallback("fetchFontsData",
172      base::Bind(&FontSettingsHandler::HandleFetchFontsData,
173                 base::Unretained(this)));
174  web_ui()->RegisterMessageCallback("openAdvancedFontSettingsOptions",
175      base::Bind(&FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions,
176                 base::Unretained(this)));
177}
178
179void FontSettingsHandler::Observe(int type,
180                                  const content::NotificationSource& source,
181                                  const content::NotificationDetails& details) {
182  DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED ||
183         type == chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED);
184  NotifyAdvancedFontSettingsAvailability();
185}
186
187void FontSettingsHandler::HandleFetchFontsData(const base::ListValue* args) {
188  content::GetFontListAsync(
189      base::Bind(&FontSettingsHandler::FontsListHasLoaded,
190                 base::Unretained(this)));
191}
192
193void FontSettingsHandler::FontsListHasLoaded(
194    scoped_ptr<base::ListValue> list) {
195  // Selects the directionality for the fonts in the given list.
196  for (size_t i = 0; i < list->GetSize(); i++) {
197    base::ListValue* font;
198    bool has_font = list->GetList(i, &font);
199    DCHECK(has_font);
200    base::string16 value;
201    bool has_value = font->GetString(1, &value);
202    DCHECK(has_value);
203    bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(value);
204    font->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
205  }
206
207  base::ListValue encoding_list;
208  const std::vector<CharacterEncoding::EncodingInfo>* encodings;
209  PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
210  encodings = CharacterEncoding::GetCurrentDisplayEncodings(
211      g_browser_process->GetApplicationLocale(),
212      pref_service->GetString(prefs::kStaticEncodings),
213      pref_service->GetString(prefs::kRecentlySelectedEncoding));
214  DCHECK(encodings);
215  DCHECK(!encodings->empty());
216
217  std::vector<CharacterEncoding::EncodingInfo>::const_iterator it;
218  for (it = encodings->begin(); it != encodings->end(); ++it) {
219    base::ListValue* option = new base::ListValue();
220    if (it->encoding_id) {
221      int cmd_id = it->encoding_id;
222      std::string encoding =
223      CharacterEncoding::GetCanonicalEncodingNameByCommandId(cmd_id);
224      base::string16 name = it->encoding_display_name;
225      bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(name);
226      option->Append(new base::StringValue(encoding));
227      option->Append(new base::StringValue(name));
228      option->Append(new base::StringValue(has_rtl_chars ? "rtl" : "ltr"));
229    } else {
230      // Add empty name/value to indicate a separator item.
231      option->Append(new base::StringValue(std::string()));
232      option->Append(new base::StringValue(std::string()));
233    }
234    encoding_list.Append(option);
235  }
236
237  base::ListValue selected_values;
238  selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
239      standard_font_.GetValue())));
240  selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
241      serif_font_.GetValue())));
242  selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
243      sans_serif_font_.GetValue())));
244  selected_values.Append(new base::StringValue(MaybeGetLocalizedFontName(
245      fixed_font_.GetValue())));
246  selected_values.Append(new base::StringValue(font_encoding_.GetValue()));
247
248  web_ui()->CallJavascriptFunction("FontSettings.setFontsData",
249                                   *list.get(), encoding_list,
250                                   selected_values);
251}
252
253void FontSettingsHandler::SetUpStandardFontSample() {
254  base::StringValue font_value(standard_font_.GetValue());
255  base::FundamentalValue size_value(default_font_size_.GetValue());
256  web_ui()->CallJavascriptFunction(
257      "FontSettings.setUpStandardFontSample", font_value, size_value);
258}
259
260void FontSettingsHandler::SetUpSerifFontSample() {
261  base::StringValue font_value(serif_font_.GetValue());
262  base::FundamentalValue size_value(default_font_size_.GetValue());
263  web_ui()->CallJavascriptFunction(
264      "FontSettings.setUpSerifFontSample", font_value, size_value);
265}
266
267void FontSettingsHandler::SetUpSansSerifFontSample() {
268  base::StringValue font_value(sans_serif_font_.GetValue());
269  base::FundamentalValue size_value(default_font_size_.GetValue());
270  web_ui()->CallJavascriptFunction(
271      "FontSettings.setUpSansSerifFontSample", font_value, size_value);
272}
273
274void FontSettingsHandler::SetUpFixedFontSample() {
275  base::StringValue font_value(fixed_font_.GetValue());
276  base::FundamentalValue size_value(default_fixed_font_size_.GetValue());
277  web_ui()->CallJavascriptFunction(
278      "FontSettings.setUpFixedFontSample", font_value, size_value);
279}
280
281void FontSettingsHandler::SetUpMinimumFontSample() {
282  base::FundamentalValue size_value(minimum_font_size_.GetValue());
283  web_ui()->CallJavascriptFunction("FontSettings.setUpMinimumFontSample",
284                                   size_value);
285}
286
287const extensions::Extension*
288FontSettingsHandler::GetAdvancedFontSettingsExtension() {
289  Profile* profile = Profile::FromWebUI(web_ui());
290  ExtensionService* service =
291      extensions::ExtensionSystem::Get(profile)->extension_service();
292  if (!service->IsExtensionEnabled(kAdvancedFontSettingsExtensionId))
293    return NULL;
294  return service->GetInstalledExtension(kAdvancedFontSettingsExtensionId);
295}
296
297void FontSettingsHandler::NotifyAdvancedFontSettingsAvailability() {
298  web_ui()->CallJavascriptFunction(
299      "FontSettings.notifyAdvancedFontSettingsAvailability",
300      base::FundamentalValue(GetAdvancedFontSettingsExtension() != NULL));
301}
302
303void FontSettingsHandler::HandleOpenAdvancedFontSettingsOptions(
304    const base::ListValue* args) {
305  const extensions::Extension* extension = GetAdvancedFontSettingsExtension();
306  if (!extension)
307    return;
308  extensions::ExtensionTabUtil::OpenOptionsPage(extension,
309      chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
310}
311
312void FontSettingsHandler::OnWebKitDefaultFontSizeChanged() {
313  SetUpStandardFontSample();
314  SetUpSerifFontSample();
315  SetUpSansSerifFontSample();
316}
317
318}  // namespace options
319