Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / tracing / tracing_controller_impl.cc
blob3a235fe5bdaf803c7790dfdb12de1e554e952550
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"
6 #include "base/bind.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"
21 #endif
23 #if defined(OS_WIN)
24 #include "content/browser/tracing/etw_system_event_consumer_win.h"
25 #endif
27 using base::trace_event::TraceLog;
28 using base::trace_event::TraceOptions;
29 using base::trace_event::CategoryFilter;
31 namespace content {
33 namespace {
35 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
36 LAZY_INSTANCE_INITIALIZER;
38 } // namespace
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),
56 #endif
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.
64 NOTREACHED();
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;
79 if (!EnableRecording(
80 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
81 pending_get_categories_done_callback_.Reset();
82 return false;
85 bool ok = DisableRecording(NULL);
86 DCHECK(ok);
87 return true;
90 void TracingControllerImpl::SetEnabledOnFileThread(
91 const CategoryFilter& category_filter,
92 int mode,
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())
117 return false;
118 is_recording_ = true;
120 #if defined(OS_ANDROID)
121 if (pending_get_categories_done_callback_.is_null())
122 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
123 #endif
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_);
135 is_system_tracing_ =
136 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
137 #endif
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),
148 category_filter,
149 base::trace_event::TraceLog::RECORDING_MODE,
150 trace_options,
151 on_enable_recording_done_callback));
152 return true;
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())
168 callback.Run();
171 bool TracingControllerImpl::DisableRecording(
172 const scoped_refptr<TraceDataSink>& trace_data_sink) {
173 DCHECK_CURRENTLY_ON(BrowserThread::UI);
175 if (!can_disable_recording())
176 return false;
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));
188 return true;
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();
197 #endif
199 // Count myself (local trace) in pending_disable_recording_ack_count_,
200 // acked below.
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(
216 task_runner,
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)));
223 #endif
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)),
235 true);
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())
252 return false;
253 OnMonitoringStateChanged(true);
255 #if defined(OS_ANDROID)
256 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
257 #endif
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),
268 category_filter,
269 base::trace_event::TraceLog::MONITORING_MODE,
270 trace_options,
271 on_enable_monitoring_done_callback));
272 return true;
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())
288 callback.Run();
291 bool TracingControllerImpl::DisableMonitoring(
292 const DisableMonitoringDoneCallback& callback) {
293 DCHECK_CURRENTLY_ON(BrowserThread::UI);
295 if (!can_disable_monitoring())
296 return false;
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));
306 return true;
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())
321 callback.Run();
324 void TracingControllerImpl::GetMonitoringStatus(
325 bool* out_enabled,
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())
338 return false;
340 if (!monitoring_data_sink.get())
341 return false;
343 monitoring_data_sink_ = monitoring_data_sink;
345 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
346 // acked below.
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();
369 #endif
371 return true;
374 bool TracingControllerImpl::GetTraceBufferUsage(
375 const GetTraceBufferUsageCallback& callback) {
376 DCHECK_CURRENTLY_ON(BrowserThread::UI);
378 if (!can_get_trace_buffer_usage() || callback.is_null())
379 return false;
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
393 // child processes.
394 BrowserThread::PostTask(
395 BrowserThread::UI, FROM_HERE,
396 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
397 base::Unretained(this), scoped_refptr<TraceMessageFilter>(),
398 status));
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();
405 return true;
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())
415 return false;
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);
430 return true;
433 bool TracingControllerImpl::CancelWatchEvent() {
434 DCHECK_CURRENTLY_ON(BrowserThread::UI);
436 if (!can_cancel_watch_event())
437 return false;
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();
445 return true;
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)));
455 return;
458 trace_message_filters_.insert(trace_message_filter);
459 if (can_cancel_watch_event()) {
460 trace_message_filter->SendSetWatchEvent(watch_category_name_,
461 watch_event_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)));
482 return;
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));
545 return;
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)
553 return;
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.
558 return;
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)),
568 true);
569 return;
572 if (pending_disable_recording_ack_count_ != 0)
573 return;
575 // All acks (including from the subprocesses and the local trace) have been
576 // received.
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()) {
595 #if defined(OS_WIN)
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();
599 #else
600 std::string json_string =
601 base::GetQuotedJSONString(events_str_ptr->data());
602 #endif
603 trace_data_sink_->SetSystemTrace(json_string);
605 DCHECK(!is_system_tracing_);
606 std::vector<std::string> category_groups;
607 OnDisableRecordingAcked(NULL, category_groups);
609 #endif
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)));
618 return;
621 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
622 return;
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.
627 return;
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)));
637 return;
640 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
641 return;
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));
657 return;
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));
670 return;
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);
683 if (has_more_events)
684 return;
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);
698 if (has_more_events)
699 return;
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));
714 return;
717 if (pending_trace_log_status_ack_count_ == 0)
718 return;
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.
723 return;
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)));
745 return;
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));
771 return;
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 */);
779 return;
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 */);
796 return;
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 {
808 return true;
811 void TracingControllerImpl::OnProcessMemoryDumpResponse(
812 TraceMessageFilter* trace_message_filter,
813 uint64 dump_guid,
814 bool success) {
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,
821 success));
822 return;
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;
831 return;
834 DCHECK_GT(pending_memory_dump_ack_count_, 0);
835 --pending_memory_dump_ack_count_;
836 pending_memory_dump_filters_.erase(it);
837 if (!success) {
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,
846 bool success) {
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)
854 return;
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_,
860 global_success);
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)
868 return;
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);
876 #endif
879 } // namespace content