Use native radiobutton for Default Search Engine picker dialog.
[chromium-blink-merge.git] / content / browser / tracing / tracing_controller_impl.cc
blobf063aa3f57e2f7deaec7c15b4cfa295d71f49c29
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/file_tracing_provider_impl.h"
13 #include "content/browser/tracing/trace_message_filter.h"
14 #include "content/browser/tracing/tracing_ui.h"
15 #include "content/common/child_process_messages.h"
16 #include "content/public/browser/browser_message_filter.h"
17 #include "content/public/common/content_switches.h"
19 #if defined(OS_CHROMEOS)
20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/dbus/debug_daemon_client.h"
22 #endif
24 #if defined(OS_WIN)
25 #include "content/browser/tracing/etw_system_event_consumer_win.h"
26 #endif
28 using base::trace_event::TraceLog;
29 using base::trace_event::TraceOptions;
30 using base::trace_event::CategoryFilter;
32 namespace content {
34 namespace {
36 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
37 LAZY_INSTANCE_INITIALIZER;
39 } // namespace
41 TracingController* TracingController::GetInstance() {
42 return TracingControllerImpl::GetInstance();
45 TracingControllerImpl::TracingControllerImpl()
46 : pending_disable_recording_ack_count_(0),
47 pending_capture_monitoring_snapshot_ack_count_(0),
48 pending_trace_log_status_ack_count_(0),
49 maximum_trace_buffer_usage_(0),
50 approximate_event_count_(0),
51 pending_memory_dump_ack_count_(0),
52 failed_memory_dump_count_(0),
53 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
54 // is specified in command line.
55 #if defined(OS_CHROMEOS) || defined(OS_WIN)
56 is_system_tracing_(false),
57 #endif
58 is_recording_(TraceLog::GetInstance()->IsEnabled()),
59 is_monitoring_(false) {
60 base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this);
62 // Deliberately leaked, like this class.
63 base::FileTracing::SetProvider(new FileTracingProviderImpl);
66 TracingControllerImpl::~TracingControllerImpl() {
67 // This is a Leaky instance.
68 NOTREACHED();
71 TracingControllerImpl* TracingControllerImpl::GetInstance() {
72 return g_controller.Pointer();
75 bool TracingControllerImpl::GetCategories(
76 const GetCategoriesDoneCallback& callback) {
77 DCHECK_CURRENTLY_ON(BrowserThread::UI);
79 // Known categories come back from child processes with the EndTracingAck
80 // message. So to get known categories, just begin and end tracing immediately
81 // afterwards. This will ping all the child processes for categories.
82 pending_get_categories_done_callback_ = callback;
83 if (!EnableRecording(
84 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
85 pending_get_categories_done_callback_.Reset();
86 return false;
89 bool ok = DisableRecording(NULL);
90 DCHECK(ok);
91 return true;
94 void TracingControllerImpl::SetEnabledOnFileThread(
95 const CategoryFilter& category_filter,
96 int mode,
97 const TraceOptions& trace_options,
98 const base::Closure& callback) {
99 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
101 TraceLog::GetInstance()->SetEnabled(
102 category_filter, static_cast<TraceLog::Mode>(mode), trace_options);
103 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
106 void TracingControllerImpl::SetDisabledOnFileThread(
107 const base::Closure& callback) {
108 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
110 TraceLog::GetInstance()->SetDisabled();
111 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
114 bool TracingControllerImpl::EnableRecording(
115 const CategoryFilter& category_filter,
116 const TraceOptions& trace_options,
117 const EnableRecordingDoneCallback& callback) {
118 DCHECK_CURRENTLY_ON(BrowserThread::UI);
120 if (!can_enable_recording())
121 return false;
122 is_recording_ = true;
124 #if defined(OS_ANDROID)
125 if (pending_get_categories_done_callback_.is_null())
126 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
127 #endif
129 trace_options_ = trace_options;
131 if (trace_options.enable_systrace) {
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_);
139 is_system_tracing_ =
140 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
141 #endif
145 base::Closure on_enable_recording_done_callback =
146 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
147 base::Unretained(this),
148 category_filter, trace_options, callback);
149 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
150 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
151 base::Unretained(this),
152 category_filter,
153 base::trace_event::TraceLog::RECORDING_MODE,
154 trace_options,
155 on_enable_recording_done_callback));
156 return true;
159 void TracingControllerImpl::OnEnableRecordingDone(
160 const CategoryFilter& category_filter,
161 const TraceOptions& trace_options,
162 const EnableRecordingDoneCallback& callback) {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI);
165 // Notify all child processes.
166 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
167 it != trace_message_filters_.end(); ++it) {
168 it->get()->SendBeginTracing(category_filter, trace_options);
171 if (!callback.is_null())
172 callback.Run();
175 bool TracingControllerImpl::DisableRecording(
176 const scoped_refptr<TraceDataSink>& trace_data_sink) {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI);
179 if (!can_disable_recording())
180 return false;
182 trace_data_sink_ = trace_data_sink;
183 trace_options_ = TraceOptions();
184 // Disable local trace early to avoid traces during end-tracing process from
185 // interfering with the process.
186 base::Closure on_disable_recording_done_callback = base::Bind(
187 &TracingControllerImpl::OnDisableRecordingDone, base::Unretained(this));
188 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
189 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
190 base::Unretained(this),
191 on_disable_recording_done_callback));
192 return true;
195 void TracingControllerImpl::OnDisableRecordingDone() {
196 DCHECK_CURRENTLY_ON(BrowserThread::UI);
198 #if defined(OS_ANDROID)
199 if (pending_get_categories_done_callback_.is_null())
200 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
201 #endif
203 // Count myself (local trace) in pending_disable_recording_ack_count_,
204 // acked below.
205 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
206 pending_disable_recording_filters_ = trace_message_filters_;
208 #if defined(OS_CHROMEOS) || defined(OS_WIN)
209 if (is_system_tracing_) {
210 // Disable system tracing.
211 is_system_tracing_ = false;
212 ++pending_disable_recording_ack_count_;
214 #if defined(OS_CHROMEOS)
215 scoped_refptr<base::TaskRunner> task_runner =
216 BrowserThread::GetBlockingPool();
217 chromeos::DBusThreadManager::Get()
218 ->GetDebugDaemonClient()
219 ->RequestStopSystemTracing(
220 task_runner,
221 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
222 base::Unretained(this)));
223 #elif defined(OS_WIN)
224 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
225 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
226 base::Unretained(this)));
227 #endif
229 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
231 // Handle special case of zero child processes by immediately flushing the
232 // trace log. Once the flush has completed the caller will be notified that
233 // tracing has ended.
234 if (pending_disable_recording_ack_count_ == 1) {
235 // Flush asynchronously now, because we don't have any children to wait for.
236 TraceLog::GetInstance()->Flush(
237 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
238 base::Unretained(this)),
239 true);
242 // Notify all child processes.
243 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
244 it != trace_message_filters_.end(); ++it) {
245 it->get()->SendEndTracing();
249 bool TracingControllerImpl::EnableMonitoring(
250 const CategoryFilter& category_filter,
251 const TraceOptions& trace_options,
252 const EnableMonitoringDoneCallback& callback) {
253 DCHECK_CURRENTLY_ON(BrowserThread::UI);
255 if (!can_enable_monitoring())
256 return false;
257 OnMonitoringStateChanged(true);
259 #if defined(OS_ANDROID)
260 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
261 #endif
263 trace_options_ = trace_options;
265 base::Closure on_enable_monitoring_done_callback =
266 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
267 base::Unretained(this),
268 category_filter, trace_options, callback);
269 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
270 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
271 base::Unretained(this),
272 category_filter,
273 base::trace_event::TraceLog::MONITORING_MODE,
274 trace_options,
275 on_enable_monitoring_done_callback));
276 return true;
279 void TracingControllerImpl::OnEnableMonitoringDone(
280 const CategoryFilter& category_filter,
281 const TraceOptions& trace_options,
282 const EnableMonitoringDoneCallback& callback) {
283 DCHECK_CURRENTLY_ON(BrowserThread::UI);
285 // Notify all child processes.
286 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
287 it != trace_message_filters_.end(); ++it) {
288 it->get()->SendEnableMonitoring(category_filter, trace_options);
291 if (!callback.is_null())
292 callback.Run();
295 bool TracingControllerImpl::DisableMonitoring(
296 const DisableMonitoringDoneCallback& callback) {
297 DCHECK_CURRENTLY_ON(BrowserThread::UI);
299 if (!can_disable_monitoring())
300 return false;
302 trace_options_ = TraceOptions();
303 base::Closure on_disable_monitoring_done_callback =
304 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
305 base::Unretained(this), callback);
306 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
307 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
308 base::Unretained(this),
309 on_disable_monitoring_done_callback));
310 return true;
313 void TracingControllerImpl::OnDisableMonitoringDone(
314 const DisableMonitoringDoneCallback& callback) {
315 DCHECK_CURRENTLY_ON(BrowserThread::UI);
317 OnMonitoringStateChanged(false);
319 // Notify all child processes.
320 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
321 it != trace_message_filters_.end(); ++it) {
322 it->get()->SendDisableMonitoring();
324 if (!callback.is_null())
325 callback.Run();
328 void TracingControllerImpl::GetMonitoringStatus(
329 bool* out_enabled,
330 CategoryFilter* out_category_filter,
331 TraceOptions* out_trace_options) {
332 *out_enabled = is_monitoring_;
333 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter();
334 *out_trace_options = trace_options_;
337 bool TracingControllerImpl::CaptureMonitoringSnapshot(
338 const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
339 DCHECK_CURRENTLY_ON(BrowserThread::UI);
341 if (!can_disable_monitoring())
342 return false;
344 if (!monitoring_data_sink.get())
345 return false;
347 monitoring_data_sink_ = monitoring_data_sink;
349 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
350 // acked below.
351 pending_capture_monitoring_snapshot_ack_count_ =
352 trace_message_filters_.size() + 1;
353 pending_capture_monitoring_filters_ = trace_message_filters_;
355 // Handle special case of zero child processes by immediately flushing the
356 // trace log. Once the flush has completed the caller will be notified that
357 // the capture snapshot has ended.
358 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
359 // Flush asynchronously now, because we don't have any children to wait for.
360 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
361 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
362 base::Unretained(this)));
365 // Notify all child processes.
366 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
367 it != trace_message_filters_.end(); ++it) {
368 it->get()->SendCaptureMonitoringSnapshot();
371 #if defined(OS_ANDROID)
372 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
373 #endif
375 return true;
378 bool TracingControllerImpl::GetTraceBufferUsage(
379 const GetTraceBufferUsageCallback& callback) {
380 DCHECK_CURRENTLY_ON(BrowserThread::UI);
382 if (!can_get_trace_buffer_usage() || callback.is_null())
383 return false;
385 pending_trace_buffer_usage_callback_ = callback;
387 // Count myself in pending_trace_log_status_ack_count_, acked below.
388 pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
389 pending_trace_log_status_filters_ = trace_message_filters_;
390 maximum_trace_buffer_usage_ = 0;
391 approximate_event_count_ = 0;
393 base::trace_event::TraceLogStatus status =
394 TraceLog::GetInstance()->GetStatus();
395 // Call OnTraceLogStatusReply unconditionally for the browser process.
396 // This will result in immediate execution of the callback if there are no
397 // child processes.
398 BrowserThread::PostTask(
399 BrowserThread::UI, FROM_HERE,
400 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
401 base::Unretained(this), scoped_refptr<TraceMessageFilter>(),
402 status));
404 // Notify all child processes.
405 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
406 it != trace_message_filters_.end(); ++it) {
407 it->get()->SendGetTraceLogStatus();
409 return true;
412 bool TracingControllerImpl::SetWatchEvent(
413 const std::string& category_name,
414 const std::string& event_name,
415 const WatchEventCallback& callback) {
416 DCHECK_CURRENTLY_ON(BrowserThread::UI);
418 if (callback.is_null())
419 return false;
421 watch_category_name_ = category_name;
422 watch_event_name_ = event_name;
423 watch_event_callback_ = callback;
425 TraceLog::GetInstance()->SetWatchEvent(
426 category_name, event_name,
427 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
428 base::Unretained(this)));
430 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
431 it != trace_message_filters_.end(); ++it) {
432 it->get()->SendSetWatchEvent(category_name, event_name);
434 return true;
437 bool TracingControllerImpl::CancelWatchEvent() {
438 DCHECK_CURRENTLY_ON(BrowserThread::UI);
440 if (!can_cancel_watch_event())
441 return false;
443 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
444 it != trace_message_filters_.end(); ++it) {
445 it->get()->SendCancelWatchEvent();
448 watch_event_callback_.Reset();
449 return true;
452 void TracingControllerImpl::AddTraceMessageFilter(
453 TraceMessageFilter* trace_message_filter) {
454 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
455 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
456 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
457 base::Unretained(this),
458 make_scoped_refptr(trace_message_filter)));
459 return;
462 trace_message_filters_.insert(trace_message_filter);
463 if (can_cancel_watch_event()) {
464 trace_message_filter->SendSetWatchEvent(watch_category_name_,
465 watch_event_name_);
467 if (can_disable_recording()) {
468 trace_message_filter->SendBeginTracing(
469 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
470 TraceLog::GetInstance()->GetCurrentTraceOptions());
472 if (can_disable_monitoring()) {
473 trace_message_filter->SendEnableMonitoring(
474 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
475 TraceLog::GetInstance()->GetCurrentTraceOptions());
479 void TracingControllerImpl::RemoveTraceMessageFilter(
480 TraceMessageFilter* trace_message_filter) {
481 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
482 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
483 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
484 base::Unretained(this),
485 make_scoped_refptr(trace_message_filter)));
486 return;
489 // If a filter is removed while a response from that filter is pending then
490 // simulate the response. Otherwise the response count will be wrong and the
491 // completion callback will never be executed.
492 if (pending_disable_recording_ack_count_ > 0) {
493 TraceMessageFilterSet::const_iterator it =
494 pending_disable_recording_filters_.find(trace_message_filter);
495 if (it != pending_disable_recording_filters_.end()) {
496 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
497 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
498 base::Unretained(this),
499 make_scoped_refptr(trace_message_filter),
500 std::vector<std::string>()));
503 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
504 TraceMessageFilterSet::const_iterator it =
505 pending_capture_monitoring_filters_.find(trace_message_filter);
506 if (it != pending_capture_monitoring_filters_.end()) {
507 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
508 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
509 base::Unretained(this),
510 make_scoped_refptr(trace_message_filter)));
513 if (pending_trace_log_status_ack_count_ > 0) {
514 TraceMessageFilterSet::const_iterator it =
515 pending_trace_log_status_filters_.find(trace_message_filter);
516 if (it != pending_trace_log_status_filters_.end()) {
517 BrowserThread::PostTask(
518 BrowserThread::UI, FROM_HERE,
519 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
520 base::Unretained(this),
521 make_scoped_refptr(trace_message_filter),
522 base::trace_event::TraceLogStatus()));
525 if (pending_memory_dump_ack_count_ > 0) {
526 TraceMessageFilterSet::const_iterator it =
527 pending_memory_dump_filters_.find(trace_message_filter);
528 if (it != pending_memory_dump_filters_.end()) {
529 BrowserThread::PostTask(
530 BrowserThread::UI, FROM_HERE,
531 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
532 base::Unretained(this),
533 make_scoped_refptr(trace_message_filter),
534 pending_memory_dump_guid_, false /* success */));
537 trace_message_filters_.erase(trace_message_filter);
540 void TracingControllerImpl::OnDisableRecordingAcked(
541 TraceMessageFilter* trace_message_filter,
542 const std::vector<std::string>& known_category_groups) {
543 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
544 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
545 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
546 base::Unretained(this),
547 make_scoped_refptr(trace_message_filter),
548 known_category_groups));
549 return;
552 // Merge known_category_groups with known_category_groups_
553 known_category_groups_.insert(known_category_groups.begin(),
554 known_category_groups.end());
556 if (pending_disable_recording_ack_count_ == 0)
557 return;
559 if (trace_message_filter &&
560 !pending_disable_recording_filters_.erase(trace_message_filter)) {
561 // The response from the specified message filter has already been received.
562 return;
565 if (--pending_disable_recording_ack_count_ == 1) {
566 // All acks from subprocesses have been received. Now flush the local trace.
567 // During or after this call, our OnLocalTraceDataCollected will be
568 // called with the last of the local trace data.
569 TraceLog::GetInstance()->Flush(
570 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
571 base::Unretained(this)),
572 true);
573 return;
576 if (pending_disable_recording_ack_count_ != 0)
577 return;
579 // All acks (including from the subprocesses and the local trace) have been
580 // received.
581 is_recording_ = false;
583 // Trigger callback if one is set.
584 if (!pending_get_categories_done_callback_.is_null()) {
585 pending_get_categories_done_callback_.Run(known_category_groups_);
586 pending_get_categories_done_callback_.Reset();
587 } else if (trace_data_sink_.get()) {
588 trace_data_sink_->Close();
589 trace_data_sink_ = NULL;
593 #if defined(OS_CHROMEOS) || defined(OS_WIN)
594 void TracingControllerImpl::OnEndSystemTracingAcked(
595 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
596 DCHECK_CURRENTLY_ON(BrowserThread::UI);
598 if (trace_data_sink_.get()) {
599 #if defined(OS_WIN)
600 // The Windows kernel events are kept into a JSon format stored as string
601 // and must not be escaped.
602 std::string json_string = events_str_ptr->data();
603 #else
604 std::string json_string =
605 base::GetQuotedJSONString(events_str_ptr->data());
606 #endif
607 trace_data_sink_->SetSystemTrace(json_string);
609 DCHECK(!is_system_tracing_);
610 std::vector<std::string> category_groups;
611 OnDisableRecordingAcked(NULL, category_groups);
613 #endif
615 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
616 TraceMessageFilter* trace_message_filter) {
617 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
618 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
619 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
620 base::Unretained(this),
621 make_scoped_refptr(trace_message_filter)));
622 return;
625 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
626 return;
628 if (trace_message_filter &&
629 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
630 // The response from the specified message filter has already been received.
631 return;
634 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
635 // All acks from subprocesses have been received. Now flush the local trace.
636 // During or after this call, our OnLocalMonitoringTraceDataCollected
637 // will be called with the last of the local trace data.
638 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
639 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
640 base::Unretained(this)));
641 return;
644 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
645 return;
647 if (monitoring_data_sink_.get()) {
648 monitoring_data_sink_->Close();
649 monitoring_data_sink_ = NULL;
653 void TracingControllerImpl::OnTraceDataCollected(
654 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
655 // OnTraceDataCollected may be called from any browser thread, either by the
656 // local event trace system or from child processes via TraceMessageFilter.
657 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
658 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
659 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
660 base::Unretained(this), events_str_ptr));
661 return;
664 if (trace_data_sink_.get())
665 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
668 void TracingControllerImpl::OnMonitoringTraceDataCollected(
669 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
670 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
671 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
672 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
673 base::Unretained(this), events_str_ptr));
674 return;
677 if (monitoring_data_sink_.get())
678 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
681 void TracingControllerImpl::OnLocalTraceDataCollected(
682 const scoped_refptr<base::RefCountedString>& events_str_ptr,
683 bool has_more_events) {
684 if (events_str_ptr->data().size())
685 OnTraceDataCollected(events_str_ptr);
687 if (has_more_events)
688 return;
690 // Simulate an DisableRecordingAcked for the local trace.
691 std::vector<std::string> category_groups;
692 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
693 OnDisableRecordingAcked(NULL, category_groups);
696 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
697 const scoped_refptr<base::RefCountedString>& events_str_ptr,
698 bool has_more_events) {
699 if (events_str_ptr->data().size())
700 OnMonitoringTraceDataCollected(events_str_ptr);
702 if (has_more_events)
703 return;
705 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
706 OnCaptureMonitoringSnapshotAcked(NULL);
709 void TracingControllerImpl::OnTraceLogStatusReply(
710 TraceMessageFilter* trace_message_filter,
711 const base::trace_event::TraceLogStatus& status) {
712 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
713 BrowserThread::PostTask(
714 BrowserThread::UI, FROM_HERE,
715 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
716 base::Unretained(this),
717 make_scoped_refptr(trace_message_filter), status));
718 return;
721 if (pending_trace_log_status_ack_count_ == 0)
722 return;
724 if (trace_message_filter &&
725 !pending_trace_log_status_filters_.erase(trace_message_filter)) {
726 // The response from the specified message filter has already been received.
727 return;
730 float percent_full = static_cast<float>(
731 static_cast<double>(status.event_count) / status.event_capacity);
732 maximum_trace_buffer_usage_ =
733 std::max(maximum_trace_buffer_usage_, percent_full);
734 approximate_event_count_ += status.event_count;
736 if (--pending_trace_log_status_ack_count_ == 0) {
737 // Trigger callback if one is set.
738 pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
739 approximate_event_count_);
740 pending_trace_buffer_usage_callback_.Reset();
744 void TracingControllerImpl::OnWatchEventMatched() {
745 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
746 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
747 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
748 base::Unretained(this)));
749 return;
752 if (!watch_event_callback_.is_null())
753 watch_event_callback_.Run();
756 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
757 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
758 tracing_uis_.insert(tracing_ui);
761 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
762 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
763 DCHECK(it != tracing_uis_.end());
764 tracing_uis_.erase(it);
767 void TracingControllerImpl::RequestGlobalMemoryDump(
768 const base::trace_event::MemoryDumpRequestArgs& args,
769 const base::trace_event::MemoryDumpCallback& callback) {
770 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
771 BrowserThread::PostTask(
772 BrowserThread::UI, FROM_HERE,
773 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump,
774 base::Unretained(this), args, callback));
775 return;
777 // Abort if another dump is already in progress.
778 if (pending_memory_dump_guid_) {
779 DVLOG(1) << "Requested memory dump " << args.dump_guid
780 << " while waiting for " << pending_memory_dump_guid_;
781 if (!callback.is_null())
782 callback.Run(args.dump_guid, false /* success */);
783 return;
786 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by
787 // OnBrowserProcessMemoryDumpDone().
788 pending_memory_dump_ack_count_ = trace_message_filters_.size() + 1;
789 pending_memory_dump_filters_.clear();
790 failed_memory_dump_count_ = 0;
792 MemoryDumpManagerDelegate::CreateProcessDump(
793 args, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone,
794 base::Unretained(this)));
796 // If there are no child processes we are just done.
797 if (pending_memory_dump_ack_count_ == 1) {
798 if (!callback.is_null())
799 callback.Run(args.dump_guid, true /* success */);
800 return;
803 pending_memory_dump_guid_ = args.dump_guid;
804 pending_memory_dump_callback_ = callback;
805 pending_memory_dump_filters_ = trace_message_filters_;
807 for (const scoped_refptr<TraceMessageFilter>& tmf : trace_message_filters_)
808 tmf->SendProcessMemoryDumpRequest(args);
811 bool TracingControllerImpl::IsCoordinatorProcess() const {
812 return true;
815 void TracingControllerImpl::OnProcessMemoryDumpResponse(
816 TraceMessageFilter* trace_message_filter,
817 uint64 dump_guid,
818 bool success) {
819 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
820 BrowserThread::PostTask(
821 BrowserThread::UI, FROM_HERE,
822 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
823 base::Unretained(this),
824 make_scoped_refptr(trace_message_filter), dump_guid,
825 success));
826 return;
829 TraceMessageFilterSet::iterator it =
830 pending_memory_dump_filters_.find(trace_message_filter);
832 if (pending_memory_dump_guid_ != dump_guid ||
833 it == pending_memory_dump_filters_.end()) {
834 DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid;
835 return;
838 DCHECK_GT(pending_memory_dump_ack_count_, 0);
839 --pending_memory_dump_ack_count_;
840 pending_memory_dump_filters_.erase(it);
841 if (!success) {
842 ++failed_memory_dump_count_;
843 DLOG(WARNING) << "Global memory dump failed because of NACK from child "
844 << trace_message_filter->peer_pid();
846 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
849 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64 dump_guid,
850 bool success) {
851 DCHECK_GT(pending_memory_dump_ack_count_, 0);
852 --pending_memory_dump_ack_count_;
853 FinalizeGlobalMemoryDumpIfAllProcessesReplied();
856 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
857 if (pending_memory_dump_ack_count_ > 0)
858 return;
860 DCHECK_NE(0u, pending_memory_dump_guid_);
861 const bool global_success = failed_memory_dump_count_ == 0;
862 if (!pending_memory_dump_callback_.is_null()) {
863 pending_memory_dump_callback_.Run(pending_memory_dump_guid_,
864 global_success);
865 pending_memory_dump_callback_.Reset();
867 pending_memory_dump_guid_ = 0;
870 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
871 if (is_monitoring_ == is_monitoring)
872 return;
874 is_monitoring_ = is_monitoring;
875 #if !defined(OS_ANDROID)
876 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
877 it != tracing_uis_.end(); it++) {
878 (*it)->OnMonitoringStateChanged(is_monitoring);
880 #endif
883 } // namespace content