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/files/file_util.h"
8 #include "base/json/string_escape.h"
9 #include "base/macros.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/trace_event/trace_event.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::trace_event::TraceLog
;
28 using base::trace_event::TraceOptions
;
29 using base::trace_event::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 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 void SetSystemTrace(const std::string
& data
) override
{
59 void Close() override
{
60 BrowserThread::PostTask(
63 base::Bind(&FileTraceDataSink::CloseOnFileThread
, this));
67 ~FileTraceDataSink() override
{ 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 void AddTraceChunk(const std::string
& chunk
) override
{
135 void SetSystemTrace(const std::string
& data
) override
{
136 system_trace_
= data
;
138 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 ~StringTraceDataSink() override
{}
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_log_status_ack_count_(0),
169 maximum_trace_buffer_usage_(0),
170 approximate_event_count_(0),
171 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
172 // is specified in command line.
173 #if defined(OS_CHROMEOS) || defined(OS_WIN)
174 is_system_tracing_(false),
176 is_recording_(TraceLog::GetInstance()->IsEnabled()),
177 is_monitoring_(false) {
180 TracingControllerImpl::~TracingControllerImpl() {
181 // This is a Leaky instance.
185 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
186 return g_controller
.Pointer();
189 bool TracingControllerImpl::GetCategories(
190 const GetCategoriesDoneCallback
& callback
) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
193 // Known categories come back from child processes with the EndTracingAck
194 // message. So to get known categories, just begin and end tracing immediately
195 // afterwards. This will ping all the child processes for categories.
196 pending_get_categories_done_callback_
= callback
;
197 if (!EnableRecording(
198 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
199 pending_get_categories_done_callback_
.Reset();
203 bool ok
= DisableRecording(NULL
);
208 void TracingControllerImpl::SetEnabledOnFileThread(
209 const CategoryFilter
& category_filter
,
211 const TraceOptions
& trace_options
,
212 const base::Closure
& callback
) {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
215 TraceLog::GetInstance()->SetEnabled(
216 category_filter
, static_cast<TraceLog::Mode
>(mode
), trace_options
);
217 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
220 void TracingControllerImpl::SetDisabledOnFileThread(
221 const base::Closure
& callback
) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
224 TraceLog::GetInstance()->SetDisabled();
225 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
228 bool TracingControllerImpl::EnableRecording(
229 const CategoryFilter
& category_filter
,
230 const TraceOptions
& trace_options
,
231 const EnableRecordingDoneCallback
& callback
) {
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
234 if (!can_enable_recording())
236 is_recording_
= true;
238 #if defined(OS_ANDROID)
239 if (pending_get_categories_done_callback_
.is_null())
240 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
243 trace_options_
= trace_options
;
245 if (trace_options
.enable_systrace
) {
246 #if defined(OS_CHROMEOS)
247 DCHECK(!is_system_tracing_
);
248 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
249 StartSystemTracing();
250 is_system_tracing_
= true;
251 #elif defined(OS_WIN)
252 DCHECK(!is_system_tracing_
);
254 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
259 base::Closure on_enable_recording_done_callback
=
260 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
261 base::Unretained(this),
262 category_filter
, trace_options
, callback
);
263 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
264 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
265 base::Unretained(this),
267 base::trace_event::TraceLog::RECORDING_MODE
,
269 on_enable_recording_done_callback
));
273 void TracingControllerImpl::OnEnableRecordingDone(
274 const CategoryFilter
& category_filter
,
275 const TraceOptions
& trace_options
,
276 const EnableRecordingDoneCallback
& callback
) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
279 // Notify all child processes.
280 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
281 it
!= trace_message_filters_
.end(); ++it
) {
282 it
->get()->SendBeginTracing(category_filter
, trace_options
);
285 if (!callback
.is_null())
289 bool TracingControllerImpl::DisableRecording(
290 const scoped_refptr
<TraceDataSink
>& trace_data_sink
) {
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
293 if (!can_disable_recording())
296 trace_data_sink_
= trace_data_sink
;
297 trace_options_
= TraceOptions();
298 // Disable local trace early to avoid traces during end-tracing process from
299 // interfering with the process.
300 base::Closure on_disable_recording_done_callback
= base::Bind(
301 &TracingControllerImpl::OnDisableRecordingDone
, base::Unretained(this));
302 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
303 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
304 base::Unretained(this),
305 on_disable_recording_done_callback
));
309 void TracingControllerImpl::OnDisableRecordingDone() {
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
312 #if defined(OS_ANDROID)
313 if (pending_get_categories_done_callback_
.is_null())
314 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
317 // Count myself (local trace) in pending_disable_recording_ack_count_,
319 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
320 pending_disable_recording_filters_
= trace_message_filters_
;
322 #if defined(OS_CHROMEOS) || defined(OS_WIN)
323 if (is_system_tracing_
) {
324 // Disable system tracing.
325 is_system_tracing_
= false;
326 ++pending_disable_recording_ack_count_
;
328 #if defined(OS_CHROMEOS)
329 scoped_refptr
<base::TaskRunner
> task_runner
=
330 BrowserThread::GetBlockingPool();
331 chromeos::DBusThreadManager::Get()
332 ->GetDebugDaemonClient()
333 ->RequestStopSystemTracing(
335 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
336 base::Unretained(this)));
337 #elif defined(OS_WIN)
338 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
339 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
340 base::Unretained(this)));
343 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
345 // Handle special case of zero child processes by immediately flushing the
346 // trace log. Once the flush has completed the caller will be notified that
347 // tracing has ended.
348 if (pending_disable_recording_ack_count_
== 1) {
349 // Flush asynchronously now, because we don't have any children to wait for.
350 TraceLog::GetInstance()->Flush(
351 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
352 base::Unretained(this)));
355 // Notify all child processes.
356 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
357 it
!= trace_message_filters_
.end(); ++it
) {
358 it
->get()->SendEndTracing();
362 bool TracingControllerImpl::EnableMonitoring(
363 const CategoryFilter
& category_filter
,
364 const TraceOptions
& trace_options
,
365 const EnableMonitoringDoneCallback
& callback
) {
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
368 if (!can_enable_monitoring())
370 OnMonitoringStateChanged(true);
372 #if defined(OS_ANDROID)
373 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
376 trace_options_
= trace_options
;
378 base::Closure on_enable_monitoring_done_callback
=
379 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
380 base::Unretained(this),
381 category_filter
, trace_options
, callback
);
382 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
383 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
384 base::Unretained(this),
386 base::trace_event::TraceLog::MONITORING_MODE
,
388 on_enable_monitoring_done_callback
));
392 void TracingControllerImpl::OnEnableMonitoringDone(
393 const CategoryFilter
& category_filter
,
394 const TraceOptions
& trace_options
,
395 const EnableMonitoringDoneCallback
& callback
) {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
398 // Notify all child processes.
399 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
400 it
!= trace_message_filters_
.end(); ++it
) {
401 it
->get()->SendEnableMonitoring(category_filter
, trace_options
);
404 if (!callback
.is_null())
408 bool TracingControllerImpl::DisableMonitoring(
409 const DisableMonitoringDoneCallback
& callback
) {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
412 if (!can_disable_monitoring())
415 trace_options_
= TraceOptions();
416 base::Closure on_disable_monitoring_done_callback
=
417 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
418 base::Unretained(this), callback
);
419 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
420 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
421 base::Unretained(this),
422 on_disable_monitoring_done_callback
));
426 scoped_refptr
<TracingController::TraceDataSink
>
427 TracingController::CreateStringSink(
428 const base::Callback
<void(base::RefCountedString
*)>& callback
) {
429 return new StringTraceDataSink(callback
);
432 scoped_refptr
<TracingController::TraceDataSink
>
433 TracingController::CreateFileSink(const base::FilePath
& file_path
,
434 const base::Closure
& callback
) {
435 return new FileTraceDataSink(file_path
, callback
);
438 void TracingControllerImpl::OnDisableMonitoringDone(
439 const DisableMonitoringDoneCallback
& callback
) {
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
442 OnMonitoringStateChanged(false);
444 // Notify all child processes.
445 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
446 it
!= trace_message_filters_
.end(); ++it
) {
447 it
->get()->SendDisableMonitoring();
449 if (!callback
.is_null())
453 void TracingControllerImpl::GetMonitoringStatus(
455 CategoryFilter
* out_category_filter
,
456 TraceOptions
* out_trace_options
) {
457 *out_enabled
= is_monitoring_
;
458 *out_category_filter
= TraceLog::GetInstance()->GetCurrentCategoryFilter();
459 *out_trace_options
= trace_options_
;
462 bool TracingControllerImpl::CaptureMonitoringSnapshot(
463 const scoped_refptr
<TraceDataSink
>& monitoring_data_sink
) {
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
466 if (!can_disable_monitoring())
469 if (!monitoring_data_sink
.get())
472 monitoring_data_sink_
= monitoring_data_sink
;
474 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
476 pending_capture_monitoring_snapshot_ack_count_
=
477 trace_message_filters_
.size() + 1;
478 pending_capture_monitoring_filters_
= trace_message_filters_
;
480 // Handle special case of zero child processes by immediately flushing the
481 // trace log. Once the flush has completed the caller will be notified that
482 // the capture snapshot has ended.
483 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
484 // Flush asynchronously now, because we don't have any children to wait for.
485 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
486 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
487 base::Unretained(this)));
490 // Notify all child processes.
491 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
492 it
!= trace_message_filters_
.end(); ++it
) {
493 it
->get()->SendCaptureMonitoringSnapshot();
496 #if defined(OS_ANDROID)
497 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
503 bool TracingControllerImpl::GetTraceBufferUsage(
504 const GetTraceBufferUsageCallback
& callback
) {
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
507 if (!can_get_trace_buffer_usage() || callback
.is_null())
510 pending_trace_buffer_usage_callback_
= callback
;
512 // Count myself in pending_trace_log_status_ack_count_, acked below.
513 pending_trace_log_status_ack_count_
= trace_message_filters_
.size() + 1;
514 pending_trace_log_status_filters_
= trace_message_filters_
;
515 maximum_trace_buffer_usage_
= 0;
516 approximate_event_count_
= 0;
518 base::trace_event::TraceLogStatus status
=
519 TraceLog::GetInstance()->GetStatus();
520 // Call OnTraceLogStatusReply unconditionally for the browser process.
521 // This will result in immediate execution of the callback if there are no
523 BrowserThread::PostTask(
524 BrowserThread::UI
, FROM_HERE
,
525 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
526 base::Unretained(this), scoped_refptr
<TraceMessageFilter
>(),
529 // Notify all child processes.
530 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
531 it
!= trace_message_filters_
.end(); ++it
) {
532 it
->get()->SendGetTraceLogStatus();
537 bool TracingControllerImpl::SetWatchEvent(
538 const std::string
& category_name
,
539 const std::string
& event_name
,
540 const WatchEventCallback
& callback
) {
541 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
543 if (callback
.is_null())
546 watch_category_name_
= category_name
;
547 watch_event_name_
= event_name
;
548 watch_event_callback_
= callback
;
550 TraceLog::GetInstance()->SetWatchEvent(
551 category_name
, event_name
,
552 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
553 base::Unretained(this)));
555 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
556 it
!= trace_message_filters_
.end(); ++it
) {
557 it
->get()->SendSetWatchEvent(category_name
, event_name
);
562 bool TracingControllerImpl::CancelWatchEvent() {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
565 if (!can_cancel_watch_event())
568 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
569 it
!= trace_message_filters_
.end(); ++it
) {
570 it
->get()->SendCancelWatchEvent();
573 watch_event_callback_
.Reset();
577 void TracingControllerImpl::AddTraceMessageFilter(
578 TraceMessageFilter
* trace_message_filter
) {
579 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
580 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
581 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
582 base::Unretained(this),
583 make_scoped_refptr(trace_message_filter
)));
587 trace_message_filters_
.insert(trace_message_filter
);
588 if (can_cancel_watch_event()) {
589 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
592 if (can_disable_recording()) {
593 trace_message_filter
->SendBeginTracing(
594 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
595 TraceLog::GetInstance()->GetCurrentTraceOptions());
597 if (can_disable_monitoring()) {
598 trace_message_filter
->SendEnableMonitoring(
599 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
600 TraceLog::GetInstance()->GetCurrentTraceOptions());
604 void TracingControllerImpl::RemoveTraceMessageFilter(
605 TraceMessageFilter
* trace_message_filter
) {
606 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
607 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
608 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
609 base::Unretained(this),
610 make_scoped_refptr(trace_message_filter
)));
614 // If a filter is removed while a response from that filter is pending then
615 // simulate the response. Otherwise the response count will be wrong and the
616 // completion callback will never be executed.
617 if (pending_disable_recording_ack_count_
> 0) {
618 TraceMessageFilterSet::const_iterator it
=
619 pending_disable_recording_filters_
.find(trace_message_filter
);
620 if (it
!= pending_disable_recording_filters_
.end()) {
621 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
622 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
623 base::Unretained(this),
624 make_scoped_refptr(trace_message_filter
),
625 std::vector
<std::string
>()));
628 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
629 TraceMessageFilterSet::const_iterator it
=
630 pending_capture_monitoring_filters_
.find(trace_message_filter
);
631 if (it
!= pending_capture_monitoring_filters_
.end()) {
632 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
633 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
634 base::Unretained(this),
635 make_scoped_refptr(trace_message_filter
)));
638 if (pending_trace_log_status_ack_count_
> 0) {
639 TraceMessageFilterSet::const_iterator it
=
640 pending_trace_log_status_filters_
.find(trace_message_filter
);
641 if (it
!= pending_trace_log_status_filters_
.end()) {
642 BrowserThread::PostTask(
643 BrowserThread::UI
, FROM_HERE
,
644 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
645 base::Unretained(this),
646 make_scoped_refptr(trace_message_filter
),
647 base::trace_event::TraceLogStatus()));
651 trace_message_filters_
.erase(trace_message_filter
);
654 void TracingControllerImpl::OnDisableRecordingAcked(
655 TraceMessageFilter
* trace_message_filter
,
656 const std::vector
<std::string
>& known_category_groups
) {
657 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
658 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
659 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
660 base::Unretained(this),
661 make_scoped_refptr(trace_message_filter
),
662 known_category_groups
));
666 // Merge known_category_groups with known_category_groups_
667 known_category_groups_
.insert(known_category_groups
.begin(),
668 known_category_groups
.end());
670 if (pending_disable_recording_ack_count_
== 0)
673 if (trace_message_filter
&&
674 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
675 // The response from the specified message filter has already been received.
679 if (--pending_disable_recording_ack_count_
== 1) {
680 // All acks from subprocesses have been received. Now flush the local trace.
681 // During or after this call, our OnLocalTraceDataCollected will be
682 // called with the last of the local trace data.
683 TraceLog::GetInstance()->Flush(
684 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
685 base::Unretained(this)));
689 if (pending_disable_recording_ack_count_
!= 0)
692 // All acks (including from the subprocesses and the local trace) have been
694 is_recording_
= false;
696 // Trigger callback if one is set.
697 if (!pending_get_categories_done_callback_
.is_null()) {
698 pending_get_categories_done_callback_
.Run(known_category_groups_
);
699 pending_get_categories_done_callback_
.Reset();
700 } else if (trace_data_sink_
.get()) {
701 trace_data_sink_
->Close();
702 trace_data_sink_
= NULL
;
706 #if defined(OS_CHROMEOS) || defined(OS_WIN)
707 void TracingControllerImpl::OnEndSystemTracingAcked(
708 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
709 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
711 if (trace_data_sink_
.get()) {
713 // The Windows kernel events are kept into a JSon format stored as string
714 // and must not be escaped.
715 std::string json_string
= events_str_ptr
->data();
717 std::string json_string
=
718 base::GetQuotedJSONString(events_str_ptr
->data());
720 trace_data_sink_
->SetSystemTrace(json_string
);
722 DCHECK(!is_system_tracing_
);
723 std::vector
<std::string
> category_groups
;
724 OnDisableRecordingAcked(NULL
, category_groups
);
728 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
729 TraceMessageFilter
* trace_message_filter
) {
730 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
731 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
732 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
733 base::Unretained(this),
734 make_scoped_refptr(trace_message_filter
)));
738 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
741 if (trace_message_filter
&&
742 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
743 // The response from the specified message filter has already been received.
747 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
748 // All acks from subprocesses have been received. Now flush the local trace.
749 // During or after this call, our OnLocalMonitoringTraceDataCollected
750 // will be called with the last of the local trace data.
751 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
752 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
753 base::Unretained(this)));
757 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
760 if (monitoring_data_sink_
.get()) {
761 monitoring_data_sink_
->Close();
762 monitoring_data_sink_
= NULL
;
766 void TracingControllerImpl::OnTraceDataCollected(
767 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
768 // OnTraceDataCollected may be called from any browser thread, either by the
769 // local event trace system or from child processes via TraceMessageFilter.
770 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
771 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
772 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
773 base::Unretained(this), events_str_ptr
));
777 if (trace_data_sink_
.get())
778 trace_data_sink_
->AddTraceChunk(events_str_ptr
->data());
781 void TracingControllerImpl::OnMonitoringTraceDataCollected(
782 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
783 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
784 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
785 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
786 base::Unretained(this), events_str_ptr
));
790 if (monitoring_data_sink_
.get())
791 monitoring_data_sink_
->AddTraceChunk(events_str_ptr
->data());
794 void TracingControllerImpl::OnLocalTraceDataCollected(
795 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
796 bool has_more_events
) {
797 if (events_str_ptr
->data().size())
798 OnTraceDataCollected(events_str_ptr
);
803 // Simulate an DisableRecordingAcked for the local trace.
804 std::vector
<std::string
> category_groups
;
805 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
806 OnDisableRecordingAcked(NULL
, category_groups
);
809 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
810 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
811 bool has_more_events
) {
812 if (events_str_ptr
->data().size())
813 OnMonitoringTraceDataCollected(events_str_ptr
);
818 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
819 OnCaptureMonitoringSnapshotAcked(NULL
);
822 void TracingControllerImpl::OnTraceLogStatusReply(
823 TraceMessageFilter
* trace_message_filter
,
824 const base::trace_event::TraceLogStatus
& status
) {
825 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
826 BrowserThread::PostTask(
827 BrowserThread::UI
, FROM_HERE
,
828 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
829 base::Unretained(this),
830 make_scoped_refptr(trace_message_filter
), status
));
834 if (pending_trace_log_status_ack_count_
== 0)
837 if (trace_message_filter
&&
838 !pending_trace_log_status_filters_
.erase(trace_message_filter
)) {
839 // The response from the specified message filter has already been received.
843 float percent_full
= static_cast<float>(
844 static_cast<double>(status
.event_count
) / status
.event_capacity
);
845 maximum_trace_buffer_usage_
=
846 std::max(maximum_trace_buffer_usage_
, percent_full
);
847 approximate_event_count_
+= status
.event_count
;
849 if (--pending_trace_log_status_ack_count_
== 0) {
850 // Trigger callback if one is set.
851 pending_trace_buffer_usage_callback_
.Run(maximum_trace_buffer_usage_
,
852 approximate_event_count_
);
853 pending_trace_buffer_usage_callback_
.Reset();
857 void TracingControllerImpl::OnWatchEventMatched() {
858 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
859 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
860 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
861 base::Unretained(this)));
865 if (!watch_event_callback_
.is_null())
866 watch_event_callback_
.Run();
869 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
870 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
871 tracing_uis_
.insert(tracing_ui
);
874 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
875 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
876 DCHECK(it
!= tracing_uis_
.end());
877 tracing_uis_
.erase(it
);
880 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
881 if (is_monitoring_
== is_monitoring
)
884 is_monitoring_
= is_monitoring
;
885 #if !defined(OS_ANDROID)
886 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
887 it
!= tracing_uis_
.end(); it
++) {
888 (*it
)->OnMonitoringStateChanged(is_monitoring
);
893 } // namespace content