OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #include "content/browser/tracing/tracing_controller_impl.h" | 4 #include "content/browser/tracing/tracing_controller_impl.h" |
5 | 5 |
6 #include "base/bind.h" | 6 #include "base/bind.h" |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/json/string_escape.h" | 9 #include "base/json/string_escape.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 using base::debug::TraceOptions; | 27 using base::debug::TraceOptions; |
28 using base::debug::CategoryFilter; | 28 using base::debug::CategoryFilter; |
29 | 29 |
30 namespace content { | 30 namespace content { |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 34 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
35 LAZY_INSTANCE_INITIALIZER; | 35 LAZY_INSTANCE_INITIALIZER; |
36 | 36 |
| 37 class FileTraceDataSink : public TracingController::TraceDataSink { |
| 38 public: |
| 39 explicit FileTraceDataSink( |
| 40 const base::FilePath& trace_file_path, const base::Closure& callback) |
| 41 : file_path_(trace_file_path), |
| 42 completion_callback_(callback), |
| 43 file_(NULL) { |
| 44 } |
| 45 |
| 46 virtual void AddTraceChunk(const std::string& chunk) OVERRIDE { |
| 47 std::string tmp = chunk; |
| 48 scoped_refptr<base::RefCountedString> chunk_ptr = |
| 49 base::RefCountedString::TakeString(&tmp); |
| 50 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 51 base::Bind(&FileTraceDataSink::AddTraceChunkOnFileThread, |
| 52 this, chunk_ptr)); |
| 53 } |
| 54 virtual void SetSystemTrace(const std::string& data) OVERRIDE { |
| 55 system_trace_ = data; |
| 56 } |
| 57 virtual void Close() OVERRIDE { |
| 58 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 59 base::Bind(&FileTraceDataSink::CloseOnFileThread, this)); |
| 60 } |
| 61 |
| 62 private: |
| 63 virtual ~FileTraceDataSink() { |
| 64 DCHECK(file_ == NULL); |
| 65 } |
| 66 |
| 67 void AddTraceChunkOnFileThread( |
| 68 const scoped_refptr<base::RefCountedString> chunk) { |
| 69 if (!OpenFileIfNeededOnFileThread()) |
| 70 return; |
| 71 fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()), 1, file_); |
| 72 } |
| 73 |
| 74 bool OpenFileIfNeededOnFileThread() { |
| 75 if (file_ != NULL) |
| 76 return true; |
| 77 file_ = base::OpenFile(file_path_, "w"); |
| 78 if (file_ == NULL) { |
| 79 LOG(ERROR) << "Failed to open " << file_path_.value(); |
| 80 return false; |
| 81 } |
| 82 const char preamble[] = "{\"traceEvents\": ["; |
| 83 fwrite(preamble, strlen(preamble), 1, file_); |
| 84 return true; |
| 85 } |
| 86 |
| 87 void CloseOnFileThread() { |
| 88 if (OpenFileIfNeededOnFileThread()) { |
| 89 fputc(']', file_); |
| 90 if (!system_trace_.empty()) { |
| 91 const char systemTraceEvents[] = ",\"systemTraceEvents\":["; |
| 92 fwrite(systemTraceEvents, strlen(systemTraceEvents), 1, file_); |
| 93 fwrite(system_trace_.c_str(), strlen(system_trace_.c_str()), 1, file_); |
| 94 fputc(']', file_); |
| 95 } |
| 96 fputc('}', file_); |
| 97 base::CloseFile(file_); |
| 98 file_ = NULL; |
| 99 } |
| 100 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 101 base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this)); |
| 102 } |
| 103 |
| 104 void FinalizeOnUIThread() { |
| 105 completion_callback_.Run(); |
| 106 } |
| 107 |
| 108 base::FilePath file_path_; |
| 109 base::Closure completion_callback_; |
| 110 FILE* file_; |
| 111 std::string system_trace_; |
| 112 |
| 113 DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink); |
| 114 }; |
| 115 |
| 116 class StringTraceDataSink : public TracingController::TraceDataSink { |
| 117 public: |
| 118 typedef base::Callback<void(base::RefCountedString*)> |
| 119 CompletionCallback; |
| 120 |
| 121 explicit StringTraceDataSink(CompletionCallback callback) |
| 122 : completion_callback_(callback) { |
| 123 } |
| 124 |
| 125 // TracingController::TraceDataSink implementation |
| 126 virtual void AddTraceChunk(const std::string& chunk) OVERRIDE { |
| 127 if (!trace_.empty()) |
| 128 trace_ += ","; |
| 129 trace_ += chunk; |
| 130 } |
| 131 virtual void SetSystemTrace(const std::string& data) OVERRIDE { |
| 132 system_trace_ = data; |
| 133 } |
| 134 virtual void Close() OVERRIDE { |
| 135 std::string result = "{\"traceEvents\":[" + trace_ + "]"; |
| 136 if (!system_trace_.empty()) |
| 137 result += ",\"systemTraceEvents\":[" + system_trace_ + "]"; |
| 138 result += "}"; |
| 139 |
| 140 completion_callback_.Run(base::RefCountedString::TakeString(&result)); |
| 141 } |
| 142 |
| 143 private: |
| 144 virtual ~StringTraceDataSink() {} |
| 145 |
| 146 std::string trace_; |
| 147 std::string system_trace_; |
| 148 CompletionCallback completion_callback_; |
| 149 |
| 150 DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink); |
| 151 }; |
| 152 |
37 } // namespace | 153 } // namespace |
38 | 154 |
39 TracingController* TracingController::GetInstance() { | 155 TracingController* TracingController::GetInstance() { |
40 return TracingControllerImpl::GetInstance(); | 156 return TracingControllerImpl::GetInstance(); |
41 } | 157 } |
42 | 158 |
43 class TracingControllerImpl::ResultFile { | |
44 public: | |
45 explicit ResultFile(const base::FilePath& path); | |
46 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
47 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
48 base::Bind(&TracingControllerImpl::ResultFile::WriteTask, | |
49 base::Unretained(this), events_str_ptr)); | |
50 } | |
51 void Close(const base::Closure& callback) { | |
52 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
53 base::Bind(&TracingControllerImpl::ResultFile::CloseTask, | |
54 base::Unretained(this), callback)); | |
55 } | |
56 void WriteSystemTrace( | |
57 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
58 BrowserThread::PostTask( | |
59 BrowserThread::FILE, | |
60 FROM_HERE, | |
61 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask, | |
62 base::Unretained(this), events_str_ptr)); | |
63 } | |
64 | |
65 const base::FilePath& path() const { return path_; } | |
66 | |
67 private: | |
68 void OpenTask(); | |
69 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr); | |
70 void WriteSystemTraceTask( | |
71 const scoped_refptr<base::RefCountedString>& events_str_ptr); | |
72 void CloseTask(const base::Closure& callback); | |
73 | |
74 FILE* file_; | |
75 base::FilePath path_; | |
76 bool has_at_least_one_result_; | |
77 scoped_refptr<base::RefCountedString> system_trace_; | |
78 | |
79 DISALLOW_COPY_AND_ASSIGN(ResultFile); | |
80 }; | |
81 | |
82 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) | |
83 : file_(NULL), | |
84 path_(path), | |
85 has_at_least_one_result_(false) { | |
86 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
87 base::Bind(&TracingControllerImpl::ResultFile::OpenTask, | |
88 base::Unretained(this))); | |
89 } | |
90 | |
91 void TracingControllerImpl::ResultFile::OpenTask() { | |
92 if (path_.empty()) | |
93 base::CreateTemporaryFile(&path_); | |
94 file_ = base::OpenFile(path_, "w"); | |
95 if (!file_) { | |
96 LOG(ERROR) << "Failed to open " << path_.value(); | |
97 return; | |
98 } | |
99 const char* preamble = "{\"traceEvents\": ["; | |
100 size_t written = fwrite(preamble, strlen(preamble), 1, file_); | |
101 DCHECK(written == 1); | |
102 } | |
103 | |
104 void TracingControllerImpl::ResultFile::WriteTask( | |
105 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
106 if (!file_ || !events_str_ptr->data().size()) | |
107 return; | |
108 | |
109 // If there is already a result in the file, then put a comma | |
110 // before the next batch of results. | |
111 if (has_at_least_one_result_) { | |
112 size_t written = fwrite(",", 1, 1, file_); | |
113 DCHECK(written == 1); | |
114 } | |
115 has_at_least_one_result_ = true; | |
116 size_t written = fwrite(events_str_ptr->data().c_str(), | |
117 events_str_ptr->data().size(), 1, | |
118 file_); | |
119 DCHECK(written == 1); | |
120 } | |
121 | |
122 void TracingControllerImpl::ResultFile::WriteSystemTraceTask( | |
123 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
124 system_trace_ = events_str_ptr; | |
125 } | |
126 | |
127 void TracingControllerImpl::ResultFile::CloseTask( | |
128 const base::Closure& callback) { | |
129 if (!file_) | |
130 return; | |
131 | |
132 const char* trailevents = "]"; | |
133 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); | |
134 DCHECK(written == 1); | |
135 | |
136 if (system_trace_.get()) { | |
137 #if defined(OS_WIN) | |
138 // The Windows kernel events are kept into a JSon format stored as string | |
139 // and must not be escaped. | |
140 std::string json_string = system_trace_->data(); | |
141 #else | |
142 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); | |
143 #endif | |
144 | |
145 const char* systemTraceHead = ",\n\"systemTraceEvents\": "; | |
146 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); | |
147 DCHECK(written == 1); | |
148 | |
149 written = fwrite(json_string.data(), json_string.size(), 1, file_); | |
150 DCHECK(written == 1); | |
151 | |
152 system_trace_ = NULL; | |
153 } | |
154 | |
155 const char* trailout = "}"; | |
156 written = fwrite(trailout, strlen(trailout), 1, file_); | |
157 DCHECK(written == 1); | |
158 base::CloseFile(file_); | |
159 file_ = NULL; | |
160 | |
161 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | |
162 } | |
163 | |
164 | |
165 TracingControllerImpl::TracingControllerImpl() : | 159 TracingControllerImpl::TracingControllerImpl() : |
166 pending_disable_recording_ack_count_(0), | 160 pending_disable_recording_ack_count_(0), |
167 pending_capture_monitoring_snapshot_ack_count_(0), | 161 pending_capture_monitoring_snapshot_ack_count_(0), |
168 pending_trace_buffer_percent_full_ack_count_(0), | 162 pending_trace_buffer_percent_full_ack_count_(0), |
169 maximum_trace_buffer_percent_full_(0), | 163 maximum_trace_buffer_percent_full_(0), |
170 // Tracing may have been enabled by ContentMainRunner if kTraceStartup | 164 // Tracing may have been enabled by ContentMainRunner if kTraceStartup |
171 // is specified in command line. | 165 // is specified in command line. |
172 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 166 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
173 is_system_tracing_(false), | 167 is_system_tracing_(false), |
174 #endif | 168 #endif |
(...skipping 17 matching lines...) Expand all Loading... |
192 // Known categories come back from child processes with the EndTracingAck | 186 // Known categories come back from child processes with the EndTracingAck |
193 // message. So to get known categories, just begin and end tracing immediately | 187 // message. So to get known categories, just begin and end tracing immediately |
194 // afterwards. This will ping all the child processes for categories. | 188 // afterwards. This will ping all the child processes for categories. |
195 pending_get_categories_done_callback_ = callback; | 189 pending_get_categories_done_callback_ = callback; |
196 if (!EnableRecording( | 190 if (!EnableRecording( |
197 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) { | 191 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) { |
198 pending_get_categories_done_callback_.Reset(); | 192 pending_get_categories_done_callback_.Reset(); |
199 return false; | 193 return false; |
200 } | 194 } |
201 | 195 |
202 bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback()); | 196 bool ok = DisableRecording(NULL); |
203 DCHECK(ok); | 197 DCHECK(ok); |
204 return true; | 198 return true; |
205 } | 199 } |
206 | 200 |
207 void TracingControllerImpl::SetEnabledOnFileThread( | 201 void TracingControllerImpl::SetEnabledOnFileThread( |
208 const CategoryFilter& category_filter, | 202 const CategoryFilter& category_filter, |
209 int mode, | 203 int mode, |
210 const TraceOptions& trace_options, | 204 const TraceOptions& trace_options, |
211 const base::Closure& callback) { | 205 const base::Closure& callback) { |
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | 273 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); |
280 it != trace_message_filters_.end(); ++it) { | 274 it != trace_message_filters_.end(); ++it) { |
281 it->get()->SendBeginTracing(category_filter, trace_options); | 275 it->get()->SendBeginTracing(category_filter, trace_options); |
282 } | 276 } |
283 | 277 |
284 if (!callback.is_null()) | 278 if (!callback.is_null()) |
285 callback.Run(); | 279 callback.Run(); |
286 } | 280 } |
287 | 281 |
288 bool TracingControllerImpl::DisableRecording( | 282 bool TracingControllerImpl::DisableRecording( |
289 const base::FilePath& result_file_path, | 283 const scoped_refptr<TraceDataSink>& trace_data_sink) { |
290 const TracingFileResultCallback& callback) { | |
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
292 | 285 |
293 if (!can_disable_recording()) | 286 if (!can_disable_recording()) |
294 return false; | 287 return false; |
295 | 288 |
| 289 trace_data_sink_ = trace_data_sink; |
296 trace_options_ = TraceOptions(); | 290 trace_options_ = TraceOptions(); |
297 // Disable local trace early to avoid traces during end-tracing process from | 291 // Disable local trace early to avoid traces during end-tracing process from |
298 // interfering with the process. | 292 // interfering with the process. |
299 base::Closure on_disable_recording_done_callback = | 293 base::Closure on_disable_recording_done_callback = |
300 base::Bind(&TracingControllerImpl::OnDisableRecordingDone, | 294 base::Bind(&TracingControllerImpl::OnDisableRecordingDone, |
301 base::Unretained(this), | 295 base::Unretained(this)); |
302 result_file_path, callback); | |
303 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 296 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
304 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, | 297 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, |
305 base::Unretained(this), | 298 base::Unretained(this), |
306 on_disable_recording_done_callback)); | 299 on_disable_recording_done_callback)); |
307 return true; | 300 return true; |
308 } | 301 } |
309 | 302 |
310 void TracingControllerImpl::OnDisableRecordingDone( | 303 void TracingControllerImpl::OnDisableRecordingDone() { |
311 const base::FilePath& result_file_path, | |
312 const TracingFileResultCallback& callback) { | |
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
314 | 305 |
315 pending_disable_recording_done_callback_ = callback; | |
316 | |
317 #if defined(OS_ANDROID) | 306 #if defined(OS_ANDROID) |
318 if (pending_get_categories_done_callback_.is_null()) | 307 if (pending_get_categories_done_callback_.is_null()) |
319 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 308 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
320 #endif | 309 #endif |
321 | 310 |
322 if (!callback.is_null() || !result_file_path.empty()) | |
323 result_file_.reset(new ResultFile(result_file_path)); | |
324 | |
325 // Count myself (local trace) in pending_disable_recording_ack_count_, | 311 // Count myself (local trace) in pending_disable_recording_ack_count_, |
326 // acked below. | 312 // acked below. |
327 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; | 313 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; |
328 pending_disable_recording_filters_ = trace_message_filters_; | 314 pending_disable_recording_filters_ = trace_message_filters_; |
329 | 315 |
330 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 316 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
331 if (is_system_tracing_) { | 317 if (is_system_tracing_) { |
332 // Disable system tracing. | 318 // Disable system tracing. |
333 is_system_tracing_ = false; | 319 is_system_tracing_ = false; |
334 ++pending_disable_recording_ack_count_; | 320 ++pending_disable_recording_ack_count_; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 base::Closure on_disable_monitoring_done_callback = | 410 base::Closure on_disable_monitoring_done_callback = |
425 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone, | 411 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone, |
426 base::Unretained(this), callback); | 412 base::Unretained(this), callback); |
427 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 413 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
428 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, | 414 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, |
429 base::Unretained(this), | 415 base::Unretained(this), |
430 on_disable_monitoring_done_callback)); | 416 on_disable_monitoring_done_callback)); |
431 return true; | 417 return true; |
432 } | 418 } |
433 | 419 |
| 420 scoped_refptr<TracingController::TraceDataSink> |
| 421 TracingController::CreateStringSink( |
| 422 const base::Callback<void(base::RefCountedString*)>& callback) { |
| 423 return new StringTraceDataSink(callback); |
| 424 } |
| 425 |
| 426 scoped_refptr<TracingController::TraceDataSink> |
| 427 TracingController::CreateFileSink( |
| 428 const base::FilePath& file_path, const base::Closure& callback) { |
| 429 return new FileTraceDataSink(file_path, callback); |
| 430 } |
| 431 |
434 void TracingControllerImpl::OnDisableMonitoringDone( | 432 void TracingControllerImpl::OnDisableMonitoringDone( |
435 const DisableMonitoringDoneCallback& callback) { | 433 const DisableMonitoringDoneCallback& callback) { |
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
437 | 435 |
438 OnMonitoringStateChanged(false); | 436 OnMonitoringStateChanged(false); |
439 | 437 |
440 // Notify all child processes. | 438 // Notify all child processes. |
441 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | 439 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); |
442 it != trace_message_filters_.end(); ++it) { | 440 it != trace_message_filters_.end(); ++it) { |
443 it->get()->SendDisableMonitoring(); | 441 it->get()->SendDisableMonitoring(); |
444 } | 442 } |
445 | |
446 if (!callback.is_null()) | 443 if (!callback.is_null()) |
447 callback.Run(); | 444 callback.Run(); |
448 } | 445 } |
449 | 446 |
450 void TracingControllerImpl::GetMonitoringStatus( | 447 void TracingControllerImpl::GetMonitoringStatus( |
451 bool* out_enabled, | 448 bool* out_enabled, |
452 CategoryFilter* out_category_filter, | 449 CategoryFilter* out_category_filter, |
453 TraceOptions* out_trace_options) { | 450 TraceOptions* out_trace_options) { |
454 *out_enabled = is_monitoring_; | 451 *out_enabled = is_monitoring_; |
455 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter(); | 452 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter(); |
456 *out_trace_options = trace_options_; | 453 *out_trace_options = trace_options_; |
457 } | 454 } |
458 | 455 |
459 bool TracingControllerImpl::CaptureMonitoringSnapshot( | 456 bool TracingControllerImpl::CaptureMonitoringSnapshot( |
460 const base::FilePath& result_file_path, | 457 const scoped_refptr<TraceDataSink>& monitoring_data_sink) { |
461 const TracingFileResultCallback& callback) { | |
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
463 | 459 |
464 if (!can_disable_monitoring()) | 460 if (!can_disable_monitoring()) |
465 return false; | 461 return false; |
466 | 462 |
467 if (callback.is_null() && result_file_path.empty()) | 463 if (!monitoring_data_sink.get()) |
468 return false; | 464 return false; |
469 | 465 |
470 pending_capture_monitoring_snapshot_done_callback_ = callback; | 466 monitoring_data_sink_ = monitoring_data_sink; |
471 monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); | |
472 | 467 |
473 // Count myself in pending_capture_monitoring_snapshot_ack_count_, | 468 // Count myself in pending_capture_monitoring_snapshot_ack_count_, |
474 // acked below. | 469 // acked below. |
475 pending_capture_monitoring_snapshot_ack_count_ = | 470 pending_capture_monitoring_snapshot_ack_count_ = |
476 trace_message_filters_.size() + 1; | 471 trace_message_filters_.size() + 1; |
477 pending_capture_monitoring_filters_ = trace_message_filters_; | 472 pending_capture_monitoring_filters_ = trace_message_filters_; |
478 | 473 |
479 // Handle special case of zero child processes by immediately flushing the | 474 // Handle special case of zero child processes by immediately flushing the |
480 // trace log. Once the flush has completed the caller will be notified that | 475 // trace log. Once the flush has completed the caller will be notified that |
481 // the capture snapshot has ended. | 476 // the capture snapshot has ended. |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 // called with the last of the local trace data. | 673 // called with the last of the local trace data. |
679 TraceLog::GetInstance()->Flush( | 674 TraceLog::GetInstance()->Flush( |
680 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | 675 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, |
681 base::Unretained(this))); | 676 base::Unretained(this))); |
682 return; | 677 return; |
683 } | 678 } |
684 | 679 |
685 if (pending_disable_recording_ack_count_ != 0) | 680 if (pending_disable_recording_ack_count_ != 0) |
686 return; | 681 return; |
687 | 682 |
688 OnDisableRecordingComplete(); | |
689 } | |
690 | |
691 void TracingControllerImpl::OnDisableRecordingComplete() { | |
692 // All acks (including from the subprocesses and the local trace) have been | 683 // All acks (including from the subprocesses and the local trace) have been |
693 // received. | 684 // received. |
694 is_recording_ = false; | 685 is_recording_ = false; |
695 | 686 |
696 // Trigger callback if one is set. | 687 // Trigger callback if one is set. |
697 if (!pending_get_categories_done_callback_.is_null()) { | 688 if (!pending_get_categories_done_callback_.is_null()) { |
698 pending_get_categories_done_callback_.Run(known_category_groups_); | 689 pending_get_categories_done_callback_.Run(known_category_groups_); |
699 pending_get_categories_done_callback_.Reset(); | 690 pending_get_categories_done_callback_.Reset(); |
700 } else if (result_file_) { | 691 } else if (trace_data_sink_.get()) { |
701 result_file_->Close( | 692 trace_data_sink_->Close(); |
702 base::Bind(&TracingControllerImpl::OnResultFileClosed, | 693 trace_data_sink_ = NULL; |
703 base::Unretained(this))); | |
704 } | 694 } |
705 } | 695 } |
706 | 696 |
707 void TracingControllerImpl::OnResultFileClosed() { | |
708 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
709 | |
710 if (!result_file_) | |
711 return; | |
712 | |
713 if (!pending_disable_recording_done_callback_.is_null()) { | |
714 pending_disable_recording_done_callback_.Run(result_file_->path()); | |
715 pending_disable_recording_done_callback_.Reset(); | |
716 } | |
717 result_file_.reset(); | |
718 } | |
719 | |
720 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 697 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
721 void TracingControllerImpl::OnEndSystemTracingAcked( | 698 void TracingControllerImpl::OnEndSystemTracingAcked( |
722 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 699 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 700 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
724 | 701 |
725 if (result_file_) | 702 if (trace_data_sink_.get()) { |
726 result_file_->WriteSystemTrace(events_str_ptr); | 703 #if defined(OS_WIN) |
727 | 704 // The Windows kernel events are kept into a JSon format stored as string |
| 705 // and must not be escaped. |
| 706 std::string json_string = events_str_ptr_->data(); |
| 707 #else |
| 708 std::string json_string = |
| 709 base::GetQuotedJSONString(events_str_ptr_->data()); |
| 710 #endif |
| 711 trace_data_sink_->SetSystemTrace(json_string); |
| 712 } |
728 DCHECK(!is_system_tracing_); | 713 DCHECK(!is_system_tracing_); |
729 std::vector<std::string> category_groups; | 714 std::vector<std::string> category_groups; |
730 OnDisableRecordingAcked(NULL, category_groups); | 715 OnDisableRecordingAcked(NULL, category_groups); |
731 } | 716 } |
732 #endif | 717 #endif |
733 | 718 |
734 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( | 719 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( |
735 TraceMessageFilter* trace_message_filter) { | 720 TraceMessageFilter* trace_message_filter) { |
736 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 721 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
737 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 722 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
(...skipping 18 matching lines...) Expand all Loading... |
756 // will be called with the last of the local trace data. | 741 // will be called with the last of the local trace data. |
757 TraceLog::GetInstance()->FlushButLeaveBufferIntact( | 742 TraceLog::GetInstance()->FlushButLeaveBufferIntact( |
758 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, | 743 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, |
759 base::Unretained(this))); | 744 base::Unretained(this))); |
760 return; | 745 return; |
761 } | 746 } |
762 | 747 |
763 if (pending_capture_monitoring_snapshot_ack_count_ != 0) | 748 if (pending_capture_monitoring_snapshot_ack_count_ != 0) |
764 return; | 749 return; |
765 | 750 |
766 if (monitoring_snapshot_file_) { | 751 if (monitoring_data_sink_.get()) { |
767 monitoring_snapshot_file_->Close( | 752 monitoring_data_sink_->Close(); |
768 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed, | 753 monitoring_data_sink_ = NULL; |
769 base::Unretained(this))); | |
770 } | 754 } |
771 } | 755 } |
772 | 756 |
773 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() { | |
774 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
775 | |
776 if (!monitoring_snapshot_file_) | |
777 return; | |
778 | |
779 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) { | |
780 pending_capture_monitoring_snapshot_done_callback_.Run( | |
781 monitoring_snapshot_file_->path()); | |
782 pending_capture_monitoring_snapshot_done_callback_.Reset(); | |
783 } | |
784 monitoring_snapshot_file_.reset(); | |
785 } | |
786 | |
787 void TracingControllerImpl::OnTraceDataCollected( | 757 void TracingControllerImpl::OnTraceDataCollected( |
788 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 758 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
789 // OnTraceDataCollected may be called from any browser thread, either by the | 759 // OnTraceDataCollected may be called from any browser thread, either by the |
790 // local event trace system or from child processes via TraceMessageFilter. | 760 // local event trace system or from child processes via TraceMessageFilter. |
791 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 761 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
792 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 762 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
793 base::Bind(&TracingControllerImpl::OnTraceDataCollected, | 763 base::Bind(&TracingControllerImpl::OnTraceDataCollected, |
794 base::Unretained(this), events_str_ptr)); | 764 base::Unretained(this), events_str_ptr)); |
795 return; | 765 return; |
796 } | 766 } |
797 | 767 |
798 if (result_file_) | 768 if (trace_data_sink_.get()) |
799 result_file_->Write(events_str_ptr); | 769 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); |
800 } | 770 } |
801 | 771 |
802 void TracingControllerImpl::OnMonitoringTraceDataCollected( | 772 void TracingControllerImpl::OnMonitoringTraceDataCollected( |
803 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 773 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
804 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 774 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
805 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 775 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
806 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, | 776 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, |
807 base::Unretained(this), events_str_ptr)); | 777 base::Unretained(this), events_str_ptr)); |
808 return; | 778 return; |
809 } | 779 } |
810 | 780 |
811 if (monitoring_snapshot_file_) | 781 if (monitoring_data_sink_.get()) |
812 monitoring_snapshot_file_->Write(events_str_ptr); | 782 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data()); |
813 } | 783 } |
814 | 784 |
815 void TracingControllerImpl::OnLocalTraceDataCollected( | 785 void TracingControllerImpl::OnLocalTraceDataCollected( |
816 const scoped_refptr<base::RefCountedString>& events_str_ptr, | 786 const scoped_refptr<base::RefCountedString>& events_str_ptr, |
817 bool has_more_events) { | 787 bool has_more_events) { |
818 if (events_str_ptr->data().size()) | 788 if (events_str_ptr->data().size()) |
819 OnTraceDataCollected(events_str_ptr); | 789 OnTraceDataCollected(events_str_ptr); |
820 | 790 |
821 if (has_more_events) | 791 if (has_more_events) |
822 return; | 792 return; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 is_monitoring_ = is_monitoring; | 872 is_monitoring_ = is_monitoring; |
903 #if !defined(OS_ANDROID) | 873 #if !defined(OS_ANDROID) |
904 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); | 874 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); |
905 it != tracing_uis_.end(); it++) { | 875 it != tracing_uis_.end(); it++) { |
906 (*it)->OnMonitoringStateChanged(is_monitoring); | 876 (*it)->OnMonitoringStateChanged(is_monitoring); |
907 } | 877 } |
908 #endif | 878 #endif |
909 } | 879 } |
910 | 880 |
911 } // namespace content | 881 } // namespace content |
OLD | NEW |