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 #if defined(OS_CHROMEOS)
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/debug_daemon_client.h"
23 using base::debug::TraceLog;
29 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
30 LAZY_INSTANCE_INITIALIZER;
34 TracingController* TracingController::GetInstance() {
35 return TracingControllerImpl::GetInstance();
38 class TracingControllerImpl::ResultFile {
40 explicit ResultFile(const base::FilePath& path);
41 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
42 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
43 base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
44 base::Unretained(this), events_str_ptr));
46 void Close(const base::Closure& callback) {
47 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
48 base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
49 base::Unretained(this), callback));
51 void WriteSystemTrace(
52 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
53 BrowserThread::PostTask(
56 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask,
57 base::Unretained(this), events_str_ptr));
60 const base::FilePath& path() const { return path_; }
64 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
65 void WriteSystemTraceTask(
66 const scoped_refptr<base::RefCountedString>& events_str_ptr);
67 void CloseTask(const base::Closure& callback);
71 bool has_at_least_one_result_;
72 scoped_refptr<base::RefCountedString> system_trace_;
74 DISALLOW_COPY_AND_ASSIGN(ResultFile);
77 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
80 has_at_least_one_result_(false) {
81 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
82 base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
83 base::Unretained(this)));
86 void TracingControllerImpl::ResultFile::OpenTask() {
88 base::CreateTemporaryFile(&path_);
89 file_ = base::OpenFile(path_, "w");
91 LOG(ERROR) << "Failed to open " << path_.value();
94 const char* preamble = "{\"traceEvents\": [";
95 size_t written = fwrite(preamble, strlen(preamble), 1, file_);
99 void TracingControllerImpl::ResultFile::WriteTask(
100 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
101 if (!file_ || !events_str_ptr->data().size())
104 // If there is already a result in the file, then put a commma
105 // before the next batch of results.
106 if (has_at_least_one_result_) {
107 size_t written = fwrite(",", 1, 1, file_);
108 DCHECK(written == 1);
110 has_at_least_one_result_ = true;
111 size_t written = fwrite(events_str_ptr->data().c_str(),
112 events_str_ptr->data().size(), 1,
114 DCHECK(written == 1);
117 void TracingControllerImpl::ResultFile::WriteSystemTraceTask(
118 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
119 system_trace_ = events_str_ptr;
122 void TracingControllerImpl::ResultFile::CloseTask(
123 const base::Closure& callback) {
127 const char* trailevents = "]";
128 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_);
129 DCHECK(written == 1);
132 std::string json_string = base::GetQuotedJSONString(system_trace_->data());
134 const char* systemTraceHead = ", \"systemTraceEvents\": ";
135 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_);
136 DCHECK(written == 1);
138 written = fwrite(json_string.data(), json_string.size(), 1, file_);
139 DCHECK(written == 1);
141 system_trace_ = NULL;
144 const char* trailout = "}";
145 written = fwrite(trailout, strlen(trailout), 1, file_);
146 DCHECK(written == 1);
147 base::CloseFile(file_);
150 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
154 TracingControllerImpl::TracingControllerImpl() :
155 pending_disable_recording_ack_count_(0),
156 pending_capture_monitoring_snapshot_ack_count_(0),
157 pending_trace_buffer_percent_full_ack_count_(0),
158 maximum_trace_buffer_percent_full_(0),
159 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
160 // is specified in command line.
161 #if defined(OS_CHROMEOS)
162 is_system_tracing_(false),
164 is_recording_(TraceLog::GetInstance()->IsEnabled()),
165 is_monitoring_(false) {
168 TracingControllerImpl::~TracingControllerImpl() {
169 // This is a Leaky instance.
173 TracingControllerImpl* TracingControllerImpl::GetInstance() {
174 return g_controller.Pointer();
177 bool TracingControllerImpl::GetCategories(
178 const GetCategoriesDoneCallback& callback) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
181 // Known categories come back from child processes with the EndTracingAck
182 // message. So to get known categories, just begin and end tracing immediately
183 // afterwards. This will ping all the child processes for categories.
184 pending_get_categories_done_callback_ = callback;
185 if (!EnableRecording("*", TracingController::Options(),
186 EnableRecordingDoneCallback())) {
187 pending_get_categories_done_callback_.Reset();
191 bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback());
196 void TracingControllerImpl::SetEnabledOnFileThread(
197 const std::string& category_filter,
200 const base::Closure& callback) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
203 TraceLog::GetInstance()->SetEnabled(
204 base::debug::CategoryFilter(category_filter),
205 static_cast<TraceLog::Mode>(mode),
206 static_cast<TraceLog::Options>(trace_options));
207 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
210 void TracingControllerImpl::SetDisabledOnFileThread(
211 const base::Closure& callback) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
214 TraceLog::GetInstance()->SetDisabled();
215 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
218 bool TracingControllerImpl::EnableRecording(
219 const std::string& category_filter,
220 TracingController::Options options,
221 const EnableRecordingDoneCallback& callback) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
224 if (!can_enable_recording())
226 is_recording_ = true;
228 #if defined(OS_ANDROID)
229 if (pending_get_categories_done_callback_.is_null())
230 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
234 int trace_options = (options & RECORD_CONTINUOUSLY) ?
235 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
236 if (options & ENABLE_SAMPLING) {
237 trace_options |= TraceLog::ENABLE_SAMPLING;
239 #if defined(OS_CHROMEOS)
240 if (options & ENABLE_SYSTRACE) {
241 DCHECK(!is_system_tracing_);
242 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
243 StartSystemTracing();
244 is_system_tracing_ = true;
248 base::Closure on_enable_recording_done_callback =
249 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
250 base::Unretained(this),
251 category_filter,trace_options, callback);
252 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
253 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
254 base::Unretained(this),
256 base::debug::TraceLog::RECORDING_MODE,
258 on_enable_recording_done_callback));
262 void TracingControllerImpl::OnEnableRecordingDone(
263 const std::string& category_filter,
265 const EnableRecordingDoneCallback& callback) {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
268 // Notify all child processes.
269 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
270 it != trace_message_filters_.end(); ++it) {
271 it->get()->SendBeginTracing(category_filter,
272 static_cast<TraceLog::Options>(trace_options));
275 if (!callback.is_null())
279 bool TracingControllerImpl::DisableRecording(
280 const base::FilePath& result_file_path,
281 const TracingFileResultCallback& callback) {
282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
284 if (!can_disable_recording())
287 options_ = TracingController::Options();
288 // Disable local trace early to avoid traces during end-tracing process from
289 // interfering with the process.
290 base::Closure on_disable_recording_done_callback =
291 base::Bind(&TracingControllerImpl::OnDisableRecordingDone,
292 base::Unretained(this),
293 result_file_path, callback);
294 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
295 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
296 base::Unretained(this),
297 on_disable_recording_done_callback));
301 void TracingControllerImpl::OnDisableRecordingDone(
302 const base::FilePath& result_file_path,
303 const TracingFileResultCallback& callback) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
306 pending_disable_recording_done_callback_ = callback;
308 #if defined(OS_ANDROID)
309 if (pending_get_categories_done_callback_.is_null())
310 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
313 if (!callback.is_null() || !result_file_path.empty())
314 result_file_.reset(new ResultFile(result_file_path));
316 // Count myself (local trace) in pending_disable_recording_ack_count_,
318 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
319 pending_disable_recording_filters_ = trace_message_filters_;
321 // Handle special case of zero child processes by immediately flushing the
322 // trace log. Once the flush has completed the caller will be notified that
323 // tracing has ended.
324 if (pending_disable_recording_ack_count_ == 1) {
325 // Flush asynchronously now, because we don't have any children to wait for.
326 TraceLog::GetInstance()->Flush(
327 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
328 base::Unretained(this)));
331 // Notify all child processes.
332 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
333 it != trace_message_filters_.end(); ++it) {
334 it->get()->SendEndTracing();
338 bool TracingControllerImpl::EnableMonitoring(
339 const std::string& category_filter,
340 TracingController::Options options,
341 const EnableMonitoringDoneCallback& callback) {
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
344 if (!can_enable_monitoring())
346 OnMonitoringStateChanged(true);
348 #if defined(OS_ANDROID)
349 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
353 int trace_options = 0;
354 if (options & ENABLE_SAMPLING)
355 trace_options |= TraceLog::ENABLE_SAMPLING;
357 base::Closure on_enable_monitoring_done_callback =
358 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
359 base::Unretained(this),
360 category_filter, trace_options, callback);
361 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
362 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
363 base::Unretained(this),
365 base::debug::TraceLog::MONITORING_MODE,
367 on_enable_monitoring_done_callback));
371 void TracingControllerImpl::OnEnableMonitoringDone(
372 const std::string& category_filter,
374 const EnableMonitoringDoneCallback& callback) {
375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
377 // Notify all child processes.
378 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
379 it != trace_message_filters_.end(); ++it) {
380 it->get()->SendEnableMonitoring(category_filter,
381 static_cast<TraceLog::Options>(trace_options));
384 if (!callback.is_null())
388 bool TracingControllerImpl::DisableMonitoring(
389 const DisableMonitoringDoneCallback& callback) {
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
392 if (!can_disable_monitoring())
395 options_ = TracingController::Options();
396 base::Closure on_disable_monitoring_done_callback =
397 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
398 base::Unretained(this), callback);
399 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
400 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
401 base::Unretained(this),
402 on_disable_monitoring_done_callback));
406 void TracingControllerImpl::OnDisableMonitoringDone(
407 const DisableMonitoringDoneCallback& callback) {
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
410 OnMonitoringStateChanged(false);
412 // Notify all child processes.
413 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
414 it != trace_message_filters_.end(); ++it) {
415 it->get()->SendDisableMonitoring();
418 if (!callback.is_null())
422 void TracingControllerImpl::GetMonitoringStatus(
424 std::string* out_category_filter,
425 TracingController::Options* out_options) {
426 *out_enabled = is_monitoring_;
427 *out_category_filter =
428 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString();
429 *out_options = options_;
432 bool TracingControllerImpl::CaptureMonitoringSnapshot(
433 const base::FilePath& result_file_path,
434 const TracingFileResultCallback& callback) {
435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
437 if (!can_disable_monitoring())
440 if (callback.is_null() && result_file_path.empty())
443 pending_capture_monitoring_snapshot_done_callback_ = callback;
444 monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
446 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
448 pending_capture_monitoring_snapshot_ack_count_ =
449 trace_message_filters_.size() + 1;
450 pending_capture_monitoring_filters_ = trace_message_filters_;
452 // Handle special case of zero child processes by immediately flushing the
453 // trace log. Once the flush has completed the caller will be notified that
454 // the capture snapshot has ended.
455 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
456 // Flush asynchronously now, because we don't have any children to wait for.
457 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
458 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
459 base::Unretained(this)));
462 // Notify all child processes.
463 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
464 it != trace_message_filters_.end(); ++it) {
465 it->get()->SendCaptureMonitoringSnapshot();
468 #if defined(OS_ANDROID)
469 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
475 bool TracingControllerImpl::GetTraceBufferPercentFull(
476 const GetTraceBufferPercentFullCallback& callback) {
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
479 if (!can_get_trace_buffer_percent_full() || callback.is_null())
482 pending_trace_buffer_percent_full_callback_ = callback;
484 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
485 pending_trace_buffer_percent_full_ack_count_ =
486 trace_message_filters_.size() + 1;
487 pending_trace_buffer_percent_full_filters_ = trace_message_filters_;
488 maximum_trace_buffer_percent_full_ = 0;
490 // Call OnTraceBufferPercentFullReply unconditionally for the browser process.
491 // This will result in immediate execution of the callback if there are no
493 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
494 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
495 base::Unretained(this),
496 scoped_refptr<TraceMessageFilter>(),
497 TraceLog::GetInstance()->GetBufferPercentFull()));
499 // Notify all child processes.
500 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
501 it != trace_message_filters_.end(); ++it) {
502 it->get()->SendGetTraceBufferPercentFull();
507 bool TracingControllerImpl::SetWatchEvent(
508 const std::string& category_name,
509 const std::string& event_name,
510 const WatchEventCallback& callback) {
511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
513 if (callback.is_null())
516 watch_category_name_ = category_name;
517 watch_event_name_ = event_name;
518 watch_event_callback_ = callback;
520 TraceLog::GetInstance()->SetWatchEvent(
521 category_name, event_name,
522 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
523 base::Unretained(this)));
525 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
526 it != trace_message_filters_.end(); ++it) {
527 it->get()->SendSetWatchEvent(category_name, event_name);
532 bool TracingControllerImpl::CancelWatchEvent() {
533 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
535 if (!can_cancel_watch_event())
538 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
539 it != trace_message_filters_.end(); ++it) {
540 it->get()->SendCancelWatchEvent();
543 watch_event_callback_.Reset();
547 void TracingControllerImpl::AddTraceMessageFilter(
548 TraceMessageFilter* trace_message_filter) {
549 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
550 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
551 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
552 base::Unretained(this),
553 make_scoped_refptr(trace_message_filter)));
557 trace_message_filters_.insert(trace_message_filter);
558 if (can_cancel_watch_event()) {
559 trace_message_filter->SendSetWatchEvent(watch_category_name_,
562 if (can_disable_recording()) {
563 trace_message_filter->SendBeginTracing(
564 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
565 TraceLog::GetInstance()->trace_options());
567 if (can_disable_monitoring()) {
568 trace_message_filter->SendEnableMonitoring(
569 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
570 TraceLog::GetInstance()->trace_options());
574 void TracingControllerImpl::RemoveTraceMessageFilter(
575 TraceMessageFilter* trace_message_filter) {
576 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
577 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
578 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
579 base::Unretained(this),
580 make_scoped_refptr(trace_message_filter)));
584 // If a filter is removed while a response from that filter is pending then
585 // simulate the response. Otherwise the response count will be wrong and the
586 // completion callback will never be executed.
587 if (pending_disable_recording_ack_count_ > 0) {
588 TraceMessageFilterSet::const_iterator it =
589 pending_disable_recording_filters_.find(trace_message_filter);
590 if (it != pending_disable_recording_filters_.end()) {
591 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
592 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
593 base::Unretained(this),
594 make_scoped_refptr(trace_message_filter),
595 std::vector<std::string>()));
598 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
599 TraceMessageFilterSet::const_iterator it =
600 pending_capture_monitoring_filters_.find(trace_message_filter);
601 if (it != pending_capture_monitoring_filters_.end()) {
602 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
603 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
604 base::Unretained(this),
605 make_scoped_refptr(trace_message_filter)));
608 if (pending_trace_buffer_percent_full_ack_count_ > 0) {
609 TraceMessageFilterSet::const_iterator it =
610 pending_trace_buffer_percent_full_filters_.find(trace_message_filter);
611 if (it != pending_trace_buffer_percent_full_filters_.end()) {
612 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
613 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
614 base::Unretained(this),
615 make_scoped_refptr(trace_message_filter),
620 trace_message_filters_.erase(trace_message_filter);
623 void TracingControllerImpl::OnDisableRecordingAcked(
624 TraceMessageFilter* trace_message_filter,
625 const std::vector<std::string>& known_category_groups) {
626 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
627 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
628 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
629 base::Unretained(this),
630 make_scoped_refptr(trace_message_filter),
631 known_category_groups));
635 // Merge known_category_groups with known_category_groups_
636 known_category_groups_.insert(known_category_groups.begin(),
637 known_category_groups.end());
639 if (pending_disable_recording_ack_count_ == 0)
642 if (trace_message_filter &&
643 !pending_disable_recording_filters_.erase(trace_message_filter)) {
644 // The response from the specified message filter has already been received.
648 if (--pending_disable_recording_ack_count_ == 1) {
649 // All acks from subprocesses have been received. Now flush the local trace.
650 // During or after this call, our OnLocalTraceDataCollected will be
651 // called with the last of the local trace data.
652 TraceLog::GetInstance()->Flush(
653 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
654 base::Unretained(this)));
658 if (pending_disable_recording_ack_count_ != 0)
661 OnDisableRecordingComplete();
664 void TracingControllerImpl::OnDisableRecordingComplete() {
665 // All acks (including from the subprocesses and the local trace) have been
667 is_recording_ = false;
669 #if defined(OS_CHROMEOS)
670 if (is_system_tracing_) {
671 // Disable system tracing now that the local trace has shutdown.
672 // This must be done last because we potentially need to push event
673 // records into the system event log for synchronizing system event
674 // timestamps with chrome event timestamps--and since the system event
675 // log is a ring-buffer (on linux) adding them at the end is the only
676 // way we're confident we'll have them in the final result.
677 is_system_tracing_ = false;
678 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
679 RequestStopSystemTracing(
680 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
681 base::Unretained(this)));
686 // Trigger callback if one is set.
687 if (!pending_get_categories_done_callback_.is_null()) {
688 pending_get_categories_done_callback_.Run(known_category_groups_);
689 pending_get_categories_done_callback_.Reset();
690 } else if (result_file_) {
692 base::Bind(&TracingControllerImpl::OnResultFileClosed,
693 base::Unretained(this)));
697 void TracingControllerImpl::OnResultFileClosed() {
698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
703 if (!pending_disable_recording_done_callback_.is_null()) {
704 pending_disable_recording_done_callback_.Run(result_file_->path());
705 pending_disable_recording_done_callback_.Reset();
707 result_file_.reset();
710 #if defined(OS_CHROMEOS)
711 void TracingControllerImpl::OnEndSystemTracingAcked(
712 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
713 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
716 result_file_->WriteSystemTrace(events_str_ptr);
718 DCHECK(!is_system_tracing_);
719 OnDisableRecordingComplete();
723 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
724 TraceMessageFilter* trace_message_filter) {
725 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
726 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
727 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
728 base::Unretained(this),
729 make_scoped_refptr(trace_message_filter)));
733 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
736 if (trace_message_filter &&
737 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
738 // The response from the specified message filter has already been received.
742 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
743 // All acks from subprocesses have been received. Now flush the local trace.
744 // During or after this call, our OnLocalMonitoringTraceDataCollected
745 // will be called with the last of the local trace data.
746 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
747 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
748 base::Unretained(this)));
752 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
755 if (monitoring_snapshot_file_) {
756 monitoring_snapshot_file_->Close(
757 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
758 base::Unretained(this)));
762 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
763 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
765 if (!monitoring_snapshot_file_)
768 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
769 pending_capture_monitoring_snapshot_done_callback_.Run(
770 monitoring_snapshot_file_->path());
771 pending_capture_monitoring_snapshot_done_callback_.Reset();
773 monitoring_snapshot_file_.reset();
776 void TracingControllerImpl::OnTraceDataCollected(
777 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
778 // OnTraceDataCollected may be called from any browser thread, either by the
779 // local event trace system or from child processes via TraceMessageFilter.
780 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
781 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
782 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
783 base::Unretained(this), events_str_ptr));
788 result_file_->Write(events_str_ptr);
791 void TracingControllerImpl::OnMonitoringTraceDataCollected(
792 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
793 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
794 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
795 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
796 base::Unretained(this), events_str_ptr));
800 if (monitoring_snapshot_file_)
801 monitoring_snapshot_file_->Write(events_str_ptr);
804 void TracingControllerImpl::OnLocalTraceDataCollected(
805 const scoped_refptr<base::RefCountedString>& events_str_ptr,
806 bool has_more_events) {
807 if (events_str_ptr->data().size())
808 OnTraceDataCollected(events_str_ptr);
813 // Simulate an DisableRecordingAcked for the local trace.
814 std::vector<std::string> category_groups;
815 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
816 OnDisableRecordingAcked(NULL, category_groups);
819 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
820 const scoped_refptr<base::RefCountedString>& events_str_ptr,
821 bool has_more_events) {
822 if (events_str_ptr->data().size())
823 OnMonitoringTraceDataCollected(events_str_ptr);
828 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
829 OnCaptureMonitoringSnapshotAcked(NULL);
832 void TracingControllerImpl::OnTraceBufferPercentFullReply(
833 TraceMessageFilter* trace_message_filter,
834 float percent_full) {
835 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
836 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
837 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
838 base::Unretained(this),
839 make_scoped_refptr(trace_message_filter),
844 if (pending_trace_buffer_percent_full_ack_count_ == 0)
847 if (trace_message_filter &&
848 !pending_trace_buffer_percent_full_filters_.erase(trace_message_filter)) {
849 // The response from the specified message filter has already been received.
853 maximum_trace_buffer_percent_full_ =
854 std::max(maximum_trace_buffer_percent_full_, percent_full);
856 if (--pending_trace_buffer_percent_full_ack_count_ == 0) {
857 // Trigger callback if one is set.
858 pending_trace_buffer_percent_full_callback_.Run(
859 maximum_trace_buffer_percent_full_);
860 pending_trace_buffer_percent_full_callback_.Reset();
864 void TracingControllerImpl::OnWatchEventMatched() {
865 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
866 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
867 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
868 base::Unretained(this)));
872 if (!watch_event_callback_.is_null())
873 watch_event_callback_.Run();
876 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui)
878 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
879 tracing_uis_.insert(tracing_ui);
882 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui)
884 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
885 DCHECK(it != tracing_uis_.end());
886 tracing_uis_.erase(it);
889 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring)
891 if (is_monitoring_ == is_monitoring)
894 is_monitoring_ = is_monitoring;
895 #if !defined(OS_ANDROID)
896 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
897 it != tracing_uis_.end(); it++) {
898 (*it)->OnMonitoringStateChanged(is_monitoring);
903 } // namespace content