prefs_tab_helper.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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/profiles/profile.h"
16#include "chrome/browser/renderer_preferences_util.h"
17#include "chrome/common/chrome_notification_types.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/public/common/unicode/uchar.h"
29#include "third_party/icu/public/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
37using content::WebContents;
38
39DEFINE_WEB_CONTENTS_USER_DATA_KEY(PrefsTabHelper);
40
41namespace {
42
43// Registers prefs only used for migration.
44void 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.
116const 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
137const 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.
145void 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"
154ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_CURSIVE)
155ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_FANTASY)
156ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_FIXED)
157ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_PICTOGRAPH)
158ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SANSERIF)
159ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SERIF)
160ALL_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.
183void 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
196struct 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.
205const 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
267const 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.
273UScriptCode 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|.
293UScriptCode 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.
309UScriptCode 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
331const 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
383const int kPrefsToMigrateLength = ARRAYSIZE_UNSAFE(kPrefNamesToMigrate);
384
385// Sets a font family pref in |prefs| to |pref_value|.
386void 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
412PrefsTabHelper::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
477PrefsTabHelper::~PrefsTabHelper() {
478}
479
480// static
481void 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
494void PrefsTabHelper::RegisterUserPrefs(
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
638void 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
649void 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
675void PrefsTabHelper::UpdateWebPreferences() {
676  web_contents_->GetRenderViewHost()->UpdateWebkitPreferences(
677      web_contents_->GetRenderViewHost()->GetWebkitPreferences());
678}
679
680void PrefsTabHelper::UpdateRendererPreferences() {
681  renderer_preferences_util::UpdateFromSystemSettings(
682      web_contents_->GetMutableRendererPrefs(), GetProfile());
683  web_contents_->GetRenderViewHost()->SyncRendererPrefs();
684}
685
686Profile* PrefsTabHelper::GetProfile() {
687  return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
688}
689
690void 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