1 // Copyright 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.
5 #include "content/browser/tracing/tracing_controller_impl.h"
8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h"
10 #include "base/json/string_escape.h"
11 #include "base/strings/string_number_conversions.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 using base::debug::TraceLog;
24 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
25 LAZY_INSTANCE_INITIALIZER;
29 TracingController* TracingController::GetInstance() {
30 return TracingControllerImpl::GetInstance();
33 class TracingControllerImpl::ResultFile {
35 explicit ResultFile(const base::FilePath& path);
36 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
37 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
38 base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
39 base::Unretained(this), events_str_ptr));
41 void Close(const base::Closure& callback) {
42 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
43 base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
44 base::Unretained(this), callback));
46 const base::FilePath& path() const { return path_; }
50 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
51 void CloseTask(const base::Closure& callback);
55 bool has_at_least_one_result_;
57 DISALLOW_COPY_AND_ASSIGN(ResultFile);
60 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
63 has_at_least_one_result_(false) {
64 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
65 base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
66 base::Unretained(this)));
69 void TracingControllerImpl::ResultFile::OpenTask() {
71 base::CreateTemporaryFile(&path_);
72 file_ = base::OpenFile(path_, "w");
74 LOG(ERROR) << "Failed to open " << path_.value();
77 const char* preamble = "{\"traceEvents\": [";
78 size_t written = fwrite(preamble, strlen(preamble), 1, file_);
82 void TracingControllerImpl::ResultFile::WriteTask(
83 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
84 if (!file_ || !events_str_ptr->data().size())
87 // If there is already a result in the file, then put a commma
88 // before the next batch of results.
89 if (has_at_least_one_result_) {
90 size_t written = fwrite(",", 1, 1, file_);
93 has_at_least_one_result_ = true;
94 size_t written = fwrite(events_str_ptr->data().c_str(),
95 events_str_ptr->data().size(), 1,
100 void TracingControllerImpl::ResultFile::CloseTask(
101 const base::Closure& callback) {
105 const char* trailout = "]}";
106 size_t written = fwrite(trailout, strlen(trailout), 1, file_);
107 DCHECK(written == 1);
108 base::CloseFile(file_);
111 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
115 TracingControllerImpl::TracingControllerImpl() :
116 pending_disable_recording_ack_count_(0),
117 pending_capture_monitoring_snapshot_ack_count_(0),
118 pending_trace_buffer_percent_full_ack_count_(0),
119 maximum_trace_buffer_percent_full_(0),
120 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
121 // is specified in command line.
122 is_recording_(TraceLog::GetInstance()->IsEnabled()),
123 is_monitoring_(false) {
126 TracingControllerImpl::~TracingControllerImpl() {
127 // This is a Leaky instance.
131 TracingControllerImpl* TracingControllerImpl::GetInstance() {
132 return g_controller.Pointer();
135 bool TracingControllerImpl::GetCategories(
136 const GetCategoriesDoneCallback& callback) {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 // Known categories come back from child processes with the EndTracingAck
140 // message. So to get known categories, just begin and end tracing immediately
141 // afterwards. This will ping all the child processes for categories.
142 pending_get_categories_done_callback_ = callback;
143 if (!EnableRecording("*", TracingController::Options(),
144 EnableRecordingDoneCallback())) {
145 pending_get_categories_done_callback_.Reset();
149 bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback());
154 void TracingControllerImpl::SetEnabledOnFileThread(
155 const std::string& category_filter,
158 const base::Closure& callback) {
159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
161 TraceLog::GetInstance()->SetEnabled(
162 base::debug::CategoryFilter(category_filter),
163 static_cast<TraceLog::Mode>(mode),
164 static_cast<TraceLog::Options>(trace_options));
165 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
168 void TracingControllerImpl::SetDisabledOnFileThread(
169 const base::Closure& callback) {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
172 TraceLog::GetInstance()->SetDisabled();
173 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
176 bool TracingControllerImpl::EnableRecording(
177 const std::string& category_filter,
178 TracingController::Options options,
179 const EnableRecordingDoneCallback& callback) {
180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 if (!can_enable_recording())
184 is_recording_ = true;
186 #if defined(OS_ANDROID)
187 if (pending_get_categories_done_callback_.is_null())
188 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
192 int trace_options = (options & RECORD_CONTINUOUSLY) ?
193 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
194 if (options & ENABLE_SAMPLING) {
195 trace_options |= TraceLog::ENABLE_SAMPLING;
197 // TODO(haraken): How to handle ENABLE_SYSTRACE?
199 base::Closure on_enable_recording_done_callback =
200 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
201 base::Unretained(this),
202 category_filter,trace_options, callback);
203 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
204 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
205 base::Unretained(this),
207 base::debug::TraceLog::RECORDING_MODE,
209 on_enable_recording_done_callback));
213 void TracingControllerImpl::OnEnableRecordingDone(
214 const std::string& category_filter,
216 const EnableRecordingDoneCallback& callback) {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
219 // Notify all child processes.
220 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
221 it != trace_message_filters_.end(); ++it) {
222 it->get()->SendBeginTracing(category_filter,
223 static_cast<TraceLog::Options>(trace_options));
226 if (!callback.is_null())
230 bool TracingControllerImpl::DisableRecording(
231 const base::FilePath& result_file_path,
232 const TracingFileResultCallback& callback) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235 if (!can_disable_recording())
238 options_ = TracingController::Options();
239 // Disable local trace early to avoid traces during end-tracing process from
240 // interfering with the process.
241 base::Closure on_disable_recording_done_callback =
242 base::Bind(&TracingControllerImpl::OnDisableRecordingDone,
243 base::Unretained(this),
244 result_file_path, callback);
245 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
246 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
247 base::Unretained(this),
248 on_disable_recording_done_callback));
252 void TracingControllerImpl::OnDisableRecordingDone(
253 const base::FilePath& result_file_path,
254 const TracingFileResultCallback& callback) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 pending_disable_recording_done_callback_ = callback;
259 #if defined(OS_ANDROID)
260 if (pending_get_categories_done_callback_.is_null())
261 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
264 if (!callback.is_null() || !result_file_path.empty())
265 result_file_.reset(new ResultFile(result_file_path));
267 // Count myself (local trace) in pending_disable_recording_ack_count_,
269 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
270 pending_disable_recording_filters_ = trace_message_filters_;
272 // Handle special case of zero child processes by immediately flushing the
273 // trace log. Once the flush has completed the caller will be notified that
274 // tracing has ended.
275 if (pending_disable_recording_ack_count_ == 1) {
276 // Flush asynchronously now, because we don't have any children to wait for.
277 TraceLog::GetInstance()->Flush(
278 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
279 base::Unretained(this)));
282 // Notify all child processes.
283 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
284 it != trace_message_filters_.end(); ++it) {
285 it->get()->SendEndTracing();
289 bool TracingControllerImpl::EnableMonitoring(
290 const std::string& category_filter,
291 TracingController::Options options,
292 const EnableMonitoringDoneCallback& callback) {
293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295 if (!can_enable_monitoring())
297 OnMonitoringStateChanged(true);
299 #if defined(OS_ANDROID)
300 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
304 int trace_options = 0;
305 if (options & ENABLE_SAMPLING)
306 trace_options |= TraceLog::ENABLE_SAMPLING;
308 base::Closure on_enable_monitoring_done_callback =
309 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
310 base::Unretained(this),
311 category_filter, trace_options, callback);
312 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
313 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
314 base::Unretained(this),
316 base::debug::TraceLog::MONITORING_MODE,
318 on_enable_monitoring_done_callback));
322 void TracingControllerImpl::OnEnableMonitoringDone(
323 const std::string& category_filter,
325 const EnableMonitoringDoneCallback& callback) {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
328 // Notify all child processes.
329 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
330 it != trace_message_filters_.end(); ++it) {
331 it->get()->SendEnableMonitoring(category_filter,
332 static_cast<TraceLog::Options>(trace_options));
335 if (!callback.is_null())
339 bool TracingControllerImpl::DisableMonitoring(
340 const DisableMonitoringDoneCallback& callback) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343 if (!can_disable_monitoring())
346 options_ = TracingController::Options();
347 base::Closure on_disable_monitoring_done_callback =
348 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
349 base::Unretained(this), callback);
350 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
351 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
352 base::Unretained(this),
353 on_disable_monitoring_done_callback));
357 void TracingControllerImpl::OnDisableMonitoringDone(
358 const DisableMonitoringDoneCallback& callback) {
359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361 OnMonitoringStateChanged(false);
363 // Notify all child processes.
364 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
365 it != trace_message_filters_.end(); ++it) {
366 it->get()->SendDisableMonitoring();
369 if (!callback.is_null())
373 void TracingControllerImpl::GetMonitoringStatus(
375 std::string* out_category_filter,
376 TracingController::Options* out_options) {
377 *out_enabled = is_monitoring_;
378 *out_category_filter =
379 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString();
380 *out_options = options_;
383 bool TracingControllerImpl::CaptureMonitoringSnapshot(
384 const base::FilePath& result_file_path,
385 const TracingFileResultCallback& callback) {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
388 if (!can_disable_monitoring())
391 if (callback.is_null() && result_file_path.empty())
394 pending_capture_monitoring_snapshot_done_callback_ = callback;
395 monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
397 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
399 pending_capture_monitoring_snapshot_ack_count_ =
400 trace_message_filters_.size() + 1;
401 pending_capture_monitoring_filters_ = trace_message_filters_;
403 // Handle special case of zero child processes by immediately flushing the
404 // trace log. Once the flush has completed the caller will be notified that
405 // the capture snapshot has ended.
406 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
407 // Flush asynchronously now, because we don't have any children to wait for.
408 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
409 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
410 base::Unretained(this)));
413 // Notify all child processes.
414 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
415 it != trace_message_filters_.end(); ++it) {
416 it->get()->SendCaptureMonitoringSnapshot();
419 #if defined(OS_ANDROID)
420 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
426 bool TracingControllerImpl::GetTraceBufferPercentFull(
427 const GetTraceBufferPercentFullCallback& callback) {
428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430 if (!can_get_trace_buffer_percent_full() || callback.is_null())
433 pending_trace_buffer_percent_full_callback_ = callback;
435 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
436 pending_trace_buffer_percent_full_ack_count_ =
437 trace_message_filters_.size() + 1;
438 pending_trace_buffer_percent_full_filters_ = trace_message_filters_;
439 maximum_trace_buffer_percent_full_ = 0;
441 // Call OnTraceBufferPercentFullReply unconditionally for the browser process.
442 // This will result in immediate execution of the callback if there are no
444 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
445 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
446 base::Unretained(this),
447 scoped_refptr<TraceMessageFilter>(),
448 TraceLog::GetInstance()->GetBufferPercentFull()));
450 // Notify all child processes.
451 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
452 it != trace_message_filters_.end(); ++it) {
453 it->get()->SendGetTraceBufferPercentFull();
458 bool TracingControllerImpl::SetWatchEvent(
459 const std::string& category_name,
460 const std::string& event_name,
461 const WatchEventCallback& callback) {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
464 if (callback.is_null())
467 watch_category_name_ = category_name;
468 watch_event_name_ = event_name;
469 watch_event_callback_ = callback;
471 TraceLog::GetInstance()->SetWatchEvent(
472 category_name, event_name,
473 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
474 base::Unretained(this)));
476 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
477 it != trace_message_filters_.end(); ++it) {
478 it->get()->SendSetWatchEvent(category_name, event_name);
483 bool TracingControllerImpl::CancelWatchEvent() {
484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
486 if (!can_cancel_watch_event())
489 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
490 it != trace_message_filters_.end(); ++it) {
491 it->get()->SendCancelWatchEvent();
494 watch_event_callback_.Reset();
498 void TracingControllerImpl::AddTraceMessageFilter(
499 TraceMessageFilter* trace_message_filter) {
500 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
501 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
502 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
503 base::Unretained(this),
504 make_scoped_refptr(trace_message_filter)));
508 trace_message_filters_.insert(trace_message_filter);
509 if (can_cancel_watch_event()) {
510 trace_message_filter->SendSetWatchEvent(watch_category_name_,
513 if (can_disable_recording()) {
514 trace_message_filter->SendBeginTracing(
515 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
516 TraceLog::GetInstance()->trace_options());
518 if (can_disable_monitoring()) {
519 trace_message_filter->SendEnableMonitoring(
520 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
521 TraceLog::GetInstance()->trace_options());
525 void TracingControllerImpl::RemoveTraceMessageFilter(
526 TraceMessageFilter* trace_message_filter) {
527 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
528 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
529 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
530 base::Unretained(this),
531 make_scoped_refptr(trace_message_filter)));
535 // If a filter is removed while a response from that filter is pending then
536 // simulate the response. Otherwise the response count will be wrong and the
537 // completion callback will never be executed.
538 if (pending_disable_recording_ack_count_ > 0) {
539 TraceMessageFilterSet::const_iterator it =
540 pending_disable_recording_filters_.find(trace_message_filter);
541 if (it != pending_disable_recording_filters_.end()) {
542 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
543 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
544 base::Unretained(this),
545 make_scoped_refptr(trace_message_filter),
546 std::vector<std::string>()));
549 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
550 TraceMessageFilterSet::const_iterator it =
551 pending_capture_monitoring_filters_.find(trace_message_filter);
552 if (it != pending_capture_monitoring_filters_.end()) {
553 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
554 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
555 base::Unretained(this),
556 make_scoped_refptr(trace_message_filter)));
559 if (pending_trace_buffer_percent_full_ack_count_ > 0) {
560 TraceMessageFilterSet::const_iterator it =
561 pending_trace_buffer_percent_full_filters_.find(trace_message_filter);
562 if (it != pending_trace_buffer_percent_full_filters_.end()) {
563 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
564 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
565 base::Unretained(this),
566 make_scoped_refptr(trace_message_filter),
571 trace_message_filters_.erase(trace_message_filter);
574 void TracingControllerImpl::OnDisableRecordingAcked(
575 TraceMessageFilter* trace_message_filter,
576 const std::vector<std::string>& known_category_groups) {
577 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
578 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
579 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
580 base::Unretained(this),
581 make_scoped_refptr(trace_message_filter),
582 known_category_groups));
586 // Merge known_category_groups with known_category_groups_
587 known_category_groups_.insert(known_category_groups.begin(),
588 known_category_groups.end());
590 if (pending_disable_recording_ack_count_ == 0)
593 if (trace_message_filter &&
594 !pending_disable_recording_filters_.erase(trace_message_filter)) {
595 // The response from the specified message filter has already been received.
599 if (--pending_disable_recording_ack_count_ == 1) {
600 // All acks from subprocesses have been received. Now flush the local trace.
601 // During or after this call, our OnLocalTraceDataCollected will be
602 // called with the last of the local trace data.
603 TraceLog::GetInstance()->Flush(
604 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
605 base::Unretained(this)));
609 if (pending_disable_recording_ack_count_ != 0)
612 // All acks (including from the subprocesses and the local trace) have been
614 is_recording_ = false;
616 // Trigger callback if one is set.
617 if (!pending_get_categories_done_callback_.is_null()) {
618 pending_get_categories_done_callback_.Run(known_category_groups_);
619 pending_get_categories_done_callback_.Reset();
620 } else if (result_file_) {
622 base::Bind(&TracingControllerImpl::OnResultFileClosed,
623 base::Unretained(this)));
627 void TracingControllerImpl::OnResultFileClosed() {
628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
633 if (!pending_disable_recording_done_callback_.is_null()) {
634 pending_disable_recording_done_callback_.Run(result_file_->path());
635 pending_disable_recording_done_callback_.Reset();
637 result_file_.reset();
640 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
641 TraceMessageFilter* trace_message_filter) {
642 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
643 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
644 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
645 base::Unretained(this),
646 make_scoped_refptr(trace_message_filter)));
650 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
653 if (trace_message_filter &&
654 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
655 // The response from the specified message filter has already been received.
659 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
660 // All acks from subprocesses have been received. Now flush the local trace.
661 // During or after this call, our OnLocalMonitoringTraceDataCollected
662 // will be called with the last of the local trace data.
663 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
664 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
665 base::Unretained(this)));
669 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
672 if (monitoring_snapshot_file_) {
673 monitoring_snapshot_file_->Close(
674 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
675 base::Unretained(this)));
679 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
680 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
682 if (!monitoring_snapshot_file_)
685 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
686 pending_capture_monitoring_snapshot_done_callback_.Run(
687 monitoring_snapshot_file_->path());
688 pending_capture_monitoring_snapshot_done_callback_.Reset();
690 monitoring_snapshot_file_.reset();
693 void TracingControllerImpl::OnTraceDataCollected(
694 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
695 // OnTraceDataCollected may be called from any browser thread, either by the
696 // local event trace system or from child processes via TraceMessageFilter.
697 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
698 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
699 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
700 base::Unretained(this), events_str_ptr));
705 result_file_->Write(events_str_ptr);
708 void TracingControllerImpl::OnMonitoringTraceDataCollected(
709 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
710 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
711 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
712 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
713 base::Unretained(this), events_str_ptr));
717 if (monitoring_snapshot_file_)
718 monitoring_snapshot_file_->Write(events_str_ptr);
721 void TracingControllerImpl::OnLocalTraceDataCollected(
722 const scoped_refptr<base::RefCountedString>& events_str_ptr,
723 bool has_more_events) {
724 if (events_str_ptr->data().size())
725 OnTraceDataCollected(events_str_ptr);
730 // Simulate an DisableRecordingAcked for the local trace.
731 std::vector<std::string> category_groups;
732 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
733 OnDisableRecordingAcked(NULL, category_groups);
736 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
737 const scoped_refptr<base::RefCountedString>& events_str_ptr,
738 bool has_more_events) {
739 if (events_str_ptr->data().size())
740 OnMonitoringTraceDataCollected(events_str_ptr);
745 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
746 OnCaptureMonitoringSnapshotAcked(NULL);
749 void TracingControllerImpl::OnTraceBufferPercentFullReply(
750 TraceMessageFilter* trace_message_filter,
751 float percent_full) {
752 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
753 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
754 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
755 base::Unretained(this),
756 make_scoped_refptr(trace_message_filter),
761 if (pending_trace_buffer_percent_full_ack_count_ == 0)
764 if (trace_message_filter &&
765 !pending_trace_buffer_percent_full_filters_.erase(trace_message_filter)) {
766 // The response from the specified message filter has already been received.
770 maximum_trace_buffer_percent_full_ =
771 std::max(maximum_trace_buffer_percent_full_, percent_full);
773 if (--pending_trace_buffer_percent_full_ack_count_ == 0) {
774 // Trigger callback if one is set.
775 pending_trace_buffer_percent_full_callback_.Run(
776 maximum_trace_buffer_percent_full_);
777 pending_trace_buffer_percent_full_callback_.Reset();
781 void TracingControllerImpl::OnWatchEventMatched() {
782 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
783 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
784 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
785 base::Unretained(this)));
789 if (!watch_event_callback_.is_null())
790 watch_event_callback_.Run();
793 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui)
795 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
796 tracing_uis_.insert(tracing_ui);
799 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui)
801 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
802 DCHECK(it != tracing_uis_.end());
803 tracing_uis_.erase(it);
806 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring)
808 if (is_monitoring_ == is_monitoring)
811 is_monitoring_ = is_monitoring;
812 #if !defined(OS_ANDROID)
813 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
814 it != tracing_uis_.end(); it++) {
815 (*it)->OnMonitoringStateChanged(is_monitoring);
820 } // namespace content