0

[tracing] Split background_tracing_utils

This CL splits background_tracing_utils and extracts parts to
components/tracing:startup_tracing (renamed :tracing_config).
to be reused in content/;
The main reason is to work around circular dependencies in follow-up.

Change-Id: If4eba4a949660810f7b8e53e3825adde275beea9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6466115
Reviewed-by: Nate Fischer <ntfschr@chromium.org>
Reviewed-by: Mikhail Khokhlov <khokhlov@google.com>
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Peter McNeeley <petermcneeley@google.com>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1448637}
This commit is contained in:
Etienne Pierre-doray
2025-04-17 15:37:11 -07:00
committed by Chromium LUCI CQ
parent 73531edeae
commit 246df77e46
21 changed files with 283 additions and 320 deletions

@ -331,7 +331,7 @@ source_set("browser") {
"//components/tpcd/metadata/browser",
"//components/tracing:background_tracing_metrics_provider",
"//components/tracing:background_tracing_utils",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/translate/core/common",
"//components/url_formatter",
"//components/url_matcher",

@ -16,6 +16,7 @@
#include "components/metrics/metrics_service.h"
#include "components/metrics/version_utils.h"
#include "components/tracing/common/background_tracing_utils.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "components/version_info/android/channel_getter.h"
#include "services/tracing/public/cpp/trace_startup_config.h"
#include "third_party/metrics_proto/trace_log.pb.h"
@ -30,7 +31,7 @@ AwBackgroundTracingMetricsProvider::~AwBackgroundTracingMetricsProvider() =
void AwBackgroundTracingMetricsProvider::DoInit() {
tracing::TraceStartupConfig::GetInstance().SetBackgroundStartupTracingEnabled(
tracing::ShouldTraceStartup());
tracing::kStartupFieldTracing.Get());
SetupFieldTracingFromFieldTrial();
metrics::MetricsService* metrics =

@ -2406,7 +2406,7 @@ static_library("browser") {
"//components/tpcd/metadata/browser:prefs",
"//components/tracing:background_tracing_metrics_provider",
"//components/tracing:background_tracing_utils",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/translate/content/browser",
"//components/translate/core/browser",
"//components/translate/core/common",

@ -215,7 +215,7 @@ static_library("login") {
"//components/session_manager:base",
"//components/signin/public/base",
"//components/startup_metric_utils",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/vector_icons",
"//components/version_info",
"//components/version_info:channel",

@ -17,6 +17,7 @@
#include "components/metrics/metrics_service.h"
#include "components/metrics/version_utils.h"
#include "components/tracing/common/background_tracing_utils.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "services/tracing/public/cpp/trace_startup_config.h"
#if BUILDFLAG(IS_WIN)
@ -40,7 +41,7 @@ ChromeBackgroundTracingMetricsProvider::
void ChromeBackgroundTracingMetricsProvider::DoInit() {
tracing::TraceStartupConfig::GetInstance().SetBackgroundStartupTracingEnabled(
tracing::ShouldTraceStartup());
tracing::kStartupFieldTracing.Get());
SetupFieldTracingFromFieldTrial();
#if BUILDFLAG(IS_WIN)

@ -27,6 +27,7 @@
#include "components/prefs/pref_service.h"
#include "components/tracing/common/background_tracing_state_manager.h"
#include "components/tracing/common/background_tracing_utils.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "components/variations/active_field_trials.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
@ -53,17 +54,8 @@
namespace {
using tracing::BackgroundTracingSetupMode;
using tracing::BackgroundTracingStateManager;
bool IsBackgroundTracingCommandLine() {
auto tracing_mode = tracing::GetBackgroundTracingSetupMode();
if (tracing_mode == BackgroundTracingSetupMode::kFromProtoConfigFile) {
return true;
}
return false;
}
} // namespace
ChromeTracingDelegate::ChromeTracingDelegate()
@ -112,14 +104,15 @@ bool ChromeTracingDelegate::IsRecordingAllowed(
bool requires_anonymized_data) const {
// If the background tracing is specified on the command-line, we allow
// any scenario to be traced and uploaded.
if (IsBackgroundTracingCommandLine()) {
if (tracing::IsBackgroundTracingEnabledFromCommandLine()) {
return true;
}
if (requires_anonymized_data &&
(incognito_launched_ || IsOffTheRecordSessionActive())) {
tracing::RecordDisallowedMetric(
tracing::TracingFinalizationDisallowedReason::kIncognitoLaunched);
UMA_HISTOGRAM_ENUMERATION(
"Tracing.Background.FinalizationDisallowedReason",
TracingFinalizationDisallowedReason::kIncognitoLaunched);
return false;
}

@ -23,6 +23,21 @@ namespace tracing {
class BackgroundTracingStateManager;
}
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with
// "TracingFinalizationDisallowedReason" in
// src/tools/metrics/histograms/enums.xml.
enum class TracingFinalizationDisallowedReason {
kIncognitoLaunched = 0,
// kProfileNotLoaded = 1, Obsolete
// kCrashMetricsNotLoaded = 2, Obsolete
// kLastSessionCrashed = 3, Obsolete
// kMetricsReportingDisabled = 4, Obsolete
// kTraceUploadedRecently = 5, Obsolete
// kLastTracingSessionDidNotEnd = 6, Obsolete as of Nov'2024.
kMaxValue = kIncognitoLaunched
};
class ChromeTracingDelegate : public content::TracingDelegate,
#if BUILDFLAG(IS_ANDROID)
public TabModelListObserver

@ -618,7 +618,7 @@ static_library("ui") {
"//components/sync_preferences",
"//components/sync_sessions",
"//components/tab_groups",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/translate/translate_internals",
"//components/ui_devtools",
"//components/ukm",

@ -6934,7 +6934,7 @@ test("unit_tests") {
"//components/tpcd/metadata/browser:test_support",
"//components/tpcd/metadata/common/proto",
"//components/tracing:background_tracing_utils",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/translate/core/browser:test_support",
"//components/ukm/content",
"//components/unexportable_keys",

@ -19,7 +19,7 @@ if (is_android) {
}
}
component("startup_tracing") {
component("tracing_config") {
sources = [
"common/background_tracing_state_manager.cc",
"common/background_tracing_state_manager.h",
@ -27,6 +27,8 @@ component("startup_tracing") {
"common/pref_names.h",
"common/trace_to_console.cc",
"common/trace_to_console.h",
"common/tracing_scenarios_config.cc",
"common/tracing_scenarios_config.h",
"common/tracing_switches.cc",
"common/tracing_switches.h",
"tracing_export.h",
@ -55,6 +57,7 @@ component("startup_tracing") {
"//base",
"//components/prefs",
"//third_party/perfetto:libperfetto",
"//third_party/snappy:snappy",
]
}
@ -84,9 +87,9 @@ component("background_tracing_utils") {
defines = [ "IS_BACKGROUND_TRACING_UTILS_IMPL" ]
deps = [
":tracing_config",
"//base",
"//content/public/browser",
"//third_party/snappy:snappy",
]
}
@ -128,7 +131,7 @@ source_set("unit_tests") {
}
deps += [
":background_tracing_utils",
":startup_tracing",
":tracing_config",
"//base/test:proto_test_support",
"//components/metrics:metrics",
"//components/prefs:test_support",

@ -8,52 +8,24 @@
#include <string>
#include <utility>
#include "base/base64.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "components/tracing/common/background_tracing_state_manager.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "components/tracing/common/tracing_switches.h"
#include "content/public/browser/background_tracing_manager.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/snappy/src/snappy.h"
namespace tracing {
BASE_FEATURE(kTracingTriggers,
"TracingTriggers",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kFieldTracing, "FieldTracing", base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kPresetTracing,
"PresetTracing",
base::FEATURE_DISABLED_BY_DEFAULT);
namespace {
const base::FeatureParam<std::string> kTracingTriggerRulesConfig{
&kTracingTriggers, "config", ""};
const base::FeatureParam<std::string> kFieldTracingConfig{&kFieldTracing,
"config", ""};
const base::FeatureParam<bool> kFieldTracingAnonymized{&kFieldTracing,
"anonymized", true};
const base::FeatureParam<bool> kFieldTracingForceUploads{
&kFieldTracing, "force_uploads", false};
const base::FeatureParam<size_t> kFieldTracingUploadLimitKb{
&kFieldTracing, "upload_limit_kb", 0};
const base::FeatureParam<bool> kStartupFieldTracing{&kFieldTracing, "startup",
false};
const base::FeatureParam<std::string> kPresetTracingConfig{&kPresetTracing,
"config", ""};
bool BlockingWriteTraceToFile(const base::FilePath& output_file,
std::string file_contents) {
if (base::WriteFile(output_file, file_contents)) {
@ -80,81 +52,6 @@ void WriteTraceToFile(
std::move(file_contents)),
std::move(done_callback));
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseSerializedTracingConfig(const base::span<const uint8_t>& config_bytes) {
perfetto::protos::gen::ChromeFieldTracingConfig config;
if (config_bytes.empty()) {
return std::nullopt;
}
if (config.ParseFromArray(config_bytes.data(), config_bytes.size())) {
return config;
}
return std::nullopt;
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseEncodedTracingConfig(const std::string& config_string) {
std::string serialized_config;
if (!base::Base64Decode(config_string, &serialized_config)) {
return std::nullopt;
}
// `serialized_config` may optionally be compressed.
std::string decompressed_config;
if (!snappy::Uncompress(serialized_config.data(), serialized_config.size(),
&decompressed_config)) {
return ParseSerializedTracingConfig(base::as_byte_span(serialized_config));
}
return ParseSerializedTracingConfig(base::as_byte_span(decompressed_config));
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetFieldTracingConfig() {
if (!base::FeatureList::IsEnabled(kFieldTracing)) {
return std::nullopt;
}
return ParseEncodedTracingConfig(kFieldTracingConfig.Get());
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetPresetTracingConfig() {
if (!base::FeatureList::IsEnabled(kPresetTracing)) {
return std::nullopt;
}
return ParseEncodedTracingConfig(kPresetTracingConfig.Get());
}
std::optional<perfetto::protos::gen::TracingTriggerRulesConfig>
GetTracingTriggerRulesConfig() {
if (!base::FeatureList::IsEnabled(kTracingTriggers)) {
return std::nullopt;
}
std::string serialized_config;
if (!base::Base64Decode(kTracingTriggerRulesConfig.Get(),
&serialized_config)) {
return std::nullopt;
}
// `serialized_config` may optionally be compressed.
std::string decompressed_config;
if (snappy::Uncompress(serialized_config.data(), serialized_config.size(),
&decompressed_config)) {
serialized_config = std::move(decompressed_config);
}
perfetto::protos::gen::TracingTriggerRulesConfig config;
if (config.ParseFromString(serialized_config)) {
return config;
}
return std::nullopt;
}
} // namespace
void RecordDisallowedMetric(TracingFinalizationDisallowedReason reason) {
UMA_HISTOGRAM_ENUMERATION("Tracing.Background.FinalizationDisallowedReason",
reason);
}
bool SetupBackgroundTracingFromProtoConfigFile(
@ -165,9 +62,10 @@ bool SetupBackgroundTracingFromProtoConfigFile(
!config_text.empty()) {
if (base::FilePath::CompareEqualIgnoreCase(config_file.Extension(),
FILE_PATH_LITERAL(".pb"))) {
config = ParseSerializedTracingConfig(base::as_byte_span(config_text));
config = tracing::ParseSerializedTracingScenariosConfig(
base::as_byte_span(config_text));
} else {
config = ParseEncodedTracingConfig(config_text);
config = tracing::ParseEncodedTracingScenariosConfig(config_text);
}
}
if (!config) {
@ -198,36 +96,35 @@ bool SetupBackgroundTracingFromCommandLine() {
return false;
}
switch (GetBackgroundTracingSetupMode()) {
case BackgroundTracingSetupMode::kDisabledInvalidCommandLine:
return false;
case BackgroundTracingSetupMode::kFromProtoConfigFile:
return SetupBackgroundTracingFromProtoConfigFile(
command_line->GetSwitchValuePath(switches::kEnableBackgroundTracing));
case BackgroundTracingSetupMode::kFromFieldTrial:
return false;
}
}
bool SetupPresetTracingFromFieldTrial() {
if (GetBackgroundTracingSetupMode() !=
BackgroundTracingSetupMode::kFromFieldTrial) {
if (!IsBackgroundTracingEnabledFromCommandLine()) {
return false;
}
if (command_line->GetSwitchValueNative(switches::kEnableBackgroundTracing)
.empty()) {
LOG(ERROR) << "--enable-background-tracing needs a config file path";
return false;
}
return SetupBackgroundTracingFromProtoConfigFile(
command_line->GetSwitchValuePath(switches::kEnableBackgroundTracing));
}
bool SetupPresetTracingFromFieldTrial() {
if (IsBackgroundTracingEnabledFromCommandLine()) {
return false;
}
auto& config = BackgroundTracingStateManager::GetInstance();
auto& manager = content::BackgroundTracingManager::GetInstance();
auto field_tracing_config = tracing::GetPresetTracingConfig();
if (field_tracing_config) {
auto tracing_scenarios_config = GetPresetTracingScenariosConfig();
if (tracing_scenarios_config) {
content::BackgroundTracingManager::DataFiltering data_filtering =
tracing::BackgroundTracingStateManager::GetInstance()
.privacy_filter_enabled()
config.privacy_filter_enabled()
? content::BackgroundTracingManager::ANONYMIZE_DATA
: content::BackgroundTracingManager::NO_DATA_FILTERING;
manager.AddPresetScenarios(std::move(*field_tracing_config),
manager.AddPresetScenarios(std::move(*tracing_scenarios_config),
data_filtering);
const auto& enabled_scenarios =
tracing::BackgroundTracingStateManager::GetInstance()
.enabled_scenarios();
const auto& enabled_scenarios = config.enabled_scenarios();
if (!enabled_scenarios.empty()) {
return manager.SetEnabledScenarios(enabled_scenarios);
}
@ -237,8 +134,7 @@ bool SetupPresetTracingFromFieldTrial() {
}
bool SetupSystemTracingFromFieldTrial() {
if (tracing::GetBackgroundTracingSetupMode() !=
BackgroundTracingSetupMode::kFromFieldTrial) {
if (IsBackgroundTracingEnabledFromCommandLine()) {
return false;
}
@ -251,48 +147,42 @@ bool SetupSystemTracingFromFieldTrial() {
}
bool SetupFieldTracingFromFieldTrial() {
if (GetBackgroundTracingSetupMode() !=
BackgroundTracingSetupMode::kFromFieldTrial) {
if (IsBackgroundTracingEnabledFromCommandLine()) {
return false;
}
bool is_local_scenario = false;
bool local_scenarios = false;
if (tracing::HasBackgroundTracingOutputPath()) {
is_local_scenario = true;
local_scenarios = true;
if (!tracing::SetBackgroundTracingOutputPath()) {
return false;
}
} else if (!kFieldTracingAnonymized.Get()) {
is_local_scenario = true;
local_scenarios = true;
}
auto& manager = content::BackgroundTracingManager::GetInstance();
auto field_tracing_config = tracing::GetFieldTracingConfig();
if (!field_tracing_config) {
auto tracing_scenarios_config = tracing::GetFieldTracingScenariosConfig();
if (!tracing_scenarios_config) {
return false;
}
if (is_local_scenario) {
if (local_scenarios) {
content::BackgroundTracingManager::DataFiltering data_filtering =
tracing::BackgroundTracingStateManager::GetInstance()
.privacy_filter_enabled()
? content::BackgroundTracingManager::ANONYMIZE_DATA
: content::BackgroundTracingManager::NO_DATA_FILTERING;
auto enabled_scenarios = manager.AddPresetScenarios(
std::move(*field_tracing_config), data_filtering);
std::move(*tracing_scenarios_config), data_filtering);
return manager.SetEnabledScenarios(enabled_scenarios);
}
return manager.InitializeFieldScenarios(
std::move(*field_tracing_config),
std::move(*tracing_scenarios_config),
content::BackgroundTracingManager::ANONYMIZE_DATA,
kFieldTracingForceUploads.Get(), kFieldTracingUploadLimitKb.Get());
}
bool HasBackgroundTracingOutputPath() {
auto* command_line = base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(switches::kBackgroundTracingOutputPath);
}
bool SetBackgroundTracingOutputPath() {
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->GetSwitchValuePath(switches::kBackgroundTracingOutputPath)
@ -309,27 +199,9 @@ bool SetBackgroundTracingOutputPath() {
return true;
}
BackgroundTracingSetupMode GetBackgroundTracingSetupMode() {
bool HasBackgroundTracingOutputPath() {
auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kEnableBackgroundTracing)) {
return BackgroundTracingSetupMode::kFromFieldTrial;
}
if (command_line->HasSwitch(switches::kEnableBackgroundTracing) &&
command_line->GetSwitchValueNative(switches::kEnableBackgroundTracing)
.empty()) {
LOG(ERROR) << "--enable-background-tracing needs a config file path";
return BackgroundTracingSetupMode::kDisabledInvalidCommandLine;
}
if (command_line->HasSwitch(switches::kEnableBackgroundTracing)) {
return BackgroundTracingSetupMode::kFromProtoConfigFile;
}
return BackgroundTracingSetupMode::kDisabledInvalidCommandLine;
}
bool ShouldTraceStartup() {
return kStartupFieldTracing.Get();
return command_line->HasSwitch(switches::kBackgroundTracingOutputPath);
}
} // namespace tracing

@ -8,44 +8,9 @@
#include "base/component_export.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "third_party/perfetto/protos/perfetto/config/chrome/scenario_config.gen.h"
namespace tracing {
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS) BASE_DECLARE_FEATURE(kFieldTracing);
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
BASE_DECLARE_FEATURE(kTracingTriggers);
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with
// "TracingFinalizationDisallowedReason" in
// src/tools/metrics/histograms/enums.xml.
enum class TracingFinalizationDisallowedReason {
kIncognitoLaunched = 0,
// kProfileNotLoaded = 1, Obsolete
// kCrashMetricsNotLoaded = 2, Obsolete
// kLastSessionCrashed = 3, Obsolete
// kMetricsReportingDisabled = 4, Obsolete
// kTraceUploadedRecently = 5, Obsolete
// kLastTracingSessionDidNotEnd = 6, Obsolete as of Nov'2024.
kMaxValue = kIncognitoLaunched
};
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
void RecordDisallowedMetric(TracingFinalizationDisallowedReason reason);
enum class BackgroundTracingSetupMode {
// Background tracing config comes from a field trial.
kFromFieldTrial,
// Background tracing config comes from a proto config file passed on
// the command-line (for local testing).
kFromProtoConfigFile,
// Background tracing is disabled due to invalid command-line flags.
kDisabledInvalidCommandLine,
};
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
bool SetupBackgroundTracingFromProtoConfigFile(
const base::FilePath& config_file);
@ -68,12 +33,6 @@ bool SetBackgroundTracingOutputPath();
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
bool HasBackgroundTracingOutputPath();
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
BackgroundTracingSetupMode GetBackgroundTracingSetupMode();
COMPONENT_EXPORT(BACKGROUND_TRACING_UTILS)
bool ShouldTraceStartup();
} // namespace tracing
#endif // COMPONENTS_TRACING_COMMON_BACKGROUND_TRACING_UTILS_H_

@ -17,14 +17,13 @@
#include "components/prefs/testing_pref_service.h"
#include "components/tracing/common/background_tracing_state_manager.h"
#include "components/tracing/common/pref_names.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "components/tracing/common/tracing_switches.h"
#include "content/public/browser/background_tracing_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/snappy/src/snappy.h"
using tracing::BackgroundTracingSetupMode;
namespace {
class BackgroundTracingUtilTest : public testing::Test {
@ -78,11 +77,6 @@ std::string GetTracingRulesConfigFromText(const std::string& proto_text) {
return serialized_message;
}
struct SetupModeParams {
const char* enable_background_tracing = nullptr;
BackgroundTracingSetupMode expected_mode;
};
TEST(BackgroundTracingUtilsTest, SetupFieldTracingFromFieldTrial) {
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@ -99,8 +93,7 @@ TEST(BackgroundTracingUtilsTest, SetupFieldTracingFromFieldTrial) {
scoped_list.InitAndEnableFeatureWithParameters(tracing::kFieldTracing,
{{"config", encoded_config}});
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromFieldTrial);
ASSERT_FALSE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_FALSE(tracing::SetupSystemTracingFromFieldTrial());
EXPECT_TRUE(tracing::SetupFieldTracingFromFieldTrial());
}
@ -121,8 +114,7 @@ TEST(BackgroundTracingUtilsTest, SetupSystemTracingFromFieldTrial) {
scoped_list.InitAndEnableFeatureWithParameters(tracing::kTracingTriggers,
{{"config", encoded_config}});
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromFieldTrial);
ASSERT_FALSE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_TRUE(tracing::SetupSystemTracingFromFieldTrial());
}
@ -144,8 +136,7 @@ TEST(BackgroundTracingUtilsTest, SetupBackgroundTracingFromProtoConfigFile) {
temp_dir.GetPath());
command_line->AppendSwitchPath(switches::kEnableBackgroundTracing, file_path);
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromProtoConfigFile);
ASSERT_TRUE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_FALSE(tracing::SetupSystemTracingFromFieldTrial());
EXPECT_FALSE(tracing::SetupFieldTracingFromFieldTrial());
EXPECT_TRUE(tracing::SetupBackgroundTracingFromCommandLine());
@ -181,39 +172,10 @@ TEST(BackgroundTracingUtilsTest, SetupFieldTracingFromFieldTrialOutputPath) {
temp_dir.GetPath());
ASSERT_TRUE(tracing::HasBackgroundTracingOutputPath());
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromFieldTrial);
ASSERT_FALSE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_TRUE(tracing::SetupFieldTracingFromFieldTrial());
}
TEST(BackgroundTracingUtilsTest, GetBackgroundTracingSetupMode) {
base::test::TaskEnvironment task_env;
auto background_tracing_manager =
content::BackgroundTracingManager::CreateInstance();
const std::vector<SetupModeParams> kParams = {
// No config file param.
{nullptr, BackgroundTracingSetupMode::kFromFieldTrial},
// Empty config filename.
{"", BackgroundTracingSetupMode::kDisabledInvalidCommandLine},
// file is valid for proto traces.
{"config.pb", BackgroundTracingSetupMode::kFromProtoConfigFile},
};
for (const SetupModeParams& params : kParams) {
SCOPED_TRACE(::testing::Message() << "enable_background_tracing "
<< params.enable_background_tracing);
base::test::ScopedCommandLine scoped_command_line;
base::CommandLine* command_line =
scoped_command_line.GetProcessCommandLine();
if (params.enable_background_tracing) {
command_line->AppendSwitchASCII(switches::kEnableBackgroundTracing,
params.enable_background_tracing);
}
EXPECT_EQ(tracing::GetBackgroundTracingSetupMode(), params.expected_mode);
}
}
TEST_F(BackgroundTracingUtilTest,
SetupBackgroundTracingFromProtoConfigFileFailed) {
auto background_tracing_manager =
@ -223,8 +185,7 @@ TEST_F(BackgroundTracingUtilTest,
base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
command_line->AppendSwitchASCII(switches::kEnableBackgroundTracing, "");
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kDisabledInvalidCommandLine);
ASSERT_TRUE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_FALSE(
tracing::SetupBackgroundTracingFromProtoConfigFile(base::FilePath()));
}
@ -257,8 +218,7 @@ TEST_F(BackgroundTracingUtilTest,
command_line->AppendSwitchPath(switches::kEnableBackgroundTracing,
config_file_path);
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromProtoConfigFile);
ASSERT_TRUE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_FALSE(
tracing::SetupBackgroundTracingFromProtoConfigFile(config_file_path));
@ -269,8 +229,7 @@ TEST_F(BackgroundTracingUtilTest,
auto background_tracing_manager =
content::BackgroundTracingManager::CreateInstance();
ASSERT_EQ(tracing::GetBackgroundTracingSetupMode(),
BackgroundTracingSetupMode::kFromFieldTrial);
ASSERT_FALSE(tracing::IsBackgroundTracingEnabledFromCommandLine());
EXPECT_FALSE(tracing::SetupBackgroundTracingFromCommandLine());
EXPECT_FALSE(
content::BackgroundTracingManager::GetInstance().HasActiveScenario());

@ -0,0 +1,140 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/tracing/common/tracing_scenarios_config.h"
#include <memory>
#include <string>
#include <utility>
#include "base/base64.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/task/task_traits.h"
#include "components/tracing/common/tracing_switches.h"
#include "third_party/snappy/src/snappy.h"
namespace tracing {
BASE_FEATURE(kTracingTriggers,
"TracingTriggers",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kFieldTracing, "FieldTracing", base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kPresetTracing,
"PresetTracing",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE_PARAM(bool,
kFieldTracingAnonymized,
&kFieldTracing,
"anonymized",
true);
BASE_FEATURE_PARAM(bool,
kFieldTracingForceUploads,
&kFieldTracing,
"force_uploads",
false);
BASE_FEATURE_PARAM(size_t,
kFieldTracingUploadLimitKb,
&kFieldTracing,
"upload_limit_kb",
0);
BASE_FEATURE_PARAM(bool,
kStartupFieldTracing,
&kFieldTracing,
"startup",
false);
namespace {
const base::FeatureParam<std::string> kTracingTriggerRulesConfig{
&kTracingTriggers, "config", ""};
const base::FeatureParam<std::string> kFieldTracingConfig{&kFieldTracing,
"config", ""};
const base::FeatureParam<std::string> kPresetTracingConfig{&kPresetTracing,
"config", ""};
} // namespace
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetPresetTracingScenariosConfig() {
if (!base::FeatureList::IsEnabled(kPresetTracing)) {
return std::nullopt;
}
return ParseEncodedTracingScenariosConfig(kPresetTracingConfig.Get());
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetFieldTracingScenariosConfig() {
if (!base::FeatureList::IsEnabled(kFieldTracing)) {
return std::nullopt;
}
return ParseEncodedTracingScenariosConfig(kFieldTracingConfig.Get());
}
std::optional<perfetto::protos::gen::TracingTriggerRulesConfig>
GetTracingTriggerRulesConfig() {
if (!base::FeatureList::IsEnabled(kTracingTriggers)) {
return std::nullopt;
}
std::string serialized_config;
if (!base::Base64Decode(kTracingTriggerRulesConfig.Get(),
&serialized_config)) {
return std::nullopt;
}
// `serialized_config` may optionally be compressed.
std::string decompressed_config;
if (snappy::Uncompress(serialized_config.data(), serialized_config.size(),
&decompressed_config)) {
serialized_config = std::move(decompressed_config);
}
perfetto::protos::gen::TracingTriggerRulesConfig config;
if (config.ParseFromString(serialized_config)) {
return config;
}
return std::nullopt;
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseSerializedTracingScenariosConfig(
const base::span<const uint8_t>& config_bytes) {
perfetto::protos::gen::ChromeFieldTracingConfig config;
if (config_bytes.empty()) {
return std::nullopt;
}
if (config.ParseFromArray(config_bytes.data(), config_bytes.size())) {
return config;
}
return std::nullopt;
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseEncodedTracingScenariosConfig(const std::string& config_string) {
std::string serialized_config;
if (!base::Base64Decode(config_string, &serialized_config)) {
return std::nullopt;
}
// `serialized_config` may optionally be compressed.
std::string decompressed_config;
if (!snappy::Uncompress(serialized_config.data(), serialized_config.size(),
&decompressed_config)) {
return ParseSerializedTracingScenariosConfig(
base::as_byte_span(serialized_config));
}
return ParseSerializedTracingScenariosConfig(
base::as_byte_span(decompressed_config));
}
bool IsBackgroundTracingEnabledFromCommandLine() {
auto* command_line = base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(switches::kEnableBackgroundTracing);
}
} // namespace tracing

@ -0,0 +1,53 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_TRACING_COMMON_TRACING_SCENARIOS_CONFIG_H_
#define COMPONENTS_TRACING_COMMON_TRACING_SCENARIOS_CONFIG_H_
#include <optional>
#include "base/containers/span.h"
#include "base/features.h"
#include "components/tracing/tracing_export.h"
#include "third_party/perfetto/protos/perfetto/config/chrome/scenario_config.gen.h"
namespace tracing {
TRACING_EXPORT BASE_DECLARE_FEATURE(kFieldTracing);
TRACING_EXPORT
BASE_DECLARE_FEATURE(kTracingTriggers);
TRACING_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kFieldTracingAnonymized);
TRACING_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kFieldTracingForceUploads);
TRACING_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kStartupFieldTracing);
TRACING_EXPORT BASE_DECLARE_FEATURE_PARAM(size_t, kFieldTracingUploadLimitKb);
TRACING_EXPORT
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseEncodedTracingScenariosConfig(const std::string& config_string);
TRACING_EXPORT
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseSerializedTracingScenariosConfig(
const base::span<const uint8_t>& config_bytes);
TRACING_EXPORT
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetPresetTracingScenariosConfig();
TRACING_EXPORT
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
GetFieldTracingScenariosConfig();
TRACING_EXPORT
std::optional<perfetto::protos::gen::TracingTriggerRulesConfig>
GetTracingTriggerRulesConfig();
TRACING_EXPORT
bool IsBackgroundTracingEnabledFromCommandLine();
} // namespace tracing
#endif // COMPONENTS_TRACING_COMMON_TRACING_SCENARIOS_CONFIG_H_

@ -137,7 +137,7 @@ source_set("browser") {
"//components/services/storage/public/mojom",
"//components/sqlite_proto",
"//components/system_media_controls",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/ui_devtools",
"//components/ukm",
"//components/ukm/debug:util",

@ -11,6 +11,7 @@
#include "base/containers/span.h"
#include "base/uuid.h"
#include "components/tracing/common/background_tracing_state_manager.h"
#include "components/tracing/common/tracing_scenarios_config.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/trace_report/trace_report_database.h"
#include "content/browser/tracing/trace_report/trace_upload_list.h"
@ -34,41 +35,6 @@
#endif
namespace content {
namespace {
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseSerializedPresetTracingConfig(
const base::span<const uint8_t>& config_bytes) {
perfetto::protos::gen::ChromeFieldTracingConfig config;
if (config_bytes.empty()) {
return std::nullopt;
}
if (config.ParseFromArray(config_bytes.data(), config_bytes.size())) {
return config;
}
return std::nullopt;
}
std::optional<perfetto::protos::gen::ChromeFieldTracingConfig>
ParseEncodedPresetTracingConfig(const std::string& config_string) {
std::string serialized_config;
if (!base::Base64Decode(config_string, &serialized_config)) {
return std::nullopt;
}
// `serialized_config` may optionally be compressed.
std::string decompressed_config;
if (!snappy::Uncompress(serialized_config.data(), serialized_config.size(),
&decompressed_config)) {
return ParseSerializedPresetTracingConfig(
base::as_byte_span(serialized_config));
}
return ParseSerializedPresetTracingConfig(
base::as_byte_span(decompressed_config));
}
} // namespace
TraceReportHandler::TraceReportHandler(
mojo::PendingReceiver<trace_report::mojom::PageHandler> receiver,
@ -190,7 +156,8 @@ void TraceReportHandler::SetPrivacyFilterEnabled(bool enable) {
void TraceReportHandler::SetScenariosConfigFromString(
const std::string& config_string,
SetScenariosConfigFromStringCallback callback) {
auto field_tracing_config = ParseEncodedPresetTracingConfig(config_string);
auto field_tracing_config =
tracing::ParseEncodedTracingScenariosConfig(config_string);
if (!field_tracing_config) {
std::move(callback).Run(false);
return;
@ -202,7 +169,7 @@ void TraceReportHandler::SetScenariosConfigFromBuffer(
mojo_base::BigBuffer config_pb,
SetScenariosConfigFromBufferCallback callback) {
auto field_tracing_config =
ParseSerializedPresetTracingConfig(config_pb.byte_span());
tracing::ParseSerializedTracingScenariosConfig(config_pb.byte_span());
if (!field_tracing_config) {
std::move(callback).Run(false);
return;

@ -77,7 +77,7 @@ target(link_target_type, "child") {
"//components/performance_manager/public/mojom",
"//components/performance_manager/scenario_api",
"//components/permissions:permissions_common",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//components/variations",
"//components/webcrypto",
"//content/common",

@ -222,7 +222,7 @@ source_set("common") {
"//components/discardable_memory/common",
"//components/input",
"//components/services/filesystem/public/mojom",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//content:content_resources",
"//content/common/fetch:fetch_api_request_proto",
"//content/public/common:interfaces",

@ -126,7 +126,7 @@ target(tracing_lib_type, "cpp") {
}
public_deps += [
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//mojo/public/cpp/bindings",
"//services/tracing/public/mojom",
]

@ -55,7 +55,7 @@ executable("ozone_demo") {
deps = [
":ozone_demo_lib",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//gpu/vulkan:buildflags",
"//mojo/core/embedder",
"//ui/events/ozone/layout",
@ -88,7 +88,7 @@ executable("skia_demo") {
deps = [
":ozone_demo_lib",
"//components/tracing:startup_tracing",
"//components/tracing:tracing_config",
"//mojo/core/embedder",
"//skia",
"//ui/events/ozone/layout",