tracing: Hook up TracingDelegate for DevTools system tracing + fix tests
Adds a way to enable/disable system trace consumer connections from content, such that we can check whether content's TracingDelegate allows this. Also fixes a few issues with the system tracing DevTools tests, primarily ensuring that the socket overrides are created before the browser initializes. With the new way to enable/disable system consumer connections, the tests are can be extended to cover most Posix platforms (when using a fake system service). Bug: 1141387 Change-Id: I82684e416aabdff9aba6daff4a5784171a615f05 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2773310 Reviewed-by: Sami Kyöstilä <skyostil@chromium.org> Reviewed-by: Andrey Kosyakov <caseq@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Commit-Queue: Eric Seckler <eseckler@chromium.org> Cr-Commit-Position: refs/heads/master@{#868068}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
6bd0ead903
commit
aa674d26b9
chrome/browser/tracing
content
services/tracing
perfetto
public
@ -43,6 +43,7 @@
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#include "ash/constants/ash_pref_names.h"
|
||||
#include "chromeos/dbus/constants/dbus_switches.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
@ -273,6 +274,12 @@ bool ChromeTracingDelegate::IsProfileLoaded() {
|
||||
|
||||
bool ChromeTracingDelegate::IsSystemWideTracingEnabled() {
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// Always allow system tracing in dev mode images.
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
chromeos::switches::kSystemDevMode)) {
|
||||
return true;
|
||||
}
|
||||
// In non-dev images, honor the pref for system-wide tracing.
|
||||
PrefService* local_state = g_browser_process->local_state();
|
||||
DCHECK(local_state);
|
||||
return local_state->GetBoolean(
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "content/gpu/in_process_gpu_thread.h"
|
||||
#include "content/public/app/content_main_delegate.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/tracing_delegate.h"
|
||||
#include "content/public/common/content_client.h"
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "content/public/common/content_descriptor_keys.h"
|
||||
@ -99,7 +100,9 @@
|
||||
#include "sandbox/policy/sandbox_type.h"
|
||||
#include "sandbox/policy/switches.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
|
||||
#include "services/tracing/public/cpp/trace_startup.h"
|
||||
#include "services/tracing/public/cpp/tracing_features.h"
|
||||
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
|
||||
#include "ui/base/ui_base_paths.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
@ -456,6 +459,19 @@ void InstallConsoleControlHandler(bool is_browser_process) {
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
bool ShouldAllowSystemTracingConsumer() {
|
||||
// System tracing consumer support is currently only supported on ChromeOS.
|
||||
// TODO(crbug.com/1173395): Also enable for Lacros-Chrome.
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// The consumer should only be enabled when the delegate allows it.
|
||||
TracingDelegate* delegate =
|
||||
GetContentClient()->browser()->GetTracingDelegate();
|
||||
return delegate && delegate->IsSystemWideTracingEnabled();
|
||||
#else // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
return false;
|
||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ContentClientCreator {
|
||||
@ -1000,6 +1016,9 @@ int ContentMainRunnerImpl::RunBrowser(MainFunctionParams& main_params,
|
||||
|
||||
BrowserTaskExecutor::PostFeatureListSetup();
|
||||
|
||||
tracing::PerfettoTracedProcess::Get()
|
||||
->SetAllowSystemTracingConsumerCallback(
|
||||
base::BindRepeating(&ShouldAllowSystemTracingConsumer));
|
||||
tracing::InitTracingPostThreadPoolStartAndFeatureList();
|
||||
|
||||
// PowerMonitor is needed in reduced mode. BrowserMainLoop will safely skip
|
||||
|
@ -72,13 +72,11 @@
|
||||
#include "ui/snapshot/snapshot.h"
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
#include "base/deferred_sequenced_task_runner.h"
|
||||
#include "base/tracing/perfetto_task_runner.h"
|
||||
#include "services/tracing/perfetto/system_test_utils.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#include "chromeos/dbus/constants/dbus_switches.h"
|
||||
#endif
|
||||
|
||||
#define EXPECT_SIZE_EQ(expected, actual) \
|
||||
do { \
|
||||
EXPECT_EQ((expected).width(), (actual).width()); \
|
||||
@ -189,60 +187,6 @@ class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest {
|
||||
}
|
||||
};
|
||||
|
||||
class SystemBackendDevToolsProtocolTest : public DevToolsProtocolTest {
|
||||
public:
|
||||
SystemBackendDevToolsProtocolTest() {
|
||||
feature_list_.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
|
||||
}
|
||||
|
||||
void SetUpCommandLine(base::CommandLine* command_line) override {
|
||||
DevToolsProtocolTest::SetUpCommandLine(command_line);
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
command_line->AppendSwitch(chromeos::switches::kSystemDevMode);
|
||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
DevToolsProtocolTest::SetUp();
|
||||
saved_consumer_sock_name_ = GetConsumerSockEnvName();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (!saved_consumer_sock_name_.empty()) {
|
||||
SetConsumerSockEnvName(saved_consumer_sock_name_);
|
||||
} else {
|
||||
UnsetConsumerSockEnvName();
|
||||
}
|
||||
saved_consumer_sock_name_ = "";
|
||||
DevToolsProtocolTest::TearDown();
|
||||
}
|
||||
|
||||
std::string GetConsumerSockEnvName() {
|
||||
const char* value = NULL;
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
value = getenv("PERFETTO_CONSUMER_SOCK_NAME");
|
||||
#endif
|
||||
return value ? value : "";
|
||||
}
|
||||
|
||||
void SetConsumerSockEnvName(const std::string& value) {
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
ASSERT_EQ(0, setenv("PERFETTO_CONSUMER_SOCK_NAME", value.c_str(),
|
||||
/*overwrite=*/true));
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnsetConsumerSockEnvName() {
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
ASSERT_EQ(0, unsetenv("PERFETTO_CONSUMER_SOCK_NAME"));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
std::string saved_consumer_sock_name_;
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
class SyntheticKeyEventTest : public DevToolsProtocolTest {
|
||||
protected:
|
||||
void SendKeyEvent(const std::string& type,
|
||||
@ -2826,71 +2770,143 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TracingWithPerfettoConfig) {
|
||||
WaitForNotification("Tracing.tracingComplete", true);
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(SystemBackendDevToolsProtocolTest,
|
||||
StartTracingWithSystemBackendRequestFailed) {
|
||||
perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
|
||||
base::trace_event::TraceConfig(),
|
||||
/*privacy_filtering_enabled=*/false,
|
||||
/*convert_to_legacy_json=*/false,
|
||||
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
|
||||
class SystemTracingDevToolsProtocolTest : public DevToolsProtocolTest {
|
||||
protected:
|
||||
base::DictionaryValue* StartSystemTrace() {
|
||||
perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
|
||||
base::trace_event::TraceConfig(),
|
||||
/*privacy_filtering_enabled=*/false,
|
||||
/*convert_to_legacy_json=*/false,
|
||||
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
|
||||
|
||||
std::string perfetto_config_encoded;
|
||||
base::Base64Encode(perfetto_config.SerializeAsString(),
|
||||
&perfetto_config_encoded);
|
||||
std::string perfetto_config_encoded;
|
||||
base::Base64Encode(perfetto_config.SerializeAsString(),
|
||||
&perfetto_config_encoded);
|
||||
|
||||
auto params = std::make_unique<base::DictionaryValue>();
|
||||
params->SetKey("perfettoConfig", base::Value(perfetto_config_encoded));
|
||||
params->SetString("transferMode", "ReturnAsStream");
|
||||
params->SetString("tracingBackend", "system");
|
||||
auto params = std::make_unique<base::DictionaryValue>();
|
||||
params->SetKey("perfettoConfig", base::Value(perfetto_config_encoded));
|
||||
params->SetString("transferMode", "ReturnAsStream");
|
||||
params->SetString("tracingBackend", "system");
|
||||
|
||||
SetConsumerSockEnvName("non_existent");
|
||||
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
|
||||
Attach();
|
||||
|
||||
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
|
||||
Attach();
|
||||
return SendCommand("Tracing.start", std::move(params), true);
|
||||
}
|
||||
};
|
||||
|
||||
base::DictionaryValue* command_result =
|
||||
SendCommand("Tracing.start", std::move(params), true);
|
||||
IN_PROC_BROWSER_TEST_F(SystemTracingDevToolsProtocolTest,
|
||||
StartSystemTracingFailsWhenSystemConsumerDisabled) {
|
||||
base::DictionaryValue* command_result = StartSystemTrace();
|
||||
ASSERT_EQ(command_result, nullptr);
|
||||
}
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
// System tracing backend recording is currently only supported on ChromeOS.
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#define MAYBE_TracingWithSystemBackend TracingWithSystemBackend
|
||||
class PosixSystemTracingDevToolsProtocolTest
|
||||
: public SystemTracingDevToolsProtocolTest {
|
||||
public:
|
||||
PosixSystemTracingDevToolsProtocolTest() {
|
||||
feature_list_.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
|
||||
tracing::PerfettoTracedProcess::Get()
|
||||
->SetAllowSystemTracingConsumerForTesting(true);
|
||||
const char* producer_sock = getenv("PERFETTO_PRODUCER_SOCK_NAME");
|
||||
saved_producer_sock_name_ = producer_sock ? producer_sock : std::string();
|
||||
const char* consumer_sock = getenv("PERFETTO_CONSUMER_SOCK_NAME");
|
||||
saved_consumer_sock_name_ = consumer_sock ? consumer_sock : std::string();
|
||||
}
|
||||
|
||||
~PosixSystemTracingDevToolsProtocolTest() override {
|
||||
if (!saved_producer_sock_name_.empty()) {
|
||||
SetProducerSockEnvName(saved_producer_sock_name_);
|
||||
} else {
|
||||
EXPECT_EQ(0, unsetenv("PERFETTO_PRODUCER_SOCK_NAME"));
|
||||
}
|
||||
if (!saved_consumer_sock_name_.empty()) {
|
||||
SetConsumerSockEnvName(saved_consumer_sock_name_);
|
||||
} else {
|
||||
EXPECT_EQ(0, unsetenv("PERFETTO_CONSUMER_SOCK_NAME"));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetProducerSockEnvName(const std::string& value) {
|
||||
ASSERT_EQ(0, setenv("PERFETTO_PRODUCER_SOCK_NAME", value.c_str(),
|
||||
/*overwrite=*/true));
|
||||
}
|
||||
void SetConsumerSockEnvName(const std::string& value) {
|
||||
ASSERT_EQ(0, setenv("PERFETTO_CONSUMER_SOCK_NAME", value.c_str(),
|
||||
/*overwrite=*/true));
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
std::string saved_producer_sock_name_;
|
||||
std::string saved_consumer_sock_name_;
|
||||
};
|
||||
|
||||
class InvalidSystemTracingDevToolsProtocolTest
|
||||
: public PosixSystemTracingDevToolsProtocolTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
// Use a non-existing backend.
|
||||
SetProducerSockEnvName("non_existing");
|
||||
SetConsumerSockEnvName("non_existing");
|
||||
|
||||
PosixSystemTracingDevToolsProtocolTest::SetUp();
|
||||
}
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InvalidSystemTracingDevToolsProtocolTest,
|
||||
StartTracingFailsWithInvalidSockets) {
|
||||
base::DictionaryValue* command_result = StartSystemTrace();
|
||||
ASSERT_EQ(command_result, nullptr);
|
||||
}
|
||||
|
||||
class FakeSystemTracingDevToolsProtocolTest
|
||||
: public PosixSystemTracingDevToolsProtocolTest {
|
||||
public:
|
||||
FakeSystemTracingDevToolsProtocolTest()
|
||||
: deferred_task_runner_(new base::DeferredSequencedTaskRunner()) {}
|
||||
|
||||
void SetUp() override {
|
||||
SetupService();
|
||||
PosixSystemTracingDevToolsProtocolTest::SetUp();
|
||||
}
|
||||
|
||||
void PreRunTestOnMainThread() override {
|
||||
deferred_task_runner_->StartWithTaskRunner(
|
||||
base::SequencedTaskRunnerHandle::Get());
|
||||
|
||||
PosixSystemTracingDevToolsProtocolTest::PreRunTestOnMainThread();
|
||||
}
|
||||
|
||||
private:
|
||||
void SetupService() {
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||
|
||||
system_service_ = std::make_unique<tracing::MockSystemService>(
|
||||
temp_dir_, std::make_unique<base::tracing::PerfettoTaskRunner>(
|
||||
deferred_task_runner_));
|
||||
|
||||
SetProducerSockEnvName(system_service_->producer());
|
||||
SetConsumerSockEnvName(system_service_->consumer());
|
||||
}
|
||||
|
||||
base::ScopedTempDir temp_dir_;
|
||||
scoped_refptr<base::DeferredSequencedTaskRunner> deferred_task_runner_;
|
||||
std::unique_ptr<tracing::MockSystemService> system_service_;
|
||||
};
|
||||
|
||||
// No system consumer support on Android to reduce Chrome binary size.
|
||||
#if defined(OS_ANDROID)
|
||||
#define MAYBE_TracingWithFakeSystemBackend DISABLED_TracingWithFakeSystemBackend
|
||||
#else
|
||||
#define MAYBE_TracingWithSystemBackend DISABLED_TracingWithSystemBackend
|
||||
#define MAYBE_TracingWithFakeSystemBackend TracingWithFakeSystemBackend
|
||||
#endif
|
||||
IN_PROC_BROWSER_TEST_F(SystemBackendDevToolsProtocolTest,
|
||||
MAYBE_TracingWithSystemBackend) {
|
||||
perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
|
||||
base::trace_event::TraceConfig(),
|
||||
/*privacy_filtering_enabled=*/false,
|
||||
/*convert_to_legacy_json=*/false,
|
||||
perfetto::protos::gen::ChromeConfig::USER_INITIATED);
|
||||
|
||||
std::string perfetto_config_encoded;
|
||||
base::Base64Encode(perfetto_config.SerializeAsString(),
|
||||
&perfetto_config_encoded);
|
||||
|
||||
auto params = std::make_unique<base::DictionaryValue>();
|
||||
params->SetKey("perfettoConfig", base::Value(perfetto_config_encoded));
|
||||
params->SetString("transferMode", "ReturnAsStream");
|
||||
params->SetString("tracingBackend", "system");
|
||||
|
||||
base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
base::ScopedTempDir temp_dir;
|
||||
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
||||
|
||||
auto system_service = std::make_unique<tracing::MockSystemService>(temp_dir);
|
||||
SetConsumerSockEnvName(system_service->consumer());
|
||||
|
||||
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
|
||||
Attach();
|
||||
|
||||
EXPECT_TRUE(tracing::ShouldSetupSystemTracing());
|
||||
|
||||
base::DictionaryValue* command_result =
|
||||
SendCommand("Tracing.start", std::move(params), true);
|
||||
IN_PROC_BROWSER_TEST_F(FakeSystemTracingDevToolsProtocolTest,
|
||||
MAYBE_TracingWithFakeSystemBackend) {
|
||||
base::DictionaryValue* command_result = StartSystemTrace();
|
||||
ASSERT_NE(command_result, nullptr);
|
||||
|
||||
command_result = SendCommand("Tracing.end", nullptr, true);
|
||||
@ -2898,6 +2914,28 @@ IN_PROC_BROWSER_TEST_F(SystemBackendDevToolsProtocolTest,
|
||||
|
||||
WaitForNotification("Tracing.tracingComplete", true);
|
||||
}
|
||||
|
||||
class FakeSystemTracingForbiddenDevToolsProtocolTest
|
||||
: public PosixSystemTracingDevToolsProtocolTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
tracing::PerfettoTracedProcess::Get()
|
||||
->SetAllowSystemTracingConsumerForTesting(false);
|
||||
PosixSystemTracingDevToolsProtocolTest::SetUp();
|
||||
}
|
||||
};
|
||||
|
||||
// No system consumer support on Android to reduce Chrome binary size.
|
||||
#if defined(OS_ANDROID)
|
||||
#define MAYBE_SystemConsumerForbidden DISABLED_SystemConsumerForbidden
|
||||
#else
|
||||
#define MAYBE_SystemConsumerForbidden SystemConsumerForbidden
|
||||
#endif
|
||||
IN_PROC_BROWSER_TEST_F(FakeSystemTracingForbiddenDevToolsProtocolTest,
|
||||
MAYBE_SystemConsumerForbidden) {
|
||||
base::DictionaryValue* command_result = StartSystemTrace();
|
||||
ASSERT_EQ(command_result, nullptr);
|
||||
}
|
||||
#endif // defined(OS_POSIX)
|
||||
|
||||
} // namespace content
|
||||
|
@ -26,9 +26,14 @@ MockSystemService::MockSystemService(const std::string& consumer_socket,
|
||||
}
|
||||
|
||||
MockSystemService::MockSystemService(const base::ScopedTempDir& tmp_dir)
|
||||
: used_tmpdir_(true),
|
||||
task_runner_(std::make_unique<base::tracing::PerfettoTaskRunner>(
|
||||
base::SequencedTaskRunnerHandle::Get())) {
|
||||
: MockSystemService(tmp_dir,
|
||||
std::make_unique<base::tracing::PerfettoTaskRunner>(
|
||||
base::SequencedTaskRunnerHandle::Get())) {}
|
||||
|
||||
MockSystemService::MockSystemService(
|
||||
const base::ScopedTempDir& tmp_dir,
|
||||
std::unique_ptr<perfetto::base::TaskRunner> task_runner)
|
||||
: used_tmpdir_(true), task_runner_(std::move(task_runner)) {
|
||||
// We need to set TMPDIR environment variable because when a new producer
|
||||
// connects to the perfetto service it needs to create a memmap'd file for
|
||||
// the shared memory buffer. Setting TMPDIR allows the service to know
|
||||
|
@ -27,7 +27,9 @@ class MockSystemService {
|
||||
public:
|
||||
MockSystemService(const std::string& consumer_socket,
|
||||
const std::string& producer_socket);
|
||||
MockSystemService(const base::ScopedTempDir& tmp_dir);
|
||||
explicit MockSystemService(const base::ScopedTempDir& tmp_dir);
|
||||
MockSystemService(const base::ScopedTempDir& tmp_dir,
|
||||
std::unique_ptr<perfetto::base::TaskRunner>);
|
||||
~MockSystemService();
|
||||
|
||||
perfetto::TracingService* GetService();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
|
||||
|
||||
#include "base/callback_helpers.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/sequenced_task_runner.h"
|
||||
@ -23,11 +24,6 @@
|
||||
#include "services/tracing/public/mojom/tracing_service.mojom.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#include "base/command_line.h"
|
||||
#include "chromeos/dbus/constants/dbus_switches.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
// As per 'gn help check':
|
||||
/*
|
||||
@ -261,28 +257,12 @@ void PerfettoTracedProcess::SetupClientLibrary() {
|
||||
init_args.platform = platform_.get();
|
||||
init_args.custom_backend = tracing_backend_.get();
|
||||
init_args.backends |= perfetto::kCustomBackend;
|
||||
// System tracing backend is currently only supported on ChromeOS.
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
// Enable the system backend for access as system consumer
|
||||
// in the browser process.
|
||||
bool is_browser = base::CommandLine::ForCurrentProcess()
|
||||
->GetSwitchValueASCII("type")
|
||||
.empty();
|
||||
|
||||
// We currently only use the system backend for consumer connections, and
|
||||
// those should only be allowed when the CrOS device is in dev mode.
|
||||
// TODO(eseckler): Augment this check with content's
|
||||
// TracingDelegate::IsSystemWideTracingEnabled().
|
||||
// TODO(eseckler): Move the check for the system wide tracing policy into the
|
||||
// consumer backend connection, it probably shouldn't affect the producer
|
||||
// connection.
|
||||
bool is_system_wide_tracing_enabled =
|
||||
base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
chromeos::switches::kSystemDevMode);
|
||||
|
||||
if (is_browser && is_system_wide_tracing_enabled &&
|
||||
tracing::ShouldSetupSystemTracing()) {
|
||||
// TODO(eseckler): Not yet supported on Android to avoid binary size regression
|
||||
// of the consumer IPC messages. We'll need a way to exclude them.
|
||||
#if defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||
if (ShouldSetupSystemTracing()) {
|
||||
init_args.backends |= perfetto::kSystemBackend;
|
||||
init_args.tracing_policy = this;
|
||||
}
|
||||
#endif
|
||||
perfetto::Tracing::Initialize(init_args);
|
||||
@ -303,6 +283,64 @@ void PerfettoTracedProcess::OnThreadPoolAvailable() {
|
||||
platform_->StartTaskRunner(GetTaskRunner()->GetOrCreateTaskRunner());
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::SetAllowSystemTracingConsumerCallback(
|
||||
base::RepeatingCallback<bool()> callback) {
|
||||
base::AutoLock lock(allow_system_consumer_lock_);
|
||||
DCHECK(!allow_system_consumer_callback_ || !callback);
|
||||
allow_system_consumer_callback_ = std::move(callback);
|
||||
allow_system_consumer_callback_runner_ =
|
||||
base::SequencedTaskRunnerHandle::Get();
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::SetAllowSystemTracingConsumerForTesting(
|
||||
bool enabled) {
|
||||
base::AutoLock lock(allow_system_consumer_lock_);
|
||||
system_consumer_enabled_for_testing_ = enabled;
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::ShouldAllowConsumerSession(
|
||||
const perfetto::TracingPolicy::ShouldAllowConsumerSessionArgs& args) {
|
||||
// Consumer connections should only be attempted in the browser process.
|
||||
CHECK(base::CommandLine::ForCurrentProcess()
|
||||
->GetSwitchValueASCII("type")
|
||||
.empty());
|
||||
|
||||
// Integrated tracing backends are always allowed.
|
||||
if (args.backend_type != perfetto::BackendType::kSystemBackend) {
|
||||
args.result_callback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// System backend is only allowed in tests or if the embedder provided a
|
||||
// callback that allows it.
|
||||
ShouldAllowSystemConsumerSession(args.result_callback);
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::ShouldAllowSystemConsumerSession(
|
||||
std::function<void(bool)> result_callback) {
|
||||
base::AutoLock lock(allow_system_consumer_lock_);
|
||||
|
||||
if (system_consumer_enabled_for_testing_) {
|
||||
result_callback(true);
|
||||
return;
|
||||
}
|
||||
if (!allow_system_consumer_callback_) {
|
||||
result_callback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!allow_system_consumer_callback_runner_->RunsTasksInCurrentSequence()) {
|
||||
allow_system_consumer_callback_runner_->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&PerfettoTracedProcess::ShouldAllowSystemConsumerSession,
|
||||
base::Unretained(this), result_callback));
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = allow_system_consumer_callback_.Run();
|
||||
result_callback(result);
|
||||
}
|
||||
|
||||
void PerfettoTracedProcess::SetupSystemTracing(
|
||||
base::Optional<const char*> system_socket) {
|
||||
// Note: Not checking for a valid sequence here so that we don't inadvertently
|
||||
|
@ -10,9 +10,12 @@
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/thread_annotations.h"
|
||||
#include "base/tracing/perfetto_task_runner.h"
|
||||
#include "services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h"
|
||||
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/tracing_policy.h"
|
||||
|
||||
namespace base {
|
||||
namespace trace_event {
|
||||
@ -42,7 +45,8 @@ class SystemProducer;
|
||||
// * Construct the new implementation when requested to
|
||||
// in PerfettoProducer::StartDataSource.
|
||||
class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
: public PerfettoTracingBackend::Delegate {
|
||||
: public PerfettoTracingBackend::Delegate,
|
||||
public perfetto::TracingPolicy {
|
||||
public:
|
||||
// If not noted otherwise, a DataSourceBase's methods are only called on
|
||||
// PerfettoTracedProcess::GetTaskRunner()'s sequence.
|
||||
@ -140,6 +144,15 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
// Called on the process's main thread once the thread pool is ready.
|
||||
void OnThreadPoolAvailable();
|
||||
|
||||
// Set a callback that returns whether a system tracing session is allowed.
|
||||
// The callback will be executed on the sequence that set it. Only a single
|
||||
// callback is supported. If no callback is set, all system consumer
|
||||
// connections are denied.
|
||||
void SetAllowSystemTracingConsumerCallback(base::RepeatingCallback<bool()>);
|
||||
|
||||
// Overrides SetAllowSystemTracingConsumerCallback() for testing.
|
||||
void SetAllowSystemTracingConsumerForTesting(bool allow);
|
||||
|
||||
// Called to initialize system tracing, i.e., connecting to a system Perfetto
|
||||
// daemon as a producer. If |system_socket| isn't provided, Perfetto's default
|
||||
// socket name is used.
|
||||
@ -198,6 +211,22 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
|
||||
// process.
|
||||
void SetupClientLibrary();
|
||||
|
||||
// perfetto::TracingPolicy implementation:
|
||||
void ShouldAllowConsumerSession(
|
||||
const perfetto::TracingPolicy::ShouldAllowConsumerSessionArgs&) override;
|
||||
|
||||
void ShouldAllowSystemConsumerSession(
|
||||
std::function<void(bool)> result_callback);
|
||||
|
||||
base::Lock allow_system_consumer_lock_;
|
||||
base::RepeatingCallback<bool()> allow_system_consumer_callback_
|
||||
GUARDED_BY(allow_system_consumer_lock_);
|
||||
scoped_refptr<base::SequencedTaskRunner>
|
||||
allow_system_consumer_callback_runner_
|
||||
GUARDED_BY(allow_system_consumer_lock_);
|
||||
bool system_consumer_enabled_for_testing_
|
||||
GUARDED_BY(allow_system_consumer_lock_) = false;
|
||||
|
||||
base::Lock data_sources_lock_;
|
||||
// The canonical set of DataSourceBases alive in this process. These will be
|
||||
// registered with the tracing service.
|
||||
|
Reference in New Issue
Block a user