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