[headless] Add active field trials support to headless_shell
This CL adds limited field trials support to headless_shell: the active field trials defined in fieldtrial_testing_config.json can be loaded if --enable-field-trial-config switch is specified. Note that variations service is not instantiated so dynamic field trials configuration is not available and cannot be enabled even if --variations-server-url switch is specified. Bug: 41486180 Change-Id: I55d88025ee7686645a050a515f3820013dd989e7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5555887 Commit-Queue: Peter Kvitek <kvitekp@chromium.org> Reviewed-by: Luc Nguyen <lucnguyen@google.com> Reviewed-by: Dominic Battre <battre@chromium.org> Reviewed-by: Andrey Kosyakov <caseq@chromium.org> Cr-Commit-Position: refs/heads/main@{#1310053}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
861ebfd801
commit
1a415977a2
@ -33,6 +33,9 @@ if (headless_enable_commands) {
|
|||||||
|
|
||||||
bundle_hyphen_data = (is_linux || is_win) && !headless_use_embedded_resources
|
bundle_hyphen_data = (is_linux || is_win) && !headless_use_embedded_resources
|
||||||
|
|
||||||
|
# If supported, field trials need to be enabled by --enable-field-trial-config switch.
|
||||||
|
headless_support_field_trials = headless_use_prefs
|
||||||
|
|
||||||
# Headless defines config applied to every target below.
|
# Headless defines config applied to every target below.
|
||||||
config("headless_defines_config") {
|
config("headless_defines_config") {
|
||||||
defines = []
|
defines = []
|
||||||
@ -52,6 +55,10 @@ config("headless_defines_config") {
|
|||||||
if (headless_mode_policy_supported) {
|
if (headless_mode_policy_supported) {
|
||||||
defines += [ "HEADLESS_MODE_POLICY_SUPPORTED" ]
|
defines += [ "HEADLESS_MODE_POLICY_SUPPORTED" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headless_support_field_trials) {
|
||||||
|
defines += [ "HEADLESS_SUPPORT_FIELD_TRIALS" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# For code inside the build component "headless".
|
# For code inside the build component "headless".
|
||||||
@ -389,6 +396,18 @@ component("headless_non_renderer") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headless_support_field_trials) {
|
||||||
|
sources += [
|
||||||
|
"lib/browser/headless_field_trials.cc",
|
||||||
|
"lib/browser/headless_field_trials.h",
|
||||||
|
]
|
||||||
|
deps += [
|
||||||
|
"//components/metrics",
|
||||||
|
"//components/variations",
|
||||||
|
"//components/variations/service",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
if (enable_printing) {
|
if (enable_printing) {
|
||||||
deps += [
|
deps += [
|
||||||
"//components/printing/browser",
|
"//components/printing/browser",
|
||||||
|
@ -9,13 +9,14 @@ specific_include_rules = {
|
|||||||
"+services/device/public/cpp/geolocation/geolocation_manager_impl_mac.h",
|
"+services/device/public/cpp/geolocation/geolocation_manager_impl_mac.h",
|
||||||
],
|
],
|
||||||
"headless_content_client.cc": [
|
"headless_content_client.cc": [
|
||||||
"+components/embedder_support/origin_trials",
|
"+components/embedder_support/origin_trials",
|
||||||
],
|
],
|
||||||
"headless_content_main_delegate.cc": [
|
"headless_content_main_delegate.cc": [
|
||||||
|
"+gpu/config/gpu_switches.h",
|
||||||
"+cc/base/switches.h",
|
"+cc/base/switches.h",
|
||||||
"+components/viz/common/switches.h",
|
"+components/viz/common/switches.h",
|
||||||
"+components/devtools/devtools_pipe/devtools_pipe.h",
|
"+components/devtools/devtools_pipe/devtools_pipe.h",
|
||||||
"+gpu/config/gpu_switches.h",
|
"+components/prefs",
|
||||||
"+third_party/blink/public/common/switches.h",
|
"+third_party/blink/public/common/switches.h",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ specific_include_rules = {
|
|||||||
"+components/prefs",
|
"+components/prefs",
|
||||||
"+components/pref_registry",
|
"+components/pref_registry",
|
||||||
"+components/keyed_service/content",
|
"+components/keyed_service/content",
|
||||||
|
"+components/metrics",
|
||||||
|
"+components/variations",
|
||||||
],
|
],
|
||||||
"headless_browser_impl_unittest.cc": [
|
"headless_browser_impl_unittest.cc": [
|
||||||
"+third_party/blink/public/common/features.h",
|
"+third_party/blink/public/common/features.h",
|
||||||
@ -58,5 +60,10 @@ specific_include_rules = {
|
|||||||
],
|
],
|
||||||
"command_line_handler.cc": [
|
"command_line_handler.cc": [
|
||||||
"+third_party/blink/public/common/switches.h",
|
"+third_party/blink/public/common/switches.h",
|
||||||
|
],
|
||||||
|
"headless_field_trials.cc": [
|
||||||
|
"+components/prefs",
|
||||||
|
"+components/metrics",
|
||||||
|
"+components/variations",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
#include "headless/lib/browser/policy/headless_policies.h"
|
#include "headless/lib/browser/policy/headless_policies.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
#include "components/metrics/metrics_service.h" // nogncheck
|
||||||
|
#include "components/variations/service/variations_service.h" // nogncheck
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace headless {
|
namespace headless {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -344,9 +349,6 @@ bool HeadlessBrowserImpl::ShouldStartDevToolsServer() {
|
|||||||
|
|
||||||
void HeadlessBrowserImpl::PreMainMessageLoopRun() {
|
void HeadlessBrowserImpl::PreMainMessageLoopRun() {
|
||||||
PlatformInitialize();
|
PlatformInitialize();
|
||||||
#if defined(HEADLESS_USE_PREFS)
|
|
||||||
CreatePrefService();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// We don't support the tethering domain on this agent host.
|
// We don't support the tethering domain on this agent host.
|
||||||
agent_host_ = content::DevToolsAgentHost::CreateForBrowser(
|
agent_host_ = content::DevToolsAgentHost::CreateForBrowser(
|
||||||
@ -375,12 +377,6 @@ void HeadlessBrowserImpl::PostMainMessageLoopRun() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HEADLESS_USE_PREFS)
|
|
||||||
PrefService* HeadlessBrowserImpl::GetPrefs() {
|
|
||||||
return local_state_.get();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HEADLESS_USE_POLICY)
|
#if defined(HEADLESS_USE_POLICY)
|
||||||
policy::PolicyService* HeadlessBrowserImpl::GetPolicyService() {
|
policy::PolicyService* HeadlessBrowserImpl::GetPolicyService() {
|
||||||
return policy_connector_ ? policy_connector_->GetPolicyService() : nullptr;
|
return policy_connector_ ? policy_connector_->GetPolicyService() : nullptr;
|
||||||
@ -389,6 +385,8 @@ policy::PolicyService* HeadlessBrowserImpl::GetPolicyService() {
|
|||||||
|
|
||||||
#if defined(HEADLESS_USE_PREFS)
|
#if defined(HEADLESS_USE_PREFS)
|
||||||
void HeadlessBrowserImpl::CreatePrefService() {
|
void HeadlessBrowserImpl::CreatePrefService() {
|
||||||
|
CHECK(!local_state_);
|
||||||
|
|
||||||
scoped_refptr<PersistentPrefStore> pref_store;
|
scoped_refptr<PersistentPrefStore> pref_store;
|
||||||
if (options()->user_data_dir.empty()) {
|
if (options()->user_data_dir.empty()) {
|
||||||
pref_store = base::MakeRefCounted<InMemoryPrefStore>();
|
pref_store = base::MakeRefCounted<InMemoryPrefStore>();
|
||||||
@ -421,6 +419,11 @@ void HeadlessBrowserImpl::CreatePrefService() {
|
|||||||
OSCrypt::RegisterLocalPrefs(pref_registry.get());
|
OSCrypt::RegisterLocalPrefs(pref_registry.get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
metrics::MetricsService::RegisterPrefs(pref_registry.get());
|
||||||
|
variations::VariationsService::RegisterPrefs(pref_registry.get());
|
||||||
|
#endif
|
||||||
|
|
||||||
PrefServiceFactory factory;
|
PrefServiceFactory factory;
|
||||||
|
|
||||||
#if defined(HEADLESS_USE_POLICY)
|
#if defined(HEADLESS_USE_POLICY)
|
||||||
@ -447,6 +450,10 @@ void HeadlessBrowserImpl::CreatePrefService() {
|
|||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_WIN)
|
#endif // BUILDFLAG(IS_WIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrefService* HeadlessBrowserImpl::GetPrefs() {
|
||||||
|
return local_state_.get();
|
||||||
|
}
|
||||||
#endif // defined(HEADLESS_USE_PREFS)
|
#endif // defined(HEADLESS_USE_PREFS)
|
||||||
|
|
||||||
} // namespace headless
|
} // namespace headless
|
||||||
|
@ -113,6 +113,7 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser {
|
|||||||
int exit_code() const { return exit_code_; }
|
int exit_code() const { return exit_code_; }
|
||||||
|
|
||||||
#if defined(HEADLESS_USE_PREFS)
|
#if defined(HEADLESS_USE_PREFS)
|
||||||
|
void CreatePrefService();
|
||||||
PrefService* GetPrefs();
|
PrefService* GetPrefs();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -129,10 +130,6 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(HEADLESS_USE_PREFS)
|
|
||||||
void CreatePrefService();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
base::OnceCallback<void(HeadlessBrowser*)> on_start_callback_;
|
base::OnceCallback<void(HeadlessBrowser*)> on_start_callback_;
|
||||||
std::optional<HeadlessBrowser::Options> options_;
|
std::optional<HeadlessBrowser::Options> options_;
|
||||||
|
|
||||||
|
135
headless/lib/browser/headless_field_trials.cc
Normal file
135
headless/lib/browser/headless_field_trials.cc
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// Copyright 2024 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "headless/lib/browser/headless_field_trials.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/command_line.h"
|
||||||
|
#include "base/feature_list.h"
|
||||||
|
#include "components/metrics/enabled_state_provider.h"
|
||||||
|
#include "components/metrics/metrics_state_manager.h"
|
||||||
|
#include "components/prefs/pref_service.h"
|
||||||
|
#include "components/variations/platform_field_trials.h"
|
||||||
|
#include "components/variations/seed_response.h"
|
||||||
|
#include "components/variations/service/safe_seed_manager.h"
|
||||||
|
#include "components/variations/service/ui_string_overrider.h"
|
||||||
|
#include "components/variations/service/variations_field_trial_creator.h"
|
||||||
|
#include "components/variations/service/variations_service_client.h"
|
||||||
|
#include "components/variations/variations_safe_seed_store_local_state.h"
|
||||||
|
#include "components/variations/variations_seed_store.h"
|
||||||
|
#include "components/variations/variations_switches.h"
|
||||||
|
#include "content/public/common/content_switch_dependent_feature_overrides.h"
|
||||||
|
|
||||||
|
namespace headless {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// A simple concrete implementation of the EnabledStateProvider interface.
|
||||||
|
class HeadlessEnabledStateProvider : public metrics::EnabledStateProvider {
|
||||||
|
public:
|
||||||
|
HeadlessEnabledStateProvider(bool consent, bool enabled)
|
||||||
|
: consent_(consent), enabled_(enabled) {}
|
||||||
|
|
||||||
|
HeadlessEnabledStateProvider(const HeadlessEnabledStateProvider&) = delete;
|
||||||
|
HeadlessEnabledStateProvider& operator=(const HeadlessEnabledStateProvider&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
~HeadlessEnabledStateProvider() override = default;
|
||||||
|
|
||||||
|
// metrics::EnabledStateProvider
|
||||||
|
bool IsConsentGiven() const override { return consent_; }
|
||||||
|
bool IsReportingEnabled() const override { return enabled_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool consent_;
|
||||||
|
bool enabled_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HeadlessVariationsServiceClient
|
||||||
|
: public variations::VariationsServiceClient {
|
||||||
|
public:
|
||||||
|
HeadlessVariationsServiceClient() = default;
|
||||||
|
~HeadlessVariationsServiceClient() override = default;
|
||||||
|
|
||||||
|
// variations::VariationsServiceClient:
|
||||||
|
base::Version GetVersionForSimulation() override { return base::Version(); }
|
||||||
|
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
|
||||||
|
override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
network_time::NetworkTimeTracker* GetNetworkTimeTracker() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
version_info::Channel GetChannel() override {
|
||||||
|
return version_info::Channel::UNKNOWN;
|
||||||
|
}
|
||||||
|
bool OverridesRestrictParameter(std::string* parameter) override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool IsEnterprise() override { return false; }
|
||||||
|
|
||||||
|
void RemoveGoogleGroupsFromPrefsForDeletedProfiles(
|
||||||
|
PrefService* local_state) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool ShouldEnableFieldTrials() {
|
||||||
|
static bool should_enable_field_trials =
|
||||||
|
base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||||
|
variations::switches::kEnableFieldTrialTestingConfig);
|
||||||
|
return should_enable_field_trials;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUpFieldTrials(PrefService* local_state,
|
||||||
|
const base::FilePath& user_data_dir) {
|
||||||
|
CHECK(local_state);
|
||||||
|
|
||||||
|
HeadlessEnabledStateProvider enabled_state_provider(/*consent=*/false,
|
||||||
|
/*enabled=*/false);
|
||||||
|
|
||||||
|
std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager =
|
||||||
|
metrics::MetricsStateManager::Create(local_state, &enabled_state_provider,
|
||||||
|
std::wstring(), user_data_dir);
|
||||||
|
|
||||||
|
metrics_state_manager->InstantiateFieldTrialList();
|
||||||
|
|
||||||
|
HeadlessVariationsServiceClient variations_service_client;
|
||||||
|
variations::VariationsFieldTrialCreator field_trial_creator(
|
||||||
|
&variations_service_client,
|
||||||
|
std::make_unique<variations::VariationsSeedStore>(
|
||||||
|
local_state, /*initial_seed=*/nullptr,
|
||||||
|
/*signature_verification_enabled=*/true,
|
||||||
|
std::make_unique<variations::VariationsSafeSeedStoreLocalState>(
|
||||||
|
local_state)),
|
||||||
|
variations::UIStringOverrider(),
|
||||||
|
/*limited_entropy_synthetic_trial=*/nullptr);
|
||||||
|
|
||||||
|
variations::SafeSeedManager safe_seed_manager(local_state);
|
||||||
|
|
||||||
|
const base::CommandLine& command_line =
|
||||||
|
*base::CommandLine::ForCurrentProcess();
|
||||||
|
|
||||||
|
// Overrides for content/common and lower layers' switches.
|
||||||
|
std::vector<base::FeatureList::FeatureOverrideInfo> feature_overrides =
|
||||||
|
content::GetSwitchDependentFeatureOverrides(command_line);
|
||||||
|
|
||||||
|
// Setup field trials directly without help of the variations service.
|
||||||
|
std::vector<std::string> variation_ids;
|
||||||
|
auto feature_list = std::make_unique<base::FeatureList>();
|
||||||
|
variations::PlatformFieldTrials platform_field_trials;
|
||||||
|
variations::SyntheticTrialRegistry synthetic_trial_registry;
|
||||||
|
field_trial_creator.SetUpFieldTrials(
|
||||||
|
variation_ids,
|
||||||
|
command_line.GetSwitchValueASCII(
|
||||||
|
variations::switches::kForceVariationIds),
|
||||||
|
feature_overrides, std::move(feature_list), metrics_state_manager.get(),
|
||||||
|
&synthetic_trial_registry, &platform_field_trials, &safe_seed_manager,
|
||||||
|
/*add_entropy_source_to_variations_ids=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace headless
|
24
headless/lib/browser/headless_field_trials.h
Normal file
24
headless/lib/browser/headless_field_trials.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2024 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef HEADLESS_LIB_BROWSER_HEADLESS_FIELD_TRIALS_H_
|
||||||
|
#define HEADLESS_LIB_BROWSER_HEADLESS_FIELD_TRIALS_H_
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
|
||||||
|
class PrefService;
|
||||||
|
|
||||||
|
namespace headless {
|
||||||
|
|
||||||
|
// Returns positive if --enable-field-trial-config switch is specified in the
|
||||||
|
// command line.
|
||||||
|
bool ShouldEnableFieldTrials();
|
||||||
|
|
||||||
|
// Instantiates metrics state manager and sets up field trials.
|
||||||
|
void SetUpFieldTrials(PrefService* local_state,
|
||||||
|
const base::FilePath& user_data_dir);
|
||||||
|
|
||||||
|
} // namespace headless
|
||||||
|
|
||||||
|
#endif // HEADLESS_LIB_BROWSER_HEADLESS_FIELD_TRIALS_H_
|
@ -69,6 +69,16 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEADLESS_USE_PREFS)
|
||||||
|
#include "components/prefs/pref_service.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
#include "content/public/app/initialize_mojo_core.h"
|
||||||
|
#include "headless/lib/browser/headless_field_trials.h"
|
||||||
|
#include "third_party/abseil-cpp/absl/types/variant.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace headless {
|
namespace headless {
|
||||||
|
|
||||||
namespace features {
|
namespace features {
|
||||||
@ -174,6 +184,33 @@ void InitApplicationLocale(const base::CommandLine& command_line) {
|
|||||||
command_line.GetSwitchValueASCII(::switches::kLang));
|
command_line.GetSwitchValueASCII(::switches::kLang));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddSwitchesForVirtualTime() {
|
||||||
|
// Only pass viz flags into the virtual time mode.
|
||||||
|
const char* const switches[] = {
|
||||||
|
// TODO(eseckler): Make --run-all-compositor-stages-before-draw a
|
||||||
|
// per-BeginFrame mode so that we can activate it for individual
|
||||||
|
// requests
|
||||||
|
// only. With surface sync becoming the default, we can then make
|
||||||
|
// virtual_time_enabled a per-request option, too.
|
||||||
|
// We control BeginFrames ourselves and need all compositing stages to
|
||||||
|
// run.
|
||||||
|
::switches::kRunAllCompositorStagesBeforeDraw,
|
||||||
|
::switches::kDisableNewContentRenderingTimeout,
|
||||||
|
cc::switches::kDisableThreadedAnimation,
|
||||||
|
// Animtion-only BeginFrames are only supported when updates from the
|
||||||
|
// impl-thread are disabled, see go/headless-rendering.
|
||||||
|
cc::switches::kDisableCheckerImaging,
|
||||||
|
// Ensure that image animations don't resync their animation timestamps
|
||||||
|
// when looping back around.
|
||||||
|
blink::switches::kDisableImageAnimationResync,
|
||||||
|
};
|
||||||
|
|
||||||
|
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
for (const auto* flag : switches) {
|
||||||
|
command_line->AppendSwitch(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
HeadlessContentMainDelegate::HeadlessContentMainDelegate(
|
HeadlessContentMainDelegate::HeadlessContentMainDelegate(
|
||||||
@ -528,31 +565,58 @@ std::optional<int> HeadlessContentMainDelegate::PostEarlyInitialization(
|
|||||||
if (absl::holds_alternative<InvokedInChildProcess>(invoked_in))
|
if (absl::holds_alternative<InvokedInChildProcess>(invoked_in))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
|
#if defined(HEADLESS_USE_PREFS)
|
||||||
|
browser_->CreatePrefService();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
// Check if we're telling content to not to create the feature list and do it
|
||||||
|
// here if so. Content can create default feature list on its own however here
|
||||||
|
// we want the feature list to be created by field trial machinery.
|
||||||
|
if (!ShouldCreateFeatureList(invoked_in)) {
|
||||||
|
SetUpFieldTrials(browser()->GetPrefs(),
|
||||||
|
browser()->options()->user_data_dir);
|
||||||
|
// Schedule a Local State write since the above function may have resulted
|
||||||
|
// in some prefs being updated. Headless shell runs are typically short and
|
||||||
|
// often end in crashes, so it helps to commit early.
|
||||||
|
browser_->GetPrefs()->CommitPendingWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we're telling content to not to initialize Mojo and do it here
|
||||||
|
// since we want it do be done after the feature list is created.
|
||||||
|
if (!ShouldInitializeMojo(invoked_in)) {
|
||||||
|
content::InitializeMojoCore();
|
||||||
|
}
|
||||||
|
#endif // defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
|
||||||
if (base::FeatureList::IsEnabled(features::kVirtualTime)) {
|
if (base::FeatureList::IsEnabled(features::kVirtualTime)) {
|
||||||
// Only pass viz flags into the virtual time mode.
|
AddSwitchesForVirtualTime();
|
||||||
const char* const switches[] = {
|
|
||||||
// TODO(eseckler): Make --run-all-compositor-stages-before-draw a
|
|
||||||
// per-BeginFrame mode so that we can activate it for individual
|
|
||||||
// requests
|
|
||||||
// only. With surface sync becoming the default, we can then make
|
|
||||||
// virtual_time_enabled a per-request option, too.
|
|
||||||
// We control BeginFrames ourselves and need all compositing stages to
|
|
||||||
// run.
|
|
||||||
::switches::kRunAllCompositorStagesBeforeDraw,
|
|
||||||
::switches::kDisableNewContentRenderingTimeout,
|
|
||||||
cc::switches::kDisableThreadedAnimation,
|
|
||||||
// Animtion-only BeginFrames are only supported when updates from the
|
|
||||||
// impl-thread are disabled, see go/headless-rendering.
|
|
||||||
cc::switches::kDisableCheckerImaging,
|
|
||||||
// Ensure that image animations don't resync their animation timestamps
|
|
||||||
// when looping back around.
|
|
||||||
blink::switches::kDisableImageAnimationResync,
|
|
||||||
};
|
|
||||||
for (const auto* flag : switches)
|
|
||||||
base::CommandLine::ForCurrentProcess()->AppendSwitch(flag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
bool HeadlessContentMainDelegate::ShouldCreateFeatureList(
|
||||||
|
InvokedIn invoked_in) {
|
||||||
|
// The content layer is always responsible for creating the FeatureList in
|
||||||
|
// child processes.
|
||||||
|
if (absl::holds_alternative<InvokedInChildProcess>(invoked_in)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VariationsFieldTrialCreator::SetUpFieldTrials() instantiates its own
|
||||||
|
// feature list so prevent content from instantiating a default one if we're
|
||||||
|
// going to set up field trials.
|
||||||
|
return !ShouldEnableFieldTrials();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeadlessContentMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {
|
||||||
|
// Mojo cannot be initialized without a feature list instance available so
|
||||||
|
// postpone its initialization until after feature list is instantiated by
|
||||||
|
// field trials setup if field trials are enabled.
|
||||||
|
return ShouldCreateFeatureList(invoked_in);
|
||||||
|
}
|
||||||
|
#endif // defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
|
||||||
} // namespace headless
|
} // namespace headless
|
||||||
|
@ -55,6 +55,12 @@ class HEADLESS_EXPORT HeadlessContentMainDelegate
|
|||||||
content::ContentRendererClient* CreateContentRendererClient() override;
|
content::ContentRendererClient* CreateContentRendererClient() override;
|
||||||
|
|
||||||
std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
|
std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
|
||||||
|
|
||||||
|
#if defined(HEADLESS_SUPPORT_FIELD_TRIALS)
|
||||||
|
bool ShouldCreateFeatureList(InvokedIn invoked_in) override;
|
||||||
|
bool ShouldInitializeMojo(InvokedIn invoked_in) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
void PlatformPreBrowserMain();
|
void PlatformPreBrowserMain();
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user