1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/runtime_features.h"
10 #include "base/base_switches.h"
11 #include "base/command_line.h"
12 #include "base/feature_list.h"
13 #include "base/memory/raw_ref.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/field_trial_params.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "build/build_config.h"
19 #include "build/chromeos_buildflags.h"
20 #include "cc/base/features.h"
21 #include "components/attribution_reporting/features.h"
22 #include "components/permissions/features.h"
23 #include "content/common/content_navigation_policy.h"
24 #include "content/common/content_switches_internal.h"
25 #include "content/common/features.h"
26 #include "content/public/common/content_features.h"
27 #include "content/public/common/content_switches.h"
28 #include "device/base/features.h"
29 #include "device/fido/features.h"
30 #include "device/gamepad/public/cpp/gamepad_features.h"
31 #include "device/vr/buildflags/buildflags.h"
32 #include "gpu/config/gpu_finch_features.h"
33 #include "gpu/config/gpu_switches.h"
34 #include "media/base/media_switches.h"
35 #include "net/base/features.h"
36 #include "services/device/public/cpp/device_features.h"
37 #include "services/network/public/cpp/features.h"
38 #include "third_party/blink/public/common/buildflags.h"
39 #include "third_party/blink/public/common/features.h"
40 #include "third_party/blink/public/common/loader/referrer_utils.h"
41 #include "third_party/blink/public/common/switches.h"
42 #include "third_party/blink/public/platform/web_runtime_features.h"
43 #include "ui/accessibility/accessibility_features.h"
44 #include "ui/base/ui_base_features.h"
45 #include "ui/events/blink/blink_features.h"
46 #include "ui/gfx/switches.h"
47 #include "ui/gl/gl_switches.h"
48 #include "ui/native_theme/native_theme_features.h"
50 #if BUILDFLAG(IS_ANDROID)
51 #include "base/android/build_info.h"
54 #if BUILDFLAG(ENABLE_VR)
55 #include "device/vr/public/cpp/features.h"
58 using blink::WebRuntimeFeatures;
62 // Sets blink runtime features for specific platforms.
63 // This should be a last resort vs runtime_enabled_features.json5.
64 void SetRuntimeFeatureDefaultsForPlatform(
65 const base::CommandLine& command_line) {
66 // Please consider setting up feature defaults for different platforms
67 // in runtime_enabled_features.json5 instead of here
68 // TODO(rodneyding): Move the more common cases here
69 // to baseFeature/switch functions below and move more complex
70 // ones to special case functions.
72 WebRuntimeFeatures::EnableCompositedSelectionUpdate(true);
75 #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS_LACROS)
76 const bool enable_canvas_2d_image_chromium =
77 command_line.HasSwitch(
78 blink::switches::kEnableGpuMemoryBufferCompositorResources) &&
79 !command_line.HasSwitch(switches::kDisable2dCanvasImageChromium) &&
80 !command_line.HasSwitch(switches::kDisableGpu) &&
81 base::FeatureList::IsEnabled(features::kCanvas2DImageChromium);
83 constexpr bool enable_canvas_2d_image_chromium = false;
85 WebRuntimeFeatures::EnableCanvas2dImageChromium(
86 enable_canvas_2d_image_chromium);
88 #if BUILDFLAG(IS_APPLE)
89 const bool enable_web_gl_image_chromium =
90 command_line.HasSwitch(
91 blink::switches::kEnableGpuMemoryBufferCompositorResources) &&
92 !command_line.HasSwitch(switches::kDisableWebGLImageChromium) &&
93 !command_line.HasSwitch(switches::kDisableGpu) &&
94 base::FeatureList::IsEnabled(features::kWebGLImageChromium);
96 const bool enable_web_gl_image_chromium =
97 command_line.HasSwitch(switches::kEnableWebGLImageChromium);
99 WebRuntimeFeatures::EnableWebGLImageChromium(enable_web_gl_image_chromium);
101 #if BUILDFLAG(IS_ANDROID)
102 if (command_line.HasSwitch(switches::kDisableMediaSessionAPI)) {
103 WebRuntimeFeatures::EnableMediaSession(false);
107 #if BUILDFLAG(IS_ANDROID)
108 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
109 base::android::SDK_VERSION_P) {
110 // Display Cutout is limited to Android P+.
111 WebRuntimeFeatures::EnableDisplayCutoutAPI(true);
115 #if BUILDFLAG(IS_ANDROID)
116 WebRuntimeFeatures::EnableMediaControlsExpandGesture(
117 base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture));
120 #if BUILDFLAG(IS_EFL)
121 // No plan to support complex UI for date/time INPUT types.
122 WebRuntimeFeatures::EnableInputMultipleFieldsUI(false);
124 // Small accelerated 2d canvas has tct issues, which are known in
125 // upstream version also.
126 WebRuntimeFeatures::EnableAcceleratedSmallCanvases(false);
130 enum RuntimeFeatureEnableOptions {
131 // - If the base::Feature default is overridden by field trial or command
132 // line, set Blink feature to the state of the base::Feature;
133 // - Otherwise if the base::Feature is enabled, enable the Blink feature.
134 // - Otherwise no change.
136 // Enables the Blink feature when the base::Feature is overridden by field
137 // trial or command line. Otherwise no change. Its difference from kDefault is
138 // that the Blink feature isn't affected by the default state of the
139 // base::Feature. This is useful for Blink origin trial features especially
140 // those implemented in both Chromium and Blink. As origin trial only controls
141 // the Blink features, for now we require the base::Feature to be enabled by
142 // default, but we don't want the default enabled status affect the Blink
143 // feature. See also https://crbug.com/1048656#c10.
144 // This can also be used for features that are enabled by default in Chromium
145 // but not in Blink on all platforms and we want to use the Blink status.
146 // However, we would prefer consistent Chromium and Blink status to this.
147 kSetOnlyIfOverridden,
150 template <typename T>
151 // Helper class that describes the desired actions for the runtime feature
152 // depending on a check for chromium base::Feature.
153 struct RuntimeFeatureToChromiumFeatureMap {
154 // This can be either an enabler function defined in web_runtime_features.cc
155 // or the string name of the feature in runtime_enabled_features.json5.
157 // The chromium base::Feature to check.
158 const raw_ref<const base::Feature> chromium_feature;
159 const RuntimeFeatureEnableOptions option = kDefault;
162 template <typename Enabler>
163 void SetRuntimeFeatureFromChromiumFeature(const base::Feature& chromium_feature,
164 RuntimeFeatureEnableOptions option,
165 const Enabler& enabler) {
166 using FeatureList = base::FeatureList;
167 const bool feature_enabled = FeatureList::IsEnabled(chromium_feature);
168 const bool is_overridden =
169 FeatureList::GetInstance()->IsFeatureOverridden(chromium_feature.name);
171 case kSetOnlyIfOverridden:
173 enabler(feature_enabled);
177 if (feature_enabled || is_overridden) {
178 enabler(feature_enabled);
186 // Sets blink runtime features that are either directly
187 // controlled by Chromium base::Feature or are overridden
188 // by base::Feature states.
189 void SetRuntimeFeaturesFromChromiumFeatures() {
190 using wf = WebRuntimeFeatures;
191 // To add a runtime feature control, add a new
192 // RuntimeFeatureToChromiumFeatureMap entry here if there is a custom
193 // enabler function defined. Otherwise add the entry with string name
195 const RuntimeFeatureToChromiumFeatureMap<void (*)(bool)>
196 blinkFeatureToBaseFeatureMapping[] =
197 { {wf::EnableAccessibilityAriaVirtualContent,
198 raw_ref(features::kEnableAccessibilityAriaVirtualContent)},
199 {wf::EnableAccessibilityExposeHTMLElement,
200 raw_ref(features::kEnableAccessibilityExposeHTMLElement)},
201 {wf::EnableAccessibilityExposeIgnoredNodes,
202 raw_ref(features::kEnableAccessibilityExposeIgnoredNodes)},
203 #if BUILDFLAG(IS_ANDROID)
204 {wf::EnableAccessibilityPageZoom,
205 raw_ref(features::kAccessibilityPageZoom)},
206 {wf::EnableAutoDisableAccessibilityV2,
207 raw_ref(features::kAutoDisableAccessibilityV2)},
209 {wf::EnableAccessibilityUseAXPositionForDocumentMarkers,
210 raw_ref(features::kUseAXPositionForDocumentMarkers)},
211 {wf::EnableAOMAriaRelationshipProperties,
212 raw_ref(features::kEnableAriaElementReflection)},
213 {wf::EnableAutoplayIgnoresWebAudio,
214 raw_ref(media::kAutoplayIgnoreWebAudio)},
215 {wf::EnableBackgroundFetch, raw_ref(features::kBackgroundFetch)},
216 {wf::EnableBrowserVerifiedUserActivationKeyboard,
217 raw_ref(features::kBrowserVerifiedUserActivationKeyboard)},
218 {wf::EnableBrowserVerifiedUserActivationMouse,
219 raw_ref(features::kBrowserVerifiedUserActivationMouse)},
220 {wf::EnableCompositeBGColorAnimation,
221 raw_ref(features::kCompositeBGColorAnimation)},
222 {wf::EnableCompositeClipPathAnimation,
223 raw_ref(features::kCompositeClipPathAnimation)},
224 {wf::EnableConsolidatedMovementXY,
225 raw_ref(features::kConsolidatedMovementXY)},
226 {wf::EnableCooperativeScheduling,
227 raw_ref(features::kCooperativeScheduling)},
228 {wf::EnableDevicePosture, raw_ref(features::kDevicePosture)},
229 {wf::EnableDigitalGoods, raw_ref(features::kDigitalGoodsApi),
230 kSetOnlyIfOverridden},
231 {wf::EnableDocumentPolicy, raw_ref(features::kDocumentPolicy)},
232 {wf::EnableDocumentPolicyNegotiation,
233 raw_ref(features::kDocumentPolicyNegotiation)},
234 {wf::EnableFedCm, raw_ref(features::kFedCm), kSetOnlyIfOverridden},
235 {wf::EnableFedCmAutoSelectedFlag, raw_ref(features::kFedCmAutoSelectedFlag),
236 kSetOnlyIfOverridden},
237 {wf::EnableFedCmAuthz, raw_ref(features::kFedCmAuthz), kDefault},
238 {wf::EnableFedCmError, raw_ref(features::kFedCmError),
239 kSetOnlyIfOverridden},
240 {wf::EnableFedCmDomainHint, raw_ref(features::kFedCmDomainHint),
241 kSetOnlyIfOverridden},
242 {wf::EnableFedCmIdPRegistration, raw_ref(features::kFedCmIdPRegistration),
244 {wf::EnableFedCmIdpSigninStatus,
245 raw_ref(features::kFedCmIdpSigninStatusEnabled), kSetOnlyIfOverridden},
246 {wf::EnableFedCmIdpSignout, raw_ref(features::kFedCmLogoutRps),
247 kSetOnlyIfOverridden},
248 {wf::EnableGamepadMultitouch, raw_ref(features::kEnableGamepadMultitouch)},
249 {wf::EnableSharedStorageAPI,
250 raw_ref(features::kPrivacySandboxAdsAPIsOverride), kSetOnlyIfOverridden},
251 {wf::EnableSharedStorageAPI,
252 raw_ref(features::kPrivacySandboxAdsAPIsM1Override), kSetOnlyIfOverridden},
253 {wf::EnableSharedStorageAPIM118,
254 raw_ref(blink::features::kSharedStorageAPIM118), kSetOnlyIfOverridden},
255 {wf::EnableFedCmMultipleIdentityProviders,
256 raw_ref(features::kFedCmMultipleIdentityProviders), kDefault},
257 {wf::EnableFedCmRevoke, raw_ref(features::kFedCmRevoke),
258 kSetOnlyIfOverridden},
259 {wf::EnableFedCmSelectiveDisclosure,
260 raw_ref(features::kFedCmSelectiveDisclosure), kDefault},
261 {wf::EnableFencedFrames, raw_ref(features::kPrivacySandboxAdsAPIsOverride),
262 kSetOnlyIfOverridden},
263 {wf::EnableFencedFrames,
264 raw_ref(features::kPrivacySandboxAdsAPIsM1Override), kSetOnlyIfOverridden},
265 {wf::EnableForcedColors, raw_ref(features::kForcedColors)},
266 {wf::EnableFractionalScrollOffsets,
267 raw_ref(features::kFractionalScrollOffsets)},
268 {wf::EnableSensorExtraClasses,
269 raw_ref(features::kGenericSensorExtraClasses)},
270 #if BUILDFLAG(IS_ANDROID)
271 {wf::EnableGetDisplayMedia, raw_ref(features::kUserMediaScreenCapturing)},
273 {wf::EnableIdleDetection, raw_ref(features::kIdleDetection),
274 kSetOnlyIfOverridden},
275 {wf::EnableInstalledApp, raw_ref(features::kInstalledApp)},
276 {wf::EnableLazyInitializeMediaControls,
277 raw_ref(features::kLazyInitializeMediaControls)},
278 {wf::EnableLazyFrameLoading, raw_ref(features::kLazyFrameLoading)},
279 {wf::EnableMachineLearningModelLoader,
280 raw_ref(features::kEnableMachineLearningModelLoaderWebPlatformApi),
281 kSetOnlyIfOverridden},
282 {wf::EnableMediaCastOverlayButton, raw_ref(media::kMediaCastOverlayButton)},
283 {wf::EnableMediaEngagementBypassAutoplayPolicies,
284 raw_ref(media::kMediaEngagementBypassAutoplayPolicies)},
285 {wf::EnableNotificationContentImage,
286 raw_ref(features::kNotificationContentImage), kSetOnlyIfOverridden},
287 {wf::EnablePaymentApp, raw_ref(features::kServiceWorkerPaymentApps)},
288 {wf::EnablePaymentRequest, raw_ref(features::kWebPayments)},
289 {wf::EnablePercentBasedScrolling,
290 raw_ref(features::kWindowsScrollingPersonality)},
291 {wf::EnablePeriodicBackgroundSync,
292 raw_ref(features::kPeriodicBackgroundSync)},
293 {wf::EnablePushMessagingSubscriptionChange,
294 raw_ref(features::kPushSubscriptionChangeEvent)},
295 {wf::EnableRestrictGamepadAccess,
296 raw_ref(features::kRestrictGamepadAccess)},
297 {wf::EnableSecurePaymentConfirmation,
298 raw_ref(features::kSecurePaymentConfirmation)},
299 {wf::EnableSecurePaymentConfirmationDebug,
300 raw_ref(features::kSecurePaymentConfirmationDebug)},
301 {wf::EnableSendBeaconThrowForBlobWithNonSimpleType,
302 raw_ref(features::kSendBeaconThrowForBlobWithNonSimpleType)},
303 {wf::EnableSharedArrayBuffer, raw_ref(features::kSharedArrayBuffer)},
304 {wf::EnableSharedArrayBufferOnDesktop,
305 raw_ref(features::kSharedArrayBufferOnDesktop)},
306 #if BUILDFLAG(IS_ANDROID)
307 {wf::EnableSmartZoom, raw_ref(features::kSmartZoom)},
309 {wf::EnableTouchDragAndContextMenu,
310 raw_ref(features::kTouchDragAndContextMenu)},
311 {wf::EnableUserActivationSameOriginVisibility,
312 raw_ref(features::kUserActivationSameOriginVisibility)},
313 {wf::EnableVideoPlaybackQuality, raw_ref(features::kVideoPlaybackQuality)},
314 {wf::EnableViewportSegments, raw_ref(features::kViewportSegments)},
315 {wf::EnableWebBluetooth, raw_ref(features::kWebBluetooth),
316 kSetOnlyIfOverridden},
317 {wf::EnableWebBluetoothGetDevices,
318 raw_ref(features::kWebBluetoothNewPermissionsBackend),
319 kSetOnlyIfOverridden},
320 {wf::EnableWebBluetoothWatchAdvertisements,
321 raw_ref(features::kWebBluetoothNewPermissionsBackend),
322 kSetOnlyIfOverridden},
323 #if BUILDFLAG(IS_ANDROID)
324 {wf::EnableWebNFC, raw_ref(features::kWebNfc), kSetOnlyIfOverridden},
326 {wf::EnableWebIdentityDigitalCredentials,
327 raw_ref(features::kWebIdentityDigitalCredentials), kDefault},
328 {wf::EnableWebOTP, raw_ref(features::kWebOTP), kSetOnlyIfOverridden},
329 {wf::EnableWebOTPAssertionFeaturePolicy,
330 raw_ref(features::kWebOTPAssertionFeaturePolicy), kSetOnlyIfOverridden},
331 {wf::EnableWebUSB, raw_ref(features::kWebUsb)},
332 {wf::EnableWebXR, raw_ref(features::kWebXr)},
333 #if BUILDFLAG(ENABLE_VR)
334 {wf::EnableWebXRFrontFacing, raw_ref(device::features::kWebXrIncubations)},
335 {wf::EnableWebXRFrameRate, raw_ref(device::features::kWebXrIncubations)},
336 {wf::EnableWebXRHandInput, raw_ref(device::features::kWebXrHandInput)},
337 {wf::EnableWebXRImageTracking,
338 raw_ref(device::features::kWebXrIncubations)},
339 {wf::EnableWebXRLayers, raw_ref(device::features::kWebXrLayers)},
340 {wf::EnableWebXRPlaneDetection,
341 raw_ref(device::features::kWebXrIncubations)},
342 {wf::EnableWebXRPoseMotionData,
343 raw_ref(device::features::kWebXrIncubations)},
345 {wf::EnableRemoveMobileViewportDoubleTap,
346 raw_ref(features::kRemoveMobileViewportDoubleTap)},
347 {wf::EnableServiceWorkerBypassFetchHandler,
348 raw_ref(features::kServiceWorkerBypassFetchHandler)},
349 {wf::EnableServiceWorkerStaticRouter,
350 raw_ref(features::kServiceWorkerStaticRouter)},
352 for (const auto& mapping : blinkFeatureToBaseFeatureMapping) {
353 SetRuntimeFeatureFromChromiumFeature(
354 *mapping.chromium_feature, mapping.option, mapping.feature_enabler);
357 // TODO(crbug/832393): Cleanup the inconsistency between custom WRF enabler
358 // function and using feature string name with EnableFeatureFromString.
359 const RuntimeFeatureToChromiumFeatureMap<const char*>
360 runtimeFeatureNameToChromiumFeatureMapping[] =
361 { {"AllowContentInitiatedDataUrlNavigations",
362 raw_ref(features::kAllowContentInitiatedDataUrlNavigations)},
363 {"AllowURNsInIframes", raw_ref(blink::features::kAllowURNsInIframes)},
364 {"AllowURNsInIframes", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
365 kSetOnlyIfOverridden},
366 {"AllowURNsInIframes", raw_ref(features::kPrivacySandboxAdsAPIsM1Override),
367 kSetOnlyIfOverridden},
368 {"AttributionReporting", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
369 kSetOnlyIfOverridden},
370 {"AttributionReporting",
371 raw_ref(features::kPrivacySandboxAdsAPIsM1Override), kSetOnlyIfOverridden},
372 {"AttributionReportingCrossAppWeb",
373 raw_ref(features::kPrivacySandboxAdsAPIsOverride), kSetOnlyIfOverridden},
374 {"AndroidDownloadableFontsMatching",
375 raw_ref(features::kAndroidDownloadableFontsMatching)},
376 #if BUILDFLAG(IS_ANDROID)
377 {"CCTNewRFMPushBehavior", raw_ref(blink::features::kCCTNewRFMPushBehavior)},
379 {"CompressionDictionaryTransport",
380 raw_ref(network::features::kCompressionDictionaryTransport)},
381 {"CompressionDictionaryTransportBackend",
382 raw_ref(network::features::kCompressionDictionaryTransportBackend)},
383 {"CookieDeprecationFacilitatedTesting",
384 raw_ref(features::kCookieDeprecationFacilitatedTesting)},
385 {"Database", raw_ref(blink::features::kWebSQLAccess), kSetOnlyIfOverridden},
386 {"Fledge", raw_ref(blink::features::kFledge), kSetOnlyIfOverridden},
387 {"Fledge", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
388 kSetOnlyIfOverridden},
389 {"Fledge", raw_ref(features::kPrivacySandboxAdsAPIsM1Override),
390 kSetOnlyIfOverridden},
391 #if BUILDFLAG(USE_FONTATIONS_BACKEND)
392 {"FontationsFontBackend", raw_ref(blink::features::kFontationsFontBackend)},
394 {"FontSrcLocalMatching", raw_ref(features::kFontSrcLocalMatching)},
395 {"LegacyWindowsDWriteFontFallback",
396 raw_ref(features::kLegacyWindowsDWriteFontFallback)},
397 {"OriginIsolationHeader", raw_ref(features::kOriginIsolationHeader)},
398 {"PartitionedCookies", raw_ref(net::features::kPartitionedCookies)},
399 {"ReduceAcceptLanguage", raw_ref(network::features::kReduceAcceptLanguage)},
400 {"StorageAccessAPI", raw_ref(features::kFirstPartySets)},
401 {"TopicsAPI", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
402 kSetOnlyIfOverridden},
403 {"TopicsAPI", raw_ref(features::kPrivacySandboxAdsAPIsM1Override),
404 kSetOnlyIfOverridden},
405 {"TopicsXHR", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
406 kSetOnlyIfOverridden},
407 {"TopicsDocumentAPI", raw_ref(features::kPrivacySandboxAdsAPIsOverride),
408 kSetOnlyIfOverridden},
409 {"TopicsDocumentAPI", raw_ref(features::kPrivacySandboxAdsAPIsM1Override),
410 kSetOnlyIfOverridden},
411 {"TouchTextEditingRedesign", raw_ref(features::kTouchTextEditingRedesign)},
412 {"TrustedTypesFromLiteral", raw_ref(features::kTrustedTypesFromLiteral)},
413 {"WebSerialBluetooth",
414 raw_ref(features::kEnableBluetoothSerialPortProfileInSerialApi)},
415 {"MediaStreamTrackTransfer", raw_ref(features::kMediaStreamTrackTransfer)},
416 {"PrivateNetworkAccessPermissionPrompt",
417 raw_ref(network::features::kPrivateNetworkAccessPermissionPrompt),
418 kSetOnlyIfOverridden},
419 {"PermissionElement", raw_ref(permissions::features::kPermissionElement)} };
420 for (const auto& mapping : runtimeFeatureNameToChromiumFeatureMapping) {
421 SetRuntimeFeatureFromChromiumFeature(
422 *mapping.chromium_feature, mapping.option, [&mapping](bool enabled) {
423 wf::EnableFeatureFromString(mapping.feature_enabler, enabled);
427 WebRuntimeFeatures::UpdateStatusFromBaseFeatures();
430 // Helper class that describes the desired enable/disable action
431 // for a runtime feature when a command line switch exists.
432 struct SwitchToFeatureMap {
433 // The enabler function defined in web_runtime_features.cc.
434 void (*feature_enabler)(bool);
435 // The switch to check for on command line.
436 const char* switch_name;
437 // This is the desired state for the runtime feature if the
438 // switch exists on command line.
439 bool target_enabled_state;
442 // Sets blink runtime features controlled by command line switches.
443 void SetRuntimeFeaturesFromCommandLine(const base::CommandLine& command_line) {
444 // To add a new switch-controlled runtime feature, add a new
445 // SwitchToFeatureMap entry to the initializer list below.
446 // Note: command line switches are now discouraged, please consider
447 // using base::Feature instead.
448 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/configuration.md#switches
449 using wrf = WebRuntimeFeatures;
450 const SwitchToFeatureMap switchToFeatureMapping[] = {
452 {wrf::EnablePermissions, switches::kDisablePermissionsAPI, false},
453 {wrf::EnablePresentation, switches::kDisablePresentationAPI, false},
454 {wrf::EnableRemotePlayback, switches::kDisableRemotePlaybackAPI, false},
455 {wrf::EnableTimerThrottlingForBackgroundTabs,
456 switches::kDisableBackgroundTimerThrottling, false},
457 // End of Stable Features
458 {wrf::EnableAutomationControlled, switches::kEnableAutomation, true},
459 {wrf::EnableAutomationControlled, switches::kHeadless, true},
460 {wrf::EnableAutomationControlled, switches::kRemoteDebuggingPipe, true},
461 {wrf::EnableDatabase, switches::kDisableDatabases, false},
462 {wrf::EnableFileSystem, switches::kDisableFileSystem, false},
463 {wrf::EnableNetInfoDownlinkMax,
464 switches::kEnableNetworkInformationDownlinkMax, true},
465 {wrf::EnableNotifications, switches::kDisableNotifications, false},
466 {wrf::EnablePreciseMemoryInfo, switches::kEnablePreciseMemoryInfo, true},
467 // Chrome's Push Messaging implementation relies on Web Notifications.
468 {wrf::EnablePushMessaging, switches::kDisableNotifications, false},
469 {wrf::EnableScriptedSpeechRecognition, switches::kDisableSpeechAPI,
471 {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechAPI, false},
472 {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechSynthesisAPI,
474 {wrf::EnableSharedWorker, switches::kDisableSharedWorkers, false},
475 {wrf::EnableTextFragmentIdentifiers,
476 switches::kDisableScrollToTextFragment, false},
477 {wrf::EnableWebAuthenticationRemoteDesktopSupport,
478 switches::kWebAuthRemoteDesktopSupport, true},
479 {wrf::EnableWebGLDeveloperExtensions,
480 switches::kEnableWebGLDeveloperExtensions, true},
481 {wrf::EnableWebGLDraftExtensions, switches::kEnableWebGLDraftExtensions,
483 {wrf::EnableWebGPUDeveloperFeatures,
484 switches::kEnableWebGPUDeveloperFeatures, true},
485 {wrf::EnableDirectSockets, switches::kEnableIsolatedWebAppsInRenderer,
489 for (const auto& mapping : switchToFeatureMapping) {
490 if (command_line.HasSwitch(mapping.switch_name)) {
491 mapping.feature_enabler(mapping.target_enabled_state);
495 // Set EnableAutomationControlled if the caller passes
496 // --remote-debugging-port=0 on the command line. This means
497 // the caller has requested an ephemeral port which is how ChromeDriver
498 // launches the browser by default.
499 // If the caller provides a specific port number, this is
500 // more likely for attaching a debugger, so we should leave
501 // EnableAutomationControlled unset to ensure the browser behaves as it does
502 // when not under automation control.
503 if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
504 std::string port_str =
505 command_line.GetSwitchValueASCII(::switches::kRemoteDebuggingPort);
507 if (base::StringToInt(port_str, &port) && port == 0) {
508 WebRuntimeFeatures::EnableAutomationControlled(true);
512 // Enable or disable OffsetParentNewSpecBehavior for Enterprise Policy. This
513 // overrides any existing settings via base::Feature.
514 if (command_line.HasSwitch(
515 blink::switches::kOffsetParentNewSpecBehaviorPolicy)) {
516 const std::string value = command_line.GetSwitchValueASCII(
517 blink::switches::kOffsetParentNewSpecBehaviorPolicy);
519 blink::switches::kOffsetParentNewSpecBehaviorPolicy_ForceEnable) {
520 WebRuntimeFeatures::EnableOffsetParentNewSpecBehavior(true);
523 blink::switches::kOffsetParentNewSpecBehaviorPolicy_ForceDisable) {
524 WebRuntimeFeatures::EnableOffsetParentNewSpecBehavior(false);
528 // Enable or disable SendMouseEventsDisabledFormControls for Enterprise
529 // Policy. This overrides any existing settings via base::Feature.
530 if (command_line.HasSwitch(
531 blink::switches::kSendMouseEventsDisabledFormControlsPolicy)) {
532 const std::string value = command_line.GetSwitchValueASCII(
533 blink::switches::kSendMouseEventsDisabledFormControlsPolicy);
534 if (value == blink::switches::
535 kSendMouseEventsDisabledFormControlsPolicy_ForceEnable) {
536 WebRuntimeFeatures::EnableSendMouseEventsDisabledFormControls(true);
538 if (value == blink::switches::
539 kSendMouseEventsDisabledFormControlsPolicy_ForceDisable) {
540 WebRuntimeFeatures::EnableSendMouseEventsDisabledFormControls(false);
544 // Enable or disable BeforeunloadEventCancelByPreventDefault for Enterprise
545 // Policy. This overrides any existing settings via base::Feature.
546 if (command_line.HasSwitch(
547 blink::switches::kBeforeunloadEventCancelByPreventDefaultPolicy)) {
548 const std::string value = command_line.GetSwitchValueASCII(
549 blink::switches::kBeforeunloadEventCancelByPreventDefaultPolicy);
552 kBeforeunloadEventCancelByPreventDefaultPolicy_ForceEnable) {
553 WebRuntimeFeatures::EnableBeforeunloadEventCancelByPreventDefault(true);
557 kBeforeunloadEventCancelByPreventDefaultPolicy_ForceDisable) {
558 WebRuntimeFeatures::EnableBeforeunloadEventCancelByPreventDefault(false);
563 // Sets blink runtime features that depend on a combination
564 // of args rather than a single check of base::Feature or switch.
565 // This can be a combination of both or custom checking logic
566 // not covered by other functions. In short, this should be used
568 void SetCustomizedRuntimeFeaturesFromCombinedArgs(
569 const base::CommandLine& command_line) {
570 // CAUTION: Only add custom enabling logic here if it cannot
571 // be covered by the other functions.
573 // These checks are custom wrappers around base::FeatureList::IsEnabled
574 // They're moved here to distinguish them from actual base checks
575 WebRuntimeFeatures::EnableOverlayScrollbars(ui::IsOverlayScrollbarEnabled());
576 WebRuntimeFeatures::EnableFluentScrollbars(ui::IsFluentScrollbarEnabled());
577 WebRuntimeFeatures::EnableFluentOverlayScrollbars(
578 ui::IsFluentOverlayScrollbarEnabled());
580 // TODO(rodneyding): This is a rare case for a stable feature
581 // Need to investigate more to determine whether to refactor it.
582 if (command_line.HasSwitch(switches::kDisableV8IdleTasks)) {
583 WebRuntimeFeatures::EnableV8IdleTasks(false);
585 WebRuntimeFeatures::EnableV8IdleTasks(true);
588 WebRuntimeFeatures::EnableBackForwardCache(
589 content::IsBackForwardCacheEnabled());
591 if (base::FeatureList::IsEnabled(network::features::kPrivateStateTokens)) {
592 WebRuntimeFeatures::EnablePrivateStateTokens(true);
593 WebRuntimeFeatures::EnablePrivateStateTokensAlwaysAllowIssuance(true);
594 } else if (base::FeatureList::IsEnabled(network::features::kFledgePst)) {
595 // See https://bit.ly/configuring-trust-tokens.
596 using network::features::TrustTokenOriginTrialSpec;
598 network::features::kTrustTokenOperationsRequiringOriginTrial.Get()) {
599 case TrustTokenOriginTrialSpec::kOriginTrialNotRequired:
600 // Setting PrivateStateTokens=true enables the Trust Tokens interface;
601 // PrivateStateTokensAlwaysAllowIssuance disables a runtime check
602 // during issuance that the origin trial is active (see
603 // blink/.../trust_token_issuance_authorization.h).
604 WebRuntimeFeatures::EnablePrivateStateTokens(true);
605 WebRuntimeFeatures::EnablePrivateStateTokensAlwaysAllowIssuance(true);
607 case TrustTokenOriginTrialSpec::kAllOperationsRequireOriginTrial:
608 // The origin trial itself will be responsible for enabling the
609 // PrivateStateTokens RuntimeEnabledFeature.
610 WebRuntimeFeatures::EnablePrivateStateTokens(false);
611 WebRuntimeFeatures::EnablePrivateStateTokensAlwaysAllowIssuance(false);
613 case TrustTokenOriginTrialSpec::kOnlyIssuanceRequiresOriginTrial:
614 // At issuance, a runtime check will be responsible for checking that
615 // the origin trial is present.
616 WebRuntimeFeatures::EnablePrivateStateTokens(true);
617 WebRuntimeFeatures::EnablePrivateStateTokensAlwaysAllowIssuance(false);
622 if (base::FeatureList::IsEnabled(blink::features::kPendingBeaconAPI)) {
623 // The Chromium flag `kPendingBeaconAPI` is true, which enables the
624 // parts of the API's implementation in Chromium.
625 if (blink::features::kPendingBeaconAPIRequiresOriginTrial.Get()) {
626 // `kPendingBeaconAPIRequiresOriginTrial`=true specifies that
627 // execution context needs to have an origin trial token in order to use
628 // the PendingBeacon web API.
629 // So disable the RuntimeEnabledFeature flag PendingBeaconAPI here and let
630 // the existence of OT token to decide whether the web API is enabled.
631 WebRuntimeFeatures::EnablePendingBeaconAPI(false);
633 WebRuntimeFeatures::EnablePendingBeaconAPI(true);
638 // Ensures that the various ways of enabling/disabling features do not produce
639 // an invalid configuration.
640 void ResolveInvalidConfigurations() {
641 // Portals cannot be enabled without the support of the browser process.
642 if (!base::FeatureList::IsEnabled(blink::features::kPortals)) {
643 LOG_IF(WARNING, WebRuntimeFeatures::IsPortalsEnabled())
644 << "Portals cannot be enabled in this configuration. Use --"
645 << switches::kEnableFeatures << "=" << blink::features::kPortals.name
647 WebRuntimeFeatures::EnablePortals(false);
650 // Fenced frames, like Portals, cannot be enabled without the support of the
652 if ((base::FeatureList::IsEnabled(features::kPrivacySandboxAdsAPIsOverride) ||
653 base::FeatureList::IsEnabled(
654 features::kPrivacySandboxAdsAPIsM1Override)) &&
655 !base::FeatureList::IsEnabled(blink::features::kFencedFrames)) {
656 LOG_IF(WARNING, WebRuntimeFeatures::IsFencedFramesEnabled())
657 << "Fenced frames cannot be enabled in this configuration. Use --"
658 << switches::kEnableFeatures << "="
659 << blink::features::kFencedFrames.name << " instead.";
660 WebRuntimeFeatures::EnableFencedFrames(false);
663 // Topics API cannot be enabled without the support of the browser process.
664 // The XHR attribute should be additionally gated by the `kBrowsingTopicsXHR`
665 // feature and the Document API by the `kBrowsingTopicsDocumentAPI` feature.
666 if (!base::FeatureList::IsEnabled(blink::features::kBrowsingTopics)) {
667 LOG_IF(WARNING, WebRuntimeFeatures::IsTopicsAPIEnabled())
668 << "Topics cannot be enabled in this configuration. Use --"
669 << switches::kEnableFeatures << "="
670 << blink::features::kBrowsingTopics.name << " in addition.";
671 WebRuntimeFeatures::EnableTopicsAPI(false);
672 WebRuntimeFeatures::EnableTopicsXHR(false);
673 WebRuntimeFeatures::EnableTopicsDocumentAPI(false);
675 if (!base::FeatureList::IsEnabled(blink::features::kBrowsingTopicsXHR)) {
676 LOG_IF(WARNING, WebRuntimeFeatures::IsTopicsXHREnabled())
677 << "Topics XHR cannot be enabled in this configuration. Use --"
678 << switches::kEnableFeatures << "="
679 << blink::features::kBrowsingTopicsXHR.name << " in addition.";
680 WebRuntimeFeatures::EnableTopicsXHR(false);
682 if (!base::FeatureList::IsEnabled(
683 blink::features::kBrowsingTopicsDocumentAPI)) {
684 LOG_IF(WARNING, WebRuntimeFeatures::IsTopicsDocumentAPIEnabled())
685 << "Topics Document API cannot be enabled in this configuration. Use "
687 << switches::kEnableFeatures << "="
688 << blink::features::kBrowsingTopicsDocumentAPI.name
690 WebRuntimeFeatures::EnableTopicsDocumentAPI(false);
694 if (!base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI)) {
695 LOG_IF(WARNING, WebRuntimeFeatures::IsSharedStorageAPIEnabled())
696 << "SharedStorage cannot be enabled in this "
697 "configuration. Use --"
698 << switches::kEnableFeatures << "="
699 << blink::features::kSharedStorageAPI.name << " in addition.";
700 WebRuntimeFeatures::EnableSharedStorageAPI(false);
703 if (!base::FeatureList::IsEnabled(blink::features::kSharedStorageAPIM118) ||
704 !base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI)) {
705 LOG_IF(WARNING, WebRuntimeFeatures::IsSharedStorageAPIM118Enabled())
706 << "SharedStorage for M118+ cannot be enabled in this "
707 "configuration. Use --"
708 << switches::kEnableFeatures << "="
709 << blink::features::kSharedStorageAPI.name << ","
710 << blink::features::kSharedStorageAPIM118.name << " in addition.";
711 WebRuntimeFeatures::EnableSharedStorageAPIM118(false);
714 if (!base::FeatureList::IsEnabled(
715 attribution_reporting::features::kConversionMeasurement)) {
716 LOG_IF(WARNING, WebRuntimeFeatures::IsAttributionReportingEnabled())
717 << "AttributionReporting cannot be enabled in this "
718 "configuration. Use --"
719 << switches::kEnableFeatures << "="
720 << attribution_reporting::features::kConversionMeasurement.name
722 WebRuntimeFeatures::EnableAttributionReporting(false);
725 if (!base::FeatureList::IsEnabled(blink::features::kInterestGroupStorage)) {
726 LOG_IF(WARNING, WebRuntimeFeatures::IsAdInterestGroupAPIEnabled())
727 << "AdInterestGroupAPI cannot be enabled in this "
728 "configuration. Use --"
729 << switches::kEnableFeatures << "="
730 << blink::features::kInterestGroupStorage.name << " in addition.";
731 WebRuntimeFeatures::EnableAdInterestGroupAPI(false);
732 WebRuntimeFeatures::EnableFledge(false);
740 void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
741 const base::CommandLine& command_line) {
742 // Sets experimental features.
743 bool enable_experimental_web_platform_features =
744 command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
745 bool enable_blink_test_features =
746 command_line.HasSwitch(switches::kEnableBlinkTestFeatures);
748 if (enable_blink_test_features) {
749 enable_experimental_web_platform_features = true;
750 WebRuntimeFeatures::EnableTestOnlyFeatures(true);
753 if (enable_experimental_web_platform_features) {
754 WebRuntimeFeatures::EnableExperimentalFeatures(true);
757 SetRuntimeFeatureDefaultsForPlatform(command_line);
759 // Sets origin trial features.
760 if (command_line.HasSwitch(
761 switches::kDisableOriginTrialControlledBlinkFeatures)) {
762 WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
765 // TODO(rodneyding): add doc explaining ways to add new runtime features
766 // controls in the following functions.
768 SetRuntimeFeaturesFromChromiumFeatures();
770 SetRuntimeFeaturesFromCommandLine(command_line);
772 SetCustomizedRuntimeFeaturesFromCombinedArgs(command_line);
774 // Enable explicitly enabled features, and then disable explicitly disabled
776 for (const std::string& feature :
777 FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
778 WebRuntimeFeatures::EnableFeatureFromString(feature, true);
780 for (const std::string& feature :
781 FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
782 WebRuntimeFeatures::EnableFeatureFromString(feature, false);
785 ResolveInvalidConfigurations();
788 } // namespace content