1 // Copyright 2013 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 "content/child/runtime_features.h"
6
7 #include <vector>
8
9 #include "base/base_switches.h"
10 #include "base/command_line.h"
11 #include "base/feature_list.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/field_trial_params.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "build/build_config.h"
17 #include "cc/base/features.h"
18 #include "content/common/content_navigation_policy.h"
19 #include "content/common/content_switches_internal.h"
20 #include "content/public/common/content_features.h"
21 #include "content/public/common/content_switches.h"
22 #include "device/fido/features.h"
23 #include "device/gamepad/public/cpp/gamepad_features.h"
24 #include "gpu/config/gpu_switches.h"
25 #include "media/base/media_switches.h"
26 #include "net/base/features.h"
27 #include "services/device/public/cpp/device_features.h"
28 #include "services/network/public/cpp/features.h"
29 #include "third_party/blink/public/common/features.h"
30 #include "third_party/blink/public/common/loader/referrer_utils.h"
31 #include "third_party/blink/public/common/switches.h"
32 #include "third_party/blink/public/platform/web_runtime_features.h"
33 #include "ui/accessibility/accessibility_features.h"
34 #include "ui/base/ui_base_features.h"
35 #include "ui/events/blink/blink_features.h"
36 #include "ui/gfx/switches.h"
37 #include "ui/gl/gl_switches.h"
38 #include "ui/native_theme/native_theme_features.h"
39
40 #if defined(OS_ANDROID)
41 #include "base/android/build_info.h"
42 #endif
43
44 #if defined(OS_WIN)
45 #include "base/win/windows_version.h"
46 #endif
47
48 using blink::WebRuntimeFeatures;
49
50 namespace {
51
52 // Sets blink runtime features for specific platforms.
53 // This should be a last resort vs runtime_enabled_features.json5.
SetRuntimeFeatureDefaultsForPlatform(const base::CommandLine & command_line)54 void SetRuntimeFeatureDefaultsForPlatform(
55 const base::CommandLine& command_line) {
56 // Please consider setting up feature defaults for different platforms
57 // in runtime_enabled_features.json5 instead of here
58 // TODO(rodneyding): Move the more common cases here
59 // to baseFeature/switch functions below and move more complex
60 // ones to special case functions.
61 #if defined(USE_AURA)
62 WebRuntimeFeatures::EnableCompositedSelectionUpdate(true);
63 #endif
64 #if defined(OS_WIN)
65 if (base::win::GetVersion() >= base::win::Version::WIN10) {
66 WebRuntimeFeatures::EnableWebBluetooth(true);
67 WebRuntimeFeatures::EnableWebBluetoothRemoteCharacteristicNewWriteValue(
68 true);
69 }
70 #endif
71
72 #if defined(OS_MAC)
73 const bool enable_canvas_2d_image_chromium =
74 command_line.HasSwitch(
75 blink::switches::kEnableGpuMemoryBufferCompositorResources) &&
76 !command_line.HasSwitch(switches::kDisable2dCanvasImageChromium) &&
77 !command_line.HasSwitch(switches::kDisableGpu) &&
78 base::FeatureList::IsEnabled(features::kCanvas2DImageChromium);
79 #else
80 constexpr bool enable_canvas_2d_image_chromium = false;
81 #endif
82 WebRuntimeFeatures::EnableCanvas2dImageChromium(
83 enable_canvas_2d_image_chromium);
84
85 #if defined(OS_MAC)
86 const bool enable_web_gl_image_chromium =
87 command_line.HasSwitch(
88 blink::switches::kEnableGpuMemoryBufferCompositorResources) &&
89 !command_line.HasSwitch(switches::kDisableWebGLImageChromium) &&
90 !command_line.HasSwitch(switches::kDisableGpu) &&
91 base::FeatureList::IsEnabled(features::kWebGLImageChromium);
92 #else
93 const bool enable_web_gl_image_chromium =
94 command_line.HasSwitch(switches::kEnableWebGLImageChromium);
95 #endif
96 WebRuntimeFeatures::EnableWebGLImageChromium(enable_web_gl_image_chromium);
97
98 #if defined(OS_ANDROID)
99 if (command_line.HasSwitch(switches::kDisableMediaSessionAPI))
100 WebRuntimeFeatures::EnableMediaSession(false);
101 #endif
102
103 #if defined(OS_ANDROID)
104 // APIs for Web Authentication are not available prior to N.
105 WebRuntimeFeatures::EnableWebAuth(
106 base::FeatureList::IsEnabled(features::kWebAuth) &&
107 base::android::BuildInfo::GetInstance()->sdk_int() >=
108 base::android::SDK_VERSION_NOUGAT);
109 #else
110 WebRuntimeFeatures::EnableWebAuth(
111 base::FeatureList::IsEnabled(features::kWebAuth));
112 #endif
113
114 #if defined(OS_ANDROID)
115 WebRuntimeFeatures::EnablePictureInPictureAPI(
116 base::FeatureList::IsEnabled(media::kPictureInPictureAPI));
117 #endif
118
119 #if defined(OS_ANDROID)
120 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
121 base::android::SDK_VERSION_P) {
122 // Display Cutout is limited to Android P+.
123 WebRuntimeFeatures::EnableDisplayCutoutAPI(true);
124 }
125 #endif
126
127 #if defined(OS_ANDROID)
128 WebRuntimeFeatures::EnableMediaControlsExpandGesture(
129 base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture));
130 #endif
131 }
132
133 enum RuntimeFeatureEnableOptions {
134 // - If the base::Feature default is overridden by field trial or command
135 // line, set Blink feature to the state of the base::Feature;
136 // - Otherwise if the base::Feature is enabled, enable the Blink feature.
137 // - Otherwise no change.
138 kDefault,
139 // Enables the Blink feature when the base::Feature is overridden by field
140 // trial or command line. Otherwise no change. Its difference from kDefault is
141 // that the Blink feature isn't affected by the default state of the
142 // base::Feature. This is useful for Blink origin trial features especially
143 // those implemented in both Chromium and Blink. As origin trial only controls
144 // the Blink features, for now we require the base::Feature to be enabled by
145 // default, but we don't want the default enabled status affect the Blink
146 // feature. See also https://crbug.com/1048656#c10.
147 // This can also be used for features that are enabled by default in Chromium
148 // but not in Blink on all platforms and we want to use the Blink status.
149 // However, we would prefer consistent Chromium and Blink status to this.
150 kSetOnlyIfOverridden,
151 };
152
153 template <typename T>
154 // Helper class that describes the desired actions for the runtime feature
155 // depending on a check for chromium base::Feature.
156 struct RuntimeFeatureToChromiumFeatureMap {
157 // This can be either an enabler function defined in web_runtime_features.cc
158 // or the string name of the feature in runtime_enabled_features.json5.
159 T feature_enabler;
160 // The chromium base::Feature to check.
161 const base::Feature& chromium_feature;
162 const RuntimeFeatureEnableOptions option = kDefault;
163 };
164
165 template <typename Enabler>
SetRuntimeFeatureFromChromiumFeature(const base::Feature & chromium_feature,RuntimeFeatureEnableOptions option,const Enabler & enabler)166 void SetRuntimeFeatureFromChromiumFeature(const base::Feature& chromium_feature,
167 RuntimeFeatureEnableOptions option,
168 const Enabler& enabler) {
169 using FeatureList = base::FeatureList;
170 const bool feature_enabled = FeatureList::IsEnabled(chromium_feature);
171 const bool is_overridden =
172 FeatureList::GetInstance()->IsFeatureOverridden(chromium_feature.name);
173 switch (option) {
174 case kSetOnlyIfOverridden:
175 if (is_overridden)
176 enabler(feature_enabled);
177 break;
178 case kDefault:
179 if (feature_enabled || is_overridden)
180 enabler(feature_enabled);
181 break;
182 default:
183 NOTREACHED();
184 }
185 }
186
187 // Sets blink runtime features that are either directly
188 // controlled by Chromium base::Feature or are overridden
189 // by base::Feature states.
SetRuntimeFeaturesFromChromiumFeatures()190 void SetRuntimeFeaturesFromChromiumFeatures() {
191 using wf = WebRuntimeFeatures;
192 // To add a runtime feature control, add a new
193 // RuntimeFeatureToChromiumFeatureMap entry here if there is a custom
194 // enabler function defined. Otherwise add the entry with string name
195 // in the next list.
196 const RuntimeFeatureToChromiumFeatureMap<void (*)(bool)>
197 blinkFeatureToBaseFeatureMapping[] =
198 {
199 // TODO(rodneyding): Sort features in alphabetical order
200 {wf::EnableWebUsb, features::kWebUsb},
201 {wf::EnableBlockingFocusWithoutUserActivation,
202 blink::features::kBlockingFocusWithoutUserActivation},
203 {wf::EnableNotificationContentImage, features::kNotificationContentImage,
204 kSetOnlyIfOverridden},
205 {wf::EnablePeriodicBackgroundSync, features::kPeriodicBackgroundSync},
206 {wf::EnableWebXR, features::kWebXr},
207 {wf::EnableWebXRARModule, features::kWebXrArModule},
208 {wf::EnableWebXRHitTest, features::kWebXrHitTest},
209 {wf::EnableWebXRAnchors, features::kWebXrIncubations},
210 {wf::EnableWebXRCameraAccess, features::kWebXrIncubations},
211 {wf::EnableWebXRDepth, features::kWebXrIncubations},
212 {wf::EnableWebXRImageTracking, features::kWebXrIncubations},
213 {wf::EnableWebXRLightEstimation, features::kWebXrIncubations},
214 {wf::EnableWebXRPlaneDetection, features::kWebXrIncubations},
215 {wf::EnableWebXRViewportScale, features::kWebXrIncubations},
216 {wf::EnableUserActivationSameOriginVisibility,
217 features::kUserActivationSameOriginVisibility},
218 {wf::EnableExpensiveBackgroundTimerThrottling,
219 features::kExpensiveBackgroundTimerThrottling},
220 {wf::EnableTimerThrottlingForHiddenFrames,
221 features::kTimerThrottlingForHiddenFrames},
222 {wf::EnableSendBeaconThrowForBlobWithNonSimpleType,
223 features::kSendBeaconThrowForBlobWithNonSimpleType},
224 {wf::EnablePaymentRequest, features::kWebPayments},
225 {wf::EnableSecurePaymentConfirmationDebug,
226 features::kSecurePaymentConfirmationDebug},
227 {wf::EnablePaymentHandlerMinimalUI, features::kWebPaymentsMinimalUI},
228 {wf::EnablePaymentApp, features::kServiceWorkerPaymentApps},
229 {wf::EnablePushSubscriptionChangeEvent,
230 features::kPushSubscriptionChangeEvent},
231 {wf::EnableGenericSensorExtraClasses, features::kGenericSensorExtraClasses},
232 {wf::EnableMediaCastOverlayButton, media::kMediaCastOverlayButton},
233 {wf::EnableLazyInitializeMediaControls,
234 features::kLazyInitializeMediaControls},
235 {wf::EnableMediaEngagementBypassAutoplayPolicies,
236 media::kMediaEngagementBypassAutoplayPolicies},
237 {wf::EnableAllowActivationDelegationAttr,
238 features::kAllowActivationDelegationAttr},
239 {wf::EnableLazyFrameLoading, features::kLazyFrameLoading},
240 {wf::EnableLazyFrameVisibleLoadTimeMetrics,
241 features::kLazyFrameVisibleLoadTimeMetrics},
242 {wf::EnableLazyImageLoading, features::kLazyImageLoading},
243 {wf::EnableLazyImageVisibleLoadTimeMetrics,
244 features::kLazyImageVisibleLoadTimeMetrics},
245 {wf::EnablePictureInPicture, media::kPictureInPicture},
246 {wf::EnableCacheInlineScriptCode, features::kCacheInlineScriptCode},
247 {wf::EnableExperimentalProductivityFeatures,
248 features::kExperimentalProductivityFeatures},
249 {wf::EnableFeaturePolicyForSandbox, features::kFeaturePolicyForSandbox},
250 {wf::EnableAccessibilityExposeDisplayNone,
251 features::kEnableAccessibilityExposeDisplayNone},
252 {wf::EnableAccessibilityExposeHTMLElement,
253 features::kEnableAccessibilityExposeHTMLElement},
254 {wf::EnableAccessibilityExposeIgnoredNodes,
255 features::kEnableAccessibilityExposeIgnoredNodes},
256 {wf::EnableAccessibilityUseAXPositionForDocumentMarkers,
257 features::kUseAXPositionForDocumentMarkers},
258 {wf::EnableAllowSyncXHRInPageDismissal,
259 blink::features::kAllowSyncXHRInPageDismissal},
260 {wf::EnableAutoplayIgnoresWebAudio, media::kAutoplayIgnoreWebAudio},
261 {wf::EnablePortals, blink::features::kPortals, kSetOnlyIfOverridden},
262 {wf::EnableImplicitRootScroller, blink::features::kImplicitRootScroller},
263 {wf::EnableTextFragmentAnchor, blink::features::kTextFragmentAnchor},
264 {wf::EnableBackgroundFetch, features::kBackgroundFetch},
265 {wf::EnableForcedColors, features::kForcedColors},
266 {wf::EnableFractionalScrollOffsets, features::kFractionalScrollOffsets},
267 #if defined(OS_ANDROID)
268 {wf::EnableGetDisplayMedia, features::kUserMediaScreenCapturing},
269 #endif
270 {wf::EnableGetCurrentBrowsingContextMedia,
271 blink::features::kRTCGetCurrentBrowsingContextMedia},
272 {wf::EnableSignedExchangePrefetchCacheForNavigations,
273 features::kSignedExchangePrefetchCacheForNavigations},
274 {wf::EnableSignedExchangeSubresourcePrefetch,
275 features::kSignedExchangeSubresourcePrefetch},
276 {wf::EnableIdleDetection, features::kIdleDetection, kSetOnlyIfOverridden},
277 {wf::EnableSkipTouchEventFilter, blink::features::kSkipTouchEventFilter},
278 {wf::EnableWebOTP, features::kWebOTP, kSetOnlyIfOverridden},
279 {wf::EnableClickPointerEvent, features::kClickPointerEvent},
280 {wf::EnableConsolidatedMovementXY, features::kConsolidatedMovementXY},
281 {wf::EnableCooperativeScheduling, features::kCooperativeScheduling},
282 {wf::EnableMouseSubframeNoImplicitCapture,
283 features::kMouseSubframeNoImplicitCapture},
284 {wf::EnableSubresourceWebBundles, features::kSubresourceWebBundles},
285 {wf::EnableCookieDeprecationMessages, features::kCookieDeprecationMessages},
286 {wf::EnableSameSiteByDefaultCookies,
287 net::features::kSameSiteByDefaultCookies},
288 {wf::EnableCookiesWithoutSameSiteMustBeSecure,
289 net::features::kCookiesWithoutSameSiteMustBeSecure},
290 {wf::EnablePointerLockOptions, features::kPointerLockOptions,
291 kSetOnlyIfOverridden},
292 {wf::EnableDocumentPolicy, features::kDocumentPolicy},
293 {wf::EnableDocumentPolicyNegotiation, features::kDocumentPolicyNegotiation},
294 {wf::EnableScrollUnification, features::kScrollUnification},
295 {wf::EnableNeverSlowMode, features::kNeverSlowMode},
296 {wf::EnableVideoPlaybackQuality, features::kVideoPlaybackQuality},
297 {wf::EnableBrowserVerifiedUserActivationKeyboard,
298 features::kBrowserVerifiedUserActivationKeyboard},
299 {wf::EnableBrowserVerifiedUserActivationMouse,
300 features::kBrowserVerifiedUserActivationMouse},
301 {wf::EnablePercentBasedScrolling, features::kPercentBasedScrolling},
302 #if defined(OS_ANDROID)
303 {wf::EnableWebNfc, features::kWebNfc, kSetOnlyIfOverridden},
304 #endif
305 {wf::EnableInstalledApp, features::kInstalledApp},
306 {wf::EnableWebAuthenticationGetAssertionFeaturePolicy,
307 device::kWebAuthGetAssertionFeaturePolicy},
308 {wf::EnableTransformInterop, blink::features::kTransformInterop},
309 {wf::EnableVideoWakeLockOptimisationHiddenMuted,
310 media::kWakeLockOptimisationHiddenMuted},
311 {wf::EnableMediaFeeds, media::kMediaFeeds},
312 {wf::EnableRestrictGamepadAccess, features::kRestrictGamepadAccess},
313 {wf::EnableCompositingOptimizations,
314 blink::features::kCompositingOptimizations},
315 {wf::EnableConversionMeasurementInfraSupport,
316 features::kConversionMeasurement},
317 {wf::EnableParseUrlProtocolHandler,
318 blink::features::kWebAppEnableProtocolHandlers},
319 {wf::EnableWebID, features::kWebID},
320 {wf::EnableWheelEventRegions, features::kWheelEventRegions},
321 };
322 for (const auto& mapping : blinkFeatureToBaseFeatureMapping) {
323 SetRuntimeFeatureFromChromiumFeature(
324 mapping.chromium_feature, mapping.option, mapping.feature_enabler);
325 }
326
327 // TODO(crbug/832393): Cleanup the inconsistency between custom WRF enabler
328 // function and using feature string name with EnableFeatureFromString.
329 const RuntimeFeatureToChromiumFeatureMap<const char*>
330 runtimeFeatureNameToChromiumFeatureMapping[] = {
331 {"AddressSpace", features::kBlockInsecurePrivateNetworkRequests},
332 {"AllowContentInitiatedDataUrlNavigations",
333 features::kAllowContentInitiatedDataUrlNavigations},
334 {"AndroidDownloadableFontsMatching",
335 features::kAndroidDownloadableFontsMatching},
336 {"AudioWorkletRealtimeThread",
337 blink::features::kAudioWorkletRealtimeThread},
338 {"BlockCredentialedSubresources",
339 features::kBlockCredentialedSubresources},
340 {"BlockHTMLParserOnStyleSheets",
341 blink::features::kBlockHTMLParserOnStyleSheets},
342 {"CSSColorSchemeUARendering", features::kCSSColorSchemeUARendering},
343 {"CSSReducedFontLoadingLayoutInvalidations",
344 blink::features::kCSSReducedFontLoadingLayoutInvalidations},
345 {"CSSMatchedPropertiesCacheDependencies",
346 blink::features::kCSSMatchedPropertiesCacheDependencies},
347 {"FeaturePolicyForClientHints",
348 features::kFeaturePolicyForClientHints},
349 {"EditingNG", blink::features::kEditingNG},
350 {"FlexAspectRatio", blink::features::kFlexAspectRatio},
351 {"FontAccess", blink::features::kFontAccess},
352 {"FontSrcLocalMatching", features::kFontSrcLocalMatching},
353 {"ForceSynchronousHTMLParsing",
354 blink::features::kForceSynchronousHTMLParsing},
355 {"IgnoreCrossOriginWindowWhenNamedAccessOnWindow",
356 blink::features::kIgnoreCrossOriginWindowWhenNamedAccessOnWindow},
357 {"LangClientHintHeader", features::kLangClientHintHeader},
358 {"LayoutNG", blink::features::kLayoutNG},
359 {"LayoutNGFieldset", blink::features::kLayoutNGFieldset},
360 {"LayoutNGFragmentItem", blink::features::kFragmentItem},
361 {"LegacyWindowsDWriteFontFallback",
362 features::kLegacyWindowsDWriteFontFallback},
363 {"LinkDisabledNewSpecBehavior",
364 blink::features::kLinkDisabledNewSpecBehavior},
365 {"OriginPolicy", features::kOriginPolicy},
366 {"OriginIsolationHeader", features::kOriginIsolationHeader},
367 {"ParentNodeReplaceChildren",
368 blink::features::kParentNodeReplaceChildren},
369 {"RawClipboard", blink::features::kRawClipboard},
370 {"StorageAccessAPI", blink::features::kStorageAccessAPI},
371 {"TargetBlankImpliesNoOpener",
372 blink::features::kTargetBlankImpliesNoOpener},
373 {"TrustedDOMTypes", features::kTrustedDOMTypes},
374 {"UserAgentClientHint", features::kUserAgentClientHint},
375 {"WebAppManifestDisplayOverride",
376 features::kWebAppManifestDisplayOverride},
377 {"WebAppWindowControlsOverlay",
378 features::kWebAppWindowControlsOverlay},
379 {"WebXRMultiGpu", blink::features::kWebXrMultiGpu},
380 };
381 for (const auto& mapping : runtimeFeatureNameToChromiumFeatureMapping) {
382 SetRuntimeFeatureFromChromiumFeature(
383 mapping.chromium_feature, mapping.option, [&mapping](bool enabled) {
384 wf::EnableFeatureFromString(mapping.feature_enabler, enabled);
385 });
386 }
387 }
388
389 // Helper class that describes the desired enable/disable action
390 // for a runtime feature when a command line switch exists.
391 struct SwitchToFeatureMap {
392 // The enabler function defined in web_runtime_features.cc.
393 void (*feature_enabler)(bool);
394 // The switch to check for on command line.
395 const char* switch_name;
396 // This is the desired state for the runtime feature if the
397 // switch exists on command line.
398 bool target_enabled_state;
399 };
400
401 // Sets blink runtime features controlled by command line switches.
SetRuntimeFeaturesFromCommandLine(const base::CommandLine & command_line)402 void SetRuntimeFeaturesFromCommandLine(const base::CommandLine& command_line) {
403 // To add a new switch-controlled runtime feature, add a new
404 // SwitchToFeatureMap entry to the initializer list below.
405 // Note: command line switches are now discouraged, please consider
406 // using base::Feature instead.
407 // https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/configuration.md#switches
408 using wrf = WebRuntimeFeatures;
409 const SwitchToFeatureMap switchToFeatureMapping[] = {
410 // Stable Features
411 {wrf::EnablePermissionsAPI, switches::kDisablePermissionsAPI, false},
412 {wrf::EnablePresentationAPI, switches::kDisablePresentationAPI, false},
413 {wrf::EnableRemotePlaybackAPI, switches::kDisableRemotePlaybackAPI,
414 false},
415 {wrf::EnableTargetBlankImpliesNoOpener,
416 switches::kDisableTargetBlankImpliesNoOpener, false},
417 {wrf::EnableTimerThrottlingForBackgroundTabs,
418 switches::kDisableBackgroundTimerThrottling, false},
419 // End of Stable Features
420 {wrf::EnableDatabase, switches::kDisableDatabases, false},
421 {wrf::EnableNotifications, switches::kDisableNotifications, false},
422 // Chrome's Push Messaging implementation relies on Web Notifications.
423 {wrf::EnablePushMessaging, switches::kDisableNotifications, false},
424 {wrf::EnableSharedWorker, switches::kDisableSharedWorkers, false},
425 {wrf::EnableScriptedSpeechRecognition, switches::kDisableSpeechAPI,
426 false},
427 {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechAPI, false},
428 {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechSynthesisAPI,
429 false},
430 {wrf::EnableFileSystem, switches::kDisableFileSystem, false},
431 {wrf::EnableWebGLDraftExtensions, switches::kEnableWebGLDraftExtensions,
432 true},
433 {wrf::EnableAutomationControlled, switches::kEnableAutomation, true},
434 {wrf::EnableAutomationControlled, switches::kHeadless, true},
435 {wrf::EnableAutomationControlled, switches::kRemoteDebuggingPipe, true},
436 {wrf::ForceOverlayFullscreenVideo, switches::kForceOverlayFullscreenVideo,
437 true},
438 {wrf::EnablePreciseMemoryInfo, switches::kEnablePreciseMemoryInfo, true},
439 {wrf::EnableNetInfoDownlinkMax,
440 switches::kEnableNetworkInformationDownlinkMax, true},
441 {wrf::EnableWebGPU, switches::kEnableUnsafeWebGPU, true},
442 {wrf::EnableTextFragmentAnchor, switches::kDisableScrollToTextFragment,
443 false},
444 {wrf::EnableAccessibilityObjectModel,
445 switches::kEnableAccessibilityObjectModel, true},
446 {wrf::EnableAllowSyncXHRInPageDismissal,
447 switches::kAllowSyncXHRInPageDismissal, true},
448 };
449 for (const auto& mapping : switchToFeatureMapping) {
450 if (command_line.HasSwitch(mapping.switch_name))
451 mapping.feature_enabler(mapping.target_enabled_state);
452 }
453
454 // Set EnableAutomationControlled if the caller passes
455 // --remote-debugging-port=0 on the command line. This means
456 // the caller has requested an ephemeral port which is how ChromeDriver
457 // launches the browser by default.
458 // If the caller provides a specific port number, this is
459 // more likely for attaching a debugger, so we should leave
460 // EnableAutomationControlled unset to ensure the browser behaves as it does
461 // when not under automation control.
462 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
463 std::string port_str =
464 command_line.GetSwitchValueASCII(::switches::kRemoteDebuggingPort);
465 int port;
466 if (base::StringToInt(port_str, &port) && port == 0) {
467 WebRuntimeFeatures::EnableAutomationControlled(true);
468 }
469 }
470 }
471
472 // Sets blink runtime features controlled by FieldTrial parameter values.
SetRuntimeFeaturesFromFieldTrialParams()473 void SetRuntimeFeaturesFromFieldTrialParams() {
474 // Automatic lazy frame loading by default is enabled and restricted to users
475 // with Lite Mode (aka Data Saver) turned on. Note that in practice, this also
476 // restricts automatic lazy loading by default to Android, since Lite Mode is
477 // only accessible through UI on Android.
478 WebRuntimeFeatures::EnableAutomaticLazyFrameLoading(
479 base::GetFieldTrialParamByFeatureAsBool(
480 features::kLazyFrameLoading, "automatic-lazy-load-frames-enabled",
481 true));
482 WebRuntimeFeatures::EnableRestrictAutomaticLazyFrameLoadingToDataSaver(
483 base::GetFieldTrialParamByFeatureAsBool(
484 features::kLazyFrameLoading,
485 "restrict-lazy-load-frames-to-data-saver-only", true));
486 WebRuntimeFeatures::EnableAutoLazyLoadOnReloads(
487 base::GetFieldTrialParamByFeatureAsBool(
488 features::kLazyFrameLoading, "enable-lazy-load-on-reload", false));
489
490 // Automatic lazy image loading by default is enabled and restricted to users
491 // with Lite Mode (aka Data Saver) turned on. Note that in practice, this also
492 // restricts automatic lazy loading by default to Android, since Lite Mode is
493 // only accessible through UI on Android.
494 WebRuntimeFeatures::EnableAutomaticLazyImageLoading(
495 base::GetFieldTrialParamByFeatureAsBool(
496 features::kLazyImageLoading, "automatic-lazy-load-images-enabled",
497 true));
498 WebRuntimeFeatures::EnableRestrictAutomaticLazyImageLoadingToDataSaver(
499 base::GetFieldTrialParamByFeatureAsBool(
500 features::kLazyImageLoading,
501 "restrict-lazy-load-images-to-data-saver-only", true));
502 }
503
504 // Sets blink runtime features that depend on a combination
505 // of args rather than a single check of base::Feature or switch.
506 // This can be a combination of both or custom checking logic
507 // not covered by other functions. In short, this should be used
508 // as a last resort.
SetCustomizedRuntimeFeaturesFromCombinedArgs(const base::CommandLine & command_line)509 void SetCustomizedRuntimeFeaturesFromCombinedArgs(
510 const base::CommandLine& command_line) {
511 // CAUTION: Only add custom enabling logic here if it cannot
512 // be covered by the other functions.
513
514 if (!command_line.HasSwitch(switches::kDisableYUVImageDecoding) &&
515 base::FeatureList::IsEnabled(
516 blink::features::kDecodeJpeg420ImagesToYUV)) {
517 WebRuntimeFeatures::EnableDecodeJpeg420ImagesToYUV(true);
518 }
519 if (!command_line.HasSwitch(switches::kDisableYUVImageDecoding) &&
520 base::FeatureList::IsEnabled(
521 blink::features::kDecodeLossyWebPImagesToYUV)) {
522 WebRuntimeFeatures::EnableDecodeLossyWebPImagesToYUV(true);
523 }
524
525 WebRuntimeFeatures::EnableSharedArrayBuffer(
526 base::FeatureList::IsEnabled(features::kSharedArrayBuffer) ||
527 base::FeatureList::IsEnabled(features::kWebAssemblyThreads));
528
529 // These checks are custom wrappers around base::FeatureList::IsEnabled
530 // They're moved here to distinguish them from actual base checks
531 WebRuntimeFeatures::EnableOverlayScrollbars(ui::IsOverlayScrollbarEnabled());
532
533 if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI)) {
534 WebRuntimeFeatures::EnableFeatureFromString("FileHandling", true);
535 }
536
537 // TODO(rodneyding): This is a rare case for a stable feature
538 // Need to investigate more to determine whether to refactor it.
539 if (command_line.HasSwitch(switches::kDisableV8IdleTasks))
540 WebRuntimeFeatures::EnableV8IdleTasks(false);
541 else
542 WebRuntimeFeatures::EnableV8IdleTasks(true);
543
544 WebRuntimeFeatures::EnableBackForwardCache(
545 content::IsBackForwardCacheEnabled());
546
547 if (base::FeatureList::IsEnabled(features::kDirectSockets))
548 WebRuntimeFeatures::EnableDirectSockets(true);
549
550 if (base::FeatureList::IsEnabled(
551 blink::features::kAppCacheRequireOriginTrial)) {
552 // The kAppCacheRequireOriginTrial is a flag that controls whether or not
553 // the renderer AppCache api and backend is gated by an origin trial. If
554 // on, then AppCache is disabled but can be re-enabled by the origin trial.
555 // The origin trial will not turn on the feature if the base::Feature
556 // AppCache is disabled.
557 WebRuntimeFeatures::EnableFeatureFromString("AppCache", false);
558 } else {
559 // If the origin trial is not required, then the kAppCache feature /
560 // about:flag is a disable-only kill switch to allow developers to test
561 // their application with AppCache fully disabled.
562 if (!base::FeatureList::IsEnabled(blink::features::kAppCache))
563 WebRuntimeFeatures::EnableFeatureFromString("AppCache", false);
564 }
565
566 if (base::FeatureList::IsEnabled(network::features::kTrustTokens)) {
567 // See https://bit.ly/configuring-trust-tokens.
568 using network::features::TrustTokenOriginTrialSpec;
569 switch (
570 network::features::kTrustTokenOperationsRequiringOriginTrial.Get()) {
571 case TrustTokenOriginTrialSpec::kOriginTrialNotRequired:
572 // Setting TrustTokens=true enables the Trust Tokens interface;
573 // TrustTokensAlwaysAllowIssuance disables a runtime check during
574 // issuance that the origin trial is active (see
575 // blink/.../trust_token_issuance_authorization.h).
576 WebRuntimeFeatures::EnableTrustTokens(true);
577 WebRuntimeFeatures::EnableTrustTokensAlwaysAllowIssuance(true);
578 break;
579 case TrustTokenOriginTrialSpec::kAllOperationsRequireOriginTrial:
580 // The origin trial itself will be responsible for enabling the
581 // TrustTokens RuntimeEnabledFeature.
582 WebRuntimeFeatures::EnableTrustTokens(false);
583 WebRuntimeFeatures::EnableTrustTokensAlwaysAllowIssuance(false);
584 break;
585 case TrustTokenOriginTrialSpec::kOnlyIssuanceRequiresOriginTrial:
586 // At issuance, a runtime check will be responsible for checking that
587 // the origin trial is present.
588 WebRuntimeFeatures::EnableTrustTokens(true);
589 WebRuntimeFeatures::EnableTrustTokensAlwaysAllowIssuance(false);
590 break;
591 }
592 }
593 }
594
595 // Ensures that the various ways of enabling/disabling features do not produce
596 // an invalid configuration.
ResolveInvalidConfigurations()597 void ResolveInvalidConfigurations() {
598 // Portals cannot be enabled without the support of the browser process.
599 if (!base::FeatureList::IsEnabled(blink::features::kPortals)) {
600 LOG_IF(WARNING, WebRuntimeFeatures::IsPortalsEnabled())
601 << "Portals cannot be enabled in this configuration. Use --"
602 << switches::kEnableFeatures << "=" << blink::features::kPortals.name
603 << " instead.";
604 WebRuntimeFeatures::EnablePortals(false);
605 }
606 }
607
608 } // namespace
609
610 namespace content {
611
SetRuntimeFeaturesDefaultsAndUpdateFromArgs(const base::CommandLine & command_line)612 void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
613 const base::CommandLine& command_line) {
614 // Sets experimental features.
615 bool enable_experimental_web_platform_features =
616 command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
617 bool enable_blink_test_features =
618 command_line.HasSwitch(switches::kEnableBlinkTestFeatures);
619
620 if (enable_blink_test_features) {
621 enable_experimental_web_platform_features = true;
622 WebRuntimeFeatures::EnableTestOnlyFeatures(true);
623 }
624
625 if (enable_experimental_web_platform_features)
626 WebRuntimeFeatures::EnableExperimentalFeatures(true);
627
628 SetRuntimeFeatureDefaultsForPlatform(command_line);
629
630 // Sets origin trial features.
631 if (command_line.HasSwitch(
632 switches::kDisableOriginTrialControlledBlinkFeatures)) {
633 WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
634 }
635
636 // TODO(rodneyding): add doc explaining ways to add new runtime features
637 // controls in the following functions.
638
639 SetRuntimeFeaturesFromChromiumFeatures();
640
641 SetRuntimeFeaturesFromCommandLine(command_line);
642
643 SetRuntimeFeaturesFromFieldTrialParams();
644
645 SetCustomizedRuntimeFeaturesFromCombinedArgs(command_line);
646
647 // Enable explicitly enabled features, and then disable explicitly disabled
648 // ones.
649 for (const std::string& feature :
650 FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
651 WebRuntimeFeatures::EnableFeatureFromString(feature, true);
652 }
653 for (const std::string& feature :
654 FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
655 WebRuntimeFeatures::EnableFeatureFromString(feature, false);
656 }
657
658 ResolveInvalidConfigurations();
659 }
660
661 } // namespace content
662