Disable PDF tests that are failing after combining PDF plugin into chrome.
[chromium-blink-merge.git] / content / browser / tracing / tracing_controller_impl.cc
blobafff0734c453a068f8654ce346778f824d0e3eaf
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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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)));
355 // Notify all child processes.
356 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
357 it != trace_message_filters_.end(); ++it) {
358 it->get()->SendEndTracing();
362 bool TracingControllerImpl::EnableMonitoring(
363 const CategoryFilter& category_filter,
364 const TraceOptions& trace_options,
365 const EnableMonitoringDoneCallback& callback) {
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
368 if (!can_enable_monitoring())
369 return false;
370 OnMonitoringStateChanged(true);
372 #if defined(OS_ANDROID)
373 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
374 #endif
376 trace_options_ = trace_options;
378 base::Closure on_enable_monitoring_done_callback =
379 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
380 base::Unretained(this),
381 category_filter, trace_options, callback);
382 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
383 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
384 base::Unretained(this),
385 category_filter,
386 base::trace_event::TraceLog::MONITORING_MODE,
387 trace_options,
388 on_enable_monitoring_done_callback));
389 return true;
392 void TracingControllerImpl::OnEnableMonitoringDone(
393 const CategoryFilter& category_filter,
394 const TraceOptions& trace_options,
395 const EnableMonitoringDoneCallback& callback) {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 // Notify all child processes.
399 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
400 it != trace_message_filters_.end(); ++it) {
401 it->get()->SendEnableMonitoring(category_filter, trace_options);
404 if (!callback.is_null())
405 callback.Run();
408 bool TracingControllerImpl::DisableMonitoring(
409 const DisableMonitoringDoneCallback& callback) {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
412 if (!can_disable_monitoring())
413 return false;
415 trace_options_ = TraceOptions();
416 base::Closure on_disable_monitoring_done_callback =
417 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
418 base::Unretained(this), callback);
419 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
420 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
421 base::Unretained(this),
422 on_disable_monitoring_done_callback));
423 return true;
426 scoped_refptr<TracingController::TraceDataSink>
427 TracingController::CreateStringSink(
428 const base::Callback<void(base::RefCountedString*)>& callback) {
429 return new StringTraceDataSink(callback);
432 scoped_refptr<TracingController::TraceDataSink>
433 TracingController::CreateFileSink(const base::FilePath& file_path,
434 const base::Closure& callback) {
435 return new FileTraceDataSink(file_path, callback);
438 void TracingControllerImpl::OnDisableMonitoringDone(
439 const DisableMonitoringDoneCallback& callback) {
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
442 OnMonitoringStateChanged(false);
444 // Notify all child processes.
445 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
446 it != trace_message_filters_.end(); ++it) {
447 it->get()->SendDisableMonitoring();
449 if (!callback.is_null())
450 callback.Run();
453 void TracingControllerImpl::GetMonitoringStatus(
454 bool* out_enabled,
455 CategoryFilter* out_category_filter,
456 TraceOptions* out_trace_options) {
457 *out_enabled = is_monitoring_;
458 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter();
459 *out_trace_options = trace_options_;
462 bool TracingControllerImpl::CaptureMonitoringSnapshot(
463 const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
466 if (!can_disable_monitoring())
467 return false;
469 if (!monitoring_data_sink.get())
470 return false;
472 monitoring_data_sink_ = monitoring_data_sink;
474 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
475 // acked below.
476 pending_capture_monitoring_snapshot_ack_count_ =
477 trace_message_filters_.size() + 1;
478 pending_capture_monitoring_filters_ = trace_message_filters_;
480 // Handle special case of zero child processes by immediately flushing the
481 // trace log. Once the flush has completed the caller will be notified that
482 // the capture snapshot has ended.
483 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
484 // Flush asynchronously now, because we don't have any children to wait for.
485 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
486 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
487 base::Unretained(this)));
490 // Notify all child processes.
491 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
492 it != trace_message_filters_.end(); ++it) {
493 it->get()->SendCaptureMonitoringSnapshot();
496 #if defined(OS_ANDROID)
497 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
498 #endif
500 return true;
503 bool TracingControllerImpl::GetTraceBufferUsage(
504 const GetTraceBufferUsageCallback& callback) {
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
507 if (!can_get_trace_buffer_usage() || callback.is_null())
508 return false;
510 pending_trace_buffer_usage_callback_ = callback;
512 // Count myself in pending_trace_log_status_ack_count_, acked below.
513 pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
514 pending_trace_log_status_filters_ = trace_message_filters_;
515 maximum_trace_buffer_usage_ = 0;
516 approximate_event_count_ = 0;
518 base::trace_event::TraceLogStatus status =
519 TraceLog::GetInstance()->GetStatus();
520 // Call OnTraceLogStatusReply unconditionally for the browser process.
521 // This will result in immediate execution of the callback if there are no
522 // child processes.
523 BrowserThread::PostTask(
524 BrowserThread::UI, FROM_HERE,
525 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
526 base::Unretained(this), scoped_refptr<TraceMessageFilter>(),
527 status));
529 // Notify all child processes.
530 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
531 it != trace_message_filters_.end(); ++it) {
532 it->get()->SendGetTraceLogStatus();
534 return true;
537 bool TracingControllerImpl::SetWatchEvent(
538 const std::string& category_name,
539 const std::string& event_name,
540 const WatchEventCallback& callback) {
541 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
543 if (callback.is_null())
544 return false;
546 watch_category_name_ = category_name;
547 watch_event_name_ = event_name;
548 watch_event_callback_ = callback;
550 TraceLog::GetInstance()->SetWatchEvent(
551 category_name, event_name,
552 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
553 base::Unretained(this)));
555 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
556 it != trace_message_filters_.end(); ++it) {
557 it->get()->SendSetWatchEvent(category_name, event_name);
559 return true;
562 bool TracingControllerImpl::CancelWatchEvent() {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
565 if (!can_cancel_watch_event())
566 return false;
568 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
569 it != trace_message_filters_.end(); ++it) {
570 it->get()->SendCancelWatchEvent();
573 watch_event_callback_.Reset();
574 return true;
577 void TracingControllerImpl::AddTraceMessageFilter(
578 TraceMessageFilter* trace_message_filter) {
579 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
580 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
581 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
582 base::Unretained(this),
583 make_scoped_refptr(trace_message_filter)));
584 return;
587 trace_message_filters_.insert(trace_message_filter);
588 if (can_cancel_watch_event()) {
589 trace_message_filter->SendSetWatchEvent(watch_category_name_,
590 watch_event_name_);
592 if (can_disable_recording()) {
593 trace_message_filter->SendBeginTracing(
594 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
595 TraceLog::GetInstance()->GetCurrentTraceOptions());
597 if (can_disable_monitoring()) {
598 trace_message_filter->SendEnableMonitoring(
599 TraceLog::GetInstance()->GetCurrentCategoryFilter(),
600 TraceLog::GetInstance()->GetCurrentTraceOptions());
604 void TracingControllerImpl::RemoveTraceMessageFilter(
605 TraceMessageFilter* trace_message_filter) {
606 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
607 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
608 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
609 base::Unretained(this),
610 make_scoped_refptr(trace_message_filter)));
611 return;
614 // If a filter is removed while a response from that filter is pending then
615 // simulate the response. Otherwise the response count will be wrong and the
616 // completion callback will never be executed.
617 if (pending_disable_recording_ack_count_ > 0) {
618 TraceMessageFilterSet::const_iterator it =
619 pending_disable_recording_filters_.find(trace_message_filter);
620 if (it != pending_disable_recording_filters_.end()) {
621 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
622 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
623 base::Unretained(this),
624 make_scoped_refptr(trace_message_filter),
625 std::vector<std::string>()));
628 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
629 TraceMessageFilterSet::const_iterator it =
630 pending_capture_monitoring_filters_.find(trace_message_filter);
631 if (it != pending_capture_monitoring_filters_.end()) {
632 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
633 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
634 base::Unretained(this),
635 make_scoped_refptr(trace_message_filter)));
638 if (pending_trace_log_status_ack_count_ > 0) {
639 TraceMessageFilterSet::const_iterator it =
640 pending_trace_log_status_filters_.find(trace_message_filter);
641 if (it != pending_trace_log_status_filters_.end()) {
642 BrowserThread::PostTask(
643 BrowserThread::UI, FROM_HERE,
644 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
645 base::Unretained(this),
646 make_scoped_refptr(trace_message_filter),
647 base::trace_event::TraceLogStatus()));
651 trace_message_filters_.erase(trace_message_filter);
654 void TracingControllerImpl::OnDisableRecordingAcked(
655 TraceMessageFilter* trace_message_filter,
656 const std::vector<std::string>& known_category_groups) {
657 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
658 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
659 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
660 base::Unretained(this),
661 make_scoped_refptr(trace_message_filter),
662 known_category_groups));
663 return;
666 // Merge known_category_groups with known_category_groups_
667 known_category_groups_.insert(known_category_groups.begin(),
668 known_category_groups.end());
670 if (pending_disable_recording_ack_count_ == 0)
671 return;
673 if (trace_message_filter &&
674 !pending_disable_recording_filters_.erase(trace_message_filter)) {
675 // The response from the specified message filter has already been received.
676 return;
679 if (--pending_disable_recording_ack_count_ == 1) {
680 // All acks from subprocesses have been received. Now flush the local trace.
681 // During or after this call, our OnLocalTraceDataCollected will be
682 // called with the last of the local trace data.
683 TraceLog::GetInstance()->Flush(
684 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
685 base::Unretained(this)));
686 return;
689 if (pending_disable_recording_ack_count_ != 0)
690 return;
692 // All acks (including from the subprocesses and the local trace) have been
693 // received.
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 (trace_data_sink_.get()) {
701 trace_data_sink_->Close();
702 trace_data_sink_ = NULL;
706 #if defined(OS_CHROMEOS) || defined(OS_WIN)
707 void TracingControllerImpl::OnEndSystemTracingAcked(
708 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
709 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
711 if (trace_data_sink_.get()) {
712 #if defined(OS_WIN)
713 // The Windows kernel events are kept into a JSon format stored as string
714 // and must not be escaped.
715 std::string json_string = events_str_ptr->data();
716 #else
717 std::string json_string =
718 base::GetQuotedJSONString(events_str_ptr->data());
719 #endif
720 trace_data_sink_->SetSystemTrace(json_string);
722 DCHECK(!is_system_tracing_);
723 std::vector<std::string> category_groups;
724 OnDisableRecordingAcked(NULL, category_groups);
726 #endif
728 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
729 TraceMessageFilter* trace_message_filter) {
730 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
731 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
732 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
733 base::Unretained(this),
734 make_scoped_refptr(trace_message_filter)));
735 return;
738 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
739 return;
741 if (trace_message_filter &&
742 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
743 // The response from the specified message filter has already been received.
744 return;
747 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
748 // All acks from subprocesses have been received. Now flush the local trace.
749 // During or after this call, our OnLocalMonitoringTraceDataCollected
750 // will be called with the last of the local trace data.
751 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
752 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
753 base::Unretained(this)));
754 return;
757 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
758 return;
760 if (monitoring_data_sink_.get()) {
761 monitoring_data_sink_->Close();
762 monitoring_data_sink_ = NULL;
766 void TracingControllerImpl::OnTraceDataCollected(
767 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
768 // OnTraceDataCollected may be called from any browser thread, either by the
769 // local event trace system or from child processes via TraceMessageFilter.
770 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
771 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
772 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
773 base::Unretained(this), events_str_ptr));
774 return;
777 if (trace_data_sink_.get())
778 trace_data_sink_->AddTraceChunk(events_str_ptr->data());
781 void TracingControllerImpl::OnMonitoringTraceDataCollected(
782 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
783 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
784 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
785 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
786 base::Unretained(this), events_str_ptr));
787 return;
790 if (monitoring_data_sink_.get())
791 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
794 void TracingControllerImpl::OnLocalTraceDataCollected(
795 const scoped_refptr<base::RefCountedString>& events_str_ptr,
796 bool has_more_events) {
797 if (events_str_ptr->data().size())
798 OnTraceDataCollected(events_str_ptr);
800 if (has_more_events)
801 return;
803 // Simulate an DisableRecordingAcked for the local trace.
804 std::vector<std::string> category_groups;
805 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
806 OnDisableRecordingAcked(NULL, category_groups);
809 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
810 const scoped_refptr<base::RefCountedString>& events_str_ptr,
811 bool has_more_events) {
812 if (events_str_ptr->data().size())
813 OnMonitoringTraceDataCollected(events_str_ptr);
815 if (has_more_events)
816 return;
818 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
819 OnCaptureMonitoringSnapshotAcked(NULL);
822 void TracingControllerImpl::OnTraceLogStatusReply(
823 TraceMessageFilter* trace_message_filter,
824 const base::trace_event::TraceLogStatus& status) {
825 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
826 BrowserThread::PostTask(
827 BrowserThread::UI, FROM_HERE,
828 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
829 base::Unretained(this),
830 make_scoped_refptr(trace_message_filter), status));
831 return;
834 if (pending_trace_log_status_ack_count_ == 0)
835 return;
837 if (trace_message_filter &&
838 !pending_trace_log_status_filters_.erase(trace_message_filter)) {
839 // The response from the specified message filter has already been received.
840 return;
843 float percent_full = static_cast<float>(
844 static_cast<double>(status.event_count) / status.event_capacity);
845 maximum_trace_buffer_usage_ =
846 std::max(maximum_trace_buffer_usage_, percent_full);
847 approximate_event_count_ += status.event_count;
849 if (--pending_trace_log_status_ack_count_ == 0) {
850 // Trigger callback if one is set.
851 pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
852 approximate_event_count_);
853 pending_trace_buffer_usage_callback_.Reset();
857 void TracingControllerImpl::OnWatchEventMatched() {
858 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
859 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
860 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
861 base::Unretained(this)));
862 return;
865 if (!watch_event_callback_.is_null())
866 watch_event_callback_.Run();
869 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
870 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
871 tracing_uis_.insert(tracing_ui);
874 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
875 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
876 DCHECK(it != tracing_uis_.end());
877 tracing_uis_.erase(it);
880 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
881 if (is_monitoring_ == is_monitoring)
882 return;
884 is_monitoring_ = is_monitoring;
885 #if !defined(OS_ANDROID)
886 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
887 it != tracing_uis_.end(); it++) {
888 (*it)->OnMonitoringStateChanged(is_monitoring);
890 #endif
893 } // namespace content