Enforce --disallow-v8-feature-flag-overrides in the renderer
This renderer command line switch is intended to prevent feature flag overrides from configuring V8 flags. To enforce this, v8 feature flag overrides have been conditioned on this command line switch in the following locations: - content::RenderProcessImpl::RenderProcessImpl() - gin::SetFeatureFlags() This change is intended to enable consistent V8 flags at build-time and run-time, and hence compatibility for bundled code caches. Bug: 388577282 Change-Id: Ifd2465cf54bc8353a2f33701157bc9be538eb777 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6144831 Commit-Queue: Thomas Lukaszewicz <tluk@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Cr-Commit-Position: refs/heads/main@{#1407497}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
ea84d23201
commit
47141e8d6a
content/renderer
gin
third_party/blink
@ -126,51 +126,58 @@ RenderProcessImpl::RenderProcessImpl()
|
||||
}
|
||||
#endif // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
|
||||
|
||||
if (base::SysInfo::IsLowEndDevice()) {
|
||||
std::string optimize_flag("--optimize-for-size");
|
||||
v8::V8::SetFlagsFromString(optimize_flag.c_str(), optimize_flag.size());
|
||||
// Do not apply V8 flag overrides if disallowed.
|
||||
const bool disallow_v8_feature_flag_overrides =
|
||||
base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kDisallowV8FeatureFlagOverrides);
|
||||
if (!disallow_v8_feature_flag_overrides) {
|
||||
if (base::SysInfo::IsLowEndDevice()) {
|
||||
std::string_view optimize_flag("--optimize-for-size");
|
||||
v8::V8::SetFlagsFromString(optimize_flag.data(), optimize_flag.size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// V8 flags are typically set in gin/v8_initializer.cc. Only those flags
|
||||
// should be set here that cannot be set in gin/v8_initializer.cc because
|
||||
// e.g. the flag can be set in chrome://flags.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
SetV8FlagIfHasSwitch(switches::kDisableJavaScriptHarmonyShipping,
|
||||
"--noharmony-shipping");
|
||||
SetV8FlagIfHasSwitch(switches::kJavaScriptHarmony, "--harmony");
|
||||
SetV8FlagIfHasSwitch(switches::kEnableExperimentalWebAssemblyFeatures,
|
||||
"--wasm-staging");
|
||||
|
||||
SetV8FlagIfOverridden(features::kV8VmFuture, "--future", "--no-future");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyBaseline, "--liftoff",
|
||||
"--no-liftoff");
|
||||
|
||||
// V8's WASM stack switching support is sufficient to enable JavaScript
|
||||
// Promise Integration.
|
||||
SetV8FlagIfOverridden(features::kEnableExperimentalWebAssemblyJSPI,
|
||||
"--experimental-wasm-jspi",
|
||||
"--no-experimental-wasm-jspi");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyLazyCompilation,
|
||||
"--wasm-lazy-compilation",
|
||||
"--no-wasm-lazy-compilation");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyMemory64,
|
||||
"--experimental-wasm-memory64",
|
||||
"--no-experimental-wasm-memory64");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyTiering, "--wasm-tier-up",
|
||||
"--no-wasm-tier-up");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyDynamicTiering,
|
||||
"--wasm-dynamic-tiering",
|
||||
"--no-wasm-dynamic-tiering");
|
||||
|
||||
SetV8FlagIfOverridden(blink::features::kWebAssemblyJSStringBuiltins,
|
||||
"--experimental-wasm-imported-strings",
|
||||
"--no-experimental-wasm-imported-strings");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// V8 flags are typically set in gin/v8_initializer.cc. Only those flags
|
||||
// should be set here that cannot be set in gin/v8_initializer.cc because
|
||||
// e.g. the flag can be set in chrome://flags.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
SetV8FlagIfHasSwitch(switches::kDisableJavaScriptHarmonyShipping,
|
||||
"--noharmony-shipping");
|
||||
SetV8FlagIfHasSwitch(switches::kJavaScriptHarmony, "--harmony");
|
||||
SetV8FlagIfHasSwitch(switches::kEnableExperimentalWebAssemblyFeatures,
|
||||
"--wasm-staging");
|
||||
|
||||
SetV8FlagIfOverridden(features::kV8VmFuture, "--future", "--no-future");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyBaseline, "--liftoff",
|
||||
"--no-liftoff");
|
||||
|
||||
// V8's WASM stack switching support is sufficient to enable JavaScript
|
||||
// Promise Integration.
|
||||
SetV8FlagIfOverridden(features::kEnableExperimentalWebAssemblyJSPI,
|
||||
"--experimental-wasm-jspi",
|
||||
"--no-experimental-wasm-jspi");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyLazyCompilation,
|
||||
"--wasm-lazy-compilation",
|
||||
"--no-wasm-lazy-compilation");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyMemory64,
|
||||
"--experimental-wasm-memory64",
|
||||
"--no-experimental-wasm-memory64");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyTiering, "--wasm-tier-up",
|
||||
"--no-wasm-tier-up");
|
||||
|
||||
SetV8FlagIfOverridden(features::kWebAssemblyDynamicTiering,
|
||||
"--wasm-dynamic-tiering", "--no-wasm-dynamic-tiering");
|
||||
|
||||
SetV8FlagIfOverridden(blink::features::kWebAssemblyJSStringBuiltins,
|
||||
"--experimental-wasm-imported-strings",
|
||||
"--no-experimental-wasm-imported-strings");
|
||||
|
||||
bool enable_shared_array_buffer_unconditionally =
|
||||
base::FeatureList::IsEnabled(features::kSharedArrayBuffer);
|
||||
|
||||
@ -185,7 +192,12 @@ RenderProcessImpl::RenderProcessImpl()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!enable_shared_array_buffer_unconditionally) {
|
||||
// Do not conditionally set the V8 SharedArrayBuffer feature flag if V8
|
||||
// feature flag overrides are disallowed.
|
||||
// TODO(crbug.com/40155376) Remove when migration to COOP+COEP is complete and
|
||||
// kSharedArrayBuffer is enabled by default.
|
||||
if (!enable_shared_array_buffer_unconditionally &&
|
||||
!disallow_v8_feature_flag_overrides) {
|
||||
// It is still possible to enable SharedArrayBuffer per context using the
|
||||
// `SharedArrayBufferConstructorEnabledCallback`. This will be done if the
|
||||
// context is cross-origin isolated or if it opts in into the reverse origin
|
||||
|
@ -1053,6 +1053,11 @@ RendererBlinkPlatformImpl::CreateWebV8ValueConverter() {
|
||||
return std::make_unique<V8ValueConverterImpl>();
|
||||
}
|
||||
|
||||
bool RendererBlinkPlatformImpl::DisallowV8FeatureFlagOverrides() const {
|
||||
return base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kDisallowV8FeatureFlagOverrides);
|
||||
}
|
||||
|
||||
void RendererBlinkPlatformImpl::AppendContentSecurityPolicy(
|
||||
const blink::WebURL& url,
|
||||
blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) {
|
||||
|
@ -232,6 +232,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
|
||||
SkBitmap* GetSadPageBitmap() override;
|
||||
std::unique_ptr<blink::WebV8ValueConverter> CreateWebV8ValueConverter()
|
||||
override;
|
||||
bool DisallowV8FeatureFlagOverrides() const override;
|
||||
void AppendContentSecurityPolicy(
|
||||
const blink::WebURL& url,
|
||||
blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) override;
|
||||
|
@ -152,11 +152,14 @@ IsolateHolder::~IsolateHolder() {
|
||||
void IsolateHolder::Initialize(ScriptMode mode,
|
||||
v8::ArrayBuffer::Allocator* allocator,
|
||||
const intptr_t* reference_table,
|
||||
const std::string js_command_line_flags,
|
||||
std::string js_command_line_flags,
|
||||
bool disallow_v8_feature_flag_overrides,
|
||||
v8::FatalErrorCallback fatal_error_callback,
|
||||
v8::OOMErrorCallback oom_error_callback) {
|
||||
CHECK(allocator);
|
||||
V8Initializer::Initialize(mode, js_command_line_flags, oom_error_callback);
|
||||
V8Initializer::Initialize(mode, js_command_line_flags,
|
||||
disallow_v8_feature_flag_overrides,
|
||||
oom_error_callback);
|
||||
g_array_buffer_allocator = allocator;
|
||||
g_reference_table = reference_table;
|
||||
g_fatal_error_callback = fatal_error_callback;
|
||||
|
@ -115,7 +115,8 @@ class GIN_EXPORT IsolateHolder {
|
||||
static void Initialize(ScriptMode mode,
|
||||
v8::ArrayBuffer::Allocator* allocator,
|
||||
const intptr_t* reference_table = nullptr,
|
||||
const std::string js_command_line_flags = {},
|
||||
std::string js_command_line_flags = {},
|
||||
bool disallow_v8_feature_flag_overrides = false,
|
||||
v8::FatalErrorCallback fatal_error_callback = nullptr,
|
||||
v8::OOMErrorCallback oom_error_callback = nullptr);
|
||||
|
||||
|
@ -261,8 +261,28 @@ class V8FeatureVisitor : public base::FeatureVisitor {
|
||||
|
||||
namespace {
|
||||
|
||||
// Sets mandatory V8 flags.
|
||||
void SetFlags(IsolateHolder::ScriptMode mode,
|
||||
const std::string& js_command_line_flags) {
|
||||
SetV8Flags("--js-explicit-resource-management");
|
||||
|
||||
if (IsolateHolder::kStrictMode == mode) {
|
||||
SetV8Flags("--use_strict");
|
||||
}
|
||||
|
||||
// Apply any --js-flags explicitly specified by the caller.
|
||||
if (!js_command_line_flags.empty()) {
|
||||
std::vector<std::string_view> flag_list = base::SplitStringPiece(
|
||||
js_command_line_flags, ",", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
for (const auto& flag : flag_list) {
|
||||
v8::V8::SetFlagsFromString(std::string(flag).c_str(), flag.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sets feature controlled V8 flags.
|
||||
void SetFeatureFlags() {
|
||||
// Chromium features prefixed with "V8Flag_" are forwarded to V8 as V8 flags,
|
||||
// with the "V8Flag_" prefix stripped off. For example, an enabled feature
|
||||
// "V8Flag_foo_bar" will be passed to V8 as the flag `--foo_bar`. Similarly,
|
||||
@ -503,11 +523,6 @@ void SetFlags(IsolateHolder::ScriptMode mode,
|
||||
"--no-js-duplicate-named-groups");
|
||||
SetV8FlagsIfOverridden(features::kJavaScriptPromiseTry, "--js-promise-try",
|
||||
"--no-js-promise-try");
|
||||
SetV8Flags("--js-explicit-resource-management");
|
||||
|
||||
if (IsolateHolder::kStrictMode == mode) {
|
||||
SetV8Flags("--use_strict");
|
||||
}
|
||||
|
||||
// WebAssembly features.
|
||||
|
||||
@ -524,17 +539,6 @@ void SetFlags(IsolateHolder::ScriptMode mode,
|
||||
SetV8FlagsIfOverridden(features::kWebAssemblyTurboshaftInstructionSelection,
|
||||
"--turboshaft-wasm-instruction-selection-staged",
|
||||
"--no-turboshaft-wasm-instruction-selection-staged");
|
||||
|
||||
if (js_command_line_flags.empty())
|
||||
return;
|
||||
|
||||
// Allow the --js-flags switch to override existing flags:
|
||||
std::vector<std::string_view> flag_list =
|
||||
base::SplitStringPiece(js_command_line_flags, ",", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
for (const auto& flag : flag_list) {
|
||||
v8::V8::SetFlagsFromString(std::string(flag).c_str(), flag.size());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -542,14 +546,19 @@ void SetFlags(IsolateHolder::ScriptMode mode,
|
||||
// static
|
||||
void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
|
||||
const std::string& js_command_line_flags,
|
||||
bool disallow_v8_feature_flag_overrides,
|
||||
v8::OOMErrorCallback oom_error_callback) {
|
||||
static bool v8_is_initialized = false;
|
||||
if (v8_is_initialized)
|
||||
return;
|
||||
|
||||
// Flags need to be set before InitializePlatform as they are used for
|
||||
// system instrumentation initialization.
|
||||
// See https://crbug.com/v8/11043
|
||||
// Flags need to be set before InitializePlatform as they are used for system
|
||||
// instrumentation initialization, see https://crbug.com/v8/11043. --js-flags
|
||||
// and other mandatory flags in `SetFlags` must be ordered after feature flag
|
||||
// overrides.
|
||||
if (!disallow_v8_feature_flag_overrides) {
|
||||
SetFeatureFlags();
|
||||
}
|
||||
SetFlags(mode, js_command_line_flags);
|
||||
|
||||
v8::V8::InitializePlatform(V8Platform::Get());
|
||||
|
@ -30,8 +30,9 @@ class GIN_EXPORT V8Initializer {
|
||||
public:
|
||||
// This should be called by IsolateHolder::Initialize().
|
||||
static void Initialize(IsolateHolder::ScriptMode mode,
|
||||
const std::string& js_command_line_flags = {},
|
||||
v8::OOMErrorCallback oom_error_callback = nullptr);
|
||||
const std::string& js_command_line_flags,
|
||||
bool disallow_v8_feature_flag_overrides,
|
||||
v8::OOMErrorCallback oom_error_callback);
|
||||
|
||||
// Get address and size information for currently loaded snapshot.
|
||||
// If no snapshot is loaded, the return values are null for addresses
|
||||
|
5
third_party/blink/public/platform/platform.h
vendored
5
third_party/blink/public/platform/platform.h
vendored
@ -790,6 +790,11 @@ class BLINK_PLATFORM_EXPORT Platform {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// V8 Configuration ---------------------------------------------
|
||||
|
||||
// Returns whether V8 feature flag overrides were disallowed by the embedder.
|
||||
virtual bool DisallowV8FeatureFlagOverrides() const { return false; }
|
||||
|
||||
// Content Security Policy --------------------------------------
|
||||
|
||||
// Appends to `csp`, the default CSP which should be applied to the given
|
||||
|
@ -903,10 +903,11 @@ void V8Initializer::InitializeIsolateHolder(
|
||||
const intptr_t* reference_table,
|
||||
const std::string& js_command_line_flags) {
|
||||
DEFINE_STATIC_LOCAL(ArrayBufferAllocator, array_buffer_allocator, ());
|
||||
gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
|
||||
&array_buffer_allocator, reference_table,
|
||||
js_command_line_flags, ReportV8FatalError,
|
||||
ReportV8OOMError);
|
||||
gin::IsolateHolder::Initialize(
|
||||
gin::IsolateHolder::kNonStrictMode, &array_buffer_allocator,
|
||||
reference_table, js_command_line_flags,
|
||||
Platform::Current()->DisallowV8FeatureFlagOverrides(), ReportV8FatalError,
|
||||
ReportV8OOMError);
|
||||
}
|
||||
|
||||
v8::Isolate* V8Initializer::InitializeMainThread() {
|
||||
|
Reference in New Issue
Block a user