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
;
40 TracingController
* TracingController::GetInstance() {
41 return TracingControllerImpl::GetInstance();
44 TracingControllerImpl::TracingControllerImpl()
45 : pending_disable_recording_ack_count_(0),
46 pending_capture_monitoring_snapshot_ack_count_(0),
47 pending_trace_log_status_ack_count_(0),
48 maximum_trace_buffer_usage_(0),
49 approximate_event_count_(0),
50 pending_memory_dump_ack_count_(0),
51 failed_memory_dump_count_(0),
52 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
53 // is specified in command line.
54 #if defined(OS_CHROMEOS) || defined(OS_WIN)
55 is_system_tracing_(false),
57 is_recording_(TraceLog::GetInstance()->IsEnabled()),
58 is_monitoring_(false) {
59 base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this);
62 TracingControllerImpl::~TracingControllerImpl() {
63 // This is a Leaky instance.
67 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
68 return g_controller
.Pointer();
71 bool TracingControllerImpl::GetCategories(
72 const GetCategoriesDoneCallback
& callback
) {
73 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
75 // Known categories come back from child processes with the EndTracingAck
76 // message. So to get known categories, just begin and end tracing immediately
77 // afterwards. This will ping all the child processes for categories.
78 pending_get_categories_done_callback_
= callback
;
80 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
81 pending_get_categories_done_callback_
.Reset();
85 bool ok
= DisableRecording(NULL
);
90 void TracingControllerImpl::SetEnabledOnFileThread(
91 const CategoryFilter
& category_filter
,
93 const TraceOptions
& trace_options
,
94 const base::Closure
& callback
) {
95 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
97 TraceLog::GetInstance()->SetEnabled(
98 category_filter
, static_cast<TraceLog::Mode
>(mode
), trace_options
);
99 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
102 void TracingControllerImpl::SetDisabledOnFileThread(
103 const base::Closure
& callback
) {
104 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
106 TraceLog::GetInstance()->SetDisabled();
107 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
110 bool TracingControllerImpl::EnableRecording(
111 const CategoryFilter
& category_filter
,
112 const TraceOptions
& trace_options
,
113 const EnableRecordingDoneCallback
& callback
) {
114 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
116 if (!can_enable_recording())
118 is_recording_
= true;
120 #if defined(OS_ANDROID)
121 if (pending_get_categories_done_callback_
.is_null())
122 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
125 trace_options_
= trace_options
;
127 if (trace_options
.enable_systrace
) {
128 #if defined(OS_CHROMEOS)
129 DCHECK(!is_system_tracing_
);
130 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
131 StartSystemTracing();
132 is_system_tracing_
= true;
133 #elif defined(OS_WIN)
134 DCHECK(!is_system_tracing_
);
136 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
141 base::Closure on_enable_recording_done_callback
=
142 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
143 base::Unretained(this),
144 category_filter
, trace_options
, callback
);
145 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
146 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
147 base::Unretained(this),
149 base::trace_event::TraceLog::RECORDING_MODE
,
151 on_enable_recording_done_callback
));
155 void TracingControllerImpl::OnEnableRecordingDone(
156 const CategoryFilter
& category_filter
,
157 const TraceOptions
& trace_options
,
158 const EnableRecordingDoneCallback
& callback
) {
159 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
161 // Notify all child processes.
162 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
163 it
!= trace_message_filters_
.end(); ++it
) {
164 it
->get()->SendBeginTracing(category_filter
, trace_options
);
167 if (!callback
.is_null())
171 bool TracingControllerImpl::DisableRecording(
172 const scoped_refptr
<TraceDataSink
>& trace_data_sink
) {
173 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
175 if (!can_disable_recording())
178 trace_data_sink_
= trace_data_sink
;
179 trace_options_
= TraceOptions();
180 // Disable local trace early to avoid traces during end-tracing process from
181 // interfering with the process.
182 base::Closure on_disable_recording_done_callback
= base::Bind(
183 &TracingControllerImpl::OnDisableRecordingDone
, base::Unretained(this));
184 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
185 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
186 base::Unretained(this),
187 on_disable_recording_done_callback
));
191 void TracingControllerImpl::OnDisableRecordingDone() {
192 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
194 #if defined(OS_ANDROID)
195 if (pending_get_categories_done_callback_
.is_null())
196 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
199 // Count myself (local trace) in pending_disable_recording_ack_count_,
201 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
202 pending_disable_recording_filters_
= trace_message_filters_
;
204 #if defined(OS_CHROMEOS) || defined(OS_WIN)
205 if (is_system_tracing_
) {
206 // Disable system tracing.
207 is_system_tracing_
= false;
208 ++pending_disable_recording_ack_count_
;
210 #if defined(OS_CHROMEOS)
211 scoped_refptr
<base::TaskRunner
> task_runner
=
212 BrowserThread::GetBlockingPool();
213 chromeos::DBusThreadManager::Get()
214 ->GetDebugDaemonClient()
215 ->RequestStopSystemTracing(
217 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
218 base::Unretained(this)));
219 #elif defined(OS_WIN)
220 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
221 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
222 base::Unretained(this)));
225 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
227 // Handle special case of zero child processes by immediately flushing the
228 // trace log. Once the flush has completed the caller will be notified that
229 // tracing has ended.
230 if (pending_disable_recording_ack_count_
== 1) {
231 // Flush asynchronously now, because we don't have any children to wait for.
232 TraceLog::GetInstance()->Flush(
233 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
234 base::Unretained(this)),
238 // Notify all child processes.
239 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
240 it
!= trace_message_filters_
.end(); ++it
) {
241 it
->get()->SendEndTracing();
245 bool TracingControllerImpl::EnableMonitoring(
246 const CategoryFilter
& category_filter
,
247 const TraceOptions
& trace_options
,
248 const EnableMonitoringDoneCallback
& callback
) {
249 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
251 if (!can_enable_monitoring())
253 OnMonitoringStateChanged(true);
255 #if defined(OS_ANDROID)
256 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
259 trace_options_
= trace_options
;
261 base::Closure on_enable_monitoring_done_callback
=
262 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
263 base::Unretained(this),
264 category_filter
, trace_options
, callback
);
265 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
266 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
267 base::Unretained(this),
269 base::trace_event::TraceLog::MONITORING_MODE
,
271 on_enable_monitoring_done_callback
));
275 void TracingControllerImpl::OnEnableMonitoringDone(
276 const CategoryFilter
& category_filter
,
277 const TraceOptions
& trace_options
,
278 const EnableMonitoringDoneCallback
& callback
) {
279 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
281 // Notify all child processes.
282 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
283 it
!= trace_message_filters_
.end(); ++it
) {
284 it
->get()->SendEnableMonitoring(category_filter
, trace_options
);
287 if (!callback
.is_null())
291 bool TracingControllerImpl::DisableMonitoring(
292 const DisableMonitoringDoneCallback
& callback
) {
293 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
295 if (!can_disable_monitoring())
298 trace_options_
= TraceOptions();
299 base::Closure on_disable_monitoring_done_callback
=
300 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
301 base::Unretained(this), callback
);
302 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
303 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
304 base::Unretained(this),
305 on_disable_monitoring_done_callback
));
309 void TracingControllerImpl::OnDisableMonitoringDone(
310 const DisableMonitoringDoneCallback
& callback
) {
311 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
313 OnMonitoringStateChanged(false);
315 // Notify all child processes.
316 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
317 it
!= trace_message_filters_
.end(); ++it
) {
318 it
->get()->SendDisableMonitoring();
320 if (!callback
.is_null())
324 void TracingControllerImpl::GetMonitoringStatus(
326 CategoryFilter
* out_category_filter
,
327 TraceOptions
* out_trace_options
) {
328 *out_enabled
= is_monitoring_
;
329 *out_category_filter
= TraceLog::GetInstance()->GetCurrentCategoryFilter();
330 *out_trace_options
= trace_options_
;
333 bool TracingControllerImpl::CaptureMonitoringSnapshot(
334 const scoped_refptr
<TraceDataSink
>& monitoring_data_sink
) {
335 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
337 if (!can_disable_monitoring())
340 if (!monitoring_data_sink
.get())
343 monitoring_data_sink_
= monitoring_data_sink
;
345 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
347 pending_capture_monitoring_snapshot_ack_count_
=
348 trace_message_filters_
.size() + 1;
349 pending_capture_monitoring_filters_
= trace_message_filters_
;
351 // Handle special case of zero child processes by immediately flushing the
352 // trace log. Once the flush has completed the caller will be notified that
353 // the capture snapshot has ended.
354 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
355 // Flush asynchronously now, because we don't have any children to wait for.
356 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
357 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
358 base::Unretained(this)));
361 // Notify all child processes.
362 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
363 it
!= trace_message_filters_
.end(); ++it
) {
364 it
->get()->SendCaptureMonitoringSnapshot();
367 #if defined(OS_ANDROID)
368 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
374 bool TracingControllerImpl::GetTraceBufferUsage(
375 const GetTraceBufferUsageCallback
& callback
) {
376 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
378 if (!can_get_trace_buffer_usage() || callback
.is_null())
381 pending_trace_buffer_usage_callback_
= callback
;
383 // Count myself in pending_trace_log_status_ack_count_, acked below.
384 pending_trace_log_status_ack_count_
= trace_message_filters_
.size() + 1;
385 pending_trace_log_status_filters_
= trace_message_filters_
;
386 maximum_trace_buffer_usage_
= 0;
387 approximate_event_count_
= 0;
389 base::trace_event::TraceLogStatus status
=
390 TraceLog::GetInstance()->GetStatus();
391 // Call OnTraceLogStatusReply unconditionally for the browser process.
392 // This will result in immediate execution of the callback if there are no
394 BrowserThread::PostTask(
395 BrowserThread::UI
, FROM_HERE
,
396 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
397 base::Unretained(this), scoped_refptr
<TraceMessageFilter
>(),
400 // Notify all child processes.
401 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
402 it
!= trace_message_filters_
.end(); ++it
) {
403 it
->get()->SendGetTraceLogStatus();
408 bool TracingControllerImpl::SetWatchEvent(
409 const std::string
& category_name
,
410 const std::string
& event_name
,
411 const WatchEventCallback
& callback
) {
412 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
414 if (callback
.is_null())
417 watch_category_name_
= category_name
;
418 watch_event_name_
= event_name
;
419 watch_event_callback_
= callback
;
421 TraceLog::GetInstance()->SetWatchEvent(
422 category_name
, event_name
,
423 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
424 base::Unretained(this)));
426 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
427 it
!= trace_message_filters_
.end(); ++it
) {
428 it
->get()->SendSetWatchEvent(category_name
, event_name
);
433 bool TracingControllerImpl::CancelWatchEvent() {
434 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
436 if (!can_cancel_watch_event())
439 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
440 it
!= trace_message_filters_
.end(); ++it
) {
441 it
->get()->SendCancelWatchEvent();
444 watch_event_callback_
.Reset();
448 void TracingControllerImpl::AddTraceMessageFilter(
449 TraceMessageFilter
* trace_message_filter
) {
450 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
451 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
452 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
453 base::Unretained(this),
454 make_scoped_refptr(trace_message_filter
)));
458 trace_message_filters_
.insert(trace_message_filter
);
459 if (can_cancel_watch_event()) {
460 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
463 if (can_disable_recording()) {
464 trace_message_filter
->SendBeginTracing(
465 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
466 TraceLog::GetInstance()->GetCurrentTraceOptions());
468 if (can_disable_monitoring()) {
469 trace_message_filter
->SendEnableMonitoring(
470 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
471 TraceLog::GetInstance()->GetCurrentTraceOptions());
475 void TracingControllerImpl::RemoveTraceMessageFilter(
476 TraceMessageFilter
* trace_message_filter
) {
477 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
478 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
479 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
480 base::Unretained(this),
481 make_scoped_refptr(trace_message_filter
)));
485 // If a filter is removed while a response from that filter is pending then
486 // simulate the response. Otherwise the response count will be wrong and the
487 // completion callback will never be executed.
488 if (pending_disable_recording_ack_count_
> 0) {
489 TraceMessageFilterSet::const_iterator it
=
490 pending_disable_recording_filters_
.find(trace_message_filter
);
491 if (it
!= pending_disable_recording_filters_
.end()) {
492 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
493 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
494 base::Unretained(this),
495 make_scoped_refptr(trace_message_filter
),
496 std::vector
<std::string
>()));
499 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
500 TraceMessageFilterSet::const_iterator it
=
501 pending_capture_monitoring_filters_
.find(trace_message_filter
);
502 if (it
!= pending_capture_monitoring_filters_
.end()) {
503 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
504 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
505 base::Unretained(this),
506 make_scoped_refptr(trace_message_filter
)));
509 if (pending_trace_log_status_ack_count_
> 0) {
510 TraceMessageFilterSet::const_iterator it
=
511 pending_trace_log_status_filters_
.find(trace_message_filter
);
512 if (it
!= pending_trace_log_status_filters_
.end()) {
513 BrowserThread::PostTask(
514 BrowserThread::UI
, FROM_HERE
,
515 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
516 base::Unretained(this),
517 make_scoped_refptr(trace_message_filter
),
518 base::trace_event::TraceLogStatus()));
521 if (pending_memory_dump_ack_count_
> 0) {
522 TraceMessageFilterSet::const_iterator it
=
523 pending_memory_dump_filters_
.find(trace_message_filter
);
524 if (it
!= pending_memory_dump_filters_
.end()) {
525 BrowserThread::PostTask(
526 BrowserThread::UI
, FROM_HERE
,
527 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
528 base::Unretained(this),
529 make_scoped_refptr(trace_message_filter
),
530 pending_memory_dump_guid_
, false /* success */));
533 trace_message_filters_
.erase(trace_message_filter
);
536 void TracingControllerImpl::OnDisableRecordingAcked(
537 TraceMessageFilter
* trace_message_filter
,
538 const std::vector
<std::string
>& known_category_groups
) {
539 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
540 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
541 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
542 base::Unretained(this),
543 make_scoped_refptr(trace_message_filter
),
544 known_category_groups
));
548 // Merge known_category_groups with known_category_groups_
549 known_category_groups_
.insert(known_category_groups
.begin(),
550 known_category_groups
.end());
552 if (pending_disable_recording_ack_count_
== 0)
555 if (trace_message_filter
&&
556 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
557 // The response from the specified message filter has already been received.
561 if (--pending_disable_recording_ack_count_
== 1) {
562 // All acks from subprocesses have been received. Now flush the local trace.
563 // During or after this call, our OnLocalTraceDataCollected will be
564 // called with the last of the local trace data.
565 TraceLog::GetInstance()->Flush(
566 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
567 base::Unretained(this)),
572 if (pending_disable_recording_ack_count_
!= 0)
575 // All acks (including from the subprocesses and the local trace) have been
577 is_recording_
= false;
579 // Trigger callback if one is set.
580 if (!pending_get_categories_done_callback_
.is_null()) {
581 pending_get_categories_done_callback_
.Run(known_category_groups_
);
582 pending_get_categories_done_callback_
.Reset();
583 } else if (trace_data_sink_
.get()) {
584 trace_data_sink_
->Close();
585 trace_data_sink_
= NULL
;
589 #if defined(OS_CHROMEOS) || defined(OS_WIN)
590 void TracingControllerImpl::OnEndSystemTracingAcked(
591 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
592 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
594 if (trace_data_sink_
.get()) {
596 // The Windows kernel events are kept into a JSon format stored as string
597 // and must not be escaped.
598 std::string json_string
= events_str_ptr
->data();
600 std::string json_string
=
601 base::GetQuotedJSONString(events_str_ptr
->data());
603 trace_data_sink_
->SetSystemTrace(json_string
);
605 DCHECK(!is_system_tracing_
);
606 std::vector
<std::string
> category_groups
;
607 OnDisableRecordingAcked(NULL
, category_groups
);
611 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
612 TraceMessageFilter
* trace_message_filter
) {
613 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
614 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
615 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
616 base::Unretained(this),
617 make_scoped_refptr(trace_message_filter
)));
621 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
624 if (trace_message_filter
&&
625 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
626 // The response from the specified message filter has already been received.
630 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
631 // All acks from subprocesses have been received. Now flush the local trace.
632 // During or after this call, our OnLocalMonitoringTraceDataCollected
633 // will be called with the last of the local trace data.
634 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
635 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
636 base::Unretained(this)));
640 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
643 if (monitoring_data_sink_
.get()) {
644 monitoring_data_sink_
->Close();
645 monitoring_data_sink_
= NULL
;
649 void TracingControllerImpl::OnTraceDataCollected(
650 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
651 // OnTraceDataCollected may be called from any browser thread, either by the
652 // local event trace system or from child processes via TraceMessageFilter.
653 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
654 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
655 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
656 base::Unretained(this), events_str_ptr
));
660 if (trace_data_sink_
.get())
661 trace_data_sink_
->AddTraceChunk(events_str_ptr
->data());
664 void TracingControllerImpl::OnMonitoringTraceDataCollected(
665 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
666 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
667 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
668 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
669 base::Unretained(this), events_str_ptr
));
673 if (monitoring_data_sink_
.get())
674 monitoring_data_sink_
->AddTraceChunk(events_str_ptr
->data());
677 void TracingControllerImpl::OnLocalTraceDataCollected(
678 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
679 bool has_more_events
) {
680 if (events_str_ptr
->data().size())
681 OnTraceDataCollected(events_str_ptr
);
686 // Simulate an DisableRecordingAcked for the local trace.
687 std::vector
<std::string
> category_groups
;
688 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
689 OnDisableRecordingAcked(NULL
, category_groups
);
692 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
693 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
694 bool has_more_events
) {
695 if (events_str_ptr
->data().size())
696 OnMonitoringTraceDataCollected(events_str_ptr
);
701 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
702 OnCaptureMonitoringSnapshotAcked(NULL
);
705 void TracingControllerImpl::OnTraceLogStatusReply(
706 TraceMessageFilter
* trace_message_filter
,
707 const base::trace_event::TraceLogStatus
& status
) {
708 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
709 BrowserThread::PostTask(
710 BrowserThread::UI
, FROM_HERE
,
711 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply
,
712 base::Unretained(this),
713 make_scoped_refptr(trace_message_filter
), status
));
717 if (pending_trace_log_status_ack_count_
== 0)
720 if (trace_message_filter
&&
721 !pending_trace_log_status_filters_
.erase(trace_message_filter
)) {
722 // The response from the specified message filter has already been received.
726 float percent_full
= static_cast<float>(
727 static_cast<double>(status
.event_count
) / status
.event_capacity
);
728 maximum_trace_buffer_usage_
=
729 std::max(maximum_trace_buffer_usage_
, percent_full
);
730 approximate_event_count_
+= status
.event_count
;
732 if (--pending_trace_log_status_ack_count_
== 0) {
733 // Trigger callback if one is set.
734 pending_trace_buffer_usage_callback_
.Run(maximum_trace_buffer_usage_
,
735 approximate_event_count_
);
736 pending_trace_buffer_usage_callback_
.Reset();
740 void TracingControllerImpl::OnWatchEventMatched() {
741 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
742 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
743 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
744 base::Unretained(this)));
748 if (!watch_event_callback_
.is_null())
749 watch_event_callback_
.Run();
752 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
753 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
754 tracing_uis_
.insert(tracing_ui
);
757 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
758 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
759 DCHECK(it
!= tracing_uis_
.end());
760 tracing_uis_
.erase(it
);
763 void TracingControllerImpl::RequestGlobalMemoryDump(
764 const base::trace_event::MemoryDumpRequestArgs
& args
,
765 const base::trace_event::MemoryDumpCallback
& callback
) {
766 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
767 BrowserThread::PostTask(
768 BrowserThread::UI
, FROM_HERE
,
769 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump
,
770 base::Unretained(this), args
, callback
));
773 // Abort if another dump is already in progress.
774 if (pending_memory_dump_guid_
) {
775 DVLOG(1) << "Requested memory dump " << args
.dump_guid
776 << " while waiting for " << pending_memory_dump_guid_
;
777 if (!callback
.is_null())
778 callback
.Run(args
.dump_guid
, false /* success */);
782 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
783 // OnBrowserProcessMemoryDumpDone().
784 pending_memory_dump_ack_count_
= trace_message_filters_
.size() + 1;
785 pending_memory_dump_filters_
.clear();
786 failed_memory_dump_count_
= 0;
788 MemoryDumpManagerDelegate::CreateProcessDump(
789 args
, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone
,
790 base::Unretained(this)));
792 // If there are no child processes we are just done.
793 if (pending_memory_dump_ack_count_
== 1) {
794 if (!callback
.is_null())
795 callback
.Run(args
.dump_guid
, true /* success */);
799 pending_memory_dump_guid_
= args
.dump_guid
;
800 pending_memory_dump_callback_
= callback
;
801 pending_memory_dump_filters_
= trace_message_filters_
;
803 for (const scoped_refptr
<TraceMessageFilter
>& tmf
: trace_message_filters_
)
804 tmf
->SendProcessMemoryDumpRequest(args
);
807 bool TracingControllerImpl::IsCoordinatorProcess() const {
811 void TracingControllerImpl::OnProcessMemoryDumpResponse(
812 TraceMessageFilter
* trace_message_filter
,
815 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
816 BrowserThread::PostTask(
817 BrowserThread::UI
, FROM_HERE
,
818 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse
,
819 base::Unretained(this),
820 make_scoped_refptr(trace_message_filter
), dump_guid
,
825 TraceMessageFilterSet::iterator it
=
826 pending_memory_dump_filters_
.find(trace_message_filter
);
828 if (pending_memory_dump_guid_
!= dump_guid
||
829 it
== pending_memory_dump_filters_
.end()) {
830 DLOG(WARNING
) << "Received unexpected memory dump response: " << dump_guid
;
834 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
835 --pending_memory_dump_ack_count_
;
836 pending_memory_dump_filters_
.erase(it
);
838 ++failed_memory_dump_count_
;
839 DLOG(WARNING
) << "Global memory dump failed because of NACK from child "
840 << trace_message_filter
->peer_pid();
842 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
845 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64 dump_guid
,
847 DCHECK_GT(pending_memory_dump_ack_count_
, 0);
848 --pending_memory_dump_ack_count_
;
849 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
852 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
853 if (pending_memory_dump_ack_count_
> 0)
856 DCHECK_NE(0u, pending_memory_dump_guid_
);
857 const bool global_success
= failed_memory_dump_count_
== 0;
858 if (!pending_memory_dump_callback_
.is_null()) {
859 pending_memory_dump_callback_
.Run(pending_memory_dump_guid_
,
861 pending_memory_dump_callback_
.Reset();
863 pending_memory_dump_guid_
= 0;
866 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
867 if (is_monitoring_
== is_monitoring
)
870 is_monitoring_
= is_monitoring
;
871 #if !defined(OS_ANDROID)
872 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
873 it
!= tracing_uis_
.end(); it
++) {
874 (*it
)->OnMonitoringStateChanged(is_monitoring
);
879 } // namespace content