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