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/prefs/prefs_tab_helper.h" 6 7 #include <string> 8 9 #include "base/prefs/overlay_user_pref_store.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/renderer_preferences_util.h" 18 #include "chrome/common/pref_font_webkit_names.h" 19 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names_util.h" 21 #include "components/user_prefs/pref_registry_syncable.h" 22 #include "content/public/browser/notification_details.h" 23 #include "content/public/browser/notification_service.h" 24 #include "content/public/browser/render_view_host.h" 25 #include "content/public/browser/web_contents.h" 26 #include "grit/locale_settings.h" 27 #include "grit/platform_locale_settings.h" 28 #include "third_party/icu/source/common/unicode/uchar.h" 29 #include "third_party/icu/source/common/unicode/uscript.h" 30 #include "webkit/common/webpreferences.h" 31 32 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(ENABLE_THEMES) 33 #include "chrome/browser/themes/theme_service.h" 34 #include "chrome/browser/themes/theme_service_factory.h" 35 #endif 36 37 using content::WebContents; 38 39 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PrefsTabHelper); 40 41 namespace { 42 43 // The list of prefs we want to observe. 44 const char* kPrefsToObserve[] = { 45 prefs::kDefaultCharset, 46 prefs::kWebKitAllowDisplayingInsecureContent, 47 prefs::kWebKitAllowRunningInsecureContent, 48 prefs::kWebKitDefaultFixedFontSize, 49 prefs::kWebKitDefaultFontSize, 50 #if defined(OS_ANDROID) 51 prefs::kWebKitFontScaleFactor, 52 prefs::kWebKitForceEnableZoom, 53 prefs::kWebKitPasswordEchoEnabled, 54 #endif 55 prefs::kWebKitJavascriptEnabled, 56 prefs::kWebKitJavaEnabled, 57 prefs::kWebKitLoadsImagesAutomatically, 58 prefs::kWebKitMinimumFontSize, 59 prefs::kWebKitMinimumLogicalFontSize, 60 prefs::kWebKitPluginsEnabled, 61 prefs::kWebkitTabsToLinks, 62 prefs::kWebKitUsesUniversalDetector 63 }; 64 65 const int kPrefsToObserveLength = arraysize(kPrefsToObserve); 66 67 #if !defined(OS_ANDROID) 68 // Registers a preference under the path |pref_name| for each script used for 69 // per-script font prefs. 70 // For example, for WEBKIT_WEBPREFS_FONTS_SERIF ("fonts.serif"): 71 // "fonts.serif.Arab", "fonts.serif.Hang", etc. are registered. 72 // |fonts_with_defaults| contains all |pref_names| already registered since they 73 // have a specified default value. 74 // On Android there are no default values for these properties and there is no 75 // way to set them (because extensions are not supported so the Font Settings 76 // API cannot be used), so we can avoid registering them altogether. 77 void RegisterFontFamilyPrefs(user_prefs::PrefRegistrySyncable* registry, 78 const std::set<std::string>& fonts_with_defaults) { 79 80 // Expand the font concatenated with script name so this stays at RO memory 81 // rather than allocated in heap. 82 static const char* const kFontFamilyMap[] = { 83 #define EXPAND_SCRIPT_FONT(map_name, script_name) map_name "." script_name, 84 85 #include "chrome/common/pref_font_script_names-inl.h" 86 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_CURSIVE) 87 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_FANTASY) 88 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_FIXED) 89 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_PICTOGRAPH) 90 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SANSERIF) 91 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SERIF) 92 ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_STANDARD) 93 94 #undef EXPAND_SCRIPT_FONT 95 }; 96 97 for (size_t i = 0; i < arraysize(kFontFamilyMap); ++i) { 98 const char* pref_name = kFontFamilyMap[i]; 99 if (fonts_with_defaults.find(pref_name) == fonts_with_defaults.end()) { 100 // We haven't already set a default value for this font preference, so set 101 // an empty string as the default. 102 registry->RegisterStringPref( 103 pref_name, 104 std::string(), 105 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 106 } 107 } 108 } 109 110 // Registers |obs| to observe per-script font prefs under the path |map_name|. 111 // On android, there's no exposed way to change these prefs, so we can save 112 // ~715KB of heap and some startup cycles by avoiding observing these prefs 113 // since they will never change. 114 void RegisterFontFamilyMapObserver( 115 PrefChangeRegistrar* registrar, 116 const char* map_name, 117 const PrefChangeRegistrar::NamedChangeCallback& obs) { 118 DCHECK(StartsWithASCII(map_name, "webkit.webprefs.", true)); 119 for (size_t i = 0; i < prefs::kWebKitScriptsForFontFamilyMapsLength; ++i) { 120 const char* script = prefs::kWebKitScriptsForFontFamilyMaps[i]; 121 std::string pref_name = base::StringPrintf("%s.%s", map_name, script); 122 registrar->Add(pref_name.c_str(), obs); 123 } 124 } 125 #endif // !defined(OS_ANDROID) 126 127 struct FontDefault { 128 const char* pref_name; 129 int resource_id; 130 }; 131 132 // Font pref defaults. The prefs that have defaults vary by platform, since not 133 // all platforms have fonts for all scripts for all generic families. 134 // TODO(falken): add proper defaults when possible for all 135 // platforms/scripts/generic families. 136 const FontDefault kFontDefaults[] = { 137 { prefs::kWebKitStandardFontFamily, IDS_STANDARD_FONT_FAMILY }, 138 { prefs::kWebKitFixedFontFamily, IDS_FIXED_FONT_FAMILY }, 139 { prefs::kWebKitSerifFontFamily, IDS_SERIF_FONT_FAMILY }, 140 { prefs::kWebKitSansSerifFontFamily, IDS_SANS_SERIF_FONT_FAMILY }, 141 { prefs::kWebKitCursiveFontFamily, IDS_CURSIVE_FONT_FAMILY }, 142 { prefs::kWebKitFantasyFontFamily, IDS_FANTASY_FONT_FAMILY }, 143 { prefs::kWebKitPictographFontFamily, IDS_PICTOGRAPH_FONT_FAMILY }, 144 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) || defined(OS_WIN) 145 { prefs::kWebKitStandardFontFamilyJapanese, 146 IDS_STANDARD_FONT_FAMILY_JAPANESE }, 147 { prefs::kWebKitFixedFontFamilyJapanese, IDS_FIXED_FONT_FAMILY_JAPANESE }, 148 { prefs::kWebKitSerifFontFamilyJapanese, IDS_SERIF_FONT_FAMILY_JAPANESE }, 149 { prefs::kWebKitSansSerifFontFamilyJapanese, 150 IDS_SANS_SERIF_FONT_FAMILY_JAPANESE }, 151 { prefs::kWebKitStandardFontFamilyKorean, IDS_STANDARD_FONT_FAMILY_KOREAN }, 152 { prefs::kWebKitSerifFontFamilyKorean, IDS_SERIF_FONT_FAMILY_KOREAN }, 153 { prefs::kWebKitSansSerifFontFamilyKorean, 154 IDS_SANS_SERIF_FONT_FAMILY_KOREAN }, 155 { prefs::kWebKitStandardFontFamilySimplifiedHan, 156 IDS_STANDARD_FONT_FAMILY_SIMPLIFIED_HAN }, 157 { prefs::kWebKitSerifFontFamilySimplifiedHan, 158 IDS_SERIF_FONT_FAMILY_SIMPLIFIED_HAN }, 159 { prefs::kWebKitSansSerifFontFamilySimplifiedHan, 160 IDS_SANS_SERIF_FONT_FAMILY_SIMPLIFIED_HAN }, 161 { prefs::kWebKitStandardFontFamilyTraditionalHan, 162 IDS_STANDARD_FONT_FAMILY_TRADITIONAL_HAN }, 163 { prefs::kWebKitSerifFontFamilyTraditionalHan, 164 IDS_SERIF_FONT_FAMILY_TRADITIONAL_HAN }, 165 { prefs::kWebKitSansSerifFontFamilyTraditionalHan, 166 IDS_SANS_SERIF_FONT_FAMILY_TRADITIONAL_HAN }, 167 #endif 168 #if defined(OS_CHROMEOS) 169 { prefs::kWebKitStandardFontFamilyArabic, IDS_STANDARD_FONT_FAMILY_ARABIC }, 170 { prefs::kWebKitSerifFontFamilyArabic, IDS_SERIF_FONT_FAMILY_ARABIC }, 171 { prefs::kWebKitSansSerifFontFamilyArabic, 172 IDS_SANS_SERIF_FONT_FAMILY_ARABIC }, 173 { prefs::kWebKitFixedFontFamilyKorean, IDS_FIXED_FONT_FAMILY_KOREAN }, 174 { prefs::kWebKitFixedFontFamilySimplifiedHan, 175 IDS_FIXED_FONT_FAMILY_SIMPLIFIED_HAN }, 176 { prefs::kWebKitFixedFontFamilyTraditionalHan, 177 IDS_FIXED_FONT_FAMILY_TRADITIONAL_HAN }, 178 #elif defined(OS_WIN) 179 { prefs::kWebKitStandardFontFamilyCyrillic, 180 IDS_STANDARD_FONT_FAMILY_CYRILLIC }, 181 { prefs::kWebKitFixedFontFamilyCyrillic, IDS_FIXED_FONT_FAMILY_CYRILLIC }, 182 { prefs::kWebKitSerifFontFamilyCyrillic, IDS_SERIF_FONT_FAMILY_CYRILLIC }, 183 { prefs::kWebKitSansSerifFontFamilyCyrillic, 184 IDS_SANS_SERIF_FONT_FAMILY_CYRILLIC }, 185 { prefs::kWebKitStandardFontFamilyGreek, IDS_STANDARD_FONT_FAMILY_GREEK }, 186 { prefs::kWebKitFixedFontFamilyGreek, IDS_FIXED_FONT_FAMILY_GREEK }, 187 { prefs::kWebKitSerifFontFamilyGreek, IDS_SERIF_FONT_FAMILY_GREEK }, 188 { prefs::kWebKitSansSerifFontFamilyGreek, IDS_SANS_SERIF_FONT_FAMILY_GREEK }, 189 { prefs::kWebKitFixedFontFamilyKorean, IDS_FIXED_FONT_FAMILY_KOREAN }, 190 { prefs::kWebKitCursiveFontFamilyKorean, IDS_CURSIVE_FONT_FAMILY_KOREAN }, 191 { prefs::kWebKitFixedFontFamilySimplifiedHan, 192 IDS_FIXED_FONT_FAMILY_SIMPLIFIED_HAN }, 193 { prefs::kWebKitFixedFontFamilyTraditionalHan, 194 IDS_FIXED_FONT_FAMILY_TRADITIONAL_HAN }, 195 #endif 196 }; 197 198 const size_t kFontDefaultsLength = arraysize(kFontDefaults); 199 200 // Returns the script of the font pref |pref_name|. For example, suppose 201 // |pref_name| is "webkit.webprefs.fonts.serif.Hant". Since the script code for 202 // the script name "Hant" is USCRIPT_TRADITIONAL_HAN, the function returns 203 // USCRIPT_TRADITIONAL_HAN. |pref_name| must be a valid font pref name. 204 UScriptCode GetScriptOfFontPref(const char* pref_name) { 205 // ICU script names are four letters. 206 static const size_t kScriptNameLength = 4; 207 208 size_t len = strlen(pref_name); 209 DCHECK_GT(len, kScriptNameLength); 210 const char* scriptName = &pref_name[len - kScriptNameLength]; 211 int32 code = u_getPropertyValueEnum(UCHAR_SCRIPT, scriptName); 212 DCHECK(code >= 0 && code < USCRIPT_CODE_LIMIT); 213 return static_cast<UScriptCode>(code); 214 } 215 216 // If |scriptCode| is a member of a family of "similar" script codes, returns 217 // the script code in that family that is used in font pref names. For example, 218 // USCRIPT_HANGUL and USCRIPT_KOREAN are considered equivalent for the purposes 219 // of font selection. Chrome uses the script code USCRIPT_HANGUL (script name 220 // "Hang") in Korean font pref names (for example, 221 // "webkit.webprefs.fonts.serif.Hang"). So, if |scriptCode| is USCRIPT_KOREAN, 222 // the function returns USCRIPT_HANGUL. If |scriptCode| is not a member of such 223 // a family, returns |scriptCode|. 224 UScriptCode GetScriptForFontPrefMatching(UScriptCode scriptCode) { 225 switch (scriptCode) { 226 case USCRIPT_HIRAGANA: 227 case USCRIPT_KATAKANA: 228 case USCRIPT_KATAKANA_OR_HIRAGANA: 229 return USCRIPT_JAPANESE; 230 case USCRIPT_KOREAN: 231 return USCRIPT_HANGUL; 232 default: 233 return scriptCode; 234 } 235 } 236 237 // Returns the primary script used by the browser's UI locale. For example, if 238 // the locale is "ru", the function returns USCRIPT_CYRILLIC, and if the locale 239 // is "en", the function returns USCRIPT_LATIN. 240 UScriptCode GetScriptOfBrowserLocale() { 241 std::string locale = g_browser_process->GetApplicationLocale(); 242 243 // For Chinese locales, uscript_getCode() just returns USCRIPT_HAN but our 244 // per-script fonts are for USCRIPT_SIMPLIFIED_HAN and 245 // USCRIPT_TRADITIONAL_HAN. 246 if (locale == "zh-CN") 247 return USCRIPT_SIMPLIFIED_HAN; 248 if (locale == "zh-TW") 249 return USCRIPT_TRADITIONAL_HAN; 250 251 UScriptCode code = USCRIPT_INVALID_CODE; 252 UErrorCode err = U_ZERO_ERROR; 253 uscript_getCode(locale.c_str(), &code, 1, &err); 254 255 // Ignore the error that multiple scripts could be returned, since we only 256 // want one script. 257 if (U_FAILURE(err) && err != U_BUFFER_OVERFLOW_ERROR) 258 code = USCRIPT_INVALID_CODE; 259 return GetScriptForFontPrefMatching(code); 260 } 261 262 // Sets a font family pref in |prefs| to |pref_value|. 263 void OverrideFontFamily(WebPreferences* prefs, 264 const std::string& generic_family, 265 const std::string& script, 266 const std::string& pref_value) { 267 webkit_glue::ScriptFontFamilyMap* map = NULL; 268 if (generic_family == "standard") 269 map = &prefs->standard_font_family_map; 270 else if (generic_family == "fixed") 271 map = &prefs->fixed_font_family_map; 272 else if (generic_family == "serif") 273 map = &prefs->serif_font_family_map; 274 else if (generic_family == "sansserif") 275 map = &prefs->sans_serif_font_family_map; 276 else if (generic_family == "cursive") 277 map = &prefs->cursive_font_family_map; 278 else if (generic_family == "fantasy") 279 map = &prefs->fantasy_font_family_map; 280 else if (generic_family == "pictograph") 281 map = &prefs->pictograph_font_family_map; 282 else 283 NOTREACHED() << "Unknown generic font family: " << generic_family; 284 (*map)[script] = UTF8ToUTF16(pref_value); 285 } 286 287 } // namespace 288 289 PrefsTabHelper::PrefsTabHelper(WebContents* contents) 290 : web_contents_(contents), 291 weak_ptr_factory_(this) { 292 PrefService* prefs = GetProfile()->GetPrefs(); 293 pref_change_registrar_.Init(prefs); 294 if (prefs) { 295 base::Closure renderer_callback = base::Bind( 296 &PrefsTabHelper::UpdateRendererPreferences, base::Unretained(this)); 297 pref_change_registrar_.Add(prefs::kAcceptLanguages, renderer_callback); 298 pref_change_registrar_.Add(prefs::kDefaultZoomLevel, renderer_callback); 299 pref_change_registrar_.Add(prefs::kEnableDoNotTrack, renderer_callback); 300 pref_change_registrar_.Add(prefs::kEnableReferrers, renderer_callback); 301 302 #if !defined(OS_MACOSX) 303 pref_change_registrar_.Add(prefs::kFullscreenAllowed, renderer_callback); 304 #endif 305 306 PrefChangeRegistrar::NamedChangeCallback webkit_callback = base::Bind( 307 &PrefsTabHelper::OnWebPrefChanged, base::Unretained(this)); 308 for (int i = 0; i < kPrefsToObserveLength; ++i) { 309 const char* pref_name = kPrefsToObserve[i]; 310 DCHECK(std::string(pref_name) == prefs::kDefaultCharset || 311 StartsWithASCII(pref_name, "webkit.webprefs.", true)); 312 pref_change_registrar_.Add(pref_name, webkit_callback); 313 } 314 315 #if !defined(OS_ANDROID) 316 RegisterFontFamilyMapObserver(&pref_change_registrar_, 317 prefs::kWebKitStandardFontFamilyMap, 318 webkit_callback); 319 RegisterFontFamilyMapObserver(&pref_change_registrar_, 320 prefs::kWebKitFixedFontFamilyMap, 321 webkit_callback); 322 RegisterFontFamilyMapObserver(&pref_change_registrar_, 323 prefs::kWebKitSerifFontFamilyMap, 324 webkit_callback); 325 RegisterFontFamilyMapObserver(&pref_change_registrar_, 326 prefs::kWebKitSansSerifFontFamilyMap, 327 webkit_callback); 328 RegisterFontFamilyMapObserver(&pref_change_registrar_, 329 prefs::kWebKitCursiveFontFamilyMap, 330 webkit_callback); 331 RegisterFontFamilyMapObserver(&pref_change_registrar_, 332 prefs::kWebKitFantasyFontFamilyMap, 333 webkit_callback); 334 RegisterFontFamilyMapObserver(&pref_change_registrar_, 335 prefs::kWebKitPictographFontFamilyMap, 336 webkit_callback); 337 #endif // !defined(OS_ANDROID) 338 } 339 340 renderer_preferences_util::UpdateFromSystemSettings( 341 web_contents_->GetMutableRendererPrefs(), GetProfile()); 342 343 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(ENABLE_THEMES) 344 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 345 content::Source<ThemeService>( 346 ThemeServiceFactory::GetForProfile(GetProfile()))); 347 #endif 348 #if defined(USE_AURA) 349 registrar_.Add(this, 350 chrome::NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED, 351 content::NotificationService::AllSources()); 352 #endif 353 } 354 355 PrefsTabHelper::~PrefsTabHelper() { 356 } 357 358 // static 359 void PrefsTabHelper::InitIncognitoUserPrefStore( 360 OverlayUserPrefStore* pref_store) { 361 // List of keys that cannot be changed in the user prefs file by the incognito 362 // profile. All preferences that store information about the browsing history 363 // or behavior of the user should have this property. 364 pref_store->RegisterOverlayPref(prefs::kBrowserWindowPlacement); 365 pref_store->RegisterOverlayPref(prefs::kSaveFileDefaultDirectory); 366 #if defined(OS_ANDROID) || defined(OS_IOS) 367 pref_store->RegisterOverlayPref(prefs::kProxy); 368 #endif // defined(OS_ANDROID) || defined(OS_IOS) 369 } 370 371 // static 372 void PrefsTabHelper::RegisterProfilePrefs( 373 user_prefs::PrefRegistrySyncable* registry) { 374 WebPreferences pref_defaults; 375 registry->RegisterBooleanPref( 376 prefs::kWebKitJavascriptEnabled, 377 pref_defaults.javascript_enabled, 378 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 379 registry->RegisterBooleanPref( 380 prefs::kWebKitWebSecurityEnabled, 381 pref_defaults.web_security_enabled, 382 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 383 registry->RegisterBooleanPref( 384 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, 385 true, 386 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 387 registry->RegisterBooleanPref( 388 prefs::kWebKitLoadsImagesAutomatically, 389 pref_defaults.loads_images_automatically, 390 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 391 registry->RegisterBooleanPref( 392 prefs::kWebKitPluginsEnabled, 393 pref_defaults.plugins_enabled, 394 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 395 registry->RegisterBooleanPref( 396 prefs::kWebKitDomPasteEnabled, 397 pref_defaults.dom_paste_enabled, 398 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 399 registry->RegisterBooleanPref( 400 prefs::kWebKitShrinksStandaloneImagesToFit, 401 pref_defaults.shrinks_standalone_images_to_fit, 402 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 403 registry->RegisterDictionaryPref( 404 prefs::kWebKitInspectorSettings, 405 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 406 registry->RegisterBooleanPref( 407 prefs::kWebKitTextAreasAreResizable, 408 pref_defaults.text_areas_are_resizable, 409 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 410 registry->RegisterBooleanPref( 411 prefs::kWebKitJavaEnabled, 412 pref_defaults.java_enabled, 413 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 414 registry->RegisterBooleanPref( 415 prefs::kWebkitTabsToLinks, 416 pref_defaults.tabs_to_links, 417 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 418 registry->RegisterBooleanPref( 419 prefs::kWebKitAllowRunningInsecureContent, 420 false, 421 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 422 registry->RegisterBooleanPref( 423 prefs::kWebKitAllowDisplayingInsecureContent, 424 true, 425 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 426 registry->RegisterBooleanPref( 427 prefs::kEnableReferrers, 428 true, 429 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 430 #if defined(OS_ANDROID) 431 registry->RegisterDoublePref( 432 prefs::kWebKitFontScaleFactor, 433 1.0, 434 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 435 registry->RegisterBooleanPref( 436 prefs::kWebKitForceEnableZoom, 437 pref_defaults.force_enable_zoom, 438 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 439 registry->RegisterBooleanPref( 440 prefs::kWebKitPasswordEchoEnabled, 441 pref_defaults.password_echo_enabled, 442 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 443 #endif 444 registry->RegisterLocalizedStringPref( 445 prefs::kAcceptLanguages, 446 IDS_ACCEPT_LANGUAGES, 447 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 448 registry->RegisterLocalizedStringPref( 449 prefs::kDefaultCharset, 450 IDS_DEFAULT_ENCODING, 451 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 452 453 // Register font prefs that have defaults. 454 std::set<std::string> fonts_with_defaults; 455 UScriptCode browser_script = GetScriptOfBrowserLocale(); 456 for (size_t i = 0; i < kFontDefaultsLength; ++i) { 457 const FontDefault& pref = kFontDefaults[i]; 458 UScriptCode pref_script = GetScriptOfFontPref(pref.pref_name); 459 460 // Suppress this default font pref value if it is for the primary script of 461 // the browser's UI locale. For example, if the pref is for the sans-serif 462 // font for the Cyrillic script, and the browser locale is "ru" (Russian), 463 // the default is suppressed. Otherwise, the default would override the 464 // user's font preferences when viewing pages in their native language. 465 // This is because users have no way yet of customizing their per-script 466 // font preferences. The font prefs accessible in the options UI are for 467 // the default, unknown script; these prefs have less priority than the 468 // per-script font prefs when the script of the content is known. This code 469 // can possibly be removed later if users can easily access per-script font 470 // prefs (e.g., via the extensions workflow), or the problem turns out to 471 // not be really critical after all. 472 if (browser_script != pref_script) { 473 registry->RegisterLocalizedStringPref( 474 pref.pref_name, 475 pref.resource_id, 476 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 477 fonts_with_defaults.insert(pref.pref_name); 478 } 479 } 480 481 // Register per-script font prefs that don't have defaults. 482 #if !defined(OS_ANDROID) 483 RegisterFontFamilyPrefs(registry, fonts_with_defaults); 484 #endif 485 486 registry->RegisterLocalizedIntegerPref( 487 prefs::kWebKitDefaultFontSize, 488 IDS_DEFAULT_FONT_SIZE, 489 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 490 registry->RegisterLocalizedIntegerPref( 491 prefs::kWebKitDefaultFixedFontSize, 492 IDS_DEFAULT_FIXED_FONT_SIZE, 493 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 494 registry->RegisterLocalizedIntegerPref( 495 prefs::kWebKitMinimumFontSize, 496 IDS_MINIMUM_FONT_SIZE, 497 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 498 registry->RegisterLocalizedIntegerPref( 499 prefs::kWebKitMinimumLogicalFontSize, 500 IDS_MINIMUM_LOGICAL_FONT_SIZE, 501 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 502 registry->RegisterLocalizedBooleanPref( 503 prefs::kWebKitUsesUniversalDetector, 504 IDS_USES_UNIVERSAL_DETECTOR, 505 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 506 registry->RegisterLocalizedStringPref( 507 prefs::kStaticEncodings, 508 IDS_STATIC_ENCODING_LIST, 509 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 510 registry->RegisterStringPref( 511 prefs::kRecentlySelectedEncoding, 512 std::string(), 513 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 514 } 515 516 void PrefsTabHelper::Observe(int type, 517 const content::NotificationSource& source, 518 const content::NotificationDetails& details) { 519 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(ENABLE_THEMES) 520 if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) { 521 UpdateRendererPreferences(); 522 return; 523 } 524 #endif 525 526 #if defined(USE_AURA) 527 if (type == chrome::NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED) { 528 UpdateRendererPreferences(); 529 return; 530 } 531 #endif // defined(USE_AURA) 532 533 NOTREACHED(); 534 } 535 536 void PrefsTabHelper::UpdateWebPreferences() { 537 web_contents_->GetRenderViewHost()->UpdateWebkitPreferences( 538 web_contents_->GetRenderViewHost()->GetWebkitPreferences()); 539 } 540 541 void PrefsTabHelper::UpdateRendererPreferences() { 542 renderer_preferences_util::UpdateFromSystemSettings( 543 web_contents_->GetMutableRendererPrefs(), GetProfile()); 544 web_contents_->GetRenderViewHost()->SyncRendererPrefs(); 545 } 546 547 Profile* PrefsTabHelper::GetProfile() { 548 return Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 549 } 550 551 void PrefsTabHelper::OnWebPrefChanged(const std::string& pref_name) { 552 // When a font family pref's value goes from non-empty to the empty string, we 553 // must add it to the usual WebPreferences struct passed to the renderer. 554 // 555 // The empty string means to fall back to the pref for the Common script 556 // ("Zyyy"). For example, if chrome.fonts.serif.Cyrl is the empty string, it 557 // means to use chrome.fonts.serif.Zyyy for Cyrillic script. Prefs that are 558 // the empty string are normally not passed to WebKit, since there are so many 559 // of them that it would cause a performance regression. Not passing the pref 560 // is normally okay since WebKit does the desired fallback behavior regardless 561 // of whether the empty string is passed or the pref is not passed at all. But 562 // if the pref has changed from non-empty to the empty string, we must let 563 // WebKit know. 564 std::string generic_family; 565 std::string script; 566 if (pref_names_util::ParseFontNamePrefPath(pref_name, 567 &generic_family, 568 &script)) { 569 PrefService* prefs = GetProfile()->GetPrefs(); 570 std::string pref_value = prefs->GetString(pref_name.c_str()); 571 if (pref_value.empty()) { 572 WebPreferences web_prefs = 573 web_contents_->GetRenderViewHost()->GetWebkitPreferences(); 574 OverrideFontFamily(&web_prefs, generic_family, script, std::string()); 575 web_contents_->GetRenderViewHost()->UpdateWebkitPreferences(web_prefs); 576 return; 577 } 578 } 579 580 UpdateWebPreferences(); 581 } 582