Refactors gesture conversion functions to ui/events/blink
[chromium-blink-merge.git] / content / browser / tracing / tracing_controller_impl.cc
blob1622819b04d21abeb2eb3af9fad223cd07e92375
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 class FileTraceDataSink : public TracingController::TraceDataSink {
39 public:
40 explicit FileTraceDataSink(const base::FilePath& trace_file_path,
41 const base::Closure& callback)
42 : file_path_(trace_file_path),
43 completion_callback_(callback),
44 file_(NULL) {}
46 void AddTraceChunk(const std::string& chunk) override {
47 std::string tmp = chunk;
48 scoped_refptr<base::RefCountedString> chunk_ptr =
49 base::RefCountedString::TakeString(&tmp);
50 BrowserThread::PostTask(
51 BrowserThread::FILE,
52 FROM_HERE,
53 base::Bind(
54 &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr));
56 void SetSystemTrace(const std::string& data) override {
57 system_trace_ = data;
59 void Close() override {
60 BrowserThread::PostTask(
61 BrowserThread::FILE,
62 FROM_HERE,
63 base::Bind(&FileTraceDataSink::CloseOnFileThread, this));
66 private:
67 ~FileTraceDataSink() override { DCHECK(file_ == NULL); }
69 void AddTraceChunkOnFileThread(
70 const scoped_refptr<base::RefCountedString> chunk) {
71 if (file_ != NULL)
72 fputc(',', file_);
73 else if (!OpenFileIfNeededOnFileThread())
74 return;
75 ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()),
76 1, file_));
79 bool OpenFileIfNeededOnFileThread() {
80 if (file_ != NULL)
81 return true;
82 file_ = base::OpenFile(file_path_, "w");
83 if (file_ == NULL) {
84 LOG(ERROR) << "Failed to open " << file_path_.value();
85 return false;
87 const char preamble[] = "{\"traceEvents\": [";
88 ignore_result(fwrite(preamble, strlen(preamble), 1, file_));
89 return true;
92 void CloseOnFileThread() {
93 if (OpenFileIfNeededOnFileThread()) {
94 fputc(']', file_);
95 if (!system_trace_.empty()) {
96 const char systemTraceEvents[] = ",\"systemTraceEvents\": ";
97 ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents),
98 1, file_));
99 ignore_result(fwrite(system_trace_.c_str(),
100 strlen(system_trace_.c_str()), 1, file_));
102 fputc('}', file_);
103 base::CloseFile(file_);
104 file_ = NULL;
106 BrowserThread::PostTask(
107 BrowserThread::UI,
108 FROM_HERE,
109 base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this));
112 void FinalizeOnUIThread() { completion_callback_.Run(); }
114 base::FilePath file_path_;
115 base::Closure completion_callback_;
116 FILE* file_;
117 std::string system_trace_;
119 DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink);
122 class StringTraceDataSink : public TracingController::TraceDataSink {
123 public:
124 typedef base::Callback<void(base::RefCountedString*)> CompletionCallback;
126 explicit StringTraceDataSink(CompletionCallback callback)
127 : completion_callback_(callback) {}
129 // TracingController::TraceDataSink implementation
130 void AddTraceChunk(const std::string& chunk) override {
131 if (!trace_.empty())
132 trace_ += ",";
133 trace_ += chunk;
135 void SetSystemTrace(const std::string& data) override {
136 system_trace_ = data;
138 void Close() override {
139 std::string result = "{\"traceEvents\":[" + trace_ + "]";
140 if (!system_trace_.empty())
141 result += ",\"systemTraceEvents\": " + system_trace_;
142 result += "}";
144 scoped_refptr<base::RefCountedString> str =
145 base::RefCountedString::TakeString(&result);
146 completion_callback_.Run(str.get());
149 private:
150 ~StringTraceDataSink() override {}
152 std::string trace_;
153 std::string system_trace_;
154 CompletionCallback completion_callback_;
156 DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink);
159 } // namespace
161 TracingController* TracingController::GetInstance() {
162 return TracingControllerImpl::GetInstance();
165 TracingControllerImpl::TracingControllerImpl()
166 : pending_disable_recording_ack_count_(0),
167 pending_capture_monitoring_snapshot_ack_count_(0),
168 pending_trace_log_status_ack_count_(0),
169 maximum_trace_buffer_usage_(0),
170 approximate_event_count_(0),
171 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
172 // is specified in command line.
173 #if defined(OS_CHROMEOS) || defined(OS_WIN)
174 is_system_tracing_(false),
175 #endif
176 is_recording_(TraceLog::GetInstance()->IsEnabled()),
177 is_monitoring_(false) {
180 TracingControllerImpl::~TracingControllerImpl() {
181 // This is a Leaky instance.
182 NOTREACHED();
185 TracingControllerImpl* TracingControllerImpl::GetInstance() {
186 return g_controller.Pointer();
189 bool TracingControllerImpl::GetCategories(
190 const GetCategoriesDoneCallback& callback) {
191 DCHECK_CURRENTLY_ON(BrowserThread::UI);
193 // Known categories come back from child processes with the EndTracingAck
194 // message. So to get known categories, just begin and end tracing immediately
195 // afterwards. This will ping all the child processes for categories.
196 pending_get_categories_done_callback_ = callback;
197 if (!EnableRecording(
198 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
199 pending_get_categories_done_callback_.Reset();
200 return false;
203 bool ok = DisableRecording(NULL);
204 DCHECK(ok);
205 return true;
208 void TracingControllerImpl::SetEnabledOnFileThread(
209 const CategoryFilter& category_filter,
210 int mode,
211 const TraceOptions& trace_options,
212 const base::Closure& callback) {
213 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
215 TraceLog::GetInstance()->SetEnabled(
216 category_filter, static_cast<TraceLog::Mode>(mode), trace_options);
217 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
220 void TracingControllerImpl::SetDisabledOnFileThread(
221 const base::Closure& callback) {
222 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
224 TraceLog::GetInstance()->SetDisabled();
225 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
228 bool TracingControllerImpl::EnableRecording(
229 const CategoryFilter& category_filter,
230 const TraceOptions& trace_options,
231 const EnableRecordingDoneCallback& callback) {
232 DCHECK_CURRENTLY_ON(BrowserThread::UI);
234 if (!can_enable_recording())
235 return false;
236 is_recording_ = true;
238 #if defined(OS_ANDROID)
239 if (pending_get_categories_done_callback_.is_null())
240 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
241 #endif
243 trace_options_ = trace_options;
245 if (trace_options.enable_systrace) {
246 #if defined(OS_CHROMEOS)
247 DCHECK(!is_system_tracing_);
248 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
249 StartSystemTracing();
250 is_system_tracing_ = true;
251 #elif defined(OS_WIN)
252 DCHECK(!is_system_tracing_);
253 is_system_tracing_ =
254 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
255 #endif
259 base::Closure on_enable_recording_done_callback =
260 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
261 base::Unretained(this),
262 category_filter, trace_options, callback);
263 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
264 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
265 base::Unretained(this),
266 category_filter,
267 base::trace_event::TraceLog::RECORDING_MODE,
268 trace_options,
269 on_enable_recording_done_callback));
270 return true;
273 void TracingControllerImpl::OnEnableRecordingDone(
274 const CategoryFilter& category_filter,
275 const TraceOptions& trace_options,
276 const EnableRecordingDoneCallback& callback) {
277 DCHECK_CURRENTLY_ON(BrowserThread::UI);
279 // Notify all child processes.
280 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
281 it != trace_message_filters_.end(); ++it) {
282 it->get()->SendBeginTracing(category_filter, trace_options);
285 if (!callback.is_null())
286 callback.Run();
289 bool TracingControllerImpl::DisableRecording(
290 const scoped_refptr<TraceDataSink>& trace_data_sink) {
291 DCHECK_CURRENTLY_ON(BrowserThread::UI);
293 if (!can_disable_recording())
294 return false;
296 trace_data_sink_ = trace_data_sink;
297 trace_options_ = TraceOptions();
298 // Disable local trace early to avoid traces during end-tracing process from
299 // interfering with the process.
300 base::Closure on_disable_recording_done_callback = base::Bind(
301 &TracingControllerImpl::OnDisableRecordingDone, base::Unretained(this));
302 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
303 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
304 base::Unretained(this),
305 on_disable_recording_done_callback));
306 return true;
309 void TracingControllerImpl::OnDisableRecordingDone() {
310 DCHECK_CURRENTLY_ON(BrowserThread::UI);
312 #if defined(OS_ANDROID)
313 if (pending_get_categories_done_callback_.is_null())
314 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
315 #endif
317 // Count myself (local trace) in pending_disable_recording_ack_count_,
318 // acked below.
319 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
320 pending_disable_recording_filters_ = trace_message_filters_;
322 #if defined(OS_CHROMEOS) || defined(OS_WIN)
323 if (is_system_tracing_) {
324 // Disable system tracing.
325 is_system_tracing_ = false;
326 ++pending_disable_recording_ack_count_;
328 #if defined(OS_CHROMEOS)
329 scoped_refptr<base::TaskRunner> task_runner =
330 BrowserThread::GetBlockingPool();
331 chromeos::DBusThreadManager::Get()
332 ->GetDebugDaemonClient()
333 ->RequestStopSystemTracing(
334 task_runner,
335 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
336 base::Unretained(this)));
337 #elif defined(OS_WIN)
338 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
339 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
340 base::Unretained(this)));
341 #endif
343 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
345 // Handle special case of zero child processes by immediately flushing the
346 // trace log. Once the flush has completed the caller will be notified that
347 // tracing has ended.
348 if (pending_disable_recording_ack_count_ == 1) {
349 // Flush asynchronously now, because we don't have any children to wait for.
350 TraceLog::GetInstance()->Flush(
351 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
352 base::Unretained(this)),
353 true);
356 // Notify all child processes.
357 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
358 it != trace_message_filters_.end(); ++it) {
359 it->get()->SendEndTracing();
363 bool TracingControllerImpl::EnableMonitoring(
364 const CategoryFilter& category_filter,
365 const TraceOptions& trace_options,
366 const EnableMonitoringDoneCallback& callback) {
367 DCHECK_CURRENTLY_ON(BrowserThread::UI);
369 if (!can_enable_monitoring())
370 return false;
371 OnMonitoringStateChanged(true);
373 #if defined(OS_ANDROID)
374 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
375 #endif
377 trace_options_ = trace_options;
379 base::Closure on_enable_monitoring_done_callback =
380 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
381 base::Unretained(this),
382 category_filter, trace_options, callback);
383 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
384 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
385 base::Unretained(this),
386 category_filter,
387 base::trace_event::TraceLog::MONITORING_MODE,
388 trace_options,
389 on_enable_monitoring_done_callback));
390 return true;
393 void TracingControllerImpl::OnEnableMonitoringDone(
394 const CategoryFilter& category_filter,
395 const TraceOptions& trace_options,
396 const EnableMonitoringDoneCallback& callback) {
397 DCHECK_CURRENTLY_ON(BrowserThread::UI);
399 // Notify all child processes.
400 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
401 it != trace_message_filters_.end(); ++it) {
402 it->get()->SendEnableMonitoring(category_filter, trace_options);
405 if (!callback.is_null())
406 callback.Run();
409 bool TracingControllerImpl::DisableMonitoring(
410 const DisableMonitoringDoneCallback& callback) {
411 DCHECK_CURRENTLY_ON(BrowserThread::UI);
413 if (!can_disable_monitoring())
414 return false;
416 trace_options_ = TraceOptions();
417 base::Closure on_disable_monitoring_done_callback =
418 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
419 base::Unretained(this), callback);
420 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
421 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
422 base::Unretained(this),
423 on_disable_monitoring_done_callback));
424 return true;
427 scoped_refptr<TracingController::TraceDataSink>
428 TracingController::CreateStringSink(
429 const base::Callback<void(base::RefCountedString*)>& callback) {
430 return new StringTraceDataSink(callback);
433 scoped_refptr<TracingController::TraceDataSink>
434 TracingController::CreateFileSink(const base::FilePath& file_path,
435 const base::Closure& callback) {
436 return new FileTraceDataSink(file_path, callback);
439 void TracingControllerImpl::OnDisableMonitoringDone(
440 const DisableMonitoringDoneCallback& callback) {
441 DCHECK_CURRENTLY_ON(BrowserThread::UI);
443 OnMonitoringStateChanged(false);
445 // Notify all child processes.
446 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
447 it != trace_message_filters_.end(); ++it) {
448 it->get()->SendDisableMonitoring();
450 if (!callback.is_null())
451 callback.Run();
454 void TracingControllerImpl::GetMonitoringStatus(
455 bool* out_enabled,
456 CategoryFilter* out_category_filter,
457 TraceOptions* out_trace_options) {
458 *out_enabled = is_monitoring_;
459 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter();
460 *out_trace_options = trace_options_;
463 bool TracingControllerImpl::CaptureMonitoringSnapshot(
464 const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
465 DCHECK_CURRENTLY_ON(BrowserThread::UI);
467 if (!can_disable_monitoring())
468 return false;
470 if (!monitoring_data_sink.get())
471 return false;
473 monitoring_data_sink_ = monitoring_data_sink;
475 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
476 // acked below.
477 pending_capture_monitoring_snapshot_ack_count_ =
478 trace_message_filters_.size() + 1;
479 pending_capture_monitoring_filters_ = trace_message_filters_;
481 // Handle special case of zero child processes by immediately flushing the
482 // trace log. Once the flush has completed the caller will be notified that
483 // the capture snapshot has ended.
484 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
485 // Flush asynchronously now, because we don't have any children to wait for.
486 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
487 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
488 base::Unretained(this)));
491 // Notify all child processes.
492 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
493 it != trace_message_filters_.end(); ++it) {
494 it->get()->SendCaptureMonitoringSnapshot();
497 #if defined(OS_ANDROID)
498 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
499 #endif
501 return true;
504 bool TracingControllerImpl::GetTraceBufferUsage(
505 const GetTraceBufferUsageCallback& callback) {
506 DCHECK_CURRENTLY_ON(BrowserThread::UI);
508 if (!can_get_trace_buffer_usage() || callback.is_null())
509 return false;
511 pending_trace_buffer_usage_callback_ = callback;
513 // Count myself in pending_trace_log_status_ack_count_, acked below.
514 pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
515 pending_trace_log_status_filters_ = trace_message_filters_;
516 maximum_trace_buffer_usage_ = 0;
517 approximate_event_count_ = 0;
519 base::trace_event::TraceLogStatus status =
520 TraceLog::GetInstance()->GetStatus();
521 // Call OnTraceLogStatusReply unconditionally for the browser process.
522 // This will result in immediate execution of the callback if there are no
523 // child processes.
524 BrowserThread::PostTask(
525 BrowserThread::UI, FROM_HERE,
526 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
527 base::Unretained(this), scoped_refptr<TraceMessageFilter>(),
528 status));
530 // Notify all child processes.
531 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
532 it != trace_message_filters_.end(); ++it) {
533 it->get()->SendGetTraceLogStatus();
535 return true;
538 bool TracingControllerImpl::SetWatchEvent(
539 const std::string& category_name,
540 const std::string& event_name,
541 const WatchEventCallback& callback) {
542 DCHECK_CURRENTLY_ON(BrowserThread::UI);
544 if (callback.is_null())
545 return false;
547 watch_category_name_ = category_name;
548 watch_event_name_ = event_name;
549 watch_event_callback_ = callback;
551 TraceLog::GetInstance()->SetWatchEvent(
552 category_name, event_name,
553 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
554 base::Unretained(this)));
556 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
557 it != trace_message_filters_.end(); ++it) {
558 it->get()->SendSetWatchEvent(category_name, event_name);
560 return true;
563 bool TracingControllerImpl::CancelWatchEvent() {
564 DCHECK_CURRENTLY_ON(BrowserThread::UI);
566 if (!can_cancel_watch_event())
567 return false;
569 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
570 it != trace_message_filters_.end(); ++it) {
571 it->get()->SendCancelWatchEvent();
574 watch_event_callback_.Reset();
575 return true;
578 void TracingControllerImpl::AddTraceMessageFilter(
579 TraceMessageFilter* trace_message_filter) {
580 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
581 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
582 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
583 base::Unretained(this),
584 make_scoped_refptr(trace_message_filter)));
585 return;
588 trace_message_filters_.insert(trace_message_filter);
589 if (can_cancel_watch_event()) {
590 trace_message_filter->SendSetWatchEvent(watch_category_name_,
591 watch_event_name_);
593 if (can_disable_recording()) {
594 trace_message_filter->SendBeginTracing(
595 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
596 TraceLog::GetInstance()->GetCurrentTraceOptions());
598 if (can_disable_monitoring()) {
599 trace_message_filter->SendEnableMonitoring(
600 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
601 TraceLog::GetInstance()->GetCurrentTraceOptions());
605 void TracingControllerImpl::RemoveTraceMessageFilter(
606 TraceMessageFilter* trace_message_filter) {
607 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
608 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
609 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
610 base::Unretained(this),
611 make_scoped_refptr(trace_message_filter)));
612 return;
615 // If a filter is removed while a response from that filter is pending then
616 // simulate the response. Otherwise the response count will be wrong and the
617 // completion callback will never be executed.
618 if (pending_disable_recording_ack_count_ > 0) {
619 TraceMessageFilterSet::const_iterator it =
620 pending_disable_recording_filters_.find(trace_message_filter);
621 if (it != pending_disable_recording_filters_.end()) {
622 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
623 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
624 base::Unretained(this),
625 make_scoped_refptr(trace_message_filter),
626 std::vector<std::string>()));
629 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
630 TraceMessageFilterSet::const_iterator it =
631 pending_capture_monitoring_filters_.find(trace_message_filter);
632 if (it != pending_capture_monitoring_filters_.end()) {
633 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
634 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
635 base::Unretained(this),
636 make_scoped_refptr(trace_message_filter)));
639 if (pending_trace_log_status_ack_count_ > 0) {
640 TraceMessageFilterSet::const_iterator it =
641 pending_trace_log_status_filters_.find(trace_message_filter);
642 if (it != pending_trace_log_status_filters_.end()) {
643 BrowserThread::PostTask(
644 BrowserThread::UI, FROM_HERE,
645 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
646 base::Unretained(this),
647 make_scoped_refptr(trace_message_filter),
648 base::trace_event::TraceLogStatus()));
652 trace_message_filters_.erase(trace_message_filter);
655 void TracingControllerImpl::OnDisableRecordingAcked(
656 TraceMessageFilter* trace_message_filter,
657 const std::vector<std::string>& known_category_groups) {
658 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
659 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
660 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
661 base::Unretained(this),
662 make_scoped_refptr(trace_message_filter),
663 known_category_groups));
664 return;
667 // Merge known_category_groups with known_category_groups_
668 known_category_groups_.insert(known_category_groups.begin(),
669 known_category_groups.end());
671 if (pending_disable_recording_ack_count_ == 0)
672 return;
674 if (trace_message_filter &&
675 !pending_disable_recording_filters_.erase(trace_message_filter)) {
676 // The response from the specified message filter has already been received.
677 return;
680 if (--pending_disable_recording_ack_count_ == 1) {
681 // All acks from subprocesses have been received. Now flush the local trace.
682 // During or after this call, our OnLocalTraceDataCollected will be
683 // called with the last of the local trace data.
684 TraceLog::GetInstance()->Flush(
685 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
686 base::Unretained(this)),
687 true);
688 return;
691 if (pending_disable_recording_ack_count_ != 0)
692 return;
694 // All acks (including from the subprocesses and the local trace) have been
695 // received.
696 is_recording_ = false;
698 // Trigger callback if one is set.
699 if (!pending_get_categories_done_callback_.is_null()) {
700 pending_get_categories_done_callback_.Run(known_category_groups_);
701 pending_get_categories_done_callback_.Reset();
702 } else if (trace_data_sink_.get()) {
703 trace_data_sink_->Close();
704 trace_data_sink_ = NULL;
708 #if defined(OS_CHROMEOS) || defined(OS_WIN)
709 void TracingControllerImpl::OnEndSystemTracingAcked(
710 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
711 DCHECK_CURRENTLY_ON(BrowserThread::UI);
713 if (trace_data_sink_.get()) {
714 #if defined(OS_WIN)
715 // The Windows kernel events are kept into a JSon format stored as string
716 // and must not be escaped.
717 std::string json_string = events_str_ptr->data();
718 #else
719 std::string json_string =
720 base::GetQuotedJSONString(events_str_ptr->data());
721 #endif
722 trace_data_sink_->SetSystemTrace(json_string);
724 DCHECK(!is_system_tracing_);
725 std::vector<std::string> category_groups;
726 OnDisableRecordingAcked(NULL, category_groups);
728 #endif
730 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
731 TraceMessageFilter* trace_message_filter) {
732 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
733 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
734 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
735 base::Unretained(this),
736 make_scoped_refptr(trace_message_filter)));
737 return;
740 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
741 return;
743 if (trace_message_filter &&
744 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
745 // The response from the specified message filter has already been received.
746 return;
749 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
750 // All acks from subprocesses have been received. Now flush the local trace.
751 // During or after this call, our OnLocalMonitoringTraceDataCollected
752 // will be called with the last of the local trace data.
753 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
754 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
755 base::Unretained(this)));
756 return;
759 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
760 return;
762 if (monitoring_data_sink_.get()) {
763 monitoring_data_sink_->Close();
764 monitoring_data_sink_ = NULL;
768 void TracingControllerImpl::OnTraceDataCollected(
769 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
770 // OnTraceDataCollected may be called from any browser thread, either by the
771 // local event trace system or from child processes via TraceMessageFilter.
772 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
773 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
774 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
775 base::Unretained(this), events_str_ptr));
776 return;
779 if (trace_data_sink_.get())
780 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
783 void TracingControllerImpl::OnMonitoringTraceDataCollected(
784 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
785 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
786 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
787 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
788 base::Unretained(this), events_str_ptr));
789 return;
792 if (monitoring_data_sink_.get())
793 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
796 void TracingControllerImpl::OnLocalTraceDataCollected(
797 const scoped_refptr<base::RefCountedString>& events_str_ptr,
798 bool has_more_events) {
799 if (events_str_ptr->data().size())
800 OnTraceDataCollected(events_str_ptr);
802 if (has_more_events)
803 return;
805 // Simulate an DisableRecordingAcked for the local trace.
806 std::vector<std::string> category_groups;
807 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
808 OnDisableRecordingAcked(NULL, category_groups);
811 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
812 const scoped_refptr<base::RefCountedString>& events_str_ptr,
813 bool has_more_events) {
814 if (events_str_ptr->data().size())
815 OnMonitoringTraceDataCollected(events_str_ptr);
817 if (has_more_events)
818 return;
820 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
821 OnCaptureMonitoringSnapshotAcked(NULL);
824 void TracingControllerImpl::OnTraceLogStatusReply(
825 TraceMessageFilter* trace_message_filter,
826 const base::trace_event::TraceLogStatus& status) {
827 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
828 BrowserThread::PostTask(
829 BrowserThread::UI, FROM_HERE,
830 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
831 base::Unretained(this),
832 make_scoped_refptr(trace_message_filter), status));
833 return;
836 if (pending_trace_log_status_ack_count_ == 0)
837 return;
839 if (trace_message_filter &&
840 !pending_trace_log_status_filters_.erase(trace_message_filter)) {
841 // The response from the specified message filter has already been received.
842 return;
845 float percent_full = static_cast<float>(
846 static_cast<double>(status.event_count) / status.event_capacity);
847 maximum_trace_buffer_usage_ =
848 std::max(maximum_trace_buffer_usage_, percent_full);
849 approximate_event_count_ += status.event_count;
851 if (--pending_trace_log_status_ack_count_ == 0) {
852 // Trigger callback if one is set.
853 pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
854 approximate_event_count_);
855 pending_trace_buffer_usage_callback_.Reset();
859 void TracingControllerImpl::OnWatchEventMatched() {
860 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
861 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
862 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
863 base::Unretained(this)));
864 return;
867 if (!watch_event_callback_.is_null())
868 watch_event_callback_.Run();
871 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
872 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
873 tracing_uis_.insert(tracing_ui);
876 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
877 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
878 DCHECK(it != tracing_uis_.end());
879 tracing_uis_.erase(it);
882 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
883 if (is_monitoring_ == is_monitoring)
884 return;
886 is_monitoring_ = is_monitoring;
887 #if !defined(OS_ANDROID)
888 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
889 it != tracing_uis_.end(); it++) {
890 (*it)->OnMonitoringStateChanged(is_monitoring);
892 #endif
895 } // namespace content