Home | History | Annotate | Download | only in prefs
      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