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/power_tracing_agent.h"
14 #include "content/browser/tracing/trace_message_filter.h"
15 #include "content/browser/tracing/tracing_ui.h"
16 #include "content/common/child_process_messages.h"
17 #include "content/public/browser/browser_message_filter.h"
18 #include "content/public/common/child_process_host.h"
19 #include "content/public/common/content_switches.h"
21 #if defined(OS_CHROMEOS)
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/debug_daemon_client.h"
27 #include "content/browser/tracing/etw_system_event_consumer_win.h"
30 using base::trace_event::TraceLog
;
31 using base::trace_event::TraceConfig
;
37 base::LazyInstance
<TracingControllerImpl
>::Leaky g_controller
=
38 LAZY_INSTANCE_INITIALIZER
;
42 TracingController
* TracingController::GetInstance() {
43 return TracingControllerImpl::GetInstance();
46 TracingControllerImpl::TracingControllerImpl()
47 : pending_disable_recording_ack_count_(0),
48 pending_capture_monitoring_snapshot_ack_count_(0),
49 pending_trace_log_status_ack_count_(0),
50 maximum_trace_buffer_usage_(0),
51 approximate_event_count_(0),
52 pending_memory_dump_ack_count_(0),
53 failed_memory_dump_count_(0),
54 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
55 // is specified in command line.
56 #if defined(OS_CHROMEOS) || defined(OS_WIN)
57 is_system_tracing_(false),
59 is_recording_(TraceLog::GetInstance()->IsEnabled()),
60 is_monitoring_(false),
61 is_power_tracing_(false) {
62 base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this);
64 // Deliberately leaked, like this class.
65 base::FileTracing::SetProvider(new FileTracingProviderImpl
);
68 TracingControllerImpl::~TracingControllerImpl() {
69 // This is a Leaky instance.
73 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
74 return g_controller
.Pointer();
77 bool TracingControllerImpl::GetCategories(
78 const GetCategoriesDoneCallback
& callback
) {
79 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
81 // Known categories come back from child processes with the EndTracingAck
82 // message. So to get known categories, just begin and end tracing immediately
83 // afterwards. This will ping all the child processes for categories.
84 pending_get_categories_done_callback_
= callback
;
85 if (!EnableRecording(TraceConfig("*", ""), EnableRecordingDoneCallback())) {
86 pending_get_categories_done_callback_
.Reset();
90 bool ok
= DisableRecording(NULL
);
95 void TracingControllerImpl::SetEnabledOnFileThread(
96 const TraceConfig
& trace_config
,
98 const base::Closure
& callback
) {
99 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
101 TraceLog::GetInstance()->SetEnabled(
102 trace_config
, static_cast<TraceLog::Mode
>(mode
));
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 TraceConfig
& trace_config
,
116 const EnableRecordingDoneCallback
& callback
) {
117 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
119 if (!can_enable_recording())
121 is_recording_
= true;
123 #if defined(OS_ANDROID)
124 if (pending_get_categories_done_callback_
.is_null())
125 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
128 if (trace_config
.IsSystraceEnabled()) {
129 #if defined(OS_CHROMEOS)
130 DCHECK(!is_system_tracing_
);
131 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
132 StartSystemTracing();
133 is_system_tracing_
= true;
134 #elif defined(OS_WIN)
135 DCHECK(!is_system_tracing_
);
137 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
141 base::Closure on_enable_recording_done_callback
=
142 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
143 base::Unretained(this),
144 trace_config
, callback
);
145 if (!BrowserThread::PostTask(
146 BrowserThread::FILE, FROM_HERE
,
147 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
148 base::Unretained(this), trace_config
,
149 base::trace_event::TraceLog::RECORDING_MODE
,
150 on_enable_recording_done_callback
))) {
151 // BrowserThread::PostTask fails if the threads haven't been created yet,
152 // so it should be safe to just use TraceLog::SetEnabled directly.
153 base::trace_event::TraceLog::GetInstance()->SetEnabled(
154 trace_config
, base::trace_event::TraceLog::RECORDING_MODE
);
155 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
156 on_enable_recording_done_callback
);
162 void TracingControllerImpl::OnEnableRecordingDone(
163 const TraceConfig
& trace_config
,
164 const EnableRecordingDoneCallback
& callback
) {
165 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
167 // Notify all child processes.
168 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
169 it
!= trace_message_filters_
.end(); ++it
) {
170 it
->get()->SendBeginTracing(trace_config
);
173 if (!callback
.is_null())
177 bool TracingControllerImpl::DisableRecording(
178 const scoped_refptr
<TraceDataSink
>& trace_data_sink
) {
179 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
181 if (!can_disable_recording())
184 trace_data_sink_
= trace_data_sink
;
185 // Disable local trace early to avoid traces during end-tracing process from
186 // interfering with the process.
187 base::Closure on_disable_recording_done_callback
= base::Bind(
188 &TracingControllerImpl::OnDisableRecordingDone
, base::Unretained(this));
189 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
190 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
191 base::Unretained(this),
192 on_disable_recording_done_callback
));
196 void TracingControllerImpl::OnDisableRecordingDone() {
197 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
199 #if defined(OS_ANDROID)
200 if (pending_get_categories_done_callback_
.is_null())
201 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
204 // Count myself (local trace) in pending_disable_recording_ack_count_,
206 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
207 pending_disable_recording_filters_
= trace_message_filters_
;
209 #if defined(OS_CHROMEOS) || defined(OS_WIN)
210 if (is_system_tracing_
) {
211 // Disable system tracing.
212 is_system_tracing_
= false;
213 ++pending_disable_recording_ack_count_
;
215 #if defined(OS_CHROMEOS)
216 scoped_refptr
<base::TaskRunner
> task_runner
=
217 BrowserThread::GetBlockingPool();
218 chromeos::DBusThreadManager::Get()
219 ->GetDebugDaemonClient()
220 ->RequestStopSystemTracing(
222 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
223 base::Unretained(this)));
224 #elif defined(OS_WIN)
225 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
226 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
227 base::Unretained(this)));
230 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
232 if (is_power_tracing_
) {
233 is_power_tracing_
= false;
234 ++pending_disable_recording_ack_count_
;
235 PowerTracingAgent::GetInstance()->StopTracing(
236 base::Bind(&TracingControllerImpl::OnEndPowerTracingAcked
,
237 base::Unretained(this)));
240 // Handle special case of zero child processes by immediately flushing the
241 // trace log. Once the flush has completed the caller will be notified that
242 // tracing has ended.
243 if (pending_disable_recording_ack_count_
== 1) {
244 // Flush/cancel asynchronously now, because we don't have any children to
246 if (trace_data_sink_
) {
247 TraceLog::GetInstance()->Flush(
248 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
249 base::Unretained(this)),
252 TraceLog::GetInstance()->CancelTracing(
253 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
254 base::Unretained(this)));
258 // Notify all child processes.
259 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
260 it
!= trace_message_filters_
.end(); ++it
) {
261 if (trace_data_sink_
)
262 it
->get()->SendEndTracing();
264 it
->get()->SendCancelTracing();
268 bool TracingControllerImpl::EnableMonitoring(
269 const TraceConfig
& trace_config
,
270 const EnableMonitoringDoneCallback
& callback
) {
271 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
273 if (!can_enable_monitoring())
275 OnMonitoringStateChanged(true);
277 #if defined(OS_ANDROID)
278 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
281 base::Closure on_enable_monitoring_done_callback
=
282 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
283 base::Unretained(this),
284 trace_config
, callback
);
285 if (!BrowserThread::PostTask(
286 BrowserThread::FILE, FROM_HERE
,
287 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
288 base::Unretained(this), trace_config
,
289 base::trace_event::TraceLog::MONITORING_MODE
,
290 on_enable_monitoring_done_callback
))) {
291 // BrowserThread::PostTask fails if the threads haven't been created yet,
292 // so it should be safe to just use TraceLog::SetEnabled directly.
293 base::trace_event::TraceLog::GetInstance()->SetEnabled(
294 trace_config
, base::trace_event::TraceLog::MONITORING_MODE
);
295 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
296 on_enable_monitoring_done_callback
);
301 void TracingControllerImpl::OnEnableMonitoringDone(
302 const TraceConfig
& trace_config
,
303 const EnableMonitoringDoneCallback
& callback
) {
304 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
306 // Notify all child processes.
307 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
308 it
!= trace_message_filters_
.end(); ++it
) {
309 it
->get()->SendEnableMonitoring(trace_config
);
312 if (!callback
.is_null())
316 bool TracingControllerImpl::DisableMonitoring(
317 const DisableMonitoringDoneCallback
& callback
) {
318 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
320 if (!can_disable_monitoring())
323 base::Closure on_disable_monitoring_done_callback
=
324 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
325 base::Unretained(this), callback
);
326 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
327 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
328 base::Unretained(this),
329 on_disable_monitoring_done_callback
));
333 void TracingControllerImpl::OnDisableMonitoringDone(
334 const DisableMonitoringDoneCallback
& callback
) {
335 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
337 OnMonitoringStateChanged(false);
339 // Notify all child processes.
340 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
341 it
!= trace_message_filters_
.end(); ++it
) {
342 it
->get()->SendDisableMonitoring();
344 if (!callback
.is_null())
348 void TracingControllerImpl::GetMonitoringStatus(
350 TraceConfig
* out_trace_config
) {
351 *out_enabled
= is_monitoring_
;
352 *out_trace_config
= TraceLog::GetInstance()->GetCurrentTraceConfig();
355 bool TracingControllerImpl::CaptureMonitoringSnapshot(
356 const scoped_refptr
<TraceDataSink
>& monitoring_data_sink
) {
357 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
359 if (!can_disable_monitoring())
362 if (!monitoring_data_sink
.get())
365 monitoring_data_sink_
= monitoring_data_sink
;
367 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
369 pending_capture_monitoring_snapshot_ack_count_
=
370 trace_message_filters_
.size() + 1;
371 pending_capture_monitoring_filters_
= trace_message_filters_
;
373 // Handle special case of zero child processes by immediately flushing the
374 // trace log. Once the flush has completed the caller will be notified that
375 // the capture snapshot has ended.
376 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
377 // Flush asynchronously now, because we don't have any children to wait for.
378 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
379 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
380 base::Unretained(this)));
383 // Notify all child processes.
384 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
385 it
!= trace_message_filters_
.end(); ++it
) {
386 it
->get()->SendCaptureMonitoringSnapshot();
389 #if defined(OS_ANDROID)
390 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
396 bool TracingControllerImpl::GetTraceBufferUsage(
397 const GetTraceBufferUsageCallback
& callback
) {
398 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
400 if (!can_get_trace_buffer_usage() || callback
.is_null())
403 pending_trace_buffer_usage_callback_
= callback
;
405 // Count myself in pending_trace_log_status_ack_count_, acked below.
406 pending_trace_log_status_ack_count_
= trace_message_filters_
.size() + 1;
407 pending_trace_log_status_filters_
= trace_message_filters_
;
408 maximum_trace_buffer_usage_
= 0;
409 approximate_event_count_
= 0;
411 base::trace_event::TraceLogStatus status
=
412 TraceLog::GetInstance()->GetStatus();
413 // Call OnTraceLogStatusReply unconditionally for the browser process.
414 // This will result in immediate execution of the callback if there are no
416 BrowserThread::PostTask(
417 BrowserThread::UI
, FROM_HERE
,
418 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
419 base::Unretained(this), scoped_refptr
<TraceMessageFilter
>(),
422 // Notify all child processes.
423 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
424 it
!= trace_message_filters_
.end(); ++it
) {
425 it
->get()->SendGetTraceLogStatus();
430 bool TracingControllerImpl::SetWatchEvent(
431 const std::string
& category_name
,
432 const std::string
& event_name
,
433 const WatchEventCallback
& callback
) {
434 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
436 if (callback
.is_null())
439 watch_category_name_
= category_name
;
440 watch_event_name_
= event_name
;
441 watch_event_callback_
= callback
;
443 TraceLog::GetInstance()->SetWatchEvent(
444 category_name
, event_name
,
445 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
446 base::Unretained(this)));
448 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
449 it
!= trace_message_filters_
.end(); ++it
) {
450 it
->get()->SendSetWatchEvent(category_name
, event_name
);
455 bool TracingControllerImpl::CancelWatchEvent() {
456 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
458 if (!can_cancel_watch_event())
461 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
462 it
!= trace_message_filters_
.end(); ++it
) {
463 it
->get()->SendCancelWatchEvent();
466 watch_event_callback_
.Reset();
470 bool TracingControllerImpl::IsRecording() const {
471 return is_recording_
;
474 void TracingControllerImpl::AddTraceMessageFilter(
475 TraceMessageFilter
* trace_message_filter
) {
476 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
477 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
478 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
479 base::Unretained(this),
480 make_scoped_refptr(trace_message_filter
)));
484 trace_message_filters_
.insert(trace_message_filter
);
485 if (can_cancel_watch_event()) {
486 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
489 if (can_disable_recording()) {
490 trace_message_filter
->SendBeginTracing(
491 TraceLog::GetInstance()->GetCurrentTraceConfig());
493 if (can_disable_monitoring()) {
494 trace_message_filter
->SendEnableMonitoring(
495 TraceLog::GetInstance()->GetCurrentTraceConfig());
498 FOR_EACH_OBSERVER(TraceMessageFilterObserver
, trace_message_filter_observers_
,
499 OnTraceMessageFilterAdded(trace_message_filter
));
502 void TracingControllerImpl::RemoveTraceMessageFilter(
503 TraceMessageFilter
* trace_message_filter
) {
504 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
505 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
506 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
507 base::Unretained(this),
508 make_scoped_refptr(trace_message_filter
)));
512 // If a filter is removed while a response from that filter is pending then
513 // simulate the response. Otherwise the response count will be wrong and the
514 // completion callback will never be executed.
515 if (pending_disable_recording_ack_count_
> 0) {
516 TraceMessageFilterSet::const_iterator it
=
517 pending_disable_recording_filters_
.find(trace_message_filter
);
518 if (it
!= pending_disable_recording_filters_
.end()) {
519 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
520 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
521 base::Unretained(this),
522 make_scoped_refptr(trace_message_filter
),
523 std::vector
<std::string
>()));
526 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
527 TraceMessageFilterSet::const_iterator it
=
528 pending_capture_monitoring_filters_
.find(trace_message_filter
);
529 if (it
!= pending_capture_monitoring_filters_
.end()) {
530 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
531 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
532 base::Unretained(this),
533 make_scoped_refptr(trace_message_filter
)));
536 if (pending_trace_log_status_ack_count_
> 0) {
537 TraceMessageFilterSet::const_iterator it
=
538 pending_trace_log_status_filters_
.find(trace_message_filter
);
539 if (it
!= pending_trace_log_status_filters_
.end()) {
540 BrowserThread::PostTask(
541 BrowserThread::UI
, FROM_HERE
,
542 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
543 base::Unretained(this),
544 make_scoped_refptr(trace_message_filter
),
545 base::trace_event::TraceLogStatus()));
548 if (pending_memory_dump_ack_count_
> 0) {
549 TraceMessageFilterSet::const_iterator it
=
550 pending_memory_dump_filters_
.find(trace_message_filter
);
551 if (it
!= pending_memory_dump_filters_
.end()) {
552 BrowserThread::PostTask(
553 BrowserThread::UI
, FROM_HERE
,
554 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
555 base::Unretained(this),
556 make_scoped_refptr(trace_message_filter
),
557 pending_memory_dump_guid_
, false /* success */));
560 trace_message_filters_
.erase(trace_message_filter
);
563 void TracingControllerImpl::OnDisableRecordingAcked(
564 TraceMessageFilter
* trace_message_filter
,
565 const std::vector
<std::string
>& known_category_groups
) {
566 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
567 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
568 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
569 base::Unretained(this),
570 make_scoped_refptr(trace_message_filter
),
571 known_category_groups
));
575 // Merge known_category_groups with known_category_groups_
576 known_category_groups_
.insert(known_category_groups
.begin(),
577 known_category_groups
.end());
579 if (pending_disable_recording_ack_count_
== 0)
582 if (trace_message_filter
&&
583 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
584 // The response from the specified message filter has already been received.
588 if (--pending_disable_recording_ack_count_
== 1) {
589 // All acks from subprocesses have been received. Now flush the local trace.
590 // During or after this call, our OnLocalTraceDataCollected will be
591 // called with the last of the local trace data.
592 if (trace_data_sink_
) {
593 TraceLog::GetInstance()->Flush(
594 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
595 base::Unretained(this)),
598 TraceLog::GetInstance()->CancelTracing(
599 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
600 base::Unretained(this)));
605 if (pending_disable_recording_ack_count_
!= 0)
608 // All acks (including from the subprocesses and the local trace) have been
610 is_recording_
= false;
612 // Trigger callback if one is set.
613 if (!pending_get_categories_done_callback_
.is_null()) {
614 pending_get_categories_done_callback_
.Run(known_category_groups_
);
615 pending_get_categories_done_callback_
.Reset();
616 } else if (trace_data_sink_
.get()) {
617 trace_data_sink_
->Close();
618 trace_data_sink_
= NULL
;
622 void TracingControllerImpl::OnEndPowerTracingAcked(
623 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
624 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
626 if (trace_data_sink_
.get()) {
627 std::string json_string
= base::GetQuotedJSONString(events_str_ptr
->data());
628 trace_data_sink_
->SetPowerTrace(json_string
);
630 std::vector
<std::string
> category_groups
;
631 OnDisableRecordingAcked(NULL
, category_groups
);
634 #if defined(OS_CHROMEOS) || defined(OS_WIN)
635 void TracingControllerImpl::OnEndSystemTracingAcked(
636 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
637 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
639 if (trace_data_sink_
.get()) {
641 // The Windows kernel events are kept into a JSon format stored as string
642 // and must not be escaped.
643 std::string json_string
= events_str_ptr
->data();
645 std::string json_string
=
646 base::GetQuotedJSONString(events_str_ptr
->data());
648 trace_data_sink_
->SetSystemTrace(json_string
);
650 DCHECK(!is_system_tracing_
);
651 std::vector
<std::string
> category_groups
;
652 OnDisableRecordingAcked(NULL
, category_groups
);
656 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
657 TraceMessageFilter
* trace_message_filter
) {
658 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
659 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
660 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
661 base::Unretained(this),
662 make_scoped_refptr(trace_message_filter
)));
666 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
669 if (trace_message_filter
&&
670 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
671 // The response from the specified message filter has already been received.
675 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
676 // All acks from subprocesses have been received. Now flush the local trace.
677 // During or after this call, our OnLocalMonitoringTraceDataCollected
678 // will be called with the last of the local trace data.
679 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
680 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
681 base::Unretained(this)));
685 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
688 if (monitoring_data_sink_
.get()) {
689 monitoring_data_sink_
->Close();
690 monitoring_data_sink_
= NULL
;
694 void TracingControllerImpl::OnTraceDataCollected(
695 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
696 // OnTraceDataCollected may be called from any browser thread, either by the
697 // local event trace system or from child processes via TraceMessageFilter.
698 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
699 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
700 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
701 base::Unretained(this), events_str_ptr
));
705 if (trace_data_sink_
.get())
706 trace_data_sink_
->AddTraceChunk(events_str_ptr
->data());
709 void TracingControllerImpl::OnMonitoringTraceDataCollected(
710 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
711 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
712 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
713 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
714 base::Unretained(this), events_str_ptr
));
718 if (monitoring_data_sink_
.get())
719 monitoring_data_sink_
->AddTraceChunk(events_str_ptr
->data());
722 void TracingControllerImpl::OnLocalTraceDataCollected(
723 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
724 bool has_more_events
) {
725 if (events_str_ptr
->data().size())
726 OnTraceDataCollected(events_str_ptr
);
731 // Simulate an DisableRecordingAcked for the local trace.
732 std::vector
<std::string
> category_groups
;
733 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
734 OnDisableRecordingAcked(NULL
, category_groups
);
737 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
738 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
739 bool has_more_events
) {
740 if (events_str_ptr
->data().size())
741 OnMonitoringTraceDataCollected(events_str_ptr
);
746 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
747 OnCaptureMonitoringSnapshotAcked(NULL
);
750 void TracingControllerImpl::OnTraceLogStatusReply(
751 TraceMessageFilter
* trace_message_filter
,
752 const base::trace_event::TraceLogStatus
& status
) {
753 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
754 BrowserThread::PostTask(
755 BrowserThread::UI
, FROM_HERE
,
756 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
757 base::Unretained(this),
758 make_scoped_refptr(trace_message_filter
), status
));
762 if (pending_trace_log_status_ack_count_
== 0)
765 if (trace_message_filter
&&
766 !pending_trace_log_status_filters_
.erase(trace_message_filter
)) {
767 // The response from the specified message filter has already been received.
771 float percent_full
= static_cast<float>(
772 static_cast<double>(status
.event_count
) / status
.event_capacity
);
773 maximum_trace_buffer_usage_
=
774 std::max(maximum_trace_buffer_usage_
, percent_full
);
775 approximate_event_count_
+= status
.event_count
;
777 if (--pending_trace_log_status_ack_count_
== 0) {
778 // Trigger callback if one is set.
779 pending_trace_buffer_usage_callback_
.Run(maximum_trace_buffer_usage_
,
780 approximate_event_count_
);
781 pending_trace_buffer_usage_callback_
.Reset();
785 void TracingControllerImpl::OnWatchEventMatched() {
786 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
787 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
788 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
789 base::Unretained(this)));
793 if (!watch_event_callback_
.is_null())
794 watch_event_callback_
.Run();
797 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
798 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
799 tracing_uis_
.insert(tracing_ui
);
802 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
803 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
804 DCHECK(it
!= tracing_uis_
.end());
805 tracing_uis_
.erase(it
);
808 void TracingControllerImpl::RequestGlobalMemoryDump(
809 const base::trace_event::MemoryDumpRequestArgs
& args
,
810 const base::trace_event::MemoryDumpCallback
& callback
) {
811 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
812 BrowserThread::PostTask(
813 BrowserThread::UI
, FROM_HERE
,
814 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump
,
815 base::Unretained(this), args
, callback
));
818 // Abort if another dump is already in progress.
819 if (pending_memory_dump_guid_
) {
820 DVLOG(1) << "Requested memory dump " << args
.dump_guid
821 << " while waiting for " << pending_memory_dump_guid_
;
822 if (!callback
.is_null())
823 callback
.Run(args
.dump_guid
, false /* success */);
827 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
828 // OnBrowserProcessMemoryDumpDone().
829 pending_memory_dump_ack_count_
= trace_message_filters_
.size() + 1;
830 pending_memory_dump_filters_
.clear();
831 pending_memory_dump_guid_
= args
.dump_guid
;
832 pending_memory_dump_callback_
= callback
;
833 failed_memory_dump_count_
= 0;
835 MemoryDumpManagerDelegate::CreateProcessDump(
836 args
, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone
,
837 base::Unretained(this)));
839 // If there are no child processes we are just done.
840 if (pending_memory_dump_ack_count_
== 1)
843 pending_memory_dump_filters_
= trace_message_filters_
;
845 for (const scoped_refptr
<TraceMessageFilter
>& tmf
: trace_message_filters_
)
846 tmf
->SendProcessMemoryDumpRequest(args
);
849 bool TracingControllerImpl::IsCoordinatorProcess() const {
853 uint64
TracingControllerImpl::GetTracingProcessId() const {
854 return ChildProcessHost::kBrowserTracingProcessId
;
857 void TracingControllerImpl::AddTraceMessageFilterObserver(
858 TraceMessageFilterObserver
* observer
) {
859 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
860 trace_message_filter_observers_
.AddObserver(observer
);
862 for (auto& filter
: trace_message_filters_
)
863 observer
->OnTraceMessageFilterAdded(filter
.get());
866 void TracingControllerImpl::RemoveTraceMessageFilterObserver(
867 TraceMessageFilterObserver
* observer
) {
868 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
869 trace_message_filter_observers_
.RemoveObserver(observer
);
871 for (auto& filter
: trace_message_filters_
)
872 observer
->OnTraceMessageFilterRemoved(filter
.get());
875 void TracingControllerImpl::OnProcessMemoryDumpResponse(
876 TraceMessageFilter
* trace_message_filter
,
879 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
880 BrowserThread::PostTask(
881 BrowserThread::UI
, FROM_HERE
,
882 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
883 base::Unretained(this),
884 make_scoped_refptr(trace_message_filter
), dump_guid
,
889 TraceMessageFilterSet::iterator it
=
890 pending_memory_dump_filters_
.find(trace_message_filter
);
892 if (pending_memory_dump_guid_
!= dump_guid
||
893 it
== pending_memory_dump_filters_
.end()) {
894 DLOG(WARNING
) << "Received unexpected memory dump response: " << dump_guid
;
898 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
899 --pending_memory_dump_ack_count_
;
900 pending_memory_dump_filters_
.erase(it
);
902 ++failed_memory_dump_count_
;
903 DLOG(WARNING
) << "Global memory dump failed because of NACK from child "
904 << trace_message_filter
->peer_pid();
906 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
909 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64 dump_guid
,
911 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
912 --pending_memory_dump_ack_count_
;
914 ++failed_memory_dump_count_
;
915 DLOG(WARNING
) << "Global memory dump aborted on the current process";
917 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
920 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
921 if (pending_memory_dump_ack_count_
> 0)
924 DCHECK_NE(0u, pending_memory_dump_guid_
);
925 const bool global_success
= failed_memory_dump_count_
== 0;
926 if (!pending_memory_dump_callback_
.is_null()) {
927 pending_memory_dump_callback_
.Run(pending_memory_dump_guid_
,
929 pending_memory_dump_callback_
.Reset();
931 pending_memory_dump_guid_
= 0;
934 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
935 if (is_monitoring_
== is_monitoring
)
938 is_monitoring_
= is_monitoring
;
939 #if !defined(OS_ANDROID)
940 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
941 it
!= tracing_uis_
.end(); it
++) {
942 (*it
)->OnMonitoringStateChanged(is_monitoring
);
947 } // namespace content