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