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