1 // Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file.
4
5 #include "libcef/browser/prefs/renderer_prefs.h"
6
7 #include <string>
8
9 #include "libcef/browser/alloy/alloy_browser_host_impl.h"
10 #include "libcef/browser/context.h"
11 #include "libcef/browser/extensions/browser_extensions_util.h"
12 #include "libcef/common/cef_switches.h"
13 #include "libcef/common/extensions/extensions_util.h"
14 #include "libcef/features/runtime_checks.h"
15
16 #include "base/command_line.h"
17 #include "base/i18n/character_encoding.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/values.h"
20 #include "chrome/browser/accessibility/animation_policy_prefs.h"
21 #include "chrome/browser/defaults.h"
22 #include "chrome/browser/extensions/extension_webkit_preferences.h"
23 #include "chrome/browser/font_family_cache.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
26 #include "chrome/common/chrome_features.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/pref_registry/pref_registry_syncable.h"
30 #include "components/prefs/command_line_pref_store.h"
31 #include "components/prefs/pref_service.h"
32 #include "components/prefs/pref_store.h"
33 #include "content/public/browser/render_process_host.h"
34 #include "content/public/browser/render_view_host.h"
35 #include "content/public/browser/site_instance.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/common/url_constants.h"
38 #include "extensions/browser/extension_registry.h"
39 #include "extensions/browser/view_type_utils.h"
40 #include "extensions/common/constants.h"
41 #include "media/media_buildflags.h"
42 #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
43 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
44 #include "ui/native_theme/native_theme.h"
45
46 namespace renderer_prefs {
47
48 namespace {
49
50 // Chrome preferences.
51 // Should match ChromeContentBrowserClient::OverrideWebkitPrefs.
SetChromePrefs(Profile * profile,blink::web_pref::WebPreferences & web)52 void SetChromePrefs(Profile* profile, blink::web_pref::WebPreferences& web) {
53 PrefService* prefs = profile->GetPrefs();
54
55 // Fill per-script font preferences.
56 FontFamilyCache::FillFontFamilyMap(profile,
57 prefs::kWebKitStandardFontFamilyMap,
58 &web.standard_font_family_map);
59 FontFamilyCache::FillFontFamilyMap(profile, prefs::kWebKitFixedFontFamilyMap,
60 &web.fixed_font_family_map);
61 FontFamilyCache::FillFontFamilyMap(profile, prefs::kWebKitSerifFontFamilyMap,
62 &web.serif_font_family_map);
63 FontFamilyCache::FillFontFamilyMap(profile,
64 prefs::kWebKitSansSerifFontFamilyMap,
65 &web.sans_serif_font_family_map);
66 FontFamilyCache::FillFontFamilyMap(profile,
67 prefs::kWebKitCursiveFontFamilyMap,
68 &web.cursive_font_family_map);
69 FontFamilyCache::FillFontFamilyMap(profile,
70 prefs::kWebKitFantasyFontFamilyMap,
71 &web.fantasy_font_family_map);
72
73 web.default_font_size = prefs->GetInteger(prefs::kWebKitDefaultFontSize);
74 web.default_fixed_font_size =
75 prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize);
76 web.minimum_font_size = prefs->GetInteger(prefs::kWebKitMinimumFontSize);
77 web.minimum_logical_font_size =
78 prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize);
79
80 web.default_encoding = prefs->GetString(prefs::kDefaultCharset);
81
82 web.dom_paste_enabled = prefs->GetBoolean(prefs::kWebKitDomPasteEnabled);
83 web.tabs_to_links = prefs->GetBoolean(prefs::kWebkitTabsToLinks);
84
85 if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled))
86 web.javascript_enabled = false;
87 if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled))
88 web.web_security_enabled = false;
89 if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled))
90 web.plugins_enabled = false;
91 web.loads_images_automatically =
92 prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically);
93
94 if (prefs->GetBoolean(prefs::kDisable3DAPIs)) {
95 web.webgl1_enabled = false;
96 web.webgl2_enabled = false;
97 }
98
99 web.allow_running_insecure_content =
100 prefs->GetBoolean(prefs::kWebKitAllowRunningInsecureContent);
101
102 web.password_echo_enabled = browser_defaults::kPasswordEchoEnabled;
103
104 web.text_areas_are_resizable =
105 prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable);
106 web.hyperlink_auditing_enabled =
107 prefs->GetBoolean(prefs::kEnableHyperlinkAuditing);
108
109 if (extensions::ExtensionsEnabled()) {
110 std::string image_animation_policy =
111 prefs->GetString(prefs::kAnimationPolicy);
112 if (image_animation_policy == kAnimationPolicyOnce) {
113 web.animation_policy =
114 blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAnimateOnce;
115 } else if (image_animation_policy == kAnimationPolicyNone) {
116 web.animation_policy =
117 blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyNoAnimation;
118 } else {
119 web.animation_policy =
120 blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAllowed;
121 }
122 }
123
124 // Make sure we will set the default_encoding with canonical encoding name.
125 web.default_encoding =
126 base::GetCanonicalEncodingNameByAliasName(web.default_encoding);
127 if (web.default_encoding.empty()) {
128 prefs->ClearPref(prefs::kDefaultCharset);
129 web.default_encoding = prefs->GetString(prefs::kDefaultCharset);
130 }
131 DCHECK(!web.default_encoding.empty());
132
133 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
134 switches::kEnablePotentiallyAnnoyingSecurityFeatures)) {
135 web.disable_reading_from_canvas = true;
136 web.strict_mixed_content_checking = true;
137 web.strict_powerful_feature_restrictions = true;
138 }
139 }
140
141 // Extension preferences.
142 // Should match ChromeContentBrowserClientExtensionsPart::OverrideWebkitPrefs.
SetExtensionPrefs(content::WebContents * web_contents,content::RenderViewHost * rvh,blink::web_pref::WebPreferences & web)143 void SetExtensionPrefs(content::WebContents* web_contents,
144 content::RenderViewHost* rvh,
145 blink::web_pref::WebPreferences& web) {
146 if (!extensions::ExtensionsEnabled())
147 return;
148
149 const extensions::ExtensionRegistry* registry =
150 extensions::ExtensionRegistry::Get(
151 rvh->GetProcess()->GetBrowserContext());
152 if (!registry)
153 return;
154
155 // Note: it's not possible for kExtensionsScheme to change during the lifetime
156 // of the process.
157 //
158 // Ensure that we are only granting extension preferences to URLs with the
159 // correct scheme. Without this check, chrome-guest:// schemes used by webview
160 // tags as well as hosts that happen to match the id of an installed extension
161 // would get the wrong preferences.
162 const GURL& site_url =
163 web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL();
164 if (!site_url.SchemeIs(extensions::kExtensionScheme))
165 return;
166
167 const extensions::Extension* extension =
168 registry->enabled_extensions().GetByID(site_url.host());
169 extension_webkit_preferences::SetPreferences(extension, &web);
170 }
171
SetString(CommandLinePrefStore * prefs,const std::string & key,const std::string & value)172 void SetString(CommandLinePrefStore* prefs,
173 const std::string& key,
174 const std::string& value) {
175 prefs->SetValue(key, base::WrapUnique(new base::Value(value)),
176 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
177 }
178
SetBool(CommandLinePrefStore * prefs,const std::string & key,bool value)179 void SetBool(CommandLinePrefStore* prefs, const std::string& key, bool value) {
180 prefs->SetValue(key, base::WrapUnique(new base::Value(value)),
181 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
182 }
183
ToBlinkPreferredColorScheme(ui::NativeTheme::PreferredColorScheme native_theme_scheme)184 blink::mojom::PreferredColorScheme ToBlinkPreferredColorScheme(
185 ui::NativeTheme::PreferredColorScheme native_theme_scheme) {
186 switch (native_theme_scheme) {
187 case ui::NativeTheme::PreferredColorScheme::kDark:
188 return blink::mojom::PreferredColorScheme::kDark;
189 case ui::NativeTheme::PreferredColorScheme::kLight:
190 return blink::mojom::PreferredColorScheme::kLight;
191 }
192
193 NOTREACHED();
194 }
195
196 // From chrome/browser/chrome_content_browser_client.cc
197 // Returns true if preferred color scheme is modified based on at least one of
198 // the following -
199 // |url| - Last committed url.
200 // |native_theme| - For other platforms based on native theme scheme.
UpdatePreferredColorScheme(blink::web_pref::WebPreferences * web_prefs,const GURL & url,const ui::NativeTheme * native_theme)201 bool UpdatePreferredColorScheme(blink::web_pref::WebPreferences* web_prefs,
202 const GURL& url,
203 const ui::NativeTheme* native_theme) {
204 auto old_preferred_color_scheme = web_prefs->preferred_color_scheme;
205
206 // Update based on native theme scheme.
207 web_prefs->preferred_color_scheme =
208 ToBlinkPreferredColorScheme(native_theme->GetPreferredColorScheme());
209
210 // Force a light preferred color scheme on certain URLs if kWebUIDarkMode is
211 // disabled; some of the UI is not yet correctly themed.
212 if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) {
213 // Update based on last committed url.
214 bool force_light = url.SchemeIs(content::kChromeUIScheme);
215 if (!force_light) {
216 force_light = url.SchemeIs(extensions::kExtensionScheme) &&
217 url.host_piece() == extension_misc::kPdfExtensionId;
218 }
219 if (force_light) {
220 web_prefs->preferred_color_scheme =
221 blink::mojom::PreferredColorScheme::kLight;
222 }
223 }
224
225 return old_preferred_color_scheme != web_prefs->preferred_color_scheme;
226 }
227
228 } // namespace
229
SetCommandLinePrefDefaults(CommandLinePrefStore * prefs)230 void SetCommandLinePrefDefaults(CommandLinePrefStore* prefs) {
231 const base::CommandLine* command_line =
232 base::CommandLine::ForCurrentProcess();
233
234 if (command_line->HasSwitch(switches::kDefaultEncoding)) {
235 SetString(prefs, prefs::kDefaultCharset,
236 command_line->GetSwitchValueASCII(switches::kDefaultEncoding));
237 }
238
239 if (command_line->HasSwitch(switches::kDisableJavascriptDomPaste))
240 SetBool(prefs, prefs::kWebKitDomPasteEnabled, false);
241 if (command_line->HasSwitch(switches::kDisableImageLoading))
242 SetBool(prefs, prefs::kWebKitLoadsImagesAutomatically, false);
243 if (command_line->HasSwitch(switches::kDisableTabToLinks))
244 SetBool(prefs, prefs::kWebkitTabsToLinks, false);
245 if (command_line->HasSwitch(switches::kDisablePlugins))
246 SetBool(prefs, prefs::kWebKitPluginsEnabled, false);
247 }
248
SetDefaultPrefs(blink::web_pref::WebPreferences & web)249 void SetDefaultPrefs(blink::web_pref::WebPreferences& web) {
250 const base::CommandLine* command_line =
251 base::CommandLine::ForCurrentProcess();
252
253 web.javascript_enabled =
254 !command_line->HasSwitch(switches::kDisableJavascript);
255 web.allow_scripts_to_close_windows =
256 !command_line->HasSwitch(switches::kDisableJavascriptCloseWindows);
257 web.javascript_can_access_clipboard =
258 !command_line->HasSwitch(switches::kDisableJavascriptAccessClipboard);
259 web.allow_universal_access_from_file_urls =
260 command_line->HasSwitch(switches::kAllowUniversalAccessFromFileUrls);
261 web.shrinks_standalone_images_to_fit =
262 command_line->HasSwitch(switches::kImageShrinkStandaloneToFit);
263 web.text_areas_are_resizable =
264 !command_line->HasSwitch(switches::kDisableTextAreaResize);
265 }
266
267 // Helper macro for setting a WebPreferences variable based on the value of a
268 // CefBrowserSettings variable.
269 #define SET_STATE(cef_var, web_var) \
270 if (cef_var == STATE_ENABLED) \
271 web_var = true; \
272 else if (cef_var == STATE_DISABLED) \
273 web_var = false;
274
SetCefPrefs(const CefBrowserSettings & cef,blink::web_pref::WebPreferences & web)275 void SetCefPrefs(const CefBrowserSettings& cef,
276 blink::web_pref::WebPreferences& web) {
277 if (cef.standard_font_family.length > 0) {
278 web.standard_font_family_map[blink::web_pref::kCommonScript] =
279 CefString(&cef.standard_font_family);
280 }
281 if (cef.fixed_font_family.length > 0) {
282 web.fixed_font_family_map[blink::web_pref::kCommonScript] =
283 CefString(&cef.fixed_font_family);
284 }
285 if (cef.serif_font_family.length > 0) {
286 web.serif_font_family_map[blink::web_pref::kCommonScript] =
287 CefString(&cef.serif_font_family);
288 }
289 if (cef.sans_serif_font_family.length > 0) {
290 web.sans_serif_font_family_map[blink::web_pref::kCommonScript] =
291 CefString(&cef.sans_serif_font_family);
292 }
293 if (cef.cursive_font_family.length > 0) {
294 web.cursive_font_family_map[blink::web_pref::kCommonScript] =
295 CefString(&cef.cursive_font_family);
296 }
297 if (cef.fantasy_font_family.length > 0) {
298 web.fantasy_font_family_map[blink::web_pref::kCommonScript] =
299 CefString(&cef.fantasy_font_family);
300 }
301
302 if (cef.default_font_size > 0)
303 web.default_font_size = cef.default_font_size;
304 if (cef.default_fixed_font_size > 0)
305 web.default_fixed_font_size = cef.default_fixed_font_size;
306 if (cef.minimum_font_size > 0)
307 web.minimum_font_size = cef.minimum_font_size;
308 if (cef.minimum_logical_font_size > 0)
309 web.minimum_logical_font_size = cef.minimum_logical_font_size;
310
311 if (cef.default_encoding.length > 0)
312 web.default_encoding = CefString(&cef.default_encoding);
313
314 SET_STATE(cef.remote_fonts, web.remote_fonts_enabled);
315 SET_STATE(cef.javascript, web.javascript_enabled);
316 SET_STATE(cef.javascript_close_windows, web.allow_scripts_to_close_windows);
317 SET_STATE(cef.javascript_access_clipboard,
318 web.javascript_can_access_clipboard);
319 SET_STATE(cef.javascript_dom_paste, web.dom_paste_enabled);
320 SET_STATE(cef.plugins, web.plugins_enabled);
321 SET_STATE(cef.image_loading, web.loads_images_automatically);
322 SET_STATE(cef.image_shrink_standalone_to_fit,
323 web.shrinks_standalone_images_to_fit);
324 SET_STATE(cef.text_area_resize, web.text_areas_are_resizable);
325 SET_STATE(cef.tab_to_links, web.tabs_to_links);
326 SET_STATE(cef.local_storage, web.local_storage_enabled);
327 SET_STATE(cef.databases, web.databases_enabled);
328
329 // Never explicitly enable GPU-related functions in this method because the
330 // GPU blacklist is not being checked here.
331 if (cef.webgl == STATE_DISABLED) {
332 web.webgl1_enabled = false;
333 web.webgl2_enabled = false;
334 }
335 }
336
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry,const std::string & locale)337 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
338 const std::string& locale) {
339 PrefsTabHelper::RegisterProfilePrefs(registry, locale);
340 RegisterAnimationPolicyPrefs(registry);
341
342 // From chrome/browser/ui/browser_ui_prefs.cc RegisterBrowserUserPrefs.
343 registry->RegisterBooleanPref(
344 prefs::kEnableDoNotTrack, false,
345 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
346 registry->RegisterBooleanPref(prefs::kCaretBrowsingEnabled, false);
347
348 registry->RegisterStringPref(prefs::kWebRTCIPHandlingPolicy,
349 blink::kWebRTCIPHandlingDefault);
350 registry->RegisterStringPref(prefs::kWebRTCUDPPortRange, std::string());
351
352 #if !BUILDFLAG(IS_MAC)
353 registry->RegisterBooleanPref(prefs::kFullscreenAllowed, true);
354 #endif
355
356 // From ChromeContentBrowserClient::RegisterProfilePrefs.
357 registry->RegisterBooleanPref(prefs::kDisable3DAPIs, false);
358 registry->RegisterBooleanPref(prefs::kEnableHyperlinkAuditing, true);
359
360 // From Profile::RegisterProfilePrefs.
361 registry->RegisterDictionaryPref(prefs::kPartitionDefaultZoomLevel);
362 registry->RegisterDictionaryPref(prefs::kPartitionPerHostZoomLevels);
363 }
364
PopulateWebPreferences(content::RenderViewHost * rvh,blink::web_pref::WebPreferences & web,SkColor & base_background_color)365 void PopulateWebPreferences(content::RenderViewHost* rvh,
366 blink::web_pref::WebPreferences& web,
367 SkColor& base_background_color) {
368 REQUIRE_ALLOY_RUNTIME();
369 CefRefPtr<AlloyBrowserHostImpl> browser = static_cast<AlloyBrowserHostImpl*>(
370 extensions::GetOwnerBrowserForHost(rvh, nullptr).get());
371
372 // Set defaults for preferences that are not handled by PrefService.
373 SetDefaultPrefs(web);
374
375 // Set preferences based on the context's PrefService.
376 if (browser) {
377 auto profile = Profile::FromBrowserContext(
378 browser->web_contents()->GetBrowserContext());
379 SetChromePrefs(profile, web);
380 }
381
382 auto* native_theme = ui::NativeTheme::GetInstanceForWeb();
383 switch (native_theme->GetPreferredColorScheme()) {
384 case ui::NativeTheme::PreferredColorScheme::kDark:
385 web.preferred_color_scheme = blink::mojom::PreferredColorScheme::kDark;
386 break;
387 case ui::NativeTheme::PreferredColorScheme::kLight:
388 web.preferred_color_scheme = blink::mojom::PreferredColorScheme::kLight;
389 break;
390 }
391
392 switch (native_theme->GetPreferredContrast()) {
393 case ui::NativeTheme::PreferredContrast::kNoPreference:
394 web.preferred_contrast = blink::mojom::PreferredContrast::kNoPreference;
395 break;
396 case ui::NativeTheme::PreferredContrast::kMore:
397 web.preferred_contrast = blink::mojom::PreferredContrast::kMore;
398 break;
399 case ui::NativeTheme::PreferredContrast::kLess:
400 web.preferred_contrast = blink::mojom::PreferredContrast::kLess;
401 break;
402 case ui::NativeTheme::PreferredContrast::kCustom:
403 web.preferred_contrast = blink::mojom::PreferredContrast::kCustom;
404 break;
405 }
406
407 auto web_contents = content::WebContents::FromRenderViewHost(rvh);
408 UpdatePreferredColorScheme(
409 &web, web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL(),
410 native_theme);
411
412 // Set preferences based on the extension.
413 SetExtensionPrefs(web_contents, rvh, web);
414
415 if (browser) {
416 // Set preferences based on CefBrowserSettings.
417 SetCefPrefs(browser->settings(), web);
418
419 web.picture_in_picture_enabled = browser->IsPictureInPictureSupported();
420
421 // Set the background color for the WebView.
422 base_background_color = browser->GetBackgroundColor();
423 } else {
424 // We don't know for sure that the browser will be windowless but assume
425 // that the global windowless state is likely to be accurate.
426 base_background_color =
427 CefContext::Get()->GetBackgroundColor(nullptr, STATE_DEFAULT);
428 }
429 }
430
PopulateWebPreferencesAfterNavigation(content::WebContents * web_contents,blink::web_pref::WebPreferences & web)431 bool PopulateWebPreferencesAfterNavigation(
432 content::WebContents* web_contents,
433 blink::web_pref::WebPreferences& web) {
434 auto* native_theme = ui::NativeTheme::GetInstanceForWeb();
435 return UpdatePreferredColorScheme(&web, web_contents->GetLastCommittedURL(),
436 native_theme);
437 }
438
439 } // namespace renderer_prefs
440