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