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