summaryrefslogtreecommitdiff
path: root/chromium/content/browser/tracing/tracing_ui.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/tracing/tracing_ui.cc')
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc130
1 files changed, 108 insertions, 22 deletions
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index c1b65f1e2c4..2bffb5eb3b0 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -40,9 +40,17 @@
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_session.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
+#include "third_party/perfetto/protos/perfetto/common/trace_stats.gen.h"
namespace content {
namespace {
+constexpr char kStreamFormat[] = "stream_format";
+constexpr char kStreamFormatProtobuf[] = "protobuf";
+constexpr char kStreamFormatJSON[] = "json";
+perfetto::TracingSession* g_tracing_session = nullptr;
void OnGotCategories(WebUIDataSource::GotDataCallback callback,
const std::set<std::string>& categorySet) {
@@ -61,18 +69,31 @@ void OnRecordingEnabledAck(WebUIDataSource::GotDataCallback callback);
bool BeginRecording(const std::string& data64,
WebUIDataSource::GotDataCallback callback) {
base::trace_event::TraceConfig trace_config("", "");
- if (!TracingUI::GetTracingOptions(data64, &trace_config))
+ std::string stream_format;
+ if (!TracingUI::GetTracingOptions(data64, trace_config, stream_format))
return false;
+ // TODO(skyostil): Migrate all use cases from TracingController to Perfetto.
+ if (stream_format == kStreamFormatProtobuf) {
+ if (g_tracing_session)
+ delete g_tracing_session;
+ g_tracing_session = perfetto::Tracing::NewTrace().release();
+ g_tracing_session->Setup(tracing::GetDefaultPerfettoConfig(trace_config));
+
+ auto shared_callback = base::MakeRefCounted<
+ base::RefCountedData<WebUIDataSource::GotDataCallback>>(
+ std::move(callback));
+ g_tracing_session->SetOnStartCallback([shared_callback] {
+ OnRecordingEnabledAck(std::move(shared_callback->data));
+ });
+ g_tracing_session->Start();
+ return true;
+ }
return TracingController::GetInstance()->StartTracing(
trace_config,
base::BindOnce(&OnRecordingEnabledAck, std::move(callback)));
}
-void OnRecordingEnabledAck(WebUIDataSource::GotDataCallback callback) {
- std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>());
-}
-
void OnTraceBufferUsageResult(WebUIDataSource::GotDataCallback callback,
float percent_full,
size_t approximate_event_count) {
@@ -80,6 +101,45 @@ void OnTraceBufferUsageResult(WebUIDataSource::GotDataCallback callback,
std::move(callback).Run(base::RefCountedString::TakeString(&str));
}
+bool GetTraceBufferUsage(WebUIDataSource::GotDataCallback callback) {
+ if (g_tracing_session) {
+ // |callback| is move-only, so in order to pass it through a copied lambda
+ // we need to temporarily move it on the heap.
+ auto shared_callback = base::MakeRefCounted<
+ base::RefCountedData<WebUIDataSource::GotDataCallback>>(
+ std::move(callback));
+ g_tracing_session->GetTraceStats(
+ [shared_callback](
+ perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
+ std::string usage;
+ perfetto::protos::gen::TraceStats trace_stats;
+ if (args.success &&
+ trace_stats.ParseFromArray(args.trace_stats_data.data(),
+ args.trace_stats_data.size())) {
+ double percent_full = tracing::GetTraceBufferUsage(trace_stats);
+ usage = base::NumberToString(percent_full);
+ }
+ std::move(shared_callback->data)
+ .Run(base::RefCountedString::TakeString(&usage));
+ });
+ return true;
+ }
+
+ return TracingController::GetInstance()->GetTraceBufferUsage(
+ base::BindOnce(OnTraceBufferUsageResult, std::move(callback)));
+}
+
+void ReadProtobufTraceData(
+ scoped_refptr<TracingController::TraceDataEndpoint> endpoint,
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ if (args.size) {
+ auto data_string = std::make_unique<std::string>(args.data, args.size);
+ endpoint->ReceiveTraceChunk(std::move(data_string));
+ }
+ if (!args.has_more)
+ endpoint->ReceivedTraceFinalContents();
+}
+
void TracingCallbackWrapperBase64(WebUIDataSource::GotDataCallback callback,
std::unique_ptr<std::string> data) {
base::RefCountedString* data_base64 = new base::RefCountedString();
@@ -87,6 +147,38 @@ void TracingCallbackWrapperBase64(WebUIDataSource::GotDataCallback callback,
std::move(callback).Run(data_base64);
}
+bool EndRecording(WebUIDataSource::GotDataCallback callback) {
+ if (!TracingController::GetInstance()->IsTracing() && !g_tracing_session)
+ return false;
+
+ scoped_refptr<TracingController::TraceDataEndpoint> data_endpoint =
+ TracingControllerImpl::CreateCompressedStringEndpoint(
+ TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce(
+ TracingCallbackWrapperBase64, std::move(callback))),
+ false /* compress_with_background_priority */);
+
+ if (g_tracing_session) {
+ perfetto::TracingSession* session = g_tracing_session;
+ g_tracing_session = nullptr;
+ session->SetOnStopCallback([session, data_endpoint] {
+ session->ReadTrace(
+ [session, data_endpoint](
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ ReadProtobufTraceData(data_endpoint, args);
+ if (!args.has_more)
+ delete session;
+ });
+ });
+ session->Stop();
+ return true;
+ }
+ return TracingController::GetInstance()->StopTracing(data_endpoint);
+}
+
+void OnRecordingEnabledAck(WebUIDataSource::GotDataCallback callback) {
+ std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>());
+}
+
bool OnBeginJSONRequest(const std::string& path,
WebUIDataSource::GotDataCallback callback) {
if (path == "json/categories") {
@@ -101,18 +193,10 @@ bool OnBeginJSONRequest(const std::string& path,
return BeginRecording(data, std::move(callback));
}
if (path == "json/get_buffer_percent_full") {
- return TracingController::GetInstance()->GetTraceBufferUsage(
- base::BindOnce(OnTraceBufferUsageResult, std::move(callback)));
+ return GetTraceBufferUsage(std::move(callback));
}
if (path == "json/end_recording_compressed") {
- if (!TracingController::GetInstance()->IsTracing())
- return false;
- scoped_refptr<TracingController::TraceDataEndpoint> data_endpoint =
- TracingControllerImpl::CreateCompressedStringEndpoint(
- TracingControllerImpl::CreateCallbackEndpoint(base::BindOnce(
- TracingCallbackWrapperBase64, std::move(callback))),
- false /* compress_with_background_priority */);
- return TracingController::GetInstance()->StopTracing(data_endpoint);
+ return EndRecording(std::move(callback));
}
LOG(ERROR) << "Unhandled request to " << path;
@@ -156,6 +240,7 @@ TracingUI::TracingUI(WebUI* web_ui)
web_ui->GetWebContents()->GetBrowserContext();
WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost);
+ source->DisableTrustedTypesCSP();
source->UseStringsJs();
source->SetDefaultResource(IDR_TRACING_HTML);
source->AddResourcePath("tracing.js", IDR_TRACING_JS);
@@ -167,9 +252,9 @@ TracingUI::TracingUI(WebUI* web_ui)
TracingUI::~TracingUI() = default;
// static
-bool TracingUI::GetTracingOptions(
- const std::string& data64,
- base::trace_event::TraceConfig* trace_config) {
+bool TracingUI::GetTracingOptions(const std::string& data64,
+ base::trace_event::TraceConfig& trace_config,
+ std::string& out_stream_format) {
std::string data;
if (!base::Base64Decode(data64, &data)) {
LOG(ERROR) << "Options were not base64 encoded.";
@@ -188,13 +273,14 @@ bool TracingUI::GetTracingOptions(
return false;
}
- if (!trace_config) {
- LOG(ERROR) << "trace_config can't be passed as NULL";
- return false;
+ if (options->HasKey(kStreamFormat)) {
+ options->GetString(kStreamFormat, &out_stream_format);
+ } else {
+ out_stream_format = kStreamFormatJSON;
}
// New style options dictionary.
- *trace_config = base::trace_event::TraceConfig(*options);
+ trace_config = base::trace_event::TraceConfig(*options);
return true;
}