font_settings_handler.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
44namespace {
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.
49std::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
59const char kAdvancedFontSettingsExtensionId[] =
60    "caclkomlalccbpcdllchkeecicepbmbm";
61
62}  // namespace
63
64
65namespace options {
66
67FontSettingsHandler::FontSettingsHandler() {
68}
69
70FontSettingsHandler::~FontSettingsHandler() {
71}
72
73void 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
115void 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
123void FontSettingsHandler::InitializePage() {
124  DCHECK(web_ui());
125  SetUpStandardFontSample();
126  SetUpSerifFontSample();
127  SetUpSansSerifFontSample();
128  SetUpFixedFontSample();
129  SetUpMinimumFontSample();
130  NotifyAdvancedFontSettingsAvailability();
131}
132
133void 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
180void 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
188void FontSettingsHandler::HandleFetchFontsData(const base::ListValue* args) {
189  content::GetFontListAsync(
190      base::Bind(&FontSettingsHandler::FontsListHasLoaded,
191                 base::Unretained(this)));
192}
193
194void 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
254void 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
261void 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
268void 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
275void 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
282void FontSettingsHandler::SetUpMinimumFontSample() {
283  base::FundamentalValue size_value(minimum_font_size_.GetValue());
284  web_ui()->CallJavascriptFunction("FontSettings.setUpMinimumFontSample",
285                                   size_value);
286}
287
288const extensions::Extension*
289FontSettingsHandler::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
298void FontSettingsHandler::NotifyAdvancedFontSettingsAvailability() {
299  web_ui()->CallJavascriptFunction(
300      "FontSettings.notifyAdvancedFontSettingsAvailability",
301      base::FundamentalValue(GetAdvancedFontSettingsExtension() != NULL));
302}
303
304void 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
313void FontSettingsHandler::OnWebKitDefaultFontSizeChanged() {
314  SetUpStandardFontSample();
315  SetUpSerifFontSample();
316  SetUpSansSerifFontSample();
317}
318
319}  // namespace options
320