Change next_proto member type.
[chromium-blink-merge.git] / content / browser / devtools / protocol / tracing_handler.cc
blob74446caa3768e06a429075d4cf6675951f3a1777
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"
7 #include <cmath>
9 #include "base/bind.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"
16 namespace content {
17 namespace devtools {
18 namespace tracing {
20 typedef DevToolsProtocolClient::Response Response;
22 namespace {
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 {
31 public:
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())
41 h->OnTraceComplete();
44 private:
45 ~DevToolsTraceSinkProxy() override {}
47 base::WeakPtr<TracingHandler> tracing_handler_;
50 } // namespace
52 TracingHandler::TracingHandler(TracingHandler::Target target)
53 : target_(target),
54 is_recording_(false),
55 weak_factory_(this) {
58 TracingHandler::~TracingHandler() {
61 void TracingHandler::SetClient(scoped_ptr<Client> client) {
62 client_.swap(client);
65 void TracingHandler::Detached() {
66 if (is_recording_)
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.
73 std::string message(
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;
78 message += "] } }";
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) {
90 if (is_recording_)
91 return Response::InternalError("Tracing is already started");
93 is_recording_ = true;
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(
103 filter,
104 options,
105 TracingController::EnableRecordingDoneCallback());
106 return Response::FallThrough();
109 TracingController::GetInstance()->EnableRecording(
110 filter,
111 options,
112 base::Bind(&TracingHandler::OnRecordingEnabled,
113 weak_factory_.GetWeakPtr(),
114 command_id));
115 return Response::OK();
118 Response TracingHandler::End(DevToolsCommandId command_id) {
119 if (!is_recording_)
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(),
132 command_id));
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;
163 if (!options)
164 return 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;
181 return ret;
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(
193 FROM_HERE, interval,
194 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage),
195 base::Unretained(TracingController::GetInstance()),
196 base::Bind(&TracingHandler::OnBufferUsage,
197 weak_factory_.GetWeakPtr())),
198 true));
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