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/debug/trace_event.h"
8 #include "base/file_util.h"
9 #include "base/json/string_escape.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "content/browser/tracing/trace_message_filter.h"
12 #include "content/browser/tracing/tracing_ui.h"
13 #include "content/common/child_process_messages.h"
14 #include "content/public/browser/browser_message_filter.h"
15 #include "content/public/common/content_switches.h"
17 #if defined(OS_CHROMEOS)
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/dbus/debug_daemon_client.h"
23 #include "content/browser/tracing/etw_system_event_consumer_win.h"
26 using base::debug::TraceLog
;
27 using base::debug::TraceOptions
;
28 using base::debug::CategoryFilter
;
34 base::LazyInstance
<TracingControllerImpl
>::Leaky g_controller
=
35 LAZY_INSTANCE_INITIALIZER
;
39 TracingController
* TracingController::GetInstance() {
40 return TracingControllerImpl::GetInstance();
43 class TracingControllerImpl::ResultFile
{
45 explicit ResultFile(const base::FilePath
& path
);
46 void Write(const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
47 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
48 base::Bind(&TracingControllerImpl::ResultFile::WriteTask
,
49 base::Unretained(this), events_str_ptr
));
51 void Close(const base::Closure
& callback
) {
52 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
53 base::Bind(&TracingControllerImpl::ResultFile::CloseTask
,
54 base::Unretained(this), callback
));
56 void WriteSystemTrace(
57 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
58 BrowserThread::PostTask(
61 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask
,
62 base::Unretained(this), events_str_ptr
));
65 const base::FilePath
& path() const { return path_
; }
69 void WriteTask(const scoped_refptr
<base::RefCountedString
>& events_str_ptr
);
70 void WriteSystemTraceTask(
71 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
);
72 void CloseTask(const base::Closure
& callback
);
76 bool has_at_least_one_result_
;
77 scoped_refptr
<base::RefCountedString
> system_trace_
;
79 DISALLOW_COPY_AND_ASSIGN(ResultFile
);
82 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath
& path
)
85 has_at_least_one_result_(false) {
86 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
87 base::Bind(&TracingControllerImpl::ResultFile::OpenTask
,
88 base::Unretained(this)));
91 void TracingControllerImpl::ResultFile::OpenTask() {
93 base::CreateTemporaryFile(&path_
);
94 file_
= base::OpenFile(path_
, "w");
96 LOG(ERROR
) << "Failed to open " << path_
.value();
99 const char* preamble
= "{\"traceEvents\": [";
100 size_t written
= fwrite(preamble
, strlen(preamble
), 1, file_
);
101 DCHECK(written
== 1);
104 void TracingControllerImpl::ResultFile::WriteTask(
105 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
106 if (!file_
|| !events_str_ptr
->data().size())
109 // If there is already a result in the file, then put a comma
110 // before the next batch of results.
111 if (has_at_least_one_result_
) {
112 size_t written
= fwrite(",", 1, 1, file_
);
113 DCHECK(written
== 1);
115 has_at_least_one_result_
= true;
116 size_t written
= fwrite(events_str_ptr
->data().c_str(),
117 events_str_ptr
->data().size(), 1,
119 DCHECK(written
== 1);
122 void TracingControllerImpl::ResultFile::WriteSystemTraceTask(
123 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
124 system_trace_
= events_str_ptr
;
127 void TracingControllerImpl::ResultFile::CloseTask(
128 const base::Closure
& callback
) {
132 const char* trailevents
= "]";
133 size_t written
= fwrite(trailevents
, strlen(trailevents
), 1, file_
);
134 DCHECK(written
== 1);
136 if (system_trace_
.get()) {
138 // The Windows kernel events are kept into a JSon format stored as string
139 // and must not be escaped.
140 std::string json_string
= system_trace_
->data();
142 std::string json_string
= base::GetQuotedJSONString(system_trace_
->data());
145 const char* systemTraceHead
= ",\n\"systemTraceEvents\": ";
146 written
= fwrite(systemTraceHead
, strlen(systemTraceHead
), 1, file_
);
147 DCHECK(written
== 1);
149 written
= fwrite(json_string
.data(), json_string
.size(), 1, file_
);
150 DCHECK(written
== 1);
152 system_trace_
= NULL
;
155 const char* trailout
= "}";
156 written
= fwrite(trailout
, strlen(trailout
), 1, file_
);
157 DCHECK(written
== 1);
158 base::CloseFile(file_
);
161 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
165 TracingControllerImpl::TracingControllerImpl() :
166 pending_disable_recording_ack_count_(0),
167 pending_capture_monitoring_snapshot_ack_count_(0),
168 pending_trace_buffer_percent_full_ack_count_(0),
169 maximum_trace_buffer_percent_full_(0),
170 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
171 // is specified in command line.
172 #if defined(OS_CHROMEOS) || defined(OS_WIN)
173 is_system_tracing_(false),
175 is_recording_(TraceLog::GetInstance()->IsEnabled()),
176 is_monitoring_(false) {
179 TracingControllerImpl::~TracingControllerImpl() {
180 // This is a Leaky instance.
184 TracingControllerImpl
* TracingControllerImpl::GetInstance() {
185 return g_controller
.Pointer();
188 bool TracingControllerImpl::GetCategories(
189 const GetCategoriesDoneCallback
& callback
) {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
192 // Known categories come back from child processes with the EndTracingAck
193 // message. So to get known categories, just begin and end tracing immediately
194 // afterwards. This will ping all the child processes for categories.
195 pending_get_categories_done_callback_
= callback
;
196 if (!EnableRecording(
197 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
198 pending_get_categories_done_callback_
.Reset();
202 bool ok
= DisableRecording(base::FilePath(), TracingFileResultCallback());
207 void TracingControllerImpl::SetEnabledOnFileThread(
208 const CategoryFilter
& category_filter
,
210 const TraceOptions
& trace_options
,
211 const base::Closure
& callback
) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
214 TraceLog::GetInstance()->SetEnabled(
215 category_filter
, static_cast<TraceLog::Mode
>(mode
), trace_options
);
216 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
219 void TracingControllerImpl::SetDisabledOnFileThread(
220 const base::Closure
& callback
) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
223 TraceLog::GetInstance()->SetDisabled();
224 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, callback
);
227 bool TracingControllerImpl::EnableRecording(
228 const CategoryFilter
& category_filter
,
229 const TraceOptions
& trace_options
,
230 const EnableRecordingDoneCallback
& callback
) {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
233 if (!can_enable_recording())
235 is_recording_
= true;
237 #if defined(OS_ANDROID)
238 if (pending_get_categories_done_callback_
.is_null())
239 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
242 trace_options_
= trace_options
;
244 if (trace_options
.enable_systrace
) {
245 #if defined(OS_CHROMEOS)
246 DCHECK(!is_system_tracing_
);
247 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
248 StartSystemTracing();
249 is_system_tracing_
= true;
250 #elif defined(OS_WIN)
251 DCHECK(!is_system_tracing_
);
253 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
258 base::Closure on_enable_recording_done_callback
=
259 base::Bind(&TracingControllerImpl::OnEnableRecordingDone
,
260 base::Unretained(this),
261 category_filter
, trace_options
, callback
);
262 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
263 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
264 base::Unretained(this),
266 base::debug::TraceLog::RECORDING_MODE
,
268 on_enable_recording_done_callback
));
272 void TracingControllerImpl::OnEnableRecordingDone(
273 const CategoryFilter
& category_filter
,
274 const TraceOptions
& trace_options
,
275 const EnableRecordingDoneCallback
& callback
) {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
278 // Notify all child processes.
279 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
280 it
!= trace_message_filters_
.end(); ++it
) {
281 it
->get()->SendBeginTracing(category_filter
, trace_options
);
284 if (!callback
.is_null())
288 bool TracingControllerImpl::DisableRecording(
289 const base::FilePath
& result_file_path
,
290 const TracingFileResultCallback
& callback
) {
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
293 if (!can_disable_recording())
296 trace_options_
= TraceOptions();
297 // Disable local trace early to avoid traces during end-tracing process from
298 // interfering with the process.
299 base::Closure on_disable_recording_done_callback
=
300 base::Bind(&TracingControllerImpl::OnDisableRecordingDone
,
301 base::Unretained(this),
302 result_file_path
, callback
);
303 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
304 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
305 base::Unretained(this),
306 on_disable_recording_done_callback
));
310 void TracingControllerImpl::OnDisableRecordingDone(
311 const base::FilePath
& result_file_path
,
312 const TracingFileResultCallback
& callback
) {
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
315 pending_disable_recording_done_callback_
= callback
;
317 #if defined(OS_ANDROID)
318 if (pending_get_categories_done_callback_
.is_null())
319 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
322 if (!callback
.is_null() || !result_file_path
.empty())
323 result_file_
.reset(new ResultFile(result_file_path
));
325 // Count myself (local trace) in pending_disable_recording_ack_count_,
327 pending_disable_recording_ack_count_
= trace_message_filters_
.size() + 1;
328 pending_disable_recording_filters_
= trace_message_filters_
;
330 #if defined(OS_CHROMEOS) || defined(OS_WIN)
331 if (is_system_tracing_
) {
332 // Disable system tracing.
333 is_system_tracing_
= false;
334 ++pending_disable_recording_ack_count_
;
336 #if defined(OS_CHROMEOS)
337 scoped_refptr
<base::TaskRunner
> task_runner
=
338 BrowserThread::GetBlockingPool();
339 chromeos::DBusThreadManager::Get()
340 ->GetDebugDaemonClient()
341 ->RequestStopSystemTracing(
343 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
344 base::Unretained(this)));
345 #elif defined(OS_WIN)
346 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
347 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked
,
348 base::Unretained(this)));
351 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
353 // Handle special case of zero child processes by immediately flushing the
354 // trace log. Once the flush has completed the caller will be notified that
355 // tracing has ended.
356 if (pending_disable_recording_ack_count_
== 1) {
357 // Flush asynchronously now, because we don't have any children to wait for.
358 TraceLog::GetInstance()->Flush(
359 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
360 base::Unretained(this)));
363 // Notify all child processes.
364 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
365 it
!= trace_message_filters_
.end(); ++it
) {
366 it
->get()->SendEndTracing();
370 bool TracingControllerImpl::EnableMonitoring(
371 const CategoryFilter
& category_filter
,
372 const TraceOptions
& trace_options
,
373 const EnableMonitoringDoneCallback
& callback
) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
376 if (!can_enable_monitoring())
378 OnMonitoringStateChanged(true);
380 #if defined(OS_ANDROID)
381 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
384 trace_options_
= trace_options
;
386 base::Closure on_enable_monitoring_done_callback
=
387 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone
,
388 base::Unretained(this),
389 category_filter
, trace_options
, callback
);
390 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
391 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread
,
392 base::Unretained(this),
394 base::debug::TraceLog::MONITORING_MODE
,
396 on_enable_monitoring_done_callback
));
400 void TracingControllerImpl::OnEnableMonitoringDone(
401 const CategoryFilter
& category_filter
,
402 const TraceOptions
& trace_options
,
403 const EnableMonitoringDoneCallback
& callback
) {
404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
406 // Notify all child processes.
407 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
408 it
!= trace_message_filters_
.end(); ++it
) {
409 it
->get()->SendEnableMonitoring(category_filter
, trace_options
);
412 if (!callback
.is_null())
416 bool TracingControllerImpl::DisableMonitoring(
417 const DisableMonitoringDoneCallback
& callback
) {
418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
420 if (!can_disable_monitoring())
423 trace_options_
= TraceOptions();
424 base::Closure on_disable_monitoring_done_callback
=
425 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone
,
426 base::Unretained(this), callback
);
427 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
428 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread
,
429 base::Unretained(this),
430 on_disable_monitoring_done_callback
));
434 void TracingControllerImpl::OnDisableMonitoringDone(
435 const DisableMonitoringDoneCallback
& callback
) {
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
438 OnMonitoringStateChanged(false);
440 // Notify all child processes.
441 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
442 it
!= trace_message_filters_
.end(); ++it
) {
443 it
->get()->SendDisableMonitoring();
446 if (!callback
.is_null())
450 void TracingControllerImpl::GetMonitoringStatus(
452 CategoryFilter
* out_category_filter
,
453 TraceOptions
* out_trace_options
) {
454 *out_enabled
= is_monitoring_
;
455 *out_category_filter
= TraceLog::GetInstance()->GetCurrentCategoryFilter();
456 *out_trace_options
= trace_options_
;
459 bool TracingControllerImpl::CaptureMonitoringSnapshot(
460 const base::FilePath
& result_file_path
,
461 const TracingFileResultCallback
& callback
) {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
464 if (!can_disable_monitoring())
467 if (callback
.is_null() && result_file_path
.empty())
470 pending_capture_monitoring_snapshot_done_callback_
= callback
;
471 monitoring_snapshot_file_
.reset(new ResultFile(result_file_path
));
473 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
475 pending_capture_monitoring_snapshot_ack_count_
=
476 trace_message_filters_
.size() + 1;
477 pending_capture_monitoring_filters_
= trace_message_filters_
;
479 // Handle special case of zero child processes by immediately flushing the
480 // trace log. Once the flush has completed the caller will be notified that
481 // the capture snapshot has ended.
482 if (pending_capture_monitoring_snapshot_ack_count_
== 1) {
483 // Flush asynchronously now, because we don't have any children to wait for.
484 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
485 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
486 base::Unretained(this)));
489 // Notify all child processes.
490 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
491 it
!= trace_message_filters_
.end(); ++it
) {
492 it
->get()->SendCaptureMonitoringSnapshot();
495 #if defined(OS_ANDROID)
496 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
502 bool TracingControllerImpl::GetTraceBufferPercentFull(
503 const GetTraceBufferPercentFullCallback
& callback
) {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
506 if (!can_get_trace_buffer_percent_full() || callback
.is_null())
509 pending_trace_buffer_percent_full_callback_
= callback
;
511 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
512 pending_trace_buffer_percent_full_ack_count_
=
513 trace_message_filters_
.size() + 1;
514 pending_trace_buffer_percent_full_filters_
= trace_message_filters_
;
515 maximum_trace_buffer_percent_full_
= 0;
517 // Call OnTraceBufferPercentFullReply unconditionally for the browser process.
518 // This will result in immediate execution of the callback if there are no
520 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
521 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply
,
522 base::Unretained(this),
523 scoped_refptr
<TraceMessageFilter
>(),
524 TraceLog::GetInstance()->GetBufferPercentFull()));
526 // Notify all child processes.
527 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
528 it
!= trace_message_filters_
.end(); ++it
) {
529 it
->get()->SendGetTraceBufferPercentFull();
534 bool TracingControllerImpl::SetWatchEvent(
535 const std::string
& category_name
,
536 const std::string
& event_name
,
537 const WatchEventCallback
& callback
) {
538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
540 if (callback
.is_null())
543 watch_category_name_
= category_name
;
544 watch_event_name_
= event_name
;
545 watch_event_callback_
= callback
;
547 TraceLog::GetInstance()->SetWatchEvent(
548 category_name
, event_name
,
549 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
550 base::Unretained(this)));
552 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
553 it
!= trace_message_filters_
.end(); ++it
) {
554 it
->get()->SendSetWatchEvent(category_name
, event_name
);
559 bool TracingControllerImpl::CancelWatchEvent() {
560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
562 if (!can_cancel_watch_event())
565 for (TraceMessageFilterSet::iterator it
= trace_message_filters_
.begin();
566 it
!= trace_message_filters_
.end(); ++it
) {
567 it
->get()->SendCancelWatchEvent();
570 watch_event_callback_
.Reset();
574 void TracingControllerImpl::AddTraceMessageFilter(
575 TraceMessageFilter
* trace_message_filter
) {
576 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
577 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
578 base::Bind(&TracingControllerImpl::AddTraceMessageFilter
,
579 base::Unretained(this),
580 make_scoped_refptr(trace_message_filter
)));
584 trace_message_filters_
.insert(trace_message_filter
);
585 if (can_cancel_watch_event()) {
586 trace_message_filter
->SendSetWatchEvent(watch_category_name_
,
589 if (can_disable_recording()) {
590 trace_message_filter
->SendBeginTracing(
591 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
592 TraceLog::GetInstance()->GetCurrentTraceOptions());
594 if (can_disable_monitoring()) {
595 trace_message_filter
->SendEnableMonitoring(
596 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
597 TraceLog::GetInstance()->GetCurrentTraceOptions());
601 void TracingControllerImpl::RemoveTraceMessageFilter(
602 TraceMessageFilter
* trace_message_filter
) {
603 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
604 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
605 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter
,
606 base::Unretained(this),
607 make_scoped_refptr(trace_message_filter
)));
611 // If a filter is removed while a response from that filter is pending then
612 // simulate the response. Otherwise the response count will be wrong and the
613 // completion callback will never be executed.
614 if (pending_disable_recording_ack_count_
> 0) {
615 TraceMessageFilterSet::const_iterator it
=
616 pending_disable_recording_filters_
.find(trace_message_filter
);
617 if (it
!= pending_disable_recording_filters_
.end()) {
618 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
619 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
620 base::Unretained(this),
621 make_scoped_refptr(trace_message_filter
),
622 std::vector
<std::string
>()));
625 if (pending_capture_monitoring_snapshot_ack_count_
> 0) {
626 TraceMessageFilterSet::const_iterator it
=
627 pending_capture_monitoring_filters_
.find(trace_message_filter
);
628 if (it
!= pending_capture_monitoring_filters_
.end()) {
629 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
630 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
631 base::Unretained(this),
632 make_scoped_refptr(trace_message_filter
)));
635 if (pending_trace_buffer_percent_full_ack_count_
> 0) {
636 TraceMessageFilterSet::const_iterator it
=
637 pending_trace_buffer_percent_full_filters_
.find(trace_message_filter
);
638 if (it
!= pending_trace_buffer_percent_full_filters_
.end()) {
639 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
640 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply
,
641 base::Unretained(this),
642 make_scoped_refptr(trace_message_filter
),
647 trace_message_filters_
.erase(trace_message_filter
);
650 void TracingControllerImpl::OnDisableRecordingAcked(
651 TraceMessageFilter
* trace_message_filter
,
652 const std::vector
<std::string
>& known_category_groups
) {
653 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
654 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
655 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked
,
656 base::Unretained(this),
657 make_scoped_refptr(trace_message_filter
),
658 known_category_groups
));
662 // Merge known_category_groups with known_category_groups_
663 known_category_groups_
.insert(known_category_groups
.begin(),
664 known_category_groups
.end());
666 if (pending_disable_recording_ack_count_
== 0)
669 if (trace_message_filter
&&
670 !pending_disable_recording_filters_
.erase(trace_message_filter
)) {
671 // The response from the specified message filter has already been received.
675 if (--pending_disable_recording_ack_count_
== 1) {
676 // All acks from subprocesses have been received. Now flush the local trace.
677 // During or after this call, our OnLocalTraceDataCollected will be
678 // called with the last of the local trace data.
679 TraceLog::GetInstance()->Flush(
680 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected
,
681 base::Unretained(this)));
685 if (pending_disable_recording_ack_count_
!= 0)
688 OnDisableRecordingComplete();
691 void TracingControllerImpl::OnDisableRecordingComplete() {
692 // All acks (including from the subprocesses and the local trace) have been
694 is_recording_
= false;
696 // Trigger callback if one is set.
697 if (!pending_get_categories_done_callback_
.is_null()) {
698 pending_get_categories_done_callback_
.Run(known_category_groups_
);
699 pending_get_categories_done_callback_
.Reset();
700 } else if (result_file_
) {
702 base::Bind(&TracingControllerImpl::OnResultFileClosed
,
703 base::Unretained(this)));
707 void TracingControllerImpl::OnResultFileClosed() {
708 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
713 if (!pending_disable_recording_done_callback_
.is_null()) {
714 pending_disable_recording_done_callback_
.Run(result_file_
->path());
715 pending_disable_recording_done_callback_
.Reset();
717 result_file_
.reset();
720 #if defined(OS_CHROMEOS) || defined(OS_WIN)
721 void TracingControllerImpl::OnEndSystemTracingAcked(
722 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
726 result_file_
->WriteSystemTrace(events_str_ptr
);
728 DCHECK(!is_system_tracing_
);
729 std::vector
<std::string
> category_groups
;
730 OnDisableRecordingAcked(NULL
, category_groups
);
734 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
735 TraceMessageFilter
* trace_message_filter
) {
736 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
737 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
738 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked
,
739 base::Unretained(this),
740 make_scoped_refptr(trace_message_filter
)));
744 if (pending_capture_monitoring_snapshot_ack_count_
== 0)
747 if (trace_message_filter
&&
748 !pending_capture_monitoring_filters_
.erase(trace_message_filter
)) {
749 // The response from the specified message filter has already been received.
753 if (--pending_capture_monitoring_snapshot_ack_count_
== 1) {
754 // All acks from subprocesses have been received. Now flush the local trace.
755 // During or after this call, our OnLocalMonitoringTraceDataCollected
756 // will be called with the last of the local trace data.
757 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
758 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected
,
759 base::Unretained(this)));
763 if (pending_capture_monitoring_snapshot_ack_count_
!= 0)
766 if (monitoring_snapshot_file_
) {
767 monitoring_snapshot_file_
->Close(
768 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed
,
769 base::Unretained(this)));
773 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
774 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
776 if (!monitoring_snapshot_file_
)
779 if (!pending_capture_monitoring_snapshot_done_callback_
.is_null()) {
780 pending_capture_monitoring_snapshot_done_callback_
.Run(
781 monitoring_snapshot_file_
->path());
782 pending_capture_monitoring_snapshot_done_callback_
.Reset();
784 monitoring_snapshot_file_
.reset();
787 void TracingControllerImpl::OnTraceDataCollected(
788 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
789 // OnTraceDataCollected may be called from any browser thread, either by the
790 // local event trace system or from child processes via TraceMessageFilter.
791 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
792 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
793 base::Bind(&TracingControllerImpl::OnTraceDataCollected
,
794 base::Unretained(this), events_str_ptr
));
799 result_file_
->Write(events_str_ptr
);
802 void TracingControllerImpl::OnMonitoringTraceDataCollected(
803 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
) {
804 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
805 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
806 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected
,
807 base::Unretained(this), events_str_ptr
));
811 if (monitoring_snapshot_file_
)
812 monitoring_snapshot_file_
->Write(events_str_ptr
);
815 void TracingControllerImpl::OnLocalTraceDataCollected(
816 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
817 bool has_more_events
) {
818 if (events_str_ptr
->data().size())
819 OnTraceDataCollected(events_str_ptr
);
824 // Simulate an DisableRecordingAcked for the local trace.
825 std::vector
<std::string
> category_groups
;
826 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups
);
827 OnDisableRecordingAcked(NULL
, category_groups
);
830 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
831 const scoped_refptr
<base::RefCountedString
>& events_str_ptr
,
832 bool has_more_events
) {
833 if (events_str_ptr
->data().size())
834 OnMonitoringTraceDataCollected(events_str_ptr
);
839 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
840 OnCaptureMonitoringSnapshotAcked(NULL
);
843 void TracingControllerImpl::OnTraceBufferPercentFullReply(
844 TraceMessageFilter
* trace_message_filter
,
845 float percent_full
) {
846 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
847 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
848 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply
,
849 base::Unretained(this),
850 make_scoped_refptr(trace_message_filter
),
855 if (pending_trace_buffer_percent_full_ack_count_
== 0)
858 if (trace_message_filter
&&
859 !pending_trace_buffer_percent_full_filters_
.erase(trace_message_filter
)) {
860 // The response from the specified message filter has already been received.
864 maximum_trace_buffer_percent_full_
=
865 std::max(maximum_trace_buffer_percent_full_
, percent_full
);
867 if (--pending_trace_buffer_percent_full_ack_count_
== 0) {
868 // Trigger callback if one is set.
869 pending_trace_buffer_percent_full_callback_
.Run(
870 maximum_trace_buffer_percent_full_
);
871 pending_trace_buffer_percent_full_callback_
.Reset();
875 void TracingControllerImpl::OnWatchEventMatched() {
876 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
877 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
878 base::Bind(&TracingControllerImpl::OnWatchEventMatched
,
879 base::Unretained(this)));
883 if (!watch_event_callback_
.is_null())
884 watch_event_callback_
.Run();
887 void TracingControllerImpl::RegisterTracingUI(TracingUI
* tracing_ui
) {
888 DCHECK(tracing_uis_
.find(tracing_ui
) == tracing_uis_
.end());
889 tracing_uis_
.insert(tracing_ui
);
892 void TracingControllerImpl::UnregisterTracingUI(TracingUI
* tracing_ui
) {
893 std::set
<TracingUI
*>::iterator it
= tracing_uis_
.find(tracing_ui
);
894 DCHECK(it
!= tracing_uis_
.end());
895 tracing_uis_
.erase(it
);
898 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring
) {
899 if (is_monitoring_
== is_monitoring
)
902 is_monitoring_
= is_monitoring
;
903 #if !defined(OS_ANDROID)
904 for (std::set
<TracingUI
*>::iterator it
= tracing_uis_
.begin();
905 it
!= tracing_uis_
.end(); it
++) {
906 (*it
)->OnMonitoringStateChanged(is_monitoring
);
911 } // namespace content