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
3 // found in the LICENSE file.
4 #include "content/browser/tracing/tracing_controller_impl.h"
7 #include "base/debug/trace_event.h"
8 #include "base/files/file_util.h"
9 #include "base/json/string_escape.h"
10 #include "base/macros.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "content/browser/tracing/trace_message_filter.h"
13 #include "content/browser/tracing/tracing_ui.h"
14 #include "content/common/child_process_messages.h"
15 #include "content/public/browser/browser_message_filter.h"
16 #include "content/public/common/content_switches.h"
18 #if defined(OS_CHROMEOS)
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/debug_daemon_client.h"
24 #include "content/browser/tracing/etw_system_event_consumer_win.h"
27 using base::debug::TraceLog;
28 using base::debug::TraceOptions;
29 using base::debug::CategoryFilter;
35 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
36 LAZY_INSTANCE_INITIALIZER;
38 class FileTraceDataSink : public TracingController::TraceDataSink {
40 explicit FileTraceDataSink(const base::FilePath& trace_file_path,
41 const base::Closure& callback)
42 : file_path_(trace_file_path),
43 completion_callback_(callback),
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(
54 &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr));
56 virtual void SetSystemTrace(const std::string& data) OVERRIDE {
59 virtual void Close() OVERRIDE {
60 BrowserThread::PostTask(
63 base::Bind(&FileTraceDataSink::CloseOnFileThread, this));
67 virtual ~FileTraceDataSink() { DCHECK(file_ == NULL); }
69 void AddTraceChunkOnFileThread(
70 const scoped_refptr<base::RefCountedString> chunk) {
73 else if (!OpenFileIfNeededOnFileThread())
75 ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()),
79 bool OpenFileIfNeededOnFileThread() {
82 file_ = base::OpenFile(file_path_, "w");
84 LOG(ERROR) << "Failed to open " << file_path_.value();
87 const char preamble[] = "{\"traceEvents\": [";
88 ignore_result(fwrite(preamble, strlen(preamble), 1, file_));
92 void CloseOnFileThread() {
93 if (OpenFileIfNeededOnFileThread()) {
95 if (!system_trace_.empty()) {
96 const char systemTraceEvents[] = ",\"systemTraceEvents\": ";
97 ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents),
99 ignore_result(fwrite(system_trace_.c_str(),
100 strlen(system_trace_.c_str()), 1, file_));
103 base::CloseFile(file_);
106 BrowserThread::PostTask(
109 base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this));
112 void FinalizeOnUIThread() { completion_callback_.Run(); }
114 base::FilePath file_path_;
115 base::Closure completion_callback_;
117 std::string system_trace_;
119 DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink);
122 class StringTraceDataSink : public TracingController::TraceDataSink {
124 typedef base::Callback<void(base::RefCountedString*)> CompletionCallback;
126 explicit StringTraceDataSink(CompletionCallback callback)
127 : completion_callback_(callback) {}
129 // TracingController::TraceDataSink implementation
130 virtual void AddTraceChunk(const std::string& chunk) OVERRIDE {
135 virtual void SetSystemTrace(const std::string& data) OVERRIDE {
136 system_trace_ = data;
138 virtual void Close() OVERRIDE {
139 std::string result = "{\"traceEvents\":[" + trace_ + "]";
140 if (!system_trace_.empty())
141 result += ",\"systemTraceEvents\": " + system_trace_;
144 scoped_refptr<base::RefCountedString> str =
145 base::RefCountedString::TakeString(&result);
146 completion_callback_.Run(str.get());
150 virtual ~StringTraceDataSink() {}
153 std::string system_trace_;
154 CompletionCallback completion_callback_;
156 DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink);
161 TracingController* TracingController::GetInstance() {
162 return TracingControllerImpl::GetInstance();
165 TracingControllerImpl::TracingControllerImpl() :
166 pending_disable_recording_ack_count_(0),
167 pending_capture_monitoring_snapshot_ack_count_(0),
168 pending_trace_buffer_percent_full_ack_count_(0),
169 maximum_trace_buffer_percent_full_(0),
170 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
171 // is specified in command line.
172 #if defined(OS_CHROMEOS) || defined(OS_WIN)
173 is_system_tracing_(false),
175 is_recording_(TraceLog::GetInstance()->IsEnabled()),
176 is_monitoring_(false) {
179 TracingControllerImpl::~TracingControllerImpl() {
180 // This is a Leaky instance.
184 TracingControllerImpl* TracingControllerImpl::GetInstance() {
185 return g_controller.Pointer();
188 bool TracingControllerImpl::GetCategories(
189 const GetCategoriesDoneCallback& callback) {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192 // Known categories come back from child processes with the EndTracingAck
193 // message. So to get known categories, just begin and end tracing immediately
194 // afterwards. This will ping all the child processes for categories.
195 pending_get_categories_done_callback_ = callback;
196 if (!EnableRecording(
197 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
198 pending_get_categories_done_callback_.Reset();
202 bool ok = DisableRecording(NULL);
207 void TracingControllerImpl::SetEnabledOnFileThread(
208 const CategoryFilter& category_filter,
210 const TraceOptions& trace_options,
211 const base::Closure& callback) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
214 TraceLog::GetInstance()->SetEnabled(
215 category_filter, static_cast<TraceLog::Mode>(mode), trace_options);
216 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
219 void TracingControllerImpl::SetDisabledOnFileThread(
220 const base::Closure& callback) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
223 TraceLog::GetInstance()->SetDisabled();
224 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
227 bool TracingControllerImpl::EnableRecording(
228 const CategoryFilter& category_filter,
229 const TraceOptions& trace_options,
230 const EnableRecordingDoneCallback& callback) {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
233 if (!can_enable_recording())
235 is_recording_ = true;
237 #if defined(OS_ANDROID)
238 if (pending_get_categories_done_callback_.is_null())
239 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
242 trace_options_ = trace_options;
244 if (trace_options.enable_systrace) {
245 #if defined(OS_CHROMEOS)
246 DCHECK(!is_system_tracing_);
247 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
248 StartSystemTracing();
249 is_system_tracing_ = true;
250 #elif defined(OS_WIN)
251 DCHECK(!is_system_tracing_);
253 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
258 base::Closure on_enable_recording_done_callback =
259 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
260 base::Unretained(this),
261 category_filter, trace_options, callback);
262 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
263 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
264 base::Unretained(this),
266 base::debug::TraceLog::RECORDING_MODE,
268 on_enable_recording_done_callback));
272 void TracingControllerImpl::OnEnableRecordingDone(
273 const CategoryFilter& category_filter,
274 const TraceOptions& trace_options,
275 const EnableRecordingDoneCallback& callback) {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
278 // Notify all child processes.
279 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
280 it != trace_message_filters_.end(); ++it) {
281 it->get()->SendBeginTracing(category_filter, trace_options);
284 if (!callback.is_null())
288 bool TracingControllerImpl::DisableRecording(
289 const scoped_refptr<TraceDataSink>& trace_data_sink) {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
292 if (!can_disable_recording())
295 trace_data_sink_ = trace_data_sink;
296 trace_options_ = TraceOptions();
297 // Disable local trace early to avoid traces during end-tracing process from
298 // interfering with the process.
299 base::Closure on_disable_recording_done_callback = base::Bind(
300 &TracingControllerImpl::OnDisableRecordingDone, base::Unretained(this));
301 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
302 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
303 base::Unretained(this),
304 on_disable_recording_done_callback));
308 void TracingControllerImpl::OnDisableRecordingDone() {
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
311 #if defined(OS_ANDROID)
312 if (pending_get_categories_done_callback_.is_null())
313 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
316 // Count myself (local trace) in pending_disable_recording_ack_count_,
318 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
319 pending_disable_recording_filters_ = trace_message_filters_;
321 #if defined(OS_CHROMEOS) || defined(OS_WIN)
322 if (is_system_tracing_) {
323 // Disable system tracing.
324 is_system_tracing_ = false;
325 ++pending_disable_recording_ack_count_;
327 #if defined(OS_CHROMEOS)
328 scoped_refptr<base::TaskRunner> task_runner =
329 BrowserThread::GetBlockingPool();
330 chromeos::DBusThreadManager::Get()
331 ->GetDebugDaemonClient()
332 ->RequestStopSystemTracing(
334 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
335 base::Unretained(this)));
336 #elif defined(OS_WIN)
337 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
338 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
339 base::Unretained(this)));
342 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
344 // Handle special case of zero child processes by immediately flushing the
345 // trace log. Once the flush has completed the caller will be notified that
346 // tracing has ended.
347 if (pending_disable_recording_ack_count_ == 1) {
348 // Flush asynchronously now, because we don't have any children to wait for.
349 TraceLog::GetInstance()->Flush(
350 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
351 base::Unretained(this)));
354 // Notify all child processes.
355 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
356 it != trace_message_filters_.end(); ++it) {
357 it->get()->SendEndTracing();
361 bool TracingControllerImpl::EnableMonitoring(
362 const CategoryFilter& category_filter,
363 const TraceOptions& trace_options,
364 const EnableMonitoringDoneCallback& callback) {
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
367 if (!can_enable_monitoring())
369 OnMonitoringStateChanged(true);
371 #if defined(OS_ANDROID)
372 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
375 trace_options_ = trace_options;
377 base::Closure on_enable_monitoring_done_callback =
378 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
379 base::Unretained(this),
380 category_filter, trace_options, callback);
381 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
382 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
383 base::Unretained(this),
385 base::debug::TraceLog::MONITORING_MODE,
387 on_enable_monitoring_done_callback));
391 void TracingControllerImpl::OnEnableMonitoringDone(
392 const CategoryFilter& category_filter,
393 const TraceOptions& trace_options,
394 const EnableMonitoringDoneCallback& callback) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
397 // Notify all child processes.
398 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
399 it != trace_message_filters_.end(); ++it) {
400 it->get()->SendEnableMonitoring(category_filter, trace_options);
403 if (!callback.is_null())
407 bool TracingControllerImpl::DisableMonitoring(
408 const DisableMonitoringDoneCallback& callback) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
411 if (!can_disable_monitoring())
414 trace_options_ = TraceOptions();
415 base::Closure on_disable_monitoring_done_callback =
416 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
417 base::Unretained(this), callback);
418 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
419 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
420 base::Unretained(this),
421 on_disable_monitoring_done_callback));
425 scoped_refptr<TracingController::TraceDataSink>
426 TracingController::CreateStringSink(
427 const base::Callback<void(base::RefCountedString*)>& callback) {
428 return new StringTraceDataSink(callback);
431 scoped_refptr<TracingController::TraceDataSink>
432 TracingController::CreateFileSink(const base::FilePath& file_path,
433 const base::Closure& callback) {
434 return new FileTraceDataSink(file_path, callback);
437 void TracingControllerImpl::OnDisableMonitoringDone(
438 const DisableMonitoringDoneCallback& callback) {
439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
441 OnMonitoringStateChanged(false);
443 // Notify all child processes.
444 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
445 it != trace_message_filters_.end(); ++it) {
446 it->get()->SendDisableMonitoring();
448 if (!callback.is_null())
452 void TracingControllerImpl::GetMonitoringStatus(
454 CategoryFilter* out_category_filter,
455 TraceOptions* out_trace_options) {
456 *out_enabled = is_monitoring_;
457 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter();
458 *out_trace_options = trace_options_;
461 bool TracingControllerImpl::CaptureMonitoringSnapshot(
462 const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
465 if (!can_disable_monitoring())
468 if (!monitoring_data_sink.get())
471 monitoring_data_sink_ = monitoring_data_sink;
473 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
475 pending_capture_monitoring_snapshot_ack_count_ =
476 trace_message_filters_.size() + 1;
477 pending_capture_monitoring_filters_ = trace_message_filters_;
479 // 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
481 // the capture snapshot has ended.
482 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
483 // Flush asynchronously now, because we don't have any children to wait for.
484 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
485 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
486 base::Unretained(this)));
489 // Notify all child processes.
490 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
491 it != trace_message_filters_.end(); ++it) {
492 it->get()->SendCaptureMonitoringSnapshot();
495 #if defined(OS_ANDROID)
496 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
502 bool TracingControllerImpl::GetTraceBufferPercentFull(
503 const GetTraceBufferPercentFullCallback& callback) {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
506 if (!can_get_trace_buffer_percent_full() || callback.is_null())
509 pending_trace_buffer_percent_full_callback_ = callback;
511 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
512 pending_trace_buffer_percent_full_ack_count_ =
513 trace_message_filters_.size() + 1;
514 pending_trace_buffer_percent_full_filters_ = trace_message_filters_;
515 maximum_trace_buffer_percent_full_ = 0;
517 // Call OnTraceBufferPercentFullReply unconditionally for the browser process.
518 // This will result in immediate execution of the callback if there are no
520 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
521 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
522 base::Unretained(this),
523 scoped_refptr<TraceMessageFilter>(),
524 TraceLog::GetInstance()->GetBufferPercentFull()));
526 // Notify all child processes.
527 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
528 it != trace_message_filters_.end(); ++it) {
529 it->get()->SendGetTraceBufferPercentFull();
534 bool TracingControllerImpl::SetWatchEvent(
535 const std::string& category_name,
536 const std::string& event_name,
537 const WatchEventCallback& callback) {
538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
540 if (callback.is_null())
543 watch_category_name_ = category_name;
544 watch_event_name_ = event_name;
545 watch_event_callback_ = callback;
547 TraceLog::GetInstance()->SetWatchEvent(
548 category_name, event_name,
549 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
550 base::Unretained(this)));
552 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
553 it != trace_message_filters_.end(); ++it) {
554 it->get()->SendSetWatchEvent(category_name, event_name);
559 bool TracingControllerImpl::CancelWatchEvent() {
560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562 if (!can_cancel_watch_event())
565 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
566 it != trace_message_filters_.end(); ++it) {
567 it->get()->SendCancelWatchEvent();
570 watch_event_callback_.Reset();
574 void TracingControllerImpl::AddTraceMessageFilter(
575 TraceMessageFilter* trace_message_filter) {
576 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
577 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
578 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
579 base::Unretained(this),
580 make_scoped_refptr(trace_message_filter)));
584 trace_message_filters_.insert(trace_message_filter);
585 if (can_cancel_watch_event()) {
586 trace_message_filter->SendSetWatchEvent(watch_category_name_,
589 if (can_disable_recording()) {
590 trace_message_filter->SendBeginTracing(
591 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
592 TraceLog::GetInstance()->GetCurrentTraceOptions());
594 if (can_disable_monitoring()) {
595 trace_message_filter->SendEnableMonitoring(
596 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
597 TraceLog::GetInstance()->GetCurrentTraceOptions());
601 void TracingControllerImpl::RemoveTraceMessageFilter(
602 TraceMessageFilter* trace_message_filter) {
603 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
604 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
605 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
606 base::Unretained(this),
607 make_scoped_refptr(trace_message_filter)));
611 // If a filter is removed while a response from that filter is pending then
612 // simulate the response. Otherwise the response count will be wrong and the
613 // completion callback will never be executed.
614 if (pending_disable_recording_ack_count_ > 0) {
615 TraceMessageFilterSet::const_iterator it =
616 pending_disable_recording_filters_.find(trace_message_filter);
617 if (it != pending_disable_recording_filters_.end()) {
618 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
619 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
620 base::Unretained(this),
621 make_scoped_refptr(trace_message_filter),
622 std::vector<std::string>()));
625 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
626 TraceMessageFilterSet::const_iterator it =
627 pending_capture_monitoring_filters_.find(trace_message_filter);
628 if (it != pending_capture_monitoring_filters_.end()) {
629 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
630 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
631 base::Unretained(this),
632 make_scoped_refptr(trace_message_filter)));
635 if (pending_trace_buffer_percent_full_ack_count_ > 0) {
636 TraceMessageFilterSet::const_iterator it =
637 pending_trace_buffer_percent_full_filters_.find(trace_message_filter);
638 if (it != pending_trace_buffer_percent_full_filters_.end()) {
639 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
640 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
641 base::Unretained(this),
642 make_scoped_refptr(trace_message_filter),
647 trace_message_filters_.erase(trace_message_filter);
650 void TracingControllerImpl::OnDisableRecordingAcked(
651 TraceMessageFilter* trace_message_filter,
652 const std::vector<std::string>& known_category_groups) {
653 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
654 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
655 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
656 base::Unretained(this),
657 make_scoped_refptr(trace_message_filter),
658 known_category_groups));
662 // Merge known_category_groups with known_category_groups_
663 known_category_groups_.insert(known_category_groups.begin(),
664 known_category_groups.end());
666 if (pending_disable_recording_ack_count_ == 0)
669 if (trace_message_filter &&
670 !pending_disable_recording_filters_.erase(trace_message_filter)) {
671 // The response from the specified message filter has already been received.
675 if (--pending_disable_recording_ack_count_ == 1) {
676 // All acks from subprocesses have been received. Now flush the local trace.
677 // During or after this call, our OnLocalTraceDataCollected will be
678 // called with the last of the local trace data.
679 TraceLog::GetInstance()->Flush(
680 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
681 base::Unretained(this)));
685 if (pending_disable_recording_ack_count_ != 0)
688 // All acks (including from the subprocesses and the local trace) have been
690 is_recording_ = false;
692 // Trigger callback if one is set.
693 if (!pending_get_categories_done_callback_.is_null()) {
694 pending_get_categories_done_callback_.Run(known_category_groups_);
695 pending_get_categories_done_callback_.Reset();
696 } else if (trace_data_sink_.get()) {
697 trace_data_sink_->Close();
698 trace_data_sink_ = NULL;
702 #if defined(OS_CHROMEOS) || defined(OS_WIN)
703 void TracingControllerImpl::OnEndSystemTracingAcked(
704 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
705 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
707 if (trace_data_sink_.get()) {
709 // The Windows kernel events are kept into a JSon format stored as string
710 // and must not be escaped.
711 std::string json_string = events_str_ptr->data();
713 std::string json_string =
714 base::GetQuotedJSONString(events_str_ptr->data());
716 trace_data_sink_->SetSystemTrace(json_string);
718 DCHECK(!is_system_tracing_);
719 std::vector<std::string> category_groups;
720 OnDisableRecordingAcked(NULL, category_groups);
724 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
725 TraceMessageFilter* trace_message_filter) {
726 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
727 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
728 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
729 base::Unretained(this),
730 make_scoped_refptr(trace_message_filter)));
734 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
737 if (trace_message_filter &&
738 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
739 // The response from the specified message filter has already been received.
743 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
744 // All acks from subprocesses have been received. Now flush the local trace.
745 // During or after this call, our OnLocalMonitoringTraceDataCollected
746 // will be called with the last of the local trace data.
747 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
748 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
749 base::Unretained(this)));
753 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
756 if (monitoring_data_sink_.get()) {
757 monitoring_data_sink_->Close();
758 monitoring_data_sink_ = NULL;
762 void TracingControllerImpl::OnTraceDataCollected(
763 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
764 // OnTraceDataCollected may be called from any browser thread, either by the
765 // local event trace system or from child processes via TraceMessageFilter.
766 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
767 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
768 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
769 base::Unretained(this), events_str_ptr));
773 if (trace_data_sink_.get())
774 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
777 void TracingControllerImpl::OnMonitoringTraceDataCollected(
778 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
779 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
780 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
781 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
782 base::Unretained(this), events_str_ptr));
786 if (monitoring_data_sink_.get())
787 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
790 void TracingControllerImpl::OnLocalTraceDataCollected(
791 const scoped_refptr<base::RefCountedString>& events_str_ptr,
792 bool has_more_events) {
793 if (events_str_ptr->data().size())
794 OnTraceDataCollected(events_str_ptr);
799 // Simulate an DisableRecordingAcked for the local trace.
800 std::vector<std::string> category_groups;
801 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
802 OnDisableRecordingAcked(NULL, category_groups);
805 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
806 const scoped_refptr<base::RefCountedString>& events_str_ptr,
807 bool has_more_events) {
808 if (events_str_ptr->data().size())
809 OnMonitoringTraceDataCollected(events_str_ptr);
814 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
815 OnCaptureMonitoringSnapshotAcked(NULL);
818 void TracingControllerImpl::OnTraceBufferPercentFullReply(
819 TraceMessageFilter* trace_message_filter,
820 float percent_full) {
821 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
822 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
823 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
824 base::Unretained(this),
825 make_scoped_refptr(trace_message_filter),
830 if (pending_trace_buffer_percent_full_ack_count_ == 0)
833 if (trace_message_filter &&
834 !pending_trace_buffer_percent_full_filters_.erase(trace_message_filter)) {
835 // The response from the specified message filter has already been received.
839 maximum_trace_buffer_percent_full_ =
840 std::max(maximum_trace_buffer_percent_full_, percent_full);
842 if (--pending_trace_buffer_percent_full_ack_count_ == 0) {
843 // Trigger callback if one is set.
844 pending_trace_buffer_percent_full_callback_.Run(
845 maximum_trace_buffer_percent_full_);
846 pending_trace_buffer_percent_full_callback_.Reset();
850 void TracingControllerImpl::OnWatchEventMatched() {
851 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
852 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
853 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
854 base::Unretained(this)));
858 if (!watch_event_callback_.is_null())
859 watch_event_callback_.Run();
862 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
863 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
864 tracing_uis_.insert(tracing_ui);
867 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
868 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
869 DCHECK(it != tracing_uis_.end());
870 tracing_uis_.erase(it);
873 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
874 if (is_monitoring_ == is_monitoring)
877 is_monitoring_ = is_monitoring;
878 #if !defined(OS_ANDROID)
879 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
880 it != tracing_uis_.end(); it++) {
881 (*it)->OnMonitoringStateChanged(is_monitoring);
886 } // namespace content