OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/devtools_tracing_handler.h" | 5 #include "content/browser/devtools/devtools_tracing_handler.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/file_util.h" | |
10 #include "base/json/json_reader.h" | |
11 #include "base/json/json_writer.h" | |
12 #include "base/location.h" | 9 #include "base/location.h" |
13 #include "base/memory/ref_counted_memory.h" | |
14 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
15 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
16 #include "base/values.h" | 12 #include "base/values.h" |
17 #include "content/browser/devtools/devtools_http_handler_impl.h" | 13 #include "content/browser/devtools/devtools_http_handler_impl.h" |
18 #include "content/browser/devtools/devtools_protocol_constants.h" | 14 #include "content/browser/devtools/devtools_protocol_constants.h" |
19 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/trace_controller.h" |
20 #include "content/public/browser/tracing_controller.h" | 16 #include "content/public/browser/trace_subscriber.h" |
21 | 17 |
22 namespace content { | 18 namespace content { |
23 | 19 |
24 namespace { | 20 namespace { |
25 | 21 |
26 const char kRecordUntilFull[] = "record-until-full"; | 22 const char kRecordUntilFull[] = "record-until-full"; |
27 const char kRecordContinuously[] = "record-continuously"; | 23 const char kRecordContinuously[] = "record-continuously"; |
28 const char kEnableSampling[] = "enable-sampling"; | 24 const char kEnableSampling[] = "enable-sampling"; |
29 | 25 |
30 void ReadFile( | |
31 const base::FilePath& path, | |
32 const base::Callback<void(const scoped_refptr<base::RefCountedString>&)> | |
33 callback) { | |
34 std::string trace_data; | |
35 if (!base::ReadFileToString(path, &trace_data)) | |
36 LOG(ERROR) << "Failed to read file: " << path.value(); | |
37 base::DeleteFile(path, false); | |
38 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
39 base::Bind(callback, make_scoped_refptr( | |
40 base::RefCountedString::TakeString(&trace_data)))); | |
41 } | |
42 | |
43 } // namespace | 26 } // namespace |
44 | 27 |
45 DevToolsTracingHandler::DevToolsTracingHandler() | 28 DevToolsTracingHandler::DevToolsTracingHandler() |
46 : weak_factory_(this) { | 29 : is_running_(false) { |
47 RegisterCommandHandler(devtools::Tracing::start::kName, | 30 RegisterCommandHandler(devtools::Tracing::start::kName, |
48 base::Bind(&DevToolsTracingHandler::OnStart, | 31 base::Bind(&DevToolsTracingHandler::OnStart, |
49 base::Unretained(this))); | 32 base::Unretained(this))); |
50 RegisterCommandHandler(devtools::Tracing::end::kName, | 33 RegisterCommandHandler(devtools::Tracing::end::kName, |
51 base::Bind(&DevToolsTracingHandler::OnEnd, | 34 base::Bind(&DevToolsTracingHandler::OnEnd, |
52 base::Unretained(this))); | 35 base::Unretained(this))); |
53 } | 36 } |
54 | 37 |
55 DevToolsTracingHandler::~DevToolsTracingHandler() { | 38 DevToolsTracingHandler::~DevToolsTracingHandler() { |
56 } | 39 } |
57 | 40 |
58 void DevToolsTracingHandler::BeginReadingRecordingResult( | 41 void DevToolsTracingHandler::OnEndTracingComplete() { |
59 const base::FilePath& path) { | 42 is_running_ = false; |
60 BrowserThread::PostTask( | |
61 BrowserThread::FILE, FROM_HERE, | |
62 base::Bind(&ReadFile, path, | |
63 base::Bind(&DevToolsTracingHandler::ReadRecordingResult, | |
64 weak_factory_.GetWeakPtr()))); | |
65 } | |
66 | |
67 void DevToolsTracingHandler::ReadRecordingResult( | |
68 const scoped_refptr<base::RefCountedString>& trace_data) { | |
69 if (trace_data->data().size()) { | |
70 scoped_ptr<base::Value> trace_value(base::JSONReader::Read( | |
71 trace_data->data())); | |
72 DictionaryValue* dictionary = NULL; | |
73 bool ok = trace_value->GetAsDictionary(&dictionary); | |
74 DCHECK(ok); | |
75 ListValue* list = NULL; | |
76 ok = dictionary->GetList("traceEvents", &list); | |
77 DCHECK(ok); | |
78 std::string buffer; | |
79 for (size_t i = 0; i < list->GetSize(); ++i) { | |
80 std::string item; | |
81 base::Value* item_value; | |
82 list->Get(i, &item_value); | |
83 base::JSONWriter::Write(item_value, &item); | |
84 if (buffer.size()) | |
85 buffer.append(","); | |
86 buffer.append(item); | |
87 if (i % 1000 == 0) { | |
88 OnTraceDataCollected(buffer); | |
89 buffer.clear(); | |
90 } | |
91 } | |
92 if (buffer.size()) | |
93 OnTraceDataCollected(buffer); | |
94 } | |
95 | |
96 SendNotification(devtools::Tracing::tracingComplete::kName, NULL); | 43 SendNotification(devtools::Tracing::tracingComplete::kName, NULL); |
97 } | 44 } |
98 | 45 |
99 void DevToolsTracingHandler::OnTraceDataCollected( | 46 void DevToolsTracingHandler::OnTraceDataCollected( |
100 const std::string& trace_fragment) { | 47 const scoped_refptr<base::RefCountedString>& trace_fragment) { |
101 // Hand-craft protocol notification message so we can substitute JSON | 48 if (is_running_) { |
102 // that we already got as string as a bare object, not a quoted string. | 49 // Hand-craft protocol notification message so we can substitute JSON |
103 std::string message = base::StringPrintf( | 50 // that we already got as string as a bare object, not a quoted string. |
104 "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }", | 51 std::string message = base::StringPrintf( |
105 devtools::Tracing::dataCollected::kName, | 52 "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }", |
106 devtools::Tracing::dataCollected::kValue, | 53 devtools::Tracing::dataCollected::kName, |
107 trace_fragment.c_str()); | 54 devtools::Tracing::dataCollected::kValue, |
108 SendRawMessage(message); | 55 trace_fragment->data().c_str()); |
| 56 SendRawMessage(message); |
| 57 } |
109 } | 58 } |
110 | 59 |
111 TracingController::Options DevToolsTracingHandler::TraceOptionsFromString( | 60 // Note, if you add more options here you also need to update: |
| 61 // base/debug/trace_event_impl:TraceOptionsFromString |
| 62 base::debug::TraceLog::Options DevToolsTracingHandler::TraceOptionsFromString( |
112 const std::string& options) { | 63 const std::string& options) { |
113 std::vector<std::string> split; | 64 std::vector<std::string> split; |
114 std::vector<std::string>::iterator iter; | 65 std::vector<std::string>::iterator iter; |
115 int ret = 0; | 66 int ret = 0; |
116 | 67 |
117 base::SplitString(options, ',', &split); | 68 base::SplitString(options, ',', &split); |
118 for (iter = split.begin(); iter != split.end(); ++iter) { | 69 for (iter = split.begin(); iter != split.end(); ++iter) { |
119 if (*iter == kRecordUntilFull) { | 70 if (*iter == kRecordUntilFull) { |
120 ret &= ~TracingController::RECORD_CONTINUOUSLY; | 71 ret |= base::debug::TraceLog::RECORD_UNTIL_FULL; |
121 } else if (*iter == kRecordContinuously) { | 72 } else if (*iter == kRecordContinuously) { |
122 ret |= TracingController::RECORD_CONTINUOUSLY; | 73 ret |= base::debug::TraceLog::RECORD_CONTINUOUSLY; |
123 } else if (*iter == kEnableSampling) { | 74 } else if (*iter == kEnableSampling) { |
124 ret |= TracingController::ENABLE_SAMPLING; | 75 ret |= base::debug::TraceLog::ENABLE_SAMPLING; |
125 } | 76 } |
126 } | 77 } |
127 return static_cast<TracingController::Options>(ret); | 78 if (!(ret & base::debug::TraceLog::RECORD_UNTIL_FULL) && |
| 79 !(ret & base::debug::TraceLog::RECORD_CONTINUOUSLY)) |
| 80 ret |= base::debug::TraceLog::RECORD_UNTIL_FULL; |
| 81 |
| 82 return static_cast<base::debug::TraceLog::Options>(ret); |
128 } | 83 } |
129 | 84 |
130 scoped_refptr<DevToolsProtocol::Response> | 85 scoped_refptr<DevToolsProtocol::Response> |
131 DevToolsTracingHandler::OnStart( | 86 DevToolsTracingHandler::OnStart( |
132 scoped_refptr<DevToolsProtocol::Command> command) { | 87 scoped_refptr<DevToolsProtocol::Command> command) { |
133 std::string categories; | 88 std::string categories; |
134 base::DictionaryValue* params = command->params(); | 89 base::DictionaryValue* params = command->params(); |
135 if (params) | 90 if (params) |
136 params->GetString(devtools::Tracing::start::kCategories, &categories); | 91 params->GetString(devtools::Tracing::start::kCategories, &categories); |
137 | 92 |
138 TracingController::Options options = TracingController::DEFAULT_OPTIONS; | 93 base::debug::TraceLog::Options options = |
| 94 base::debug::TraceLog::RECORD_UNTIL_FULL; |
139 if (params && params->HasKey(devtools::Tracing::start::kTraceOptions)) { | 95 if (params && params->HasKey(devtools::Tracing::start::kTraceOptions)) { |
140 std::string options_param; | 96 std::string options_param; |
141 params->GetString(devtools::Tracing::start::kTraceOptions, &options_param); | 97 params->GetString(devtools::Tracing::start::kTraceOptions, &options_param); |
142 options = TraceOptionsFromString(options_param); | 98 options = TraceOptionsFromString(options_param); |
143 } | 99 } |
144 | 100 |
145 TracingController::GetInstance()->EnableRecording( | 101 TraceController::GetInstance()->BeginTracing(this, categories, options); |
146 categories, options, | 102 is_running_ = true; |
147 TracingController::EnableRecordingDoneCallback()); | |
148 return command->SuccessResponse(NULL); | 103 return command->SuccessResponse(NULL); |
149 } | 104 } |
150 | 105 |
151 scoped_refptr<DevToolsProtocol::Response> | 106 scoped_refptr<DevToolsProtocol::Response> |
152 DevToolsTracingHandler::OnEnd( | 107 DevToolsTracingHandler::OnEnd( |
153 scoped_refptr<DevToolsProtocol::Command> command) { | 108 scoped_refptr<DevToolsProtocol::Command> command) { |
154 TracingController::GetInstance()->DisableRecording( | 109 TraceController::GetInstance()->EndTracingAsync(this); |
155 base::FilePath(), | |
156 base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult, | |
157 weak_factory_.GetWeakPtr())); | |
158 return command->SuccessResponse(NULL); | 110 return command->SuccessResponse(NULL); |
159 } | 111 } |
160 | 112 |
161 } // namespace content | 113 } // namespace content |
OLD | NEW |