Index: content/browser/devtools/protocol/tracing_handler.cc |
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc |
index fd886972825748b44e33a40a90f28b81841db878..7188bf734272cfcada23f141a6497391ad9fbbc5 100644 |
--- a/content/browser/devtools/protocol/tracing_handler.cc |
+++ b/content/browser/devtools/protocol/tracing_handler.cc |
@@ -14,12 +14,13 @@ |
#include "base/timer/timer.h" |
#include "base/trace_event/memory_dump_manager.h" |
#include "base/trace_event/trace_event_impl.h" |
+#include "content/browser/devtools/devtools_io_context.h" |
namespace content { |
namespace devtools { |
namespace tracing { |
-typedef DevToolsProtocolClient::Response Response; |
+using Response = DevToolsProtocolClient::Response; |
namespace { |
@@ -45,11 +46,48 @@ class DevToolsTraceSinkProxy : public TracingController::TraceDataSink { |
base::WeakPtr<TracingHandler> tracing_handler_; |
}; |
+class DevToolsStreamTraceSink : public TracingController::TraceDataSink { |
+ public: |
+ explicit DevToolsStreamTraceSink( |
+ base::WeakPtr<TracingHandler> handler, |
+ const scoped_refptr<DevToolsIOContext::Stream>& stream) |
+ : stream_(stream), |
+ tracing_handler_(handler), |
+ first_chunk_(true) {} |
+ |
+ void AddTraceChunk(const std::string& chunk) override { |
+ // FIXME: change interface to pass chunks as refcounted strings. |
+ scoped_refptr<base::RefCountedString> ref_counted_chunk |
+ = new base::RefCountedString(); |
+ std::string prefix = first_chunk_ ? "[" : ","; |
+ ref_counted_chunk->data() = prefix + chunk; |
+ first_chunk_ = false; |
+ stream_->Append(ref_counted_chunk); |
+ } |
+ |
+ void Close() override { |
+ if (TracingHandler* h = tracing_handler_.get()) { |
+ std::string suffix = "]"; |
+ stream_->Append(base::RefCountedString::TakeString(&suffix)); |
+ h->OnTraceToStreamComplete(stream_->id()); |
+ } |
+ } |
+ |
+ private: |
+ ~DevToolsStreamTraceSink() override {} |
+ |
+ scoped_refptr<DevToolsIOContext::Stream> stream_; |
+ base::WeakPtr<TracingHandler> tracing_handler_; |
+ bool first_chunk_; |
+}; |
+ |
} // namespace |
-TracingHandler::TracingHandler(TracingHandler::Target target) |
+TracingHandler::TracingHandler(TracingHandler::Target target, |
+ DevToolsIOContext* io_context) |
: target_(target), |
did_initiate_recording_(false), |
+ io_context_(io_context), |
weak_factory_(this) { |
} |
@@ -62,7 +100,7 @@ void TracingHandler::SetClient(scoped_ptr<Client> client) { |
void TracingHandler::Detached() { |
if (IsRecording()) |
- DisableRecording(true); |
+ DisableRecording(scoped_refptr<TracingController::TraceDataSink>()); |
} |
void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) { |
@@ -81,6 +119,10 @@ void TracingHandler::OnTraceComplete() { |
client_->TracingComplete(TracingCompleteParams::Create()); |
} |
+void TracingHandler::OnTraceToStreamComplete(const std::string& id) { |
+ client_->TracingComplete(TracingCompleteParams::Create()->set_stream_id(id)); |
+} |
+ |
Response TracingHandler::Start(DevToolsCommandId command_id, |
const std::string* categories, |
const std::string* options, |
@@ -117,7 +159,27 @@ Response TracingHandler::End(DevToolsCommandId command_id) { |
if (!IsRecording()) |
return Response::InternalError("Tracing is not started"); |
- DisableRecording(false); |
+ scoped_refptr<TracingController::TracingController::TraceDataSink> proxy = |
+ new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()); |
+ DisableRecording(proxy); |
+ // If inspected target is a render process Tracing.end will be handled by |
+ // tracing agent in the renderer. |
+ return target_ == Renderer ? Response::FallThrough() : Response::OK(); |
+} |
+ |
+Response TracingHandler::End(DevToolsCommandId command_id, |
+ const bool* return_as_stream) { |
+ if (!IsRecording()) |
+ return Response::InternalError("Tracing is not started"); |
+ |
+ scoped_refptr<TracingController::TraceDataSink> proxy; |
+ if (return_as_stream && *return_as_stream) { |
+ proxy = new DevToolsStreamTraceSink(weak_factory_.GetWeakPtr(), |
+ io_context_->CreateTempFileBackedStream()); |
+ } else { |
+ proxy = new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()); |
+ } |
+ DisableRecording(proxy); |
// If inspected target is a render process Tracing.end will be handled by |
// tracing agent in the renderer. |
return target_ == Renderer ? Response::FallThrough() : Response::OK(); |
@@ -196,10 +258,10 @@ void TracingHandler::SetupTimer(double usage_reporting_interval) { |
buffer_usage_poll_timer_->Reset(); |
} |
-void TracingHandler::DisableRecording(bool abort) { |
+void TracingHandler::DisableRecording( |
+ const scoped_refptr<TracingController::TraceDataSink>& trace_data_sink) { |
buffer_usage_poll_timer_.reset(); |
- TracingController::GetInstance()->DisableRecording( |
- abort ? nullptr : new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr())); |
+ TracingController::GetInstance()->DisableRecording(trace_data_sink); |
did_initiate_recording_ = false; |
} |