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