0

Let blink runtime features override the default status of chromium features

This honors blink feature status ("test", "experimental", "stable")
in third_party/blink/renderer/platform/runtime_enabled_features.json5,
overriding of the default status of the corresponding chromium features,
unless the status of the chromium feature is overridden by finch trial
or command line switches.

This resolves the following problems of blink features with
status:"test", status"experimental", status:"stable" when the
corresponding chromium feature is disabled:
1. unexpected disabling of the blink feature for web tests
2. unexpected enabling of a blink feature for unit tests (in which case
   the blink feature should not have a status).

This CL only affects how blink features with status are enabled with
--enable-experimental-web-platform-features
(or chrome://flags/#enable-experimental-web-platform-features)
--enable-blink-test-features when the corresponding chromium feature is
disabled by default.

This doesn't affect
1. finch experiments (which still controls the blink features through
   the chromium features);
2. other command line flags that affect blink features (either directly
   or indirectly through chromium features);
3. the priority relationship among 1 and 2 and the changed factors
   mentioned above.

The features that will be affected by this CL have been prepared in
either of the following methods (tracked by crbug.com/1121839, based
on feedbacks in https://docs.google.com/spreadsheets/d/1DAtdbGy7XZCC_1_IXHXZKx568pw0eDlVETCtJBexqZc/edit#gid=0):
a) For features that should be enabled for web tests but were not
   because of the chromium feature disabled by default, temporarily
   explicitly enable it in content/child/runtime_features.cc.
   An example is crrev.com/c/2380213.
   These changes are removed in this CL.
b) For features that are not ready to be enabled for web tests, or are
   not meaningful to be enabled for web tests (e.g. the feature is
   implemented at both chromium side and blink side), the blink status
   is removed to let the chromium feature fully control the blink
   feature. An example is crrev.com/c/2376067.

Bug: 1048656, 1121839
Change-Id: I8b2f15e30767dce9212097f79c8c07a373af892d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2375886
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: Jason Chase <chasej@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803712}
This commit is contained in:
Xianzhu Wang
2020-09-02 01:22:16 +00:00
committed by Commit Bot
parent b10c267113
commit 05355f4ad6
7 changed files with 167 additions and 135 deletions

@ -256,6 +256,10 @@ void FeatureList::InitializeFromSharedMemory(
}
}
bool FeatureList::IsFeatureOverridden(const std::string& feature_name) const {
return overrides_.count(feature_name);
}
bool FeatureList::IsFeatureOverriddenFromCommandLine(
const std::string& feature_name,
OverrideState state) const {

@ -157,6 +157,11 @@ class BASE_EXPORT FeatureList {
// of the associated field trial.
void InitializeFromSharedMemory(PersistentMemoryAllocator* allocator);
// Returns true if the state of |feature_name| has been overridden (regardless
// of whether the overridden value is the same as the default value) for any
// reason (e.g. command line or field trial).
bool IsFeatureOverridden(const std::string& feature_name) const;
// Returns true if the state of |feature_name| has been overridden via
// |InitializeFromCommandLine()|. This includes features explicitly
// disabled/enabled with --disable-features and --enable-features, as well as

@ -281,10 +281,37 @@ TEST_F(FeatureListTest, CommandLineDisableTakesPrecedenceOverFieldTrial) {
EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
}
TEST_F(FeatureListTest, IsFeatureOverriddenFromFieldTrial) {
auto feature_list = std::make_unique<FeatureList>();
// No features are overridden from the field trails yet.
EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
// Now, register a field trial to override |kFeatureOnByDefaultName| state
// and check that the function still returns false for that feature.
feature_list->RegisterFieldTrialOverride(
kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT,
FieldTrialList::CreateFieldTrial("Trial1", "A"));
feature_list->RegisterFieldTrialOverride(
kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
FieldTrialList::CreateFieldTrial("Trial2", "A"));
EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatureList(std::move(feature_list));
// Check the expected feature states for good measure.
EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
}
TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
auto feature_list = std::make_unique<FeatureList>();
// No features are overridden from the command line yet
EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
@ -298,6 +325,7 @@ TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
// It should now be overridden for the enabled group.
EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
@ -308,6 +336,7 @@ TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
feature_list->AssociateReportingFieldTrial(
kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
FieldTrialList::CreateFieldTrial("Trial1", "A"));
EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
@ -318,6 +347,7 @@ TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
feature_list->RegisterFieldTrialOverride(
kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
FieldTrialList::CreateFieldTrial("Trial2", "A"));
EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(

@ -136,10 +136,11 @@ void SetRuntimeFeatureDefaultsForPlatform(
}
enum RuntimeFeatureEnableOptions {
// Always set the Blink feature to the enabled state of the base::Feature.
// Example: A run time feature that is completely controlled
// by base::Feature.
kUseFeatureState,
// - If the base::Feature default is overridden by field trial or command
// line, set Blink feature to the state of the base::Feature;
// - Otherwise if the base::Feature is enabled, enable the Blink feature.
// - Otherwise no change.
kDefault,
// Enables the Blink feature when the base::Feature is enabled,
// otherwise no change.
kEnableOnly,
@ -185,8 +186,11 @@ void SetRuntimeFeatureFromChromiumFeature(const base::Feature& chromium_feature,
if (!feature_enabled)
enabler(false);
break;
case kUseFeatureState:
enabler(feature_enabled);
case kDefault:
if (feature_enabled || FeatureList::GetInstance()->IsFeatureOverridden(
chromium_feature.name)) {
enabler(feature_enabled);
}
break;
}
}
@ -211,9 +215,9 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
kDisableOnly},
{wf::EnablePeriodicBackgroundSync, features::kPeriodicBackgroundSync,
kEnableOnly},
{wf::EnableWebXR, features::kWebXr, kUseFeatureState},
{wf::EnableWebXRARModule, features::kWebXrArModule, kUseFeatureState},
{wf::EnableWebXRHitTest, features::kWebXrHitTest, kUseFeatureState},
{wf::EnableWebXR, features::kWebXr, kDefault},
{wf::EnableWebXRARModule, features::kWebXrArModule, kDefault},
{wf::EnableWebXRHitTest, features::kWebXrHitTest, kDefault},
{wf::EnableWebXRAnchors, features::kWebXrIncubations, kEnableOnly},
{wf::EnableWebXRCameraAccess, features::kWebXrIncubations, kEnableOnly},
{wf::EnableWebXRDepth, features::kWebXrIncubations, kEnableOnly},
@ -222,16 +226,16 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
{wf::EnableWebXRReflectionEstimation, features::kWebXrIncubations,
kEnableOnly},
{wf::EnableUserActivationSameOriginVisibility,
features::kUserActivationSameOriginVisibility, kUseFeatureState},
features::kUserActivationSameOriginVisibility, kDefault},
{wf::EnableExpensiveBackgroundTimerThrottling,
features::kExpensiveBackgroundTimerThrottling, kUseFeatureState},
features::kExpensiveBackgroundTimerThrottling, kDefault},
{wf::EnableTimerThrottlingForHiddenFrames,
features::kTimerThrottlingForHiddenFrames, kUseFeatureState},
features::kTimerThrottlingForHiddenFrames, kDefault},
{wf::EnableSendBeaconThrowForBlobWithNonSimpleType,
features::kSendBeaconThrowForBlobWithNonSimpleType, kEnableOnly},
{wf::EnablePaymentRequest, features::kWebPayments, kUseFeatureState},
{wf::EnablePaymentRequest, features::kWebPayments, kDefault},
{wf::EnableSecurePaymentConfirmationDebug,
features::kSecurePaymentConfirmationDebug, kUseFeatureState},
features::kSecurePaymentConfirmationDebug, kDefault},
{wf::EnablePaymentHandlerMinimalUI, features::kWebPaymentsMinimalUI,
kEnableOnly},
{wf::EnablePaymentApp, features::kServiceWorkerPaymentApps, kEnableOnly},
@ -240,24 +244,24 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
{wf::EnableGenericSensorExtraClasses, features::kGenericSensorExtraClasses,
kEnableOnly},
{wf::EnableMediaCastOverlayButton, media::kMediaCastOverlayButton,
kUseFeatureState},
kDefault},
{wf::EnableLazyInitializeMediaControls,
features::kLazyInitializeMediaControls, kUseFeatureState},
features::kLazyInitializeMediaControls, kDefault},
{wf::EnableMediaEngagementBypassAutoplayPolicies,
media::kMediaEngagementBypassAutoplayPolicies, kUseFeatureState},
media::kMediaEngagementBypassAutoplayPolicies, kDefault},
{wf::EnableOverflowIconsForMediaControls,
media::kOverflowIconsForMediaControls, kUseFeatureState},
media::kOverflowIconsForMediaControls, kDefault},
{wf::EnableAllowActivationDelegationAttr,
features::kAllowActivationDelegationAttr, kUseFeatureState},
{wf::EnableLazyFrameLoading, features::kLazyFrameLoading, kUseFeatureState},
features::kAllowActivationDelegationAttr, kDefault},
{wf::EnableLazyFrameLoading, features::kLazyFrameLoading, kDefault},
{wf::EnableLazyFrameVisibleLoadTimeMetrics,
features::kLazyFrameVisibleLoadTimeMetrics, kUseFeatureState},
{wf::EnableLazyImageLoading, features::kLazyImageLoading, kUseFeatureState},
features::kLazyFrameVisibleLoadTimeMetrics, kDefault},
{wf::EnableLazyImageLoading, features::kLazyImageLoading, kDefault},
{wf::EnableLazyImageVisibleLoadTimeMetrics,
features::kLazyImageVisibleLoadTimeMetrics, kUseFeatureState},
{wf::EnablePictureInPicture, media::kPictureInPicture, kUseFeatureState},
features::kLazyImageVisibleLoadTimeMetrics, kDefault},
{wf::EnablePictureInPicture, media::kPictureInPicture, kDefault},
{wf::EnableCacheInlineScriptCode, features::kCacheInlineScriptCode,
kUseFeatureState},
kDefault},
{wf::EnableExperimentalProductivityFeatures,
features::kExperimentalProductivityFeatures, kEnableOnly},
{wf::EnableFeaturePolicyForSandbox, features::kFeaturePolicyForSandbox,
@ -267,42 +271,41 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
{wf::EnableAccessibilityExposeDisplayNone,
features::kEnableAccessibilityExposeDisplayNone, kEnableOnly},
{wf::EnableAccessibilityExposeHTMLElement,
features::kEnableAccessibilityExposeHTMLElement, kUseFeatureState},
features::kEnableAccessibilityExposeHTMLElement, kDefault},
{wf::EnableAllowSyncXHRInPageDismissal,
blink::features::kAllowSyncXHRInPageDismissal, kEnableOnly},
{wf::EnableAutoplayIgnoresWebAudio, media::kAutoplayIgnoreWebAudio,
kUseFeatureState},
kDefault},
{wf::EnablePortals, blink::features::kPortals,
kEnableOnlyIfOverriddenFromCommandLine},
{wf::EnableImplicitRootScroller, blink::features::kImplicitRootScroller,
kUseFeatureState},
kDefault},
{wf::EnableCSSOMViewScrollCoordinates,
blink::features::kCSSOMViewScrollCoordinates, kEnableOnly},
{wf::EnableTextFragmentAnchor, blink::features::kTextFragmentAnchor,
kUseFeatureState},
kDefault},
{wf::EnableBackgroundFetch, features::kBackgroundFetch, kDisableOnly},
{wf::EnableForcedColors, features::kForcedColors, kUseFeatureState},
{wf::EnableForcedColors, features::kForcedColors, kDefault},
{wf::EnableFractionalScrollOffsets, features::kFractionalScrollOffsets,
kUseFeatureState},
{wf::EnableGetDisplayMedia, blink::features::kRTCGetDisplayMedia,
kUseFeatureState},
kDefault},
{wf::EnableGetDisplayMedia, blink::features::kRTCGetDisplayMedia, kDefault},
{wf::EnableSignedExchangePrefetchCacheForNavigations,
features::kSignedExchangePrefetchCacheForNavigations, kUseFeatureState},
features::kSignedExchangePrefetchCacheForNavigations, kDefault},
{wf::EnableSignedExchangeSubresourcePrefetch,
features::kSignedExchangeSubresourcePrefetch, kUseFeatureState},
features::kSignedExchangeSubresourcePrefetch, kDefault},
{wf::EnableIdleDetection, features::kIdleDetection, kDisableOnly},
{wf::EnableSkipTouchEventFilter, blink::features::kSkipTouchEventFilter,
kUseFeatureState},
kDefault},
{wf::EnableSmsReceiver, features::kSmsReceiver, kDisableOnly},
{wf::EnableClickPointerEvent, features::kClickPointerEvent, kEnableOnly},
{wf::EnableConsolidatedMovementXY, features::kConsolidatedMovementXY,
kUseFeatureState},
kDefault},
{wf::EnableCooperativeScheduling, features::kCooperativeScheduling,
kUseFeatureState},
kDefault},
{wf::EnableMouseSubframeNoImplicitCapture,
features::kMouseSubframeNoImplicitCapture, kUseFeatureState},
features::kMouseSubframeNoImplicitCapture, kDefault},
{wf::EnableSubresourceWebBundles, features::kSubresourceWebBundles,
kUseFeatureState},
kDefault},
{wf::EnableCookieDeprecationMessages, features::kCookieDeprecationMessages,
kEnableOnly},
{wf::EnableSameSiteByDefaultCookies,
@ -310,43 +313,37 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
{wf::EnableCookiesWithoutSameSiteMustBeSecure,
net::features::kCookiesWithoutSameSiteMustBeSecure, kEnableOnly},
{wf::EnablePointerLockOptions, features::kPointerLockOptions, kEnableOnly},
{wf::EnableDocumentPolicy, features::kDocumentPolicy, kUseFeatureState},
{wf::EnableDocumentPolicy, features::kDocumentPolicy, kDefault},
{wf::EnableDocumentPolicyNegotiation, features::kDocumentPolicyNegotiation,
kUseFeatureState},
{wf::EnableScrollUnification, features::kScrollUnification,
kUseFeatureState},
{wf::EnableNeverSlowMode, features::kNeverSlowMode, kUseFeatureState},
{wf::EnableShadowDOMV0, blink::features::kWebComponentsV0,
kUseFeatureState},
{wf::EnableCustomElementsV0, blink::features::kWebComponentsV0,
kUseFeatureState},
{wf::EnableHTMLImports, blink::features::kWebComponentsV0,
kUseFeatureState},
{wf::EnableVideoPlaybackQuality, features::kVideoPlaybackQuality,
kUseFeatureState},
kDefault},
{wf::EnableScrollUnification, features::kScrollUnification, kDefault},
{wf::EnableNeverSlowMode, features::kNeverSlowMode, kDefault},
{wf::EnableShadowDOMV0, blink::features::kWebComponentsV0, kDefault},
{wf::EnableCustomElementsV0, blink::features::kWebComponentsV0, kDefault},
{wf::EnableHTMLImports, blink::features::kWebComponentsV0, kDefault},
{wf::EnableVideoPlaybackQuality, features::kVideoPlaybackQuality, kDefault},
{wf::EnableBrowserVerifiedUserActivationKeyboard,
features::kBrowserVerifiedUserActivationKeyboard, kEnableOnly},
{wf::EnableBrowserVerifiedUserActivationMouse,
features::kBrowserVerifiedUserActivationMouse, kEnableOnly},
{wf::EnablePercentBasedScrolling, features::kPercentBasedScrolling,
kUseFeatureState},
kDefault},
#if defined(OS_ANDROID)
{wf::EnableWebNfc, features::kWebNfc, kDisableOnly},
#endif
{wf::EnableInstalledApp, features::kInstalledApp, kDisableOnly},
{wf::EnableWebAuthenticationGetAssertionFeaturePolicy,
device::kWebAuthGetAssertionFeaturePolicy, kUseFeatureState},
{wf::EnableTransformInterop, blink::features::kTransformInterop,
kUseFeatureState},
device::kWebAuthGetAssertionFeaturePolicy, kDefault},
{wf::EnableTransformInterop, blink::features::kTransformInterop, kDefault},
{wf::EnableVideoWakeLockOptimisationHiddenMuted,
media::kWakeLockOptimisationHiddenMuted, kUseFeatureState},
{wf::EnableMediaFeeds, media::kMediaFeeds, kUseFeatureState},
media::kWakeLockOptimisationHiddenMuted, kDefault},
{wf::EnableMediaFeeds, media::kMediaFeeds, kDefault},
{wf::EnableRestrictGamepadAccess, features::kRestrictGamepadAccess,
kEnableOnly},
{wf::EnableCompositingOptimizations,
blink::features::kCompositingOptimizations, kUseFeatureState},
blink::features::kCompositingOptimizations, kDefault},
{wf::EnableConversionMeasurementInfraSupport,
features::kConversionMeasurement, kUseFeatureState},
features::kConversionMeasurement, kDefault},
};
for (const auto& mapping : blinkFeatureToBaseFeatureMapping) {
SetRuntimeFeatureFromChromiumFeature(
@ -360,66 +357,56 @@ void SetRuntimeFeaturesFromChromiumFeatures() {
{"AddressSpace", features::kBlockInsecurePrivateNetworkRequests,
kEnableOnly},
{"AllowContentInitiatedDataUrlNavigations",
features::kAllowContentInitiatedDataUrlNavigations,
kUseFeatureState},
features::kAllowContentInitiatedDataUrlNavigations, kDefault},
{"AudioWorkletRealtimeThread",
blink::features::kAudioWorkletRealtimeThread, kEnableOnly},
{"BlockCredentialedSubresources",
features::kBlockCredentialedSubresources, kDisableOnly},
{"BlockHTMLParserOnStyleSheets",
blink::features::kBlockHTMLParserOnStyleSheets, kUseFeatureState},
blink::features::kBlockHTMLParserOnStyleSheets, kDefault},
{"CSSColorSchemeUARendering", features::kCSSColorSchemeUARendering,
kUseFeatureState},
kDefault},
{"CSSReducedFontLoadingInvalidations",
blink::features::kCSSReducedFontLoadingInvalidations,
kUseFeatureState},
blink::features::kCSSReducedFontLoadingInvalidations, kDefault},
{"CSSReducedFontLoadingLayoutInvalidations",
blink::features::kCSSReducedFontLoadingLayoutInvalidations,
kUseFeatureState},
kDefault},
{"CSSMatchedPropertiesCacheDependencies",
blink::features::kCSSMatchedPropertiesCacheDependencies,
kUseFeatureState},
{"CustomElementsV0", blink::features::kWebComponentsV0,
kUseFeatureState},
blink::features::kCSSMatchedPropertiesCacheDependencies, kDefault},
{"CustomElementsV0", blink::features::kWebComponentsV0, kDefault},
{"FeaturePolicyForClientHints",
features::kFeaturePolicyForClientHints, kUseFeatureState},
{"FontAccess", blink::features::kFontAccess, kUseFeatureState},
{"FontSrcLocalMatching", features::kFontSrcLocalMatching,
kUseFeatureState},
features::kFeaturePolicyForClientHints, kDefault},
{"FontAccess", blink::features::kFontAccess, kDefault},
{"FontSrcLocalMatching", features::kFontSrcLocalMatching, kDefault},
{"ForceSynchronousHTMLParsing",
blink::features::kForceSynchronousHTMLParsing, kUseFeatureState},
{"HTMLImports", blink::features::kWebComponentsV0, kUseFeatureState},
blink::features::kForceSynchronousHTMLParsing, kDefault},
{"HTMLImports", blink::features::kWebComponentsV0, kDefault},
{"IgnoreCrossOriginWindowWhenNamedAccessOnWindow",
blink::features::kIgnoreCrossOriginWindowWhenNamedAccessOnWindow,
kEnableOnly},
{"LangClientHintHeader", features::kLangClientHintHeader,
kUseFeatureState},
{"LayoutNG", blink::features::kLayoutNG, kUseFeatureState},
{"LayoutNGFieldset", blink::features::kLayoutNGFieldset,
kUseFeatureState},
{"LayoutNGFlexBox", blink::features::kFlexNG, kUseFeatureState},
{"LayoutNGFragmentItem", blink::features::kFragmentItem,
kUseFeatureState},
{"LayoutNGRuby", blink::features::kLayoutNGRuby, kUseFeatureState},
{"LangClientHintHeader", features::kLangClientHintHeader, kDefault},
{"LayoutNG", blink::features::kLayoutNG, kDefault},
{"LayoutNGFieldset", blink::features::kLayoutNGFieldset, kDefault},
{"LayoutNGFlexBox", blink::features::kFlexNG, kDefault},
{"LayoutNGFragmentItem", blink::features::kFragmentItem, kDefault},
{"LayoutNGRuby", blink::features::kLayoutNGRuby, kDefault},
{"LegacyWindowsDWriteFontFallback",
features::kLegacyWindowsDWriteFontFallback, kUseFeatureState},
features::kLegacyWindowsDWriteFontFallback, kDefault},
{"LinkDisabledNewSpecBehavior",
blink::features::kLinkDisabledNewSpecBehavior, kUseFeatureState},
{"OriginPolicy", features::kOriginPolicy, kUseFeatureState},
{"OriginIsolationHeader", features::kOriginIsolationHeader,
kUseFeatureState},
blink::features::kLinkDisabledNewSpecBehavior, kDefault},
{"OriginPolicy", features::kOriginPolicy, kDefault},
{"OriginIsolationHeader", features::kOriginIsolationHeader, kDefault},
{"ParentNodeReplaceChildren",
blink::features::kParentNodeReplaceChildren, kUseFeatureState},
blink::features::kParentNodeReplaceChildren, kDefault},
{"RawClipboard", blink::features::kRawClipboard, kEnableOnly},
{"ShadowDOMV0", blink::features::kWebComponentsV0, kUseFeatureState},
{"ShadowDOMV0", blink::features::kWebComponentsV0, kDefault},
{"StorageAccessAPI", blink::features::kStorageAccessAPI, kEnableOnly},
{"TransferableStreams", blink::features::kTransferableStreams,
kEnableOnly},
{"TrustedDOMTypes", features::kTrustedDOMTypes, kEnableOnly},
{"UserAgentClientHint", features::kUserAgentClientHint,
kUseFeatureState},
{"UserAgentClientHint", features::kUserAgentClientHint, kDefault},
{"WebAppManifestDisplayOverride",
features::kWebAppManifestDisplayOverride, kUseFeatureState},
features::kWebAppManifestDisplayOverride, kDefault},
};
for (const auto& mapping : runtimeFeatureNameToChromiumFeatureMapping) {
@ -555,9 +542,7 @@ void SetRuntimeFeaturesFromFieldTrialParams() {
// not covered by other functions. In short, this should be used
// as a last resort.
void SetCustomizedRuntimeFeaturesFromCombinedArgs(
const base::CommandLine& command_line,
bool enable_experimental_web_platform_features,
bool enable_blink_test_features) {
const base::CommandLine& command_line) {
// CAUTION: Only add custom enabling logic here if it cannot
// be covered by the other functions.
@ -597,32 +582,6 @@ void SetCustomizedRuntimeFeaturesFromCombinedArgs(
else
WebRuntimeFeatures::EnableV8IdleTasks(true);
// This is a hack to get the tests passing as they require
// these blink features to be enabled while they are disabled
// by base::Feature controls earlier in code.
// TODO(rodneyding): Investigate more on proper treatments of
// these features.
if (enable_experimental_web_platform_features) {
WebRuntimeFeatures::EnableCompositingOptimizations(true);
WebRuntimeFeatures::EnableNetInfoDownlinkMax(true);
WebRuntimeFeatures::EnableSignedExchangePrefetchCacheForNavigations(true);
WebRuntimeFeatures::EnableSignedExchangeSubresourcePrefetch(true);
}
if (enable_blink_test_features) {
WebRuntimeFeatures::EnableSubresourceWebBundles(true);
}
// Except for stable release mode, web tests still run with Web Components
// v0 features enabled.
// TODO(crbug.com/937746): remove this once the features are deleted.
if (command_line.HasSwitch("run-web-tests") &&
!command_line.HasSwitch("stable-release-mode")) {
WebRuntimeFeatures::EnableShadowDOMV0(true);
WebRuntimeFeatures::EnableCustomElementsV0(true);
WebRuntimeFeatures::EnableHTMLImports(true);
}
WebRuntimeFeatures::EnableBackForwardCache(
content::IsBackForwardCacheEnabled());
@ -711,9 +670,7 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
SetRuntimeFeaturesFromFieldTrialParams();
SetCustomizedRuntimeFeaturesFromCombinedArgs(
command_line, enable_experimental_web_platform_features,
enable_blink_test_features);
SetCustomizedRuntimeFeaturesFromCombinedArgs(command_line);
// Enable explicitly enabled features, and then disable explicitly disabled
// ones.

@ -26,19 +26,45 @@ Add your code to the function
If your Blink feature has a custom enabler function, add a new entry to
`blinkFeatureToBaseFeatureMapping`. For example, a new entry like this:
```
{wf::EnableNewFeatureX, features::kNewFeatureX, kEnableOnly},
{wf::EnableNewFeatureX, features::kNewFeatureX, kDefault},
```
will call `wf::EnableNewFeatureX` to enable it only if `features::kNewFeatureX`
is enabled.
is enabled, or to set it to the same status as `features::kNewFeatureX` if its
default status is overridden by any field trial or command line switch.
If your Blink feature does not have a custom enabler function, you need to add
the entry to `runtimeFeatureNameToChromiumFeatureMapping`. For example, a new
entry like this:
```
{"NewFeatureY", features::kNewFeatureY, kUseFeatureState},
{"NewFeatureY", features::kNewFeatureY, kDefault},
```
will call `wf::EnableFeatureFromString` with your feature name to set it to
whichever state your `features::kNewFeatureY` is in.
will call `wf::EnableFeatureFromString` with your feature name instead of
`wf::EnableNewFeatureX` in the same cases as above.
The following table summarizes the relationship between the default status of
the Chromium feature and the status of the blink feature, when `kDefault` is
specified, if **not overridden** by field trial or command line switches
(horizontal headers: blink feature status; vertical headers: chromium feature
default status):
| |No status|`status:"test"`|`status:"experimental"`|`status:"stable"`|
|-|---------|-----------------|--------------------------|-------------------|
|`FEATURE_DISABLED_BY_DEFAULT`|Disabled everywhere|Blink feature is enabled for tests, or everywhere with `--enable-blink-test-features` [1]|Blink feature is enabled for tests, or everywhere with `--enable-experimental-web-platform-features` [1]|Blink feature is enabled everywhere [2]|
|`FEATURE_ENABLED_BY_DEFAULT`|Enabled everywhere|Enabled everywhere|Enabled everywhere|Enabled everywhere|
\[1]: `base::FeatureList::IsEnabled(features::kNewFeatureX)` is still
false. These combinations are suitable for features there are fully implemented
at blink side. Otherwise normally the blink feature should not have a status so
that the Chromium feature can fully controll the feature.
\[2]: This combination is counter-intuitive and should be avoided.
Field trial and command line switches can always override the Chromium feature
status and the blink feature status.
Besides `kDefault`, there are also other options for the relationship
between the Chromium feature and the blink feature. These other options should
only be used in rare cases when the default relationship doesn't work.
For more detailed explanation on the options you have, read the comment in enum
[RuntimeFeatureEnableOptions][EnableOptions].

@ -70,6 +70,13 @@ When a feature has shipped and is no longer at risk of needing to be disabled, i
If a feature is not stable and no longer under active development, remove `status: "test"/"experimental"` on it (and consider deleting the code implementing the feature).
### Relationship between a Chromium Feature and a Blink Feature
In some cases, e.g. for finch expeirment, you may need to define a Chromium feature for a blink feature. Their relationship is
defined in [content/child/runtime_features.cc]. See the [initialize blink features] doc for more details.
**Note:** If a feature is implemented at both Chromium side and blink side, as the blink feature doesn't fully work by itself, we normally don't set the blink feature's status so that the Chromium feature can fully control the blink feature ([example][controlled by chromium feature]).
### Runtime Enabled CSS Properties
If your feature is adding new CSS Properties you will need to use the runtime_flag argument in [renderer/core/css/css_properties.json5][cssProperties].
@ -189,3 +196,6 @@ https://groups.google.com/a/chromium.org/d/msg/blink-dev/JBakhu5J6Qs/re2LkfEslTA
[make_internal_runtime_flags.py]: <https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/build/scripts/make_internal_runtime_flags.py>
[code_generator_v8.py]: <https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/scripts/code_generator_v8.py>
[virtual/stable]: <https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/web_tests/VirtualTestSuites;drc=9878f26d52d32871ed1c085444196e5453909eec;l=112>
[content/child/runtime_features.cc]: <https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/common/features.cc>
[initialize blink features]: <https://chromium.googlesource.com/chromium/src/+/master/docs/initialize_blink_features.md>
[controlled by chromium feature]: <https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/runtime_enabled_features.json5;drc=70bddadf50a14254072cf7ca0bcf83e4331a7d4f;l=833>

@ -1257,7 +1257,7 @@
{
name: "NetInfoDownlinkMax",
// Only Android, ChromeOS support NetInfo downlinkMax, type and ontypechange now
status: {"Android": "stable", "ChromeOS": "stable"},
status: {"Android": "stable", "ChromeOS": "stable", "default": "experimental"},
},
{
name: "NeverSlowMode",