42ba66da9a40e4b894e6424c37b0b0dce168aced
[platform/framework/web/chromium-efl.git] / content / child / runtime_features.cc
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.
4
5 #include "content/child/runtime_features.h"
6
7 #include <string>
8 #include <vector>
9
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"
49
50 #if BUILDFLAG(IS_ANDROID)
51 #include "base/android/build_info.h"
52 #endif
53
54 #if BUILDFLAG(ENABLE_VR)
55 #include "device/vr/public/cpp/features.h"
56 #endif
57
58 using blink::WebRuntimeFeatures;
59
60 namespace {
61
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.
71 #if defined(USE_AURA)
72   WebRuntimeFeatures::EnableCompositedSelectionUpdate(true);
73 #endif
74
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);
82 #else
83   constexpr bool enable_canvas_2d_image_chromium = false;
84 #endif
85   WebRuntimeFeatures::EnableCanvas2dImageChromium(
86       enable_canvas_2d_image_chromium);
87
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);
95 #else
96   const bool enable_web_gl_image_chromium =
97       command_line.HasSwitch(switches::kEnableWebGLImageChromium);
98 #endif
99   WebRuntimeFeatures::EnableWebGLImageChromium(enable_web_gl_image_chromium);
100
101 #if BUILDFLAG(IS_ANDROID)
102   if (command_line.HasSwitch(switches::kDisableMediaSessionAPI)) {
103     WebRuntimeFeatures::EnableMediaSession(false);
104   }
105 #endif
106
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);
112   }
113 #endif
114
115 #if BUILDFLAG(IS_ANDROID)
116   WebRuntimeFeatures::EnableMediaControlsExpandGesture(
117       base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture));
118 #endif
119
120 #if BUILDFLAG(IS_EFL)
121   // No plan to support complex UI for date/time INPUT types.
122   WebRuntimeFeatures::EnableInputMultipleFieldsUI(false);
123
124   // Small accelerated 2d canvas has tct issues, which are known in
125   // upstream version also.
126   WebRuntimeFeatures::EnableAcceleratedSmallCanvases(false);
127 #endif
128 }
129
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.
135   kDefault,
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,
148 };
149
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.
156   T feature_enabler;
157   // The chromium base::Feature to check.
158   const raw_ref<const base::Feature> chromium_feature;
159   const RuntimeFeatureEnableOptions option = kDefault;
160 };
161
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);
170   switch (option) {
171     case kSetOnlyIfOverridden:
172       if (is_overridden) {
173         enabler(feature_enabled);
174       }
175       break;
176     case kDefault:
177       if (feature_enabled || is_overridden) {
178         enabler(feature_enabled);
179       }
180       break;
181     default:
182       NOTREACHED();
183   }
184 }
185
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
194   // in the next list.
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)},
208 #endif
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),
243      kDefault},
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)},
272 #endif
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)},
308 #endif
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},
325 #endif
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)},
344 #endif
345     {wf::EnableRemoveMobileViewportDoubleTap,
346      raw_ref(features::kRemoveMobileViewportDoubleTap)},
347     {wf::EnableServiceWorkerBypassFetchHandler,
348      raw_ref(features::kServiceWorkerBypassFetchHandler)},
349     {wf::EnableServiceWorkerStaticRouter,
350      raw_ref(features::kServiceWorkerStaticRouter)},
351   };
352   for (const auto& mapping : blinkFeatureToBaseFeatureMapping) {
353     SetRuntimeFeatureFromChromiumFeature(
354         *mapping.chromium_feature, mapping.option, mapping.feature_enabler);
355   }
356
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)},
378 #endif
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)},
393 #endif
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);
424         });
425   }
426
427   WebRuntimeFeatures::UpdateStatusFromBaseFeatures();
428 }
429
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;
440 };
441
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[] = {
451       // Stable Features
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,
470        false},
471       {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechAPI, false},
472       {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechSynthesisAPI,
473        false},
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,
482        true},
483       {wrf::EnableWebGPUDeveloperFeatures,
484        switches::kEnableWebGPUDeveloperFeatures, true},
485       {wrf::EnableDirectSockets, switches::kEnableIsolatedWebAppsInRenderer,
486        true},
487   };
488
489   for (const auto& mapping : switchToFeatureMapping) {
490     if (command_line.HasSwitch(mapping.switch_name)) {
491       mapping.feature_enabler(mapping.target_enabled_state);
492     }
493   }
494
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);
506     int port;
507     if (base::StringToInt(port_str, &port) && port == 0) {
508       WebRuntimeFeatures::EnableAutomationControlled(true);
509     }
510   }
511
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);
518     if (value ==
519         blink::switches::kOffsetParentNewSpecBehaviorPolicy_ForceEnable) {
520       WebRuntimeFeatures::EnableOffsetParentNewSpecBehavior(true);
521     }
522     if (value ==
523         blink::switches::kOffsetParentNewSpecBehaviorPolicy_ForceDisable) {
524       WebRuntimeFeatures::EnableOffsetParentNewSpecBehavior(false);
525     }
526   }
527
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);
537     }
538     if (value == blink::switches::
539                      kSendMouseEventsDisabledFormControlsPolicy_ForceDisable) {
540       WebRuntimeFeatures::EnableSendMouseEventsDisabledFormControls(false);
541     }
542   }
543
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);
550     if (value ==
551         blink::switches::
552             kBeforeunloadEventCancelByPreventDefaultPolicy_ForceEnable) {
553       WebRuntimeFeatures::EnableBeforeunloadEventCancelByPreventDefault(true);
554     }
555     if (value ==
556         blink::switches::
557             kBeforeunloadEventCancelByPreventDefaultPolicy_ForceDisable) {
558       WebRuntimeFeatures::EnableBeforeunloadEventCancelByPreventDefault(false);
559     }
560   }
561 }
562
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
567 // as a last resort.
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.
572
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());
579
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);
584   } else {
585     WebRuntimeFeatures::EnableV8IdleTasks(true);
586   }
587
588   WebRuntimeFeatures::EnableBackForwardCache(
589       content::IsBackForwardCacheEnabled());
590
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;
597     switch (
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);
606         break;
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);
612         break;
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);
618         break;
619     }
620   }
621
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);
632     } else {
633       WebRuntimeFeatures::EnablePendingBeaconAPI(true);
634     }
635   }
636 }
637
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
646         << " instead.";
647     WebRuntimeFeatures::EnablePortals(false);
648   }
649
650   // Fenced frames, like Portals, cannot be enabled without the support of the
651   // browser process.
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);
661   }
662
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);
674   } else {
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);
681     }
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 "
686              "--"
687           << switches::kEnableFeatures << "="
688           << blink::features::kBrowsingTopicsDocumentAPI.name
689           << " in addition.";
690       WebRuntimeFeatures::EnableTopicsDocumentAPI(false);
691     }
692   }
693
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);
701   }
702
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);
712   }
713
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
721         << " in addition.";
722     WebRuntimeFeatures::EnableAttributionReporting(false);
723   }
724
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);
733   }
734 }
735
736 }  // namespace
737
738 namespace content {
739
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);
747
748   if (enable_blink_test_features) {
749     enable_experimental_web_platform_features = true;
750     WebRuntimeFeatures::EnableTestOnlyFeatures(true);
751   }
752
753   if (enable_experimental_web_platform_features) {
754     WebRuntimeFeatures::EnableExperimentalFeatures(true);
755   }
756
757   SetRuntimeFeatureDefaultsForPlatform(command_line);
758
759   // Sets origin trial features.
760   if (command_line.HasSwitch(
761           switches::kDisableOriginTrialControlledBlinkFeatures)) {
762     WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
763   }
764
765   // TODO(rodneyding): add doc explaining ways to add new runtime features
766   // controls in the following functions.
767
768   SetRuntimeFeaturesFromChromiumFeatures();
769
770   SetRuntimeFeaturesFromCommandLine(command_line);
771
772   SetCustomizedRuntimeFeaturesFromCombinedArgs(command_line);
773
774   // Enable explicitly enabled features, and then disable explicitly disabled
775   // ones.
776   for (const std::string& feature :
777        FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
778     WebRuntimeFeatures::EnableFeatureFromString(feature, true);
779   }
780   for (const std::string& feature :
781        FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
782     WebRuntimeFeatures::EnableFeatureFromString(feature, false);
783   }
784
785   ResolveInvalidConfigurations();
786 }
787
788 }  // namespace content