Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / browser / devtools / protocol / tracing_handler.cc
bloba4319b9efd04a7bc4d0d318ab26ff556a7f553ae
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/strings/string_split.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "base/trace_event/trace_event_impl.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::trace_event::TraceOptions options = TraceOptionsFromString(options_str);
95 base::trace_event::CategoryFilter filter(categories ? *categories
96 : std::string());
97 if (buffer_usage_reporting_interval)
98 SetupTimer(*buffer_usage_reporting_interval);
100 // If inspected target is a render process Tracing.start will be handled by
101 // tracing agent in the renderer.
102 if (target_ == Renderer) {
103 TracingController::GetInstance()->EnableRecording(
104 filter,
105 options,
106 TracingController::EnableRecordingDoneCallback());
107 return Response::FallThrough();
110 TracingController::GetInstance()->EnableRecording(
111 filter,
112 options,
113 base::Bind(&TracingHandler::OnRecordingEnabled,
114 weak_factory_.GetWeakPtr(),
115 command_id));
116 return Response::OK();
119 Response TracingHandler::End(DevToolsCommandId command_id) {
120 if (!is_recording_)
121 return Response::InternalError("Tracing is not started");
123 DisableRecording(false);
124 // If inspected target is a render process Tracing.end will be handled by
125 // tracing agent in the renderer.
126 return target_ == Renderer ? Response::FallThrough() : Response::OK();
129 Response TracingHandler::GetCategories(DevToolsCommandId command_id) {
130 TracingController::GetInstance()->GetCategories(
131 base::Bind(&TracingHandler::OnCategoriesReceived,
132 weak_factory_.GetWeakPtr(),
133 command_id));
134 return Response::OK();
137 void TracingHandler::OnRecordingEnabled(DevToolsCommandId command_id) {
138 client_->SendStartResponse(command_id, StartResponse::Create());
141 void TracingHandler::OnBufferUsage(float percent_full,
142 size_t approximate_event_count) {
143 // TODO(crbug426117): remove set_value once all clients have switched to
144 // the new interface of the event.
145 client_->BufferUsage(BufferUsageParams::Create()
146 ->set_value(percent_full)
147 ->set_percent_full(percent_full)
148 ->set_event_count(approximate_event_count));
151 void TracingHandler::OnCategoriesReceived(
152 DevToolsCommandId command_id,
153 const std::set<std::string>& category_set) {
154 std::vector<std::string> categories;
155 for (const std::string& category : category_set)
156 categories.push_back(category);
157 client_->SendGetCategoriesResponse(command_id,
158 GetCategoriesResponse::Create()->set_categories(categories));
161 base::trace_event::TraceOptions TracingHandler::TraceOptionsFromString(
162 const std::string* options) {
163 base::trace_event::TraceOptions ret;
164 if (!options)
165 return ret;
167 std::vector<std::string> split;
168 std::vector<std::string>::iterator iter;
170 base::SplitString(*options, ',', &split);
171 for (iter = split.begin(); iter != split.end(); ++iter) {
172 if (*iter == kRecordUntilFull) {
173 ret.record_mode = base::trace_event::RECORD_UNTIL_FULL;
174 } else if (*iter == kRecordContinuously) {
175 ret.record_mode = base::trace_event::RECORD_CONTINUOUSLY;
176 } else if (*iter == kRecordAsMuchAsPossible) {
177 ret.record_mode = base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
178 } else if (*iter == kEnableSampling) {
179 ret.enable_sampling = true;
182 return ret;
185 void TracingHandler::SetupTimer(double usage_reporting_interval) {
186 if (usage_reporting_interval == 0) return;
188 if (usage_reporting_interval < kMinimumReportingInterval)
189 usage_reporting_interval = kMinimumReportingInterval;
191 base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
192 std::ceil(usage_reporting_interval));
193 buffer_usage_poll_timer_.reset(new base::Timer(
194 FROM_HERE, interval,
195 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage),
196 base::Unretained(TracingController::GetInstance()),
197 base::Bind(&TracingHandler::OnBufferUsage,
198 weak_factory_.GetWeakPtr())),
199 true));
200 buffer_usage_poll_timer_->Reset();
203 void TracingHandler::DisableRecording(bool abort) {
204 is_recording_ = false;
205 buffer_usage_poll_timer_.reset();
206 TracingController::GetInstance()->DisableRecording(
207 abort ? nullptr : new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()));
210 } // namespace tracing
211 } // namespace devtools
212 } // namespace content