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/format_macros.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"
15 #include "base/trace_event/memory_dump_manager.h"
16 #include "base/trace_event/trace_event_impl.h"
22 typedef DevToolsProtocolClient::Response Response
;
26 const double kMinimumReportingInterval
= 250.0;
28 class DevToolsTraceSinkProxy
: public TracingController::TraceDataSink
{
30 explicit DevToolsTraceSinkProxy(base::WeakPtr
<TracingHandler
> handler
)
31 : tracing_handler_(handler
) {}
33 void AddTraceChunk(const std::string
& chunk
) override
{
34 if (TracingHandler
* h
= tracing_handler_
.get())
35 h
->OnTraceDataCollected(chunk
);
37 void Close() override
{
38 if (TracingHandler
* h
= tracing_handler_
.get())
43 ~DevToolsTraceSinkProxy() override
{}
45 base::WeakPtr
<TracingHandler
> tracing_handler_
;
50 TracingHandler::TracingHandler(TracingHandler::Target target
)
52 did_initiate_recording_(false),
56 TracingHandler::~TracingHandler() {
59 void TracingHandler::SetClient(scoped_ptr
<Client
> client
) {
63 void TracingHandler::Detached() {
65 DisableRecording(true);
68 void TracingHandler::OnTraceDataCollected(const std::string
& trace_fragment
) {
69 // Hand-craft protocol notification message so we can substitute JSON
70 // that we already got as string as a bare object, not a quoted string.
72 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
73 const size_t messageSuffixSize
= 10;
74 message
.reserve(message
.size() + trace_fragment
.size() + messageSuffixSize
);
75 message
+= trace_fragment
;
77 client_
->SendRawMessage(message
);
80 void TracingHandler::OnTraceComplete() {
81 client_
->TracingComplete(TracingCompleteParams::Create());
84 Response
TracingHandler::Start(DevToolsCommandId command_id
,
85 const std::string
* categories
,
86 const std::string
* options
,
87 const double* buffer_usage_reporting_interval
) {
89 return Response::InternalError("Tracing is already started");
91 did_initiate_recording_
= true;
93 base::trace_event::TraceConfig
trace_config(
94 categories
? *categories
: std::string(),
95 options
? *options
: 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(
104 TracingController::EnableRecordingDoneCallback());
105 return Response::FallThrough();
108 TracingController::GetInstance()->EnableRecording(
110 base::Bind(&TracingHandler::OnRecordingEnabled
,
111 weak_factory_
.GetWeakPtr(),
113 return Response::OK();
116 Response
TracingHandler::End(DevToolsCommandId command_id
) {
118 return Response::InternalError("Tracing is not started");
120 DisableRecording(false);
121 // If inspected target is a render process Tracing.end will be handled by
122 // tracing agent in the renderer.
123 return target_
== Renderer
? Response::FallThrough() : Response::OK();
126 Response
TracingHandler::GetCategories(DevToolsCommandId command_id
) {
127 TracingController::GetInstance()->GetCategories(
128 base::Bind(&TracingHandler::OnCategoriesReceived
,
129 weak_factory_
.GetWeakPtr(),
131 return Response::OK();
134 void TracingHandler::OnRecordingEnabled(DevToolsCommandId command_id
) {
135 client_
->SendStartResponse(command_id
, StartResponse::Create());
138 void TracingHandler::OnBufferUsage(float percent_full
,
139 size_t approximate_event_count
) {
140 // TODO(crbug426117): remove set_value once all clients have switched to
141 // the new interface of the event.
142 client_
->BufferUsage(BufferUsageParams::Create()
143 ->set_value(percent_full
)
144 ->set_percent_full(percent_full
)
145 ->set_event_count(approximate_event_count
));
148 void TracingHandler::OnCategoriesReceived(
149 DevToolsCommandId command_id
,
150 const std::set
<std::string
>& category_set
) {
151 std::vector
<std::string
> categories
;
152 for (const std::string
& category
: category_set
)
153 categories
.push_back(category
);
154 client_
->SendGetCategoriesResponse(command_id
,
155 GetCategoriesResponse::Create()->set_categories(categories
));
158 Response
TracingHandler::RequestMemoryDump(DevToolsCommandId command_id
) {
159 if (!did_initiate_recording_
)
160 return Response::InternalError("Tracing is not started");
162 base::trace_event::MemoryDumpManager::GetInstance()->RequestGlobalDump(
163 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED
,
164 base::Bind(&TracingHandler::OnMemoryDumpFinished
,
165 weak_factory_
.GetWeakPtr(), command_id
));
166 return Response::OK();
169 void TracingHandler::OnMemoryDumpFinished(DevToolsCommandId command_id
,
172 client_
->SendRequestMemoryDumpResponse(
174 RequestMemoryDumpResponse::Create()
175 ->set_dump_guid(base::StringPrintf("0x%" PRIx64
, dump_guid
))
176 ->set_success(success
));
179 void TracingHandler::SetupTimer(double usage_reporting_interval
) {
180 if (usage_reporting_interval
== 0) return;
182 if (usage_reporting_interval
< kMinimumReportingInterval
)
183 usage_reporting_interval
= kMinimumReportingInterval
;
185 base::TimeDelta interval
= base::TimeDelta::FromMilliseconds(
186 std::ceil(usage_reporting_interval
));
187 buffer_usage_poll_timer_
.reset(new base::Timer(
189 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage
),
190 base::Unretained(TracingController::GetInstance()),
191 base::Bind(&TracingHandler::OnBufferUsage
,
192 weak_factory_
.GetWeakPtr())),
194 buffer_usage_poll_timer_
->Reset();
197 void TracingHandler::DisableRecording(bool abort
) {
198 buffer_usage_poll_timer_
.reset();
199 TracingController::GetInstance()->DisableRecording(
200 abort
? nullptr : new DevToolsTraceSinkProxy(weak_factory_
.GetWeakPtr()));
201 did_initiate_recording_
= false;
204 bool TracingHandler::IsRecording() const {
205 return TracingController::GetInstance()->IsRecording();
208 } // namespace tracing
209 } // namespace devtools
210 } // namespace content