OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/devtools/protocol/tracing_handler.h" | 5 #include "content/browser/devtools/protocol/tracing_handler.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
11 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
14 #include "base/timer/timer.h" | 14 #include "base/timer/timer.h" |
15 #include "base/trace_event/memory_dump_manager.h" | 15 #include "base/trace_event/memory_dump_manager.h" |
16 #include "base/trace_event/trace_event_impl.h" | 16 #include "base/trace_event/trace_event_impl.h" |
| 17 #include "content/browser/devtools/devtools_io_context.h" |
17 | 18 |
18 namespace content { | 19 namespace content { |
19 namespace devtools { | 20 namespace devtools { |
20 namespace tracing { | 21 namespace tracing { |
21 | 22 |
22 typedef DevToolsProtocolClient::Response Response; | 23 using Response = DevToolsProtocolClient::Response; |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 const double kMinimumReportingInterval = 250.0; | 27 const double kMinimumReportingInterval = 250.0; |
27 | 28 |
28 class DevToolsTraceSinkProxy : public TracingController::TraceDataSink { | 29 class DevToolsTraceSinkProxy : public TracingController::TraceDataSink { |
29 public: | 30 public: |
30 explicit DevToolsTraceSinkProxy(base::WeakPtr<TracingHandler> handler) | 31 explicit DevToolsTraceSinkProxy(base::WeakPtr<TracingHandler> handler) |
31 : tracing_handler_(handler) {} | 32 : tracing_handler_(handler) {} |
32 | 33 |
33 void AddTraceChunk(const std::string& chunk) override { | 34 void AddTraceChunk(const std::string& chunk) override { |
34 if (TracingHandler* h = tracing_handler_.get()) | 35 if (TracingHandler* h = tracing_handler_.get()) |
35 h->OnTraceDataCollected(chunk); | 36 h->OnTraceDataCollected(chunk); |
36 } | 37 } |
37 void Close() override { | 38 void Close() override { |
38 if (TracingHandler* h = tracing_handler_.get()) | 39 if (TracingHandler* h = tracing_handler_.get()) |
39 h->OnTraceComplete(); | 40 h->OnTraceComplete(); |
40 } | 41 } |
41 | 42 |
42 private: | 43 private: |
43 ~DevToolsTraceSinkProxy() override {} | 44 ~DevToolsTraceSinkProxy() override {} |
44 | 45 |
45 base::WeakPtr<TracingHandler> tracing_handler_; | 46 base::WeakPtr<TracingHandler> tracing_handler_; |
46 }; | 47 }; |
47 | 48 |
| 49 class DevToolsStreamTraceSink : public TracingController::TraceDataSink { |
| 50 public: |
| 51 explicit DevToolsStreamTraceSink( |
| 52 base::WeakPtr<TracingHandler> handler, |
| 53 const scoped_refptr<DevToolsIOContext::Stream>& stream) |
| 54 : stream_(stream), |
| 55 tracing_handler_(handler), |
| 56 first_chunk_(true) {} |
| 57 |
| 58 void AddTraceChunk(const std::string& chunk) override { |
| 59 // FIXME: change interface to pass chunks as refcounted strings. |
| 60 scoped_refptr<base::RefCountedString> ref_counted_chunk |
| 61 = new base::RefCountedString(); |
| 62 std::string prefix = first_chunk_ ? "[" : ","; |
| 63 ref_counted_chunk->data() = prefix + chunk; |
| 64 first_chunk_ = false; |
| 65 stream_->Append(ref_counted_chunk); |
| 66 } |
| 67 |
| 68 void Close() override { |
| 69 if (TracingHandler* h = tracing_handler_.get()) { |
| 70 std::string suffix = "]"; |
| 71 stream_->Append(base::RefCountedString::TakeString(&suffix)); |
| 72 h->OnTraceToStreamComplete(stream_->id()); |
| 73 } |
| 74 } |
| 75 |
| 76 private: |
| 77 ~DevToolsStreamTraceSink() override {} |
| 78 |
| 79 scoped_refptr<DevToolsIOContext::Stream> stream_; |
| 80 base::WeakPtr<TracingHandler> tracing_handler_; |
| 81 bool first_chunk_; |
| 82 }; |
| 83 |
48 } // namespace | 84 } // namespace |
49 | 85 |
50 TracingHandler::TracingHandler(TracingHandler::Target target) | 86 TracingHandler::TracingHandler(TracingHandler::Target target, |
| 87 DevToolsIOContext* io_context) |
51 : target_(target), | 88 : target_(target), |
52 did_initiate_recording_(false), | 89 did_initiate_recording_(false), |
| 90 io_context_(io_context), |
53 weak_factory_(this) { | 91 weak_factory_(this) { |
54 } | 92 } |
55 | 93 |
56 TracingHandler::~TracingHandler() { | 94 TracingHandler::~TracingHandler() { |
57 } | 95 } |
58 | 96 |
59 void TracingHandler::SetClient(scoped_ptr<Client> client) { | 97 void TracingHandler::SetClient(scoped_ptr<Client> client) { |
60 client_.swap(client); | 98 client_.swap(client); |
61 } | 99 } |
62 | 100 |
63 void TracingHandler::Detached() { | 101 void TracingHandler::Detached() { |
64 if (IsRecording()) | 102 if (IsRecording()) |
65 DisableRecording(true); | 103 DisableRecording(scoped_refptr<TracingController::TraceDataSink>()); |
66 } | 104 } |
67 | 105 |
68 void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) { | 106 void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) { |
69 // Hand-craft protocol notification message so we can substitute JSON | 107 // 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. | 108 // that we already got as string as a bare object, not a quoted string. |
71 std::string message( | 109 std::string message( |
72 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": ["); | 110 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": ["); |
73 const size_t messageSuffixSize = 10; | 111 const size_t messageSuffixSize = 10; |
74 message.reserve(message.size() + trace_fragment.size() + messageSuffixSize); | 112 message.reserve(message.size() + trace_fragment.size() + messageSuffixSize); |
75 message += trace_fragment; | 113 message += trace_fragment; |
76 message += "] } }"; | 114 message += "] } }"; |
77 client_->SendRawMessage(message); | 115 client_->SendRawMessage(message); |
78 } | 116 } |
79 | 117 |
80 void TracingHandler::OnTraceComplete() { | 118 void TracingHandler::OnTraceComplete() { |
81 client_->TracingComplete(TracingCompleteParams::Create()); | 119 client_->TracingComplete(TracingCompleteParams::Create()); |
82 } | 120 } |
83 | 121 |
| 122 void TracingHandler::OnTraceToStreamComplete(const std::string& id) { |
| 123 client_->TracingComplete(TracingCompleteParams::Create()->set_stream_id(id)); |
| 124 } |
| 125 |
84 Response TracingHandler::Start(DevToolsCommandId command_id, | 126 Response TracingHandler::Start(DevToolsCommandId command_id, |
85 const std::string* categories, | 127 const std::string* categories, |
86 const std::string* options, | 128 const std::string* options, |
87 const double* buffer_usage_reporting_interval) { | 129 const double* buffer_usage_reporting_interval) { |
88 if (IsRecording()) | 130 if (IsRecording()) |
89 return Response::InternalError("Tracing is already started"); | 131 return Response::InternalError("Tracing is already started"); |
90 | 132 |
91 did_initiate_recording_ = true; | 133 did_initiate_recording_ = true; |
92 | 134 |
93 base::trace_event::TraceConfig trace_config( | 135 base::trace_event::TraceConfig trace_config( |
(...skipping 16 matching lines...) Expand all Loading... |
110 base::Bind(&TracingHandler::OnRecordingEnabled, | 152 base::Bind(&TracingHandler::OnRecordingEnabled, |
111 weak_factory_.GetWeakPtr(), | 153 weak_factory_.GetWeakPtr(), |
112 command_id)); | 154 command_id)); |
113 return Response::OK(); | 155 return Response::OK(); |
114 } | 156 } |
115 | 157 |
116 Response TracingHandler::End(DevToolsCommandId command_id) { | 158 Response TracingHandler::End(DevToolsCommandId command_id) { |
117 if (!IsRecording()) | 159 if (!IsRecording()) |
118 return Response::InternalError("Tracing is not started"); | 160 return Response::InternalError("Tracing is not started"); |
119 | 161 |
120 DisableRecording(false); | 162 scoped_refptr<TracingController::TracingController::TraceDataSink> proxy = |
| 163 new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()); |
| 164 DisableRecording(proxy); |
121 // If inspected target is a render process Tracing.end will be handled by | 165 // If inspected target is a render process Tracing.end will be handled by |
122 // tracing agent in the renderer. | 166 // tracing agent in the renderer. |
123 return target_ == Renderer ? Response::FallThrough() : Response::OK(); | 167 return target_ == Renderer ? Response::FallThrough() : Response::OK(); |
| 168 } |
| 169 |
| 170 Response TracingHandler::End(DevToolsCommandId command_id, |
| 171 const bool* return_as_stream) { |
| 172 if (!IsRecording()) |
| 173 return Response::InternalError("Tracing is not started"); |
| 174 |
| 175 scoped_refptr<TracingController::TraceDataSink> proxy; |
| 176 if (return_as_stream && *return_as_stream) { |
| 177 proxy = new DevToolsStreamTraceSink(weak_factory_.GetWeakPtr(), |
| 178 io_context_->CreateTempFileBackedStream()); |
| 179 } else { |
| 180 proxy = new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()); |
| 181 } |
| 182 DisableRecording(proxy); |
| 183 // If inspected target is a render process Tracing.end will be handled by |
| 184 // tracing agent in the renderer. |
| 185 return target_ == Renderer ? Response::FallThrough() : Response::OK(); |
124 } | 186 } |
125 | 187 |
126 Response TracingHandler::GetCategories(DevToolsCommandId command_id) { | 188 Response TracingHandler::GetCategories(DevToolsCommandId command_id) { |
127 TracingController::GetInstance()->GetCategories( | 189 TracingController::GetInstance()->GetCategories( |
128 base::Bind(&TracingHandler::OnCategoriesReceived, | 190 base::Bind(&TracingHandler::OnCategoriesReceived, |
129 weak_factory_.GetWeakPtr(), | 191 weak_factory_.GetWeakPtr(), |
130 command_id)); | 192 command_id)); |
131 return Response::OK(); | 193 return Response::OK(); |
132 } | 194 } |
133 | 195 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 buffer_usage_poll_timer_.reset(new base::Timer( | 251 buffer_usage_poll_timer_.reset(new base::Timer( |
190 FROM_HERE, interval, | 252 FROM_HERE, interval, |
191 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage), | 253 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage), |
192 base::Unretained(TracingController::GetInstance()), | 254 base::Unretained(TracingController::GetInstance()), |
193 base::Bind(&TracingHandler::OnBufferUsage, | 255 base::Bind(&TracingHandler::OnBufferUsage, |
194 weak_factory_.GetWeakPtr())), | 256 weak_factory_.GetWeakPtr())), |
195 true)); | 257 true)); |
196 buffer_usage_poll_timer_->Reset(); | 258 buffer_usage_poll_timer_->Reset(); |
197 } | 259 } |
198 | 260 |
199 void TracingHandler::DisableRecording(bool abort) { | 261 void TracingHandler::DisableRecording( |
| 262 const scoped_refptr<TracingController::TraceDataSink>& trace_data_sink) { |
200 buffer_usage_poll_timer_.reset(); | 263 buffer_usage_poll_timer_.reset(); |
201 TracingController::GetInstance()->DisableRecording( | 264 TracingController::GetInstance()->DisableRecording(trace_data_sink); |
202 abort ? nullptr : new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr())); | |
203 did_initiate_recording_ = false; | 265 did_initiate_recording_ = false; |
204 } | 266 } |
205 | 267 |
206 bool TracingHandler::IsRecording() const { | 268 bool TracingHandler::IsRecording() const { |
207 return TracingController::GetInstance()->IsRecording(); | 269 return TracingController::GetInstance()->IsRecording(); |
208 } | 270 } |
209 | 271 |
210 } // namespace tracing | 272 } // namespace tracing |
211 } // namespace devtools | 273 } // namespace devtools |
212 } // namespace content | 274 } // namespace content |
OLD | NEW |