1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/devtools/protocol/tracing_handler.h"
10 #include "base/debug/trace_event_impl.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
20 typedef DevToolsProtocolClient::Response Response
;
24 const char kRecordUntilFull
[] = "record-until-full";
25 const char kRecordContinuously
[] = "record-continuously";
26 const char kRecordAsMuchAsPossible
[] = "record-as-much-as-possible";
27 const char kEnableSampling
[] = "enable-sampling";
28 const double kMinimumReportingInterval
= 250.0;
30 class DevToolsTraceSinkProxy
: public TracingController::TraceDataSink
{
32 explicit DevToolsTraceSinkProxy(base::WeakPtr
<TracingHandler
> handler
)
33 : tracing_handler_(handler
) {}
35 void AddTraceChunk(const std::string
& chunk
) override
{
36 if (TracingHandler
* h
= tracing_handler_
.get())
37 h
->OnTraceDataCollected(chunk
);
39 void Close() override
{
40 if (TracingHandler
* h
= tracing_handler_
.get())
45 ~DevToolsTraceSinkProxy() override
{}
47 base::WeakPtr
<TracingHandler
> tracing_handler_
;
52 TracingHandler::TracingHandler(TracingHandler::Target target
)
58 TracingHandler::~TracingHandler() {
61 void TracingHandler::SetClient(scoped_ptr
<Client
> client
) {
65 void TracingHandler::Detached() {
67 DisableRecording(true);
70 void TracingHandler::OnTraceDataCollected(const std::string
& trace_fragment
) {
71 // Hand-craft protocol notification message so we can substitute JSON
72 // that we already got as string as a bare object, not a quoted string.
74 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
75 const size_t messageSuffixSize
= 10;
76 message
.reserve(message
.size() + trace_fragment
.size() + messageSuffixSize
);
77 message
+= trace_fragment
;
79 client_
->SendRawMessage(message
);
82 void TracingHandler::OnTraceComplete() {
83 client_
->TracingComplete(TracingCompleteParams::Create());
86 Response
TracingHandler::Start(DevToolsCommandId command_id
,
87 const std::string
* categories
,
88 const std::string
* options_str
,
89 const double* buffer_usage_reporting_interval
) {
91 return Response::InternalError("Tracing is already started");
94 base::debug::TraceOptions options
= TraceOptionsFromString(options_str
);
95 base::debug::CategoryFilter
filter(categories
? *categories
: std::string());
96 if (buffer_usage_reporting_interval
)
97 SetupTimer(*buffer_usage_reporting_interval
);
99 // If inspected target is a render process Tracing.start will be handled by
100 // tracing agent in the renderer.
101 if (target_
== Renderer
) {
102 TracingController::GetInstance()->EnableRecording(
105 TracingController::EnableRecordingDoneCallback());
106 return Response::FallThrough();
109 TracingController::GetInstance()->EnableRecording(
112 base::Bind(&TracingHandler::OnRecordingEnabled
,
113 weak_factory_
.GetWeakPtr(),
115 return Response::OK();
118 Response
TracingHandler::End(DevToolsCommandId command_id
) {
120 return Response::InternalError("Tracing is not started");
122 DisableRecording(false);
123 // If inspected target is a render process Tracing.end will be handled by
124 // tracing agent in the renderer.
125 return target_
== Renderer
? Response::FallThrough() : Response::OK();
128 Response
TracingHandler::GetCategories(DevToolsCommandId command_id
) {
129 TracingController::GetInstance()->GetCategories(
130 base::Bind(&TracingHandler::OnCategoriesReceived
,
131 weak_factory_
.GetWeakPtr(),
133 return Response::OK();
136 void TracingHandler::OnRecordingEnabled(DevToolsCommandId command_id
) {
137 client_
->SendStartResponse(command_id
, StartResponse::Create());
140 void TracingHandler::OnBufferUsage(float percent_full
,
141 size_t approximate_event_count
) {
142 // TODO(crbug426117): remove set_value once all clients have switched to
143 // the new interface of the event.
144 client_
->BufferUsage(BufferUsageParams::Create()
145 ->set_value(percent_full
)
146 ->set_percent_full(percent_full
)
147 ->set_event_count(approximate_event_count
));
150 void TracingHandler::OnCategoriesReceived(
151 DevToolsCommandId command_id
,
152 const std::set
<std::string
>& category_set
) {
153 std::vector
<std::string
> categories
;
154 for (const std::string
& category
: category_set
)
155 categories
.push_back(category
);
156 client_
->SendGetCategoriesResponse(command_id
,
157 GetCategoriesResponse::Create()->set_categories(categories
));
160 base::debug::TraceOptions
TracingHandler::TraceOptionsFromString(
161 const std::string
* options
) {
162 base::debug::TraceOptions ret
;
166 std::vector
<std::string
> split
;
167 std::vector
<std::string
>::iterator iter
;
169 base::SplitString(*options
, ',', &split
);
170 for (iter
= split
.begin(); iter
!= split
.end(); ++iter
) {
171 if (*iter
== kRecordUntilFull
) {
172 ret
.record_mode
= base::debug::RECORD_UNTIL_FULL
;
173 } else if (*iter
== kRecordContinuously
) {
174 ret
.record_mode
= base::debug::RECORD_CONTINUOUSLY
;
175 } else if (*iter
== kRecordAsMuchAsPossible
) {
176 ret
.record_mode
= base::debug::RECORD_AS_MUCH_AS_POSSIBLE
;
177 } else if (*iter
== kEnableSampling
) {
178 ret
.enable_sampling
= true;
184 void TracingHandler::SetupTimer(double usage_reporting_interval
) {
185 if (usage_reporting_interval
== 0) return;
187 if (usage_reporting_interval
< kMinimumReportingInterval
)
188 usage_reporting_interval
= kMinimumReportingInterval
;
190 base::TimeDelta interval
= base::TimeDelta::FromMilliseconds(
191 std::ceil(usage_reporting_interval
));
192 buffer_usage_poll_timer_
.reset(new base::Timer(
194 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage
),
195 base::Unretained(TracingController::GetInstance()),
196 base::Bind(&TracingHandler::OnBufferUsage
,
197 weak_factory_
.GetWeakPtr())),
199 buffer_usage_poll_timer_
->Reset();
202 void TracingHandler::DisableRecording(bool abort
) {
203 is_recording_
= false;
204 buffer_usage_poll_timer_
.reset();
205 TracingController::GetInstance()->DisableRecording(
206 abort
? nullptr : new DevToolsTraceSinkProxy(weak_factory_
.GetWeakPtr()));
209 } // namespace tracing
210 } // namespace devtools
211 } // namespace content