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/file_tracing_provider_impl.h"
13 #include "content/browser/tracing/trace_message_filter.h"
14 #include "content/browser/tracing/tracing_ui.h"
15 #include "content/common/child_process_messages.h"
16 #include "content/public/browser/browser_message_filter.h"
17 #include "content/public/common/content_switches.h"
19 #if defined(OS_CHROMEOS)
20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/dbus/debug_daemon_client.h"
25 #include "content/browser/tracing/etw_system_event_consumer_win.h"
28 using base::trace_event::TraceLog
;
29 using base::trace_event::TraceOptions
;
30 using base::trace_event::CategoryFilter
;
36 base::LazyInstance
<TracingControllerImpl
>::Leaky g_controller
=
37 LAZY_INSTANCE_INITIALIZER
;
41 TracingController
* TracingController::GetInstance() {
42 return TracingControllerImpl::GetInstance();
45 TracingControllerImpl::TracingControllerImpl()
46 : pending_disable_recording_ack_count_(0),
47 pending_capture_monitoring_snapshot_ack_count_(0),
48 pending_trace_log_status_ack_count_(0),
49 maximum_trace_buffer_usage_(0),
50 approximate_event_count_(0),
51 pending_memory_dump_ack_count_(0),
52 failed_memory_dump_count_(0),
53 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
54 // is specified in command line.
55 #if defined(OS_CHROMEOS) || defined(OS_WIN)
56 is_system_tracing_(false),
58 is_recording_(TraceLog::GetInstance()->IsEnabled()),
59 is_monitoring_(false) {
60 base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this);
62 // Deliberately leaked, like this class.
63 base::FileTracing::SetProvider(new FileTracingProviderImpl
);
66 TracingControllerImpl::~TracingControllerImpl() {
67 // This is a Leaky instance.
71 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
72 return g_controller
.Pointer();
75 bool TracingControllerImpl::GetCategories(
76 const GetCategoriesDoneCallback
& callback
) {
77 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
79 // Known categories come back from child processes with the EndTracingAck
80 // message. So to get known categories, just begin and end tracing immediately
81 // afterwards. This will ping all the child processes for categories.
82 pending_get_categories_done_callback_
= callback
;
84 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
85 pending_get_categories_done_callback_
.Reset();
89 bool ok
= DisableRecording(NULL
);
94 void TracingControllerImpl::SetEnabledOnFileThread(
95 const CategoryFilter
& category_filter
,
97 const TraceOptions
& trace_options
,
98 const base::Closure
& callback
) {
99 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
101 TraceLog::GetInstance()->SetEnabled(
102 category_filter
, static_cast<TraceLog::Mode
>(mode
), trace_options
);
103 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
106 void TracingControllerImpl::SetDisabledOnFileThread(
107 const base::Closure
& callback
) {
108 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
110 TraceLog::GetInstance()->SetDisabled();
111 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
114 bool TracingControllerImpl::EnableRecording(
115 const CategoryFilter
& category_filter
,
116 const TraceOptions
& trace_options
,
117 const EnableRecordingDoneCallback
& callback
) {
118 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
120 if (!can_enable_recording())
122 is_recording_
= true;
124 #if defined(OS_ANDROID)
125 if (pending_get_categories_done_callback_
.is_null())
126 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
129 trace_options_
= trace_options
;
131 if (trace_options
.enable_systrace
) {
132 #if defined(OS_CHROMEOS)
133 DCHECK(!is_system_tracing_
);
134 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
135 StartSystemTracing();
136 is_system_tracing_
= true;
137 #elif defined(OS_WIN)
138 DCHECK(!is_system_tracing_
);
140 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
145 base::Closure on_enable_recording_done_callback
=
146 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
147 base::Unretained(this),
148 category_filter
, trace_options
, callback
);
149 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
150 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
151 base::Unretained(this),
153 base::trace_event::TraceLog::RECORDING_MODE
,
155 on_enable_recording_done_callback
));
159 void TracingControllerImpl::OnEnableRecordingDone(
160 const CategoryFilter
& category_filter
,
161 const TraceOptions
& trace_options
,
162 const EnableRecordingDoneCallback
& callback
) {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
165 // Notify all child processes.
166 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
167 it
!= trace_message_filters_
.end(); ++it
) {
168 it
->get()->SendBeginTracing(category_filter
, trace_options
);
171 if (!callback
.is_null())
175 bool TracingControllerImpl::DisableRecording(
176 const scoped_refptr
<TraceDataSink
>& trace_data_sink
) {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
179 if (!can_disable_recording())
182 trace_data_sink_
= trace_data_sink
;
183 trace_options_
= TraceOptions();
184 // Disable local trace early to avoid traces during end-tracing process from
185 // interfering with the process.
186 base::Closure on_disable_recording_done_callback
= base::Bind(
187 &TracingControllerImpl::OnDisableRecordingDone
, base::Unretained(this));
188 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
189 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
190 base::Unretained(this),
191 on_disable_recording_done_callback
));
195 void TracingControllerImpl::OnDisableRecordingDone() {
196 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
198 #if defined(OS_ANDROID)
199 if (pending_get_categories_done_callback_
.is_null())
200 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
203 // Count myself (local trace) in pending_disable_recording_ack_count_,
205 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
206 pending_disable_recording_filters_
= trace_message_filters_
;
208 #if defined(OS_CHROMEOS) || defined(OS_WIN)
209 if (is_system_tracing_
) {
210 // Disable system tracing.
211 is_system_tracing_
= false;
212 ++pending_disable_recording_ack_count_
;
214 #if defined(OS_CHROMEOS)
215 scoped_refptr
<base::TaskRunner
> task_runner
=
216 BrowserThread::GetBlockingPool();
217 chromeos::DBusThreadManager::Get()
218 ->GetDebugDaemonClient()
219 ->RequestStopSystemTracing(
221 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
222 base::Unretained(this)));
223 #elif defined(OS_WIN)
224 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
225 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
226 base::Unretained(this)));
229 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
231 // Handle special case of zero child processes by immediately flushing the
232 // trace log. Once the flush has completed the caller will be notified that
233 // tracing has ended.
234 if (pending_disable_recording_ack_count_
== 1) {
235 // Flush asynchronously now, because we don't have any children to wait for.
236 TraceLog::GetInstance()->Flush(
237 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
238 base::Unretained(this)),
242 // Notify all child processes.
243 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
244 it
!= trace_message_filters_
.end(); ++it
) {
245 it
->get()->SendEndTracing();
249 bool TracingControllerImpl::EnableMonitoring(
250 const CategoryFilter
& category_filter
,
251 const TraceOptions
& trace_options
,
252 const EnableMonitoringDoneCallback
& callback
) {
253 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
255 if (!can_enable_monitoring())
257 OnMonitoringStateChanged(true);
259 #if defined(OS_ANDROID)
260 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
263 trace_options_
= trace_options
;
265 base::Closure on_enable_monitoring_done_callback
=
266 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
267 base::Unretained(this),
268 category_filter
, trace_options
, callback
);
269 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
270 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
271 base::Unretained(this),
273 base::trace_event::TraceLog::MONITORING_MODE
,
275 on_enable_monitoring_done_callback
));
279 void TracingControllerImpl::OnEnableMonitoringDone(
280 const CategoryFilter
& category_filter
,
281 const TraceOptions
& trace_options
,
282 const EnableMonitoringDoneCallback
& callback
) {
283 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
285 // Notify all child processes.
286 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
287 it
!= trace_message_filters_
.end(); ++it
) {
288 it
->get()->SendEnableMonitoring(category_filter
, trace_options
);
291 if (!callback
.is_null())
295 bool TracingControllerImpl::DisableMonitoring(
296 const DisableMonitoringDoneCallback
& callback
) {
297 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
299 if (!can_disable_monitoring())
302 trace_options_
= TraceOptions();
303 base::Closure on_disable_monitoring_done_callback
=
304 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
305 base::Unretained(this), callback
);
306 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
307 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
308 base::Unretained(this),
309 on_disable_monitoring_done_callback
));
313 void TracingControllerImpl::OnDisableMonitoringDone(
314 const DisableMonitoringDoneCallback
& callback
) {
315 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
317 OnMonitoringStateChanged(false);
319 // Notify all child processes.
320 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
321 it
!= trace_message_filters_
.end(); ++it
) {
322 it
->get()->SendDisableMonitoring();
324 if (!callback
.is_null())
328 void TracingControllerImpl::GetMonitoringStatus(
330 CategoryFilter
* out_category_filter
,
331 TraceOptions
* out_trace_options
) {
332 *out_enabled
= is_monitoring_
;
333 *out_category_filter
= TraceLog::GetInstance()->GetCurrentCategoryFilter();
334 *out_trace_options
= trace_options_
;
337 bool TracingControllerImpl::CaptureMonitoringSnapshot(
338 const scoped_refptr
<TraceDataSink
>& monitoring_data_sink
) {
339 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
341 if (!can_disable_monitoring())
344 if (!monitoring_data_sink
.get())
347 monitoring_data_sink_
= monitoring_data_sink
;
349 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
351 pending_capture_monitoring_snapshot_ack_count_
=
352 trace_message_filters_
.size() + 1;
353 pending_capture_monitoring_filters_
= trace_message_filters_
;
355 // Handle special case of zero child processes by immediately flushing the
356 // trace log. Once the flush has completed the caller will be notified that
357 // the capture snapshot has ended.
358 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
359 // Flush asynchronously now, because we don't have any children to wait for.
360 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
361 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
362 base::Unretained(this)));
365 // Notify all child processes.
366 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
367 it
!= trace_message_filters_
.end(); ++it
) {
368 it
->get()->SendCaptureMonitoringSnapshot();
371 #if defined(OS_ANDROID)
372 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
378 bool TracingControllerImpl::GetTraceBufferUsage(
379 const GetTraceBufferUsageCallback
& callback
) {
380 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
382 if (!can_get_trace_buffer_usage() || callback
.is_null())
385 pending_trace_buffer_usage_callback_
= callback
;
387 // Count myself in pending_trace_log_status_ack_count_, acked below.
388 pending_trace_log_status_ack_count_
= trace_message_filters_
.size() + 1;
389 pending_trace_log_status_filters_
= trace_message_filters_
;
390 maximum_trace_buffer_usage_
= 0;
391 approximate_event_count_
= 0;
393 base::trace_event::TraceLogStatus status
=
394 TraceLog::GetInstance()->GetStatus();
395 // Call OnTraceLogStatusReply unconditionally for the browser process.
396 // This will result in immediate execution of the callback if there are no
398 BrowserThread::PostTask(
399 BrowserThread::UI
, FROM_HERE
,
400 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
401 base::Unretained(this), scoped_refptr
<TraceMessageFilter
>(),
404 // Notify all child processes.
405 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
406 it
!= trace_message_filters_
.end(); ++it
) {
407 it
->get()->SendGetTraceLogStatus();
412 bool TracingControllerImpl::SetWatchEvent(
413 const std::string
& category_name
,
414 const std::string
& event_name
,
415 const WatchEventCallback
& callback
) {
416 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
418 if (callback
.is_null())
421 watch_category_name_
= category_name
;
422 watch_event_name_
= event_name
;
423 watch_event_callback_
= callback
;
425 TraceLog::GetInstance()->SetWatchEvent(
426 category_name
, event_name
,
427 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
428 base::Unretained(this)));
430 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
431 it
!= trace_message_filters_
.end(); ++it
) {
432 it
->get()->SendSetWatchEvent(category_name
, event_name
);
437 bool TracingControllerImpl::CancelWatchEvent() {
438 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
440 if (!can_cancel_watch_event())
443 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
444 it
!= trace_message_filters_
.end(); ++it
) {
445 it
->get()->SendCancelWatchEvent();
448 watch_event_callback_
.Reset();
452 void TracingControllerImpl::AddTraceMessageFilter(
453 TraceMessageFilter
* trace_message_filter
) {
454 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
455 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
456 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
457 base::Unretained(this),
458 make_scoped_refptr(trace_message_filter
)));
462 trace_message_filters_
.insert(trace_message_filter
);
463 if (can_cancel_watch_event()) {
464 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
467 if (can_disable_recording()) {
468 trace_message_filter
->SendBeginTracing(
469 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
470 TraceLog::GetInstance()->GetCurrentTraceOptions());
472 if (can_disable_monitoring()) {
473 trace_message_filter
->SendEnableMonitoring(
474 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
475 TraceLog::GetInstance()->GetCurrentTraceOptions());
479 void TracingControllerImpl::RemoveTraceMessageFilter(
480 TraceMessageFilter
* trace_message_filter
) {
481 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
482 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
483 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
484 base::Unretained(this),
485 make_scoped_refptr(trace_message_filter
)));
489 // If a filter is removed while a response from that filter is pending then
490 // simulate the response. Otherwise the response count will be wrong and the
491 // completion callback will never be executed.
492 if (pending_disable_recording_ack_count_
> 0) {
493 TraceMessageFilterSet::const_iterator it
=
494 pending_disable_recording_filters_
.find(trace_message_filter
);
495 if (it
!= pending_disable_recording_filters_
.end()) {
496 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
497 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
498 base::Unretained(this),
499 make_scoped_refptr(trace_message_filter
),
500 std::vector
<std::string
>()));
503 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
504 TraceMessageFilterSet::const_iterator it
=
505 pending_capture_monitoring_filters_
.find(trace_message_filter
);
506 if (it
!= pending_capture_monitoring_filters_
.end()) {
507 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
508 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
509 base::Unretained(this),
510 make_scoped_refptr(trace_message_filter
)));
513 if (pending_trace_log_status_ack_count_
> 0) {
514 TraceMessageFilterSet::const_iterator it
=
515 pending_trace_log_status_filters_
.find(trace_message_filter
);
516 if (it
!= pending_trace_log_status_filters_
.end()) {
517 BrowserThread::PostTask(
518 BrowserThread::UI
, FROM_HERE
,
519 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
520 base::Unretained(this),
521 make_scoped_refptr(trace_message_filter
),
522 base::trace_event::TraceLogStatus()));
525 if (pending_memory_dump_ack_count_
> 0) {
526 TraceMessageFilterSet::const_iterator it
=
527 pending_memory_dump_filters_
.find(trace_message_filter
);
528 if (it
!= pending_memory_dump_filters_
.end()) {
529 BrowserThread::PostTask(
530 BrowserThread::UI
, FROM_HERE
,
531 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
532 base::Unretained(this),
533 make_scoped_refptr(trace_message_filter
),
534 pending_memory_dump_guid_
, false /* success */));
537 trace_message_filters_
.erase(trace_message_filter
);
540 void TracingControllerImpl::OnDisableRecordingAcked(
541 TraceMessageFilter
* trace_message_filter
,
542 const std::vector
<std::string
>& known_category_groups
) {
543 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
544 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
545 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
546 base::Unretained(this),
547 make_scoped_refptr(trace_message_filter
),
548 known_category_groups
));
552 // Merge known_category_groups with known_category_groups_
553 known_category_groups_
.insert(known_category_groups
.begin(),
554 known_category_groups
.end());
556 if (pending_disable_recording_ack_count_
== 0)
559 if (trace_message_filter
&&
560 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
561 // The response from the specified message filter has already been received.
565 if (--pending_disable_recording_ack_count_
== 1) {
566 // All acks from subprocesses have been received. Now flush the local trace.
567 // During or after this call, our OnLocalTraceDataCollected will be
568 // called with the last of the local trace data.
569 TraceLog::GetInstance()->Flush(
570 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
571 base::Unretained(this)),
576 if (pending_disable_recording_ack_count_
!= 0)
579 // All acks (including from the subprocesses and the local trace) have been
581 is_recording_
= false;
583 // Trigger callback if one is set.
584 if (!pending_get_categories_done_callback_
.is_null()) {
585 pending_get_categories_done_callback_
.Run(known_category_groups_
);
586 pending_get_categories_done_callback_
.Reset();
587 } else if (trace_data_sink_
.get()) {
588 trace_data_sink_
->Close();
589 trace_data_sink_
= NULL
;
593 #if defined(OS_CHROMEOS) || defined(OS_WIN)
594 void TracingControllerImpl::OnEndSystemTracingAcked(
595 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
596 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
598 if (trace_data_sink_
.get()) {
600 // The Windows kernel events are kept into a JSon format stored as string
601 // and must not be escaped.
602 std::string json_string
= events_str_ptr
->data();
604 std::string json_string
=
605 base::GetQuotedJSONString(events_str_ptr
->data());
607 trace_data_sink_
->SetSystemTrace(json_string
);
609 DCHECK(!is_system_tracing_
);
610 std::vector
<std::string
> category_groups
;
611 OnDisableRecordingAcked(NULL
, category_groups
);
615 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
616 TraceMessageFilter
* trace_message_filter
) {
617 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
618 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
619 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
620 base::Unretained(this),
621 make_scoped_refptr(trace_message_filter
)));
625 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
628 if (trace_message_filter
&&
629 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
630 // The response from the specified message filter has already been received.
634 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
635 // All acks from subprocesses have been received. Now flush the local trace.
636 // During or after this call, our OnLocalMonitoringTraceDataCollected
637 // will be called with the last of the local trace data.
638 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
639 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
640 base::Unretained(this)));
644 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
647 if (monitoring_data_sink_
.get()) {
648 monitoring_data_sink_
->Close();
649 monitoring_data_sink_
= NULL
;
653 void TracingControllerImpl::OnTraceDataCollected(
654 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
655 // OnTraceDataCollected may be called from any browser thread, either by the
656 // local event trace system or from child processes via TraceMessageFilter.
657 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
658 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
659 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
660 base::Unretained(this), events_str_ptr
));
664 if (trace_data_sink_
.get())
665 trace_data_sink_
->AddTraceChunk(events_str_ptr
->data());
668 void TracingControllerImpl::OnMonitoringTraceDataCollected(
669 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
670 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
671 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
672 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
673 base::Unretained(this), events_str_ptr
));
677 if (monitoring_data_sink_
.get())
678 monitoring_data_sink_
->AddTraceChunk(events_str_ptr
->data());
681 void TracingControllerImpl::OnLocalTraceDataCollected(
682 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
683 bool has_more_events
) {
684 if (events_str_ptr
->data().size())
685 OnTraceDataCollected(events_str_ptr
);
690 // Simulate an DisableRecordingAcked for the local trace.
691 std::vector
<std::string
> category_groups
;
692 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
693 OnDisableRecordingAcked(NULL
, category_groups
);
696 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
697 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
698 bool has_more_events
) {
699 if (events_str_ptr
->data().size())
700 OnMonitoringTraceDataCollected(events_str_ptr
);
705 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
706 OnCaptureMonitoringSnapshotAcked(NULL
);
709 void TracingControllerImpl::OnTraceLogStatusReply(
710 TraceMessageFilter
* trace_message_filter
,
711 const base::trace_event::TraceLogStatus
& status
) {
712 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
713 BrowserThread::PostTask(
714 BrowserThread::UI
, FROM_HERE
,
715 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
716 base::Unretained(this),
717 make_scoped_refptr(trace_message_filter
), status
));
721 if (pending_trace_log_status_ack_count_
== 0)
724 if (trace_message_filter
&&
725 !pending_trace_log_status_filters_
.erase(trace_message_filter
)) {
726 // The response from the specified message filter has already been received.
730 float percent_full
= static_cast<float>(
731 static_cast<double>(status
.event_count
) / status
.event_capacity
);
732 maximum_trace_buffer_usage_
=
733 std::max(maximum_trace_buffer_usage_
, percent_full
);
734 approximate_event_count_
+= status
.event_count
;
736 if (--pending_trace_log_status_ack_count_
== 0) {
737 // Trigger callback if one is set.
738 pending_trace_buffer_usage_callback_
.Run(maximum_trace_buffer_usage_
,
739 approximate_event_count_
);
740 pending_trace_buffer_usage_callback_
.Reset();
744 void TracingControllerImpl::OnWatchEventMatched() {
745 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
746 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
747 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
748 base::Unretained(this)));
752 if (!watch_event_callback_
.is_null())
753 watch_event_callback_
.Run();
756 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
757 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
758 tracing_uis_
.insert(tracing_ui
);
761 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
762 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
763 DCHECK(it
!= tracing_uis_
.end());
764 tracing_uis_
.erase(it
);
767 void TracingControllerImpl::RequestGlobalMemoryDump(
768 const base::trace_event::MemoryDumpRequestArgs
& args
,
769 const base::trace_event::MemoryDumpCallback
& callback
) {
770 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
771 BrowserThread::PostTask(
772 BrowserThread::UI
, FROM_HERE
,
773 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump
,
774 base::Unretained(this), args
, callback
));
777 // Abort if another dump is already in progress.
778 if (pending_memory_dump_guid_
) {
779 DVLOG(1) << "Requested memory dump " << args
.dump_guid
780 << " while waiting for " << pending_memory_dump_guid_
;
781 if (!callback
.is_null())
782 callback
.Run(args
.dump_guid
, false /* success */);
786 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
787 // OnBrowserProcessMemoryDumpDone().
788 pending_memory_dump_ack_count_
= trace_message_filters_
.size() + 1;
789 pending_memory_dump_filters_
.clear();
790 failed_memory_dump_count_
= 0;
792 MemoryDumpManagerDelegate::CreateProcessDump(
793 args
, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone
,
794 base::Unretained(this)));
796 // If there are no child processes we are just done.
797 if (pending_memory_dump_ack_count_
== 1) {
798 if (!callback
.is_null())
799 callback
.Run(args
.dump_guid
, true /* success */);
803 pending_memory_dump_guid_
= args
.dump_guid
;
804 pending_memory_dump_callback_
= callback
;
805 pending_memory_dump_filters_
= trace_message_filters_
;
807 for (const scoped_refptr
<TraceMessageFilter
>& tmf
: trace_message_filters_
)
808 tmf
->SendProcessMemoryDumpRequest(args
);
811 bool TracingControllerImpl::IsCoordinatorProcess() const {
815 void TracingControllerImpl::OnProcessMemoryDumpResponse(
816 TraceMessageFilter
* trace_message_filter
,
819 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
820 BrowserThread::PostTask(
821 BrowserThread::UI
, FROM_HERE
,
822 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
823 base::Unretained(this),
824 make_scoped_refptr(trace_message_filter
), dump_guid
,
829 TraceMessageFilterSet::iterator it
=
830 pending_memory_dump_filters_
.find(trace_message_filter
);
832 if (pending_memory_dump_guid_
!= dump_guid
||
833 it
== pending_memory_dump_filters_
.end()) {
834 DLOG(WARNING
) << "Received unexpected memory dump response: " << dump_guid
;
838 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
839 --pending_memory_dump_ack_count_
;
840 pending_memory_dump_filters_
.erase(it
);
842 ++failed_memory_dump_count_
;
843 DLOG(WARNING
) << "Global memory dump failed because of NACK from child "
844 << trace_message_filter
->peer_pid();
846 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
849 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64 dump_guid
,
851 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
852 --pending_memory_dump_ack_count_
;
853 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
856 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
857 if (pending_memory_dump_ack_count_
> 0)
860 DCHECK_NE(0u, pending_memory_dump_guid_
);
861 const bool global_success
= failed_memory_dump_count_
== 0;
862 if (!pending_memory_dump_callback_
.is_null()) {
863 pending_memory_dump_callback_
.Run(pending_memory_dump_guid_
,
865 pending_memory_dump_callback_
.Reset();
867 pending_memory_dump_guid_
= 0;
870 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
871 if (is_monitoring_
== is_monitoring
)
874 is_monitoring_
= is_monitoring
;
875 #if !defined(OS_ANDROID)
876 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
877 it
!= tracing_uis_
.end(); it
++) {
878 (*it
)->OnMonitoringStateChanged(is_monitoring
);
883 } // namespace content