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()->Initialize(
63 this /* delegate */, true /* is_coordinator */);
65 // Deliberately leaked, like this class.
66 base::FileTracing::SetProvider(new FileTracingProviderImpl
);
69 TracingControllerImpl::~TracingControllerImpl() {
70 // This is a Leaky instance.
74 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
75 return g_controller
.Pointer();
78 bool TracingControllerImpl::GetCategories(
79 const GetCategoriesDoneCallback
& callback
) {
80 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
82 // Known categories come back from child processes with the EndTracingAck
83 // message. So to get known categories, just begin and end tracing immediately
84 // afterwards. This will ping all the child processes for categories.
85 pending_get_categories_done_callback_
= callback
;
86 if (!EnableRecording(TraceConfig("*", ""), EnableRecordingDoneCallback())) {
87 pending_get_categories_done_callback_
.Reset();
91 bool ok
= DisableRecording(NULL
);
96 void TracingControllerImpl::SetEnabledOnFileThread(
97 const TraceConfig
& trace_config
,
99 const base::Closure
& callback
) {
100 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
102 TraceLog::GetInstance()->SetEnabled(
103 trace_config
, static_cast<TraceLog::Mode
>(mode
));
104 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
107 void TracingControllerImpl::SetDisabledOnFileThread(
108 const base::Closure
& callback
) {
109 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
111 TraceLog::GetInstance()->SetDisabled();
112 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
115 bool TracingControllerImpl::EnableRecording(
116 const TraceConfig
& trace_config
,
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 if (trace_config
.IsSystraceEnabled()) {
130 DCHECK(!is_power_tracing_
);
131 is_power_tracing_
= PowerTracingAgent::GetInstance()->StartTracing();
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();
144 base::Closure on_enable_recording_done_callback
=
145 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
146 base::Unretained(this),
147 trace_config
, callback
);
148 if (!BrowserThread::PostTask(
149 BrowserThread::FILE, FROM_HERE
,
150 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
151 base::Unretained(this), trace_config
,
152 base::trace_event::TraceLog::RECORDING_MODE
,
153 on_enable_recording_done_callback
))) {
154 // BrowserThread::PostTask fails if the threads haven't been created yet,
155 // so it should be safe to just use TraceLog::SetEnabled directly.
156 base::trace_event::TraceLog::GetInstance()->SetEnabled(
157 trace_config
, base::trace_event::TraceLog::RECORDING_MODE
);
158 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
159 on_enable_recording_done_callback
);
165 void TracingControllerImpl::OnEnableRecordingDone(
166 const TraceConfig
& trace_config
,
167 const EnableRecordingDoneCallback
& callback
) {
168 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
170 // Notify all child processes.
171 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
172 it
!= trace_message_filters_
.end(); ++it
) {
173 it
->get()->SendBeginTracing(trace_config
);
176 if (!callback
.is_null())
180 bool TracingControllerImpl::DisableRecording(
181 const scoped_refptr
<TraceDataSink
>& trace_data_sink
) {
182 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
184 if (!can_disable_recording())
187 trace_data_sink_
= trace_data_sink
;
188 // Disable local trace early to avoid traces during end-tracing process from
189 // interfering with the process.
190 base::Closure on_disable_recording_done_callback
= base::Bind(
191 &TracingControllerImpl::OnDisableRecordingDone
, base::Unretained(this));
192 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
193 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
194 base::Unretained(this),
195 on_disable_recording_done_callback
));
199 void TracingControllerImpl::OnDisableRecordingDone() {
200 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
202 #if defined(OS_ANDROID)
203 if (pending_get_categories_done_callback_
.is_null())
204 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
207 // Count myself (local trace) in pending_disable_recording_ack_count_,
209 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
210 pending_disable_recording_filters_
= trace_message_filters_
;
212 #if defined(OS_CHROMEOS) || defined(OS_WIN)
213 if (is_system_tracing_
) {
214 // Disable system tracing.
215 is_system_tracing_
= false;
216 ++pending_disable_recording_ack_count_
;
218 #if defined(OS_CHROMEOS)
219 scoped_refptr
<base::TaskRunner
> task_runner
=
220 BrowserThread::GetBlockingPool();
221 chromeos::DBusThreadManager::Get()
222 ->GetDebugDaemonClient()
223 ->RequestStopSystemTracing(
225 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
226 base::Unretained(this)));
227 #elif defined(OS_WIN)
228 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
229 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
230 base::Unretained(this)));
233 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
235 if (is_power_tracing_
) {
236 is_power_tracing_
= false;
237 ++pending_disable_recording_ack_count_
;
238 PowerTracingAgent::GetInstance()->StopTracing(
239 base::Bind(&TracingControllerImpl::OnEndPowerTracingAcked
,
240 base::Unretained(this)));
243 // Handle special case of zero child processes by immediately flushing the
244 // trace log. Once the flush has completed the caller will be notified that
245 // tracing has ended.
246 if (pending_disable_recording_ack_count_
== 1) {
247 // Flush/cancel asynchronously now, because we don't have any children to
249 if (trace_data_sink_
) {
250 TraceLog::GetInstance()->Flush(
251 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
252 base::Unretained(this)),
255 TraceLog::GetInstance()->CancelTracing(
256 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
257 base::Unretained(this)));
261 // Notify all child processes.
262 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
263 it
!= trace_message_filters_
.end(); ++it
) {
264 if (trace_data_sink_
)
265 it
->get()->SendEndTracing();
267 it
->get()->SendCancelTracing();
271 bool TracingControllerImpl::EnableMonitoring(
272 const TraceConfig
& trace_config
,
273 const EnableMonitoringDoneCallback
& callback
) {
274 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
276 if (!can_enable_monitoring())
278 OnMonitoringStateChanged(true);
280 #if defined(OS_ANDROID)
281 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
284 base::Closure on_enable_monitoring_done_callback
=
285 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
286 base::Unretained(this),
287 trace_config
, callback
);
288 if (!BrowserThread::PostTask(
289 BrowserThread::FILE, FROM_HERE
,
290 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
291 base::Unretained(this), trace_config
,
292 base::trace_event::TraceLog::MONITORING_MODE
,
293 on_enable_monitoring_done_callback
))) {
294 // BrowserThread::PostTask fails if the threads haven't been created yet,
295 // so it should be safe to just use TraceLog::SetEnabled directly.
296 base::trace_event::TraceLog::GetInstance()->SetEnabled(
297 trace_config
, base::trace_event::TraceLog::MONITORING_MODE
);
298 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
299 on_enable_monitoring_done_callback
);
304 void TracingControllerImpl::OnEnableMonitoringDone(
305 const TraceConfig
& trace_config
,
306 const EnableMonitoringDoneCallback
& callback
) {
307 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
309 // Notify all child processes.
310 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
311 it
!= trace_message_filters_
.end(); ++it
) {
312 it
->get()->SendEnableMonitoring(trace_config
);
315 if (!callback
.is_null())
319 bool TracingControllerImpl::DisableMonitoring(
320 const DisableMonitoringDoneCallback
& callback
) {
321 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
323 if (!can_disable_monitoring())
326 base::Closure on_disable_monitoring_done_callback
=
327 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
328 base::Unretained(this), callback
);
329 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
330 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
331 base::Unretained(this),
332 on_disable_monitoring_done_callback
));
336 void TracingControllerImpl::OnDisableMonitoringDone(
337 const DisableMonitoringDoneCallback
& callback
) {
338 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
340 OnMonitoringStateChanged(false);
342 // Notify all child processes.
343 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
344 it
!= trace_message_filters_
.end(); ++it
) {
345 it
->get()->SendDisableMonitoring();
347 if (!callback
.is_null())
351 void TracingControllerImpl::GetMonitoringStatus(
353 TraceConfig
* out_trace_config
) {
354 *out_enabled
= is_monitoring_
;
355 *out_trace_config
= TraceLog::GetInstance()->GetCurrentTraceConfig();
358 bool TracingControllerImpl::CaptureMonitoringSnapshot(
359 const scoped_refptr
<TraceDataSink
>& monitoring_data_sink
) {
360 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
362 if (!can_disable_monitoring())
365 if (!monitoring_data_sink
.get())
368 monitoring_data_sink_
= monitoring_data_sink
;
370 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
372 pending_capture_monitoring_snapshot_ack_count_
=
373 trace_message_filters_
.size() + 1;
374 pending_capture_monitoring_filters_
= trace_message_filters_
;
376 // Handle special case of zero child processes by immediately flushing the
377 // trace log. Once the flush has completed the caller will be notified that
378 // the capture snapshot has ended.
379 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
380 // Flush asynchronously now, because we don't have any children to wait for.
381 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
382 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
383 base::Unretained(this)));
386 // Notify all child processes.
387 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
388 it
!= trace_message_filters_
.end(); ++it
) {
389 it
->get()->SendCaptureMonitoringSnapshot();
392 #if defined(OS_ANDROID)
393 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
399 bool TracingControllerImpl::GetTraceBufferUsage(
400 const GetTraceBufferUsageCallback
& callback
) {
401 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
403 if (!can_get_trace_buffer_usage() || callback
.is_null())
406 pending_trace_buffer_usage_callback_
= callback
;
408 // Count myself in pending_trace_log_status_ack_count_, acked below.
409 pending_trace_log_status_ack_count_
= trace_message_filters_
.size() + 1;
410 pending_trace_log_status_filters_
= trace_message_filters_
;
411 maximum_trace_buffer_usage_
= 0;
412 approximate_event_count_
= 0;
414 base::trace_event::TraceLogStatus status
=
415 TraceLog::GetInstance()->GetStatus();
416 // Call OnTraceLogStatusReply unconditionally for the browser process.
417 // This will result in immediate execution of the callback if there are no
419 BrowserThread::PostTask(
420 BrowserThread::UI
, FROM_HERE
,
421 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
422 base::Unretained(this), scoped_refptr
<TraceMessageFilter
>(),
425 // Notify all child processes.
426 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
427 it
!= trace_message_filters_
.end(); ++it
) {
428 it
->get()->SendGetTraceLogStatus();
433 bool TracingControllerImpl::SetWatchEvent(
434 const std::string
& category_name
,
435 const std::string
& event_name
,
436 const WatchEventCallback
& callback
) {
437 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
439 if (callback
.is_null())
442 watch_category_name_
= category_name
;
443 watch_event_name_
= event_name
;
444 watch_event_callback_
= callback
;
446 TraceLog::GetInstance()->SetWatchEvent(
447 category_name
, event_name
,
448 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
449 base::Unretained(this)));
451 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
452 it
!= trace_message_filters_
.end(); ++it
) {
453 it
->get()->SendSetWatchEvent(category_name
, event_name
);
458 bool TracingControllerImpl::CancelWatchEvent() {
459 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
461 if (!can_cancel_watch_event())
464 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
465 it
!= trace_message_filters_
.end(); ++it
) {
466 it
->get()->SendCancelWatchEvent();
469 watch_event_callback_
.Reset();
473 bool TracingControllerImpl::IsRecording() const {
474 return is_recording_
;
477 void TracingControllerImpl::AddTraceMessageFilter(
478 TraceMessageFilter
* trace_message_filter
) {
479 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
480 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
481 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
482 base::Unretained(this),
483 make_scoped_refptr(trace_message_filter
)));
487 trace_message_filters_
.insert(trace_message_filter
);
488 if (can_cancel_watch_event()) {
489 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
492 if (can_disable_recording()) {
493 trace_message_filter
->SendBeginTracing(
494 TraceLog::GetInstance()->GetCurrentTraceConfig());
496 if (can_disable_monitoring()) {
497 trace_message_filter
->SendEnableMonitoring(
498 TraceLog::GetInstance()->GetCurrentTraceConfig());
501 FOR_EACH_OBSERVER(TraceMessageFilterObserver
, trace_message_filter_observers_
,
502 OnTraceMessageFilterAdded(trace_message_filter
));
505 void TracingControllerImpl::RemoveTraceMessageFilter(
506 TraceMessageFilter
* trace_message_filter
) {
507 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
508 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
509 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
510 base::Unretained(this),
511 make_scoped_refptr(trace_message_filter
)));
515 // If a filter is removed while a response from that filter is pending then
516 // simulate the response. Otherwise the response count will be wrong and the
517 // completion callback will never be executed.
518 if (pending_disable_recording_ack_count_
> 0) {
519 TraceMessageFilterSet::const_iterator it
=
520 pending_disable_recording_filters_
.find(trace_message_filter
);
521 if (it
!= pending_disable_recording_filters_
.end()) {
522 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
523 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
524 base::Unretained(this),
525 make_scoped_refptr(trace_message_filter
),
526 std::vector
<std::string
>()));
529 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
530 TraceMessageFilterSet::const_iterator it
=
531 pending_capture_monitoring_filters_
.find(trace_message_filter
);
532 if (it
!= pending_capture_monitoring_filters_
.end()) {
533 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
534 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
535 base::Unretained(this),
536 make_scoped_refptr(trace_message_filter
)));
539 if (pending_trace_log_status_ack_count_
> 0) {
540 TraceMessageFilterSet::const_iterator it
=
541 pending_trace_log_status_filters_
.find(trace_message_filter
);
542 if (it
!= pending_trace_log_status_filters_
.end()) {
543 BrowserThread::PostTask(
544 BrowserThread::UI
, FROM_HERE
,
545 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
546 base::Unretained(this),
547 make_scoped_refptr(trace_message_filter
),
548 base::trace_event::TraceLogStatus()));
551 if (pending_memory_dump_ack_count_
> 0) {
552 TraceMessageFilterSet::const_iterator it
=
553 pending_memory_dump_filters_
.find(trace_message_filter
);
554 if (it
!= pending_memory_dump_filters_
.end()) {
555 BrowserThread::PostTask(
556 BrowserThread::UI
, FROM_HERE
,
557 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
558 base::Unretained(this),
559 make_scoped_refptr(trace_message_filter
),
560 pending_memory_dump_guid_
, false /* success */));
563 trace_message_filters_
.erase(trace_message_filter
);
566 void TracingControllerImpl::OnDisableRecordingAcked(
567 TraceMessageFilter
* trace_message_filter
,
568 const std::vector
<std::string
>& known_category_groups
) {
569 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
570 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
571 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
572 base::Unretained(this),
573 make_scoped_refptr(trace_message_filter
),
574 known_category_groups
));
578 // Merge known_category_groups with known_category_groups_
579 known_category_groups_
.insert(known_category_groups
.begin(),
580 known_category_groups
.end());
582 if (pending_disable_recording_ack_count_
== 0)
585 if (trace_message_filter
&&
586 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
587 // The response from the specified message filter has already been received.
591 if (--pending_disable_recording_ack_count_
== 1) {
592 // All acks from subprocesses have been received. Now flush the local trace.
593 // During or after this call, our OnLocalTraceDataCollected will be
594 // called with the last of the local trace data.
595 if (trace_data_sink_
) {
596 TraceLog::GetInstance()->Flush(
597 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
598 base::Unretained(this)),
601 TraceLog::GetInstance()->CancelTracing(
602 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
603 base::Unretained(this)));
608 if (pending_disable_recording_ack_count_
!= 0)
611 // All acks (including from the subprocesses and the local trace) have been
613 is_recording_
= false;
615 // Trigger callback if one is set.
616 if (!pending_get_categories_done_callback_
.is_null()) {
617 pending_get_categories_done_callback_
.Run(known_category_groups_
);
618 pending_get_categories_done_callback_
.Reset();
619 } else if (trace_data_sink_
.get()) {
620 trace_data_sink_
->Close();
621 trace_data_sink_
= NULL
;
625 void TracingControllerImpl::OnEndPowerTracingAcked(
626 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
627 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
629 if (trace_data_sink_
.get()) {
630 std::string json_string
= base::GetQuotedJSONString(events_str_ptr
->data());
631 trace_data_sink_
->SetPowerTrace(json_string
);
633 std::vector
<std::string
> category_groups
;
634 OnDisableRecordingAcked(NULL
, category_groups
);
637 #if defined(OS_CHROMEOS) || defined(OS_WIN)
638 void TracingControllerImpl::OnEndSystemTracingAcked(
639 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
640 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
642 if (trace_data_sink_
.get()) {
644 // The Windows kernel events are kept into a JSon format stored as string
645 // and must not be escaped.
646 std::string json_string
= events_str_ptr
->data();
648 std::string json_string
=
649 base::GetQuotedJSONString(events_str_ptr
->data());
651 trace_data_sink_
->SetSystemTrace(json_string
);
653 DCHECK(!is_system_tracing_
);
654 std::vector
<std::string
> category_groups
;
655 OnDisableRecordingAcked(NULL
, category_groups
);
659 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
660 TraceMessageFilter
* trace_message_filter
) {
661 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
662 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
663 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
664 base::Unretained(this),
665 make_scoped_refptr(trace_message_filter
)));
669 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
672 if (trace_message_filter
&&
673 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
674 // The response from the specified message filter has already been received.
678 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
679 // All acks from subprocesses have been received. Now flush the local trace.
680 // During or after this call, our OnLocalMonitoringTraceDataCollected
681 // will be called with the last of the local trace data.
682 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
683 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
684 base::Unretained(this)));
688 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
691 if (monitoring_data_sink_
.get()) {
692 monitoring_data_sink_
->Close();
693 monitoring_data_sink_
= NULL
;
697 void TracingControllerImpl::OnTraceDataCollected(
698 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
699 // OnTraceDataCollected may be called from any browser thread, either by the
700 // local event trace system or from child processes via TraceMessageFilter.
701 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
702 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
703 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
704 base::Unretained(this), events_str_ptr
));
708 if (trace_data_sink_
.get())
709 trace_data_sink_
->AddTraceChunk(events_str_ptr
->data());
712 void TracingControllerImpl::OnMonitoringTraceDataCollected(
713 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
714 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
715 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
716 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
717 base::Unretained(this), events_str_ptr
));
721 if (monitoring_data_sink_
.get())
722 monitoring_data_sink_
->AddTraceChunk(events_str_ptr
->data());
725 void TracingControllerImpl::OnLocalTraceDataCollected(
726 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
727 bool has_more_events
) {
728 if (events_str_ptr
->data().size())
729 OnTraceDataCollected(events_str_ptr
);
734 // Simulate an DisableRecordingAcked for the local trace.
735 std::vector
<std::string
> category_groups
;
736 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
737 OnDisableRecordingAcked(NULL
, category_groups
);
740 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
741 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
742 bool has_more_events
) {
743 if (events_str_ptr
->data().size())
744 OnMonitoringTraceDataCollected(events_str_ptr
);
749 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
750 OnCaptureMonitoringSnapshotAcked(NULL
);
753 void TracingControllerImpl::OnTraceLogStatusReply(
754 TraceMessageFilter
* trace_message_filter
,
755 const base::trace_event::TraceLogStatus
& status
) {
756 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
757 BrowserThread::PostTask(
758 BrowserThread::UI
, FROM_HERE
,
759 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
760 base::Unretained(this),
761 make_scoped_refptr(trace_message_filter
), status
));
765 if (pending_trace_log_status_ack_count_
== 0)
768 if (trace_message_filter
&&
769 !pending_trace_log_status_filters_
.erase(trace_message_filter
)) {
770 // The response from the specified message filter has already been received.
774 float percent_full
= static_cast<float>(
775 static_cast<double>(status
.event_count
) / status
.event_capacity
);
776 maximum_trace_buffer_usage_
=
777 std::max(maximum_trace_buffer_usage_
, percent_full
);
778 approximate_event_count_
+= status
.event_count
;
780 if (--pending_trace_log_status_ack_count_
== 0) {
781 // Trigger callback if one is set.
782 pending_trace_buffer_usage_callback_
.Run(maximum_trace_buffer_usage_
,
783 approximate_event_count_
);
784 pending_trace_buffer_usage_callback_
.Reset();
788 void TracingControllerImpl::OnWatchEventMatched() {
789 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
790 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
791 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
792 base::Unretained(this)));
796 if (!watch_event_callback_
.is_null())
797 watch_event_callback_
.Run();
800 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
801 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
802 tracing_uis_
.insert(tracing_ui
);
805 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
806 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
807 DCHECK(it
!= tracing_uis_
.end());
808 tracing_uis_
.erase(it
);
811 void TracingControllerImpl::RequestGlobalMemoryDump(
812 const base::trace_event::MemoryDumpRequestArgs
& args
,
813 const base::trace_event::MemoryDumpCallback
& callback
) {
814 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
815 BrowserThread::PostTask(
816 BrowserThread::UI
, FROM_HERE
,
817 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump
,
818 base::Unretained(this), args
, callback
));
821 // Abort if another dump is already in progress.
822 if (pending_memory_dump_guid_
) {
823 DVLOG(1) << "Requested memory dump " << args
.dump_guid
824 << " while waiting for " << pending_memory_dump_guid_
;
825 if (!callback
.is_null())
826 callback
.Run(args
.dump_guid
, false /* success */);
830 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
831 // OnBrowserProcessMemoryDumpDone().
832 pending_memory_dump_ack_count_
= trace_message_filters_
.size() + 1;
833 pending_memory_dump_filters_
.clear();
834 pending_memory_dump_guid_
= args
.dump_guid
;
835 pending_memory_dump_callback_
= callback
;
836 failed_memory_dump_count_
= 0;
838 MemoryDumpManagerDelegate::CreateProcessDump(
839 args
, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone
,
840 base::Unretained(this)));
842 // If there are no child processes we are just done.
843 if (pending_memory_dump_ack_count_
== 1)
846 pending_memory_dump_filters_
= trace_message_filters_
;
848 for (const scoped_refptr
<TraceMessageFilter
>& tmf
: trace_message_filters_
)
849 tmf
->SendProcessMemoryDumpRequest(args
);
852 uint64
TracingControllerImpl::GetTracingProcessId() const {
853 return ChildProcessHost::kBrowserTracingProcessId
;
856 void TracingControllerImpl::AddTraceMessageFilterObserver(
857 TraceMessageFilterObserver
* observer
) {
858 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
859 trace_message_filter_observers_
.AddObserver(observer
);
861 for (auto& filter
: trace_message_filters_
)
862 observer
->OnTraceMessageFilterAdded(filter
.get());
865 void TracingControllerImpl::RemoveTraceMessageFilterObserver(
866 TraceMessageFilterObserver
* observer
) {
867 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
868 trace_message_filter_observers_
.RemoveObserver(observer
);
870 for (auto& filter
: trace_message_filters_
)
871 observer
->OnTraceMessageFilterRemoved(filter
.get());
874 void TracingControllerImpl::OnProcessMemoryDumpResponse(
875 TraceMessageFilter
* trace_message_filter
,
878 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
879 BrowserThread::PostTask(
880 BrowserThread::UI
, FROM_HERE
,
881 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
882 base::Unretained(this),
883 make_scoped_refptr(trace_message_filter
), dump_guid
,
888 TraceMessageFilterSet::iterator it
=
889 pending_memory_dump_filters_
.find(trace_message_filter
);
891 if (pending_memory_dump_guid_
!= dump_guid
||
892 it
== pending_memory_dump_filters_
.end()) {
893 DLOG(WARNING
) << "Received unexpected memory dump response: " << dump_guid
;
897 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
898 --pending_memory_dump_ack_count_
;
899 pending_memory_dump_filters_
.erase(it
);
901 ++failed_memory_dump_count_
;
902 DLOG(WARNING
) << "Global memory dump failed because of NACK from child "
903 << trace_message_filter
->peer_pid();
905 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
908 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64 dump_guid
,
910 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
911 --pending_memory_dump_ack_count_
;
913 ++failed_memory_dump_count_
;
914 DLOG(WARNING
) << "Global memory dump aborted on the current process";
916 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
919 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
920 if (pending_memory_dump_ack_count_
> 0)
923 DCHECK_NE(0u, pending_memory_dump_guid_
);
924 const bool global_success
= failed_memory_dump_count_
== 0;
925 if (!pending_memory_dump_callback_
.is_null()) {
926 pending_memory_dump_callback_
.Run(pending_memory_dump_guid_
,
928 pending_memory_dump_callback_
.Reset();
930 pending_memory_dump_guid_
= 0;
933 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
934 if (is_monitoring_
== is_monitoring
)
937 is_monitoring_
= is_monitoring
;
938 #if !defined(OS_ANDROID)
939 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
940 it
!= tracing_uis_
.end(); it
++) {
941 (*it
)->OnMonitoringStateChanged(is_monitoring
);
946 } // namespace content