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_->handle()); |
| 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), |
| 89 io_context_(io_context), |
52 did_initiate_recording_(false), | 90 did_initiate_recording_(false), |
53 weak_factory_(this) { | 91 weak_factory_(this) {} |
54 } | |
55 | 92 |
56 TracingHandler::~TracingHandler() { | 93 TracingHandler::~TracingHandler() { |
57 } | 94 } |
58 | 95 |
59 void TracingHandler::SetClient(scoped_ptr<Client> client) { | 96 void TracingHandler::SetClient(scoped_ptr<Client> client) { |
60 client_.swap(client); | 97 client_.swap(client); |
61 } | 98 } |
62 | 99 |
63 void TracingHandler::Detached() { | 100 void TracingHandler::Detached() { |
64 if (IsRecording()) | 101 if (IsRecording()) |
65 DisableRecording(true); | 102 DisableRecording(scoped_refptr<TracingController::TraceDataSink>()); |
66 } | 103 } |
67 | 104 |
68 void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) { | 105 void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) { |
69 // Hand-craft protocol notification message so we can substitute JSON | 106 // 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. | 107 // that we already got as string as a bare object, not a quoted string. |
71 std::string message( | 108 std::string message( |
72 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": ["); | 109 "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": ["); |
73 const size_t messageSuffixSize = 10; | 110 const size_t messageSuffixSize = 10; |
74 message.reserve(message.size() + trace_fragment.size() + messageSuffixSize); | 111 message.reserve(message.size() + trace_fragment.size() + messageSuffixSize); |
75 message += trace_fragment; | 112 message += trace_fragment; |
76 message += "] } }"; | 113 message += "] } }"; |
77 client_->SendRawMessage(message); | 114 client_->SendRawMessage(message); |
78 } | 115 } |
79 | 116 |
80 void TracingHandler::OnTraceComplete() { | 117 void TracingHandler::OnTraceComplete() { |
81 client_->TracingComplete(TracingCompleteParams::Create()); | 118 client_->TracingComplete(TracingCompleteParams::Create()); |
82 } | 119 } |
83 | 120 |
| 121 void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) { |
| 122 } |
| 123 |
84 Response TracingHandler::Start(DevToolsCommandId command_id, | 124 Response TracingHandler::Start(DevToolsCommandId command_id, |
85 const std::string* categories, | 125 const std::string* categories, |
86 const std::string* options, | 126 const std::string* options, |
87 const double* buffer_usage_reporting_interval) { | 127 const double* buffer_usage_reporting_interval) { |
| 128 return Start(command_id, categories, options, buffer_usage_reporting_interval, |
| 129 nullptr); |
| 130 } |
| 131 |
| 132 Response TracingHandler::Start(DevToolsCommandId command_id, |
| 133 const std::string* categories, |
| 134 const std::string* options, |
| 135 const double* buffer_usage_reporting_interval, |
| 136 const std::string* transfer_mode) { |
88 if (IsRecording()) | 137 if (IsRecording()) |
89 return Response::InternalError("Tracing is already started"); | 138 return Response::InternalError("Tracing is already started"); |
90 | 139 |
91 did_initiate_recording_ = true; | 140 did_initiate_recording_ = true; |
92 | |
93 base::trace_event::TraceConfig trace_config( | 141 base::trace_event::TraceConfig trace_config( |
94 categories ? *categories : std::string(), | 142 categories ? *categories : std::string(), |
95 options ? *options : std::string()); | 143 options ? *options : std::string()); |
96 if (buffer_usage_reporting_interval) | 144 if (buffer_usage_reporting_interval) |
97 SetupTimer(*buffer_usage_reporting_interval); | 145 SetupTimer(*buffer_usage_reporting_interval); |
98 | 146 |
99 // If inspected target is a render process Tracing.start will be handled by | 147 // If inspected target is a render process Tracing.start will be handled by |
100 // tracing agent in the renderer. | 148 // tracing agent in the renderer. |
101 if (target_ == Renderer) { | 149 if (target_ == Renderer) { |
102 TracingController::GetInstance()->EnableRecording( | 150 TracingController::GetInstance()->EnableRecording( |
103 trace_config, | 151 trace_config, |
104 TracingController::EnableRecordingDoneCallback()); | 152 TracingController::EnableRecordingDoneCallback()); |
105 return Response::FallThrough(); | 153 return Response::FallThrough(); |
106 } | 154 } |
107 | 155 |
108 TracingController::GetInstance()->EnableRecording( | 156 TracingController::GetInstance()->EnableRecording( |
109 trace_config, | 157 trace_config, |
110 base::Bind(&TracingHandler::OnRecordingEnabled, | 158 base::Bind(&TracingHandler::OnRecordingEnabled, |
111 weak_factory_.GetWeakPtr(), | 159 weak_factory_.GetWeakPtr(), |
112 command_id)); | 160 command_id)); |
113 return Response::OK(); | 161 return Response::OK(); |
114 } | 162 } |
115 | 163 |
116 Response TracingHandler::End(DevToolsCommandId command_id) { | 164 Response TracingHandler::End(DevToolsCommandId command_id) { |
117 if (!IsRecording()) | 165 if (!IsRecording()) |
118 return Response::InternalError("Tracing is not started"); | 166 return Response::InternalError("Tracing is not started"); |
119 | 167 |
120 DisableRecording(false); | 168 scoped_refptr<TracingController::TraceDataSink> proxy; |
| 169 proxy = new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()); |
| 170 DisableRecording(proxy); |
121 // If inspected target is a render process Tracing.end will be handled by | 171 // If inspected target is a render process Tracing.end will be handled by |
122 // tracing agent in the renderer. | 172 // tracing agent in the renderer. |
123 return target_ == Renderer ? Response::FallThrough() : Response::OK(); | 173 return target_ == Renderer ? Response::FallThrough() : Response::OK(); |
124 } | 174 } |
125 | 175 |
126 Response TracingHandler::GetCategories(DevToolsCommandId command_id) { | 176 Response TracingHandler::GetCategories(DevToolsCommandId command_id) { |
127 TracingController::GetInstance()->GetCategories( | 177 TracingController::GetInstance()->GetCategories( |
128 base::Bind(&TracingHandler::OnCategoriesReceived, | 178 base::Bind(&TracingHandler::OnCategoriesReceived, |
129 weak_factory_.GetWeakPtr(), | 179 weak_factory_.GetWeakPtr(), |
130 command_id)); | 180 command_id)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 buffer_usage_poll_timer_.reset(new base::Timer( | 239 buffer_usage_poll_timer_.reset(new base::Timer( |
190 FROM_HERE, interval, | 240 FROM_HERE, interval, |
191 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage), | 241 base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage), |
192 base::Unretained(TracingController::GetInstance()), | 242 base::Unretained(TracingController::GetInstance()), |
193 base::Bind(&TracingHandler::OnBufferUsage, | 243 base::Bind(&TracingHandler::OnBufferUsage, |
194 weak_factory_.GetWeakPtr())), | 244 weak_factory_.GetWeakPtr())), |
195 true)); | 245 true)); |
196 buffer_usage_poll_timer_->Reset(); | 246 buffer_usage_poll_timer_->Reset(); |
197 } | 247 } |
198 | 248 |
199 void TracingHandler::DisableRecording(bool abort) { | 249 void TracingHandler::DisableRecording( |
| 250 const scoped_refptr<TracingController::TraceDataSink>& trace_data_sink) { |
200 buffer_usage_poll_timer_.reset(); | 251 buffer_usage_poll_timer_.reset(); |
201 TracingController::GetInstance()->DisableRecording( | 252 TracingController::GetInstance()->DisableRecording(trace_data_sink); |
202 abort ? nullptr : new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr())); | |
203 did_initiate_recording_ = false; | 253 did_initiate_recording_ = false; |
204 } | 254 } |
205 | 255 |
206 bool TracingHandler::IsRecording() const { | 256 bool TracingHandler::IsRecording() const { |
207 return TracingController::GetInstance()->IsRecording(); | 257 return TracingController::GetInstance()->IsRecording(); |
208 } | 258 } |
209 | 259 |
210 } // namespace tracing | 260 } // namespace tracing |
211 } // namespace devtools | 261 } // namespace devtools |
212 } // namespace content | 262 } // namespace content |
OLD | NEW |