Add a FrameHostMsg_BeginNavigation IPC
[chromium-blink-merge.git] / content / browser / tracing / tracing_controller_impl.cc
blob63a44fcbcbf41c00c31f78ce4bfc1ac09f7ffe5a
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/debug/trace_event.h"
8 #include "base/file_util.h"
9 #include "base/json/string_escape.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "content/browser/tracing/trace_message_filter.h"
12 #include "content/browser/tracing/tracing_ui.h"
13 #include "content/common/child_process_messages.h"
14 #include "content/public/browser/browser_message_filter.h"
15 #include "content/public/common/content_switches.h"
17 #if defined(OS_CHROMEOS)
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/dbus/debug_daemon_client.h"
20 #endif
22 #if defined(OS_WIN)
23 #include "content/browser/tracing/etw_system_event_consumer_win.h"
24 #endif
26 using base::debug::TraceLog;
28 namespace content {
30 namespace {
32 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
33 LAZY_INSTANCE_INITIALIZER;
35 } // namespace
37 TracingController* TracingController::GetInstance() {
38 return TracingControllerImpl::GetInstance();
41 class TracingControllerImpl::ResultFile {
42 public:
43 explicit ResultFile(const base::FilePath& path);
44 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
45 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
46 base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
47 base::Unretained(this), events_str_ptr));
49 void Close(const base::Closure& callback) {
50 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
51 base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
52 base::Unretained(this), callback));
54 void WriteSystemTrace(
55 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
56 BrowserThread::PostTask(
57 BrowserThread::FILE,
58 FROM_HERE,
59 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask,
60 base::Unretained(this), events_str_ptr));
63 const base::FilePath& path() const { return path_; }
65 private:
66 void OpenTask();
67 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
68 void WriteSystemTraceTask(
69 const scoped_refptr<base::RefCountedString>& events_str_ptr);
70 void CloseTask(const base::Closure& callback);
72 FILE* file_;
73 base::FilePath path_;
74 bool has_at_least_one_result_;
75 scoped_refptr<base::RefCountedString> system_trace_;
77 DISALLOW_COPY_AND_ASSIGN(ResultFile);
80 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
81 : file_(NULL),
82 path_(path),
83 has_at_least_one_result_(false) {
84 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
85 base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
86 base::Unretained(this)));
89 void TracingControllerImpl::ResultFile::OpenTask() {
90 if (path_.empty())
91 base::CreateTemporaryFile(&path_);
92 file_ = base::OpenFile(path_, "w");
93 if (!file_) {
94 LOG(ERROR) << "Failed to open " << path_.value();
95 return;
97 const char* preamble = "{\"traceEvents\": [";
98 size_t written = fwrite(preamble, strlen(preamble), 1, file_);
99 DCHECK(written == 1);
102 void TracingControllerImpl::ResultFile::WriteTask(
103 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
104 if (!file_ || !events_str_ptr->data().size())
105 return;
107 // If there is already a result in the file, then put a comma
108 // before the next batch of results.
109 if (has_at_least_one_result_) {
110 size_t written = fwrite(",", 1, 1, file_);
111 DCHECK(written == 1);
113 has_at_least_one_result_ = true;
114 size_t written = fwrite(events_str_ptr->data().c_str(),
115 events_str_ptr->data().size(), 1,
116 file_);
117 DCHECK(written == 1);
120 void TracingControllerImpl::ResultFile::WriteSystemTraceTask(
121 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
122 system_trace_ = events_str_ptr;
125 void TracingControllerImpl::ResultFile::CloseTask(
126 const base::Closure& callback) {
127 if (!file_)
128 return;
130 const char* trailevents = "]";
131 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_);
132 DCHECK(written == 1);
134 if (system_trace_) {
135 #if defined(OS_WIN)
136 // The Windows kernel events are kept into a JSon format stored as string
137 // and must not be escaped.
138 std::string json_string = system_trace_->data();
139 #else
140 std::string json_string = base::GetQuotedJSONString(system_trace_->data());
141 #endif
143 const char* systemTraceHead = ",\n\"systemTraceEvents\": ";
144 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_);
145 DCHECK(written == 1);
147 written = fwrite(json_string.data(), json_string.size(), 1, file_);
148 DCHECK(written == 1);
150 system_trace_ = NULL;
153 const char* trailout = "}";
154 written = fwrite(trailout, strlen(trailout), 1, file_);
155 DCHECK(written == 1);
156 base::CloseFile(file_);
157 file_ = NULL;
159 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
163 TracingControllerImpl::TracingControllerImpl() :
164 pending_disable_recording_ack_count_(0),
165 pending_capture_monitoring_snapshot_ack_count_(0),
166 pending_trace_buffer_percent_full_ack_count_(0),
167 maximum_trace_buffer_percent_full_(0),
168 // Tracing may have been enabled by ContentMainRunner if kTraceStartup
169 // is specified in command line.
170 #if defined(OS_CHROMEOS) || defined(OS_WIN)
171 is_system_tracing_(false),
172 #endif
173 is_recording_(TraceLog::GetInstance()->IsEnabled()),
174 is_monitoring_(false) {
177 TracingControllerImpl::~TracingControllerImpl() {
178 // This is a Leaky instance.
179 NOTREACHED();
182 TracingControllerImpl* TracingControllerImpl::GetInstance() {
183 return g_controller.Pointer();
186 bool TracingControllerImpl::GetCategories(
187 const GetCategoriesDoneCallback& callback) {
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
190 // Known categories come back from child processes with the EndTracingAck
191 // message. So to get known categories, just begin and end tracing immediately
192 // afterwards. This will ping all the child processes for categories.
193 pending_get_categories_done_callback_ = callback;
194 if (!EnableRecording("*", TracingController::Options(),
195 EnableRecordingDoneCallback())) {
196 pending_get_categories_done_callback_.Reset();
197 return false;
200 bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback());
201 DCHECK(ok);
202 return true;
205 void TracingControllerImpl::SetEnabledOnFileThread(
206 const std::string& category_filter,
207 int mode,
208 int trace_options,
209 const base::Closure& callback) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
212 TraceLog::GetInstance()->SetEnabled(
213 base::debug::CategoryFilter(category_filter),
214 static_cast<TraceLog::Mode>(mode),
215 static_cast<TraceLog::Options>(trace_options));
216 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
219 void TracingControllerImpl::SetDisabledOnFileThread(
220 const base::Closure& callback) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
223 TraceLog::GetInstance()->SetDisabled();
224 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
227 bool TracingControllerImpl::EnableRecording(
228 const std::string& category_filter,
229 TracingController::Options options,
230 const EnableRecordingDoneCallback& callback) {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
233 if (!can_enable_recording())
234 return false;
235 is_recording_ = true;
237 #if defined(OS_ANDROID)
238 if (pending_get_categories_done_callback_.is_null())
239 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
240 #endif
242 options_ = options;
243 int trace_options = (options & RECORD_CONTINUOUSLY) ?
244 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
245 if (options & ENABLE_SAMPLING) {
246 trace_options |= TraceLog::ENABLE_SAMPLING;
249 if (options & ENABLE_SYSTRACE) {
250 #if defined(OS_CHROMEOS)
251 DCHECK(!is_system_tracing_);
252 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
253 StartSystemTracing();
254 is_system_tracing_ = true;
255 #elif defined(OS_WIN)
256 DCHECK(!is_system_tracing_);
257 is_system_tracing_ =
258 EtwSystemEventConsumer::GetInstance()->StartSystemTracing();
259 #endif
263 base::Closure on_enable_recording_done_callback =
264 base::Bind(&TracingControllerImpl::OnEnableRecordingDone,
265 base::Unretained(this),
266 category_filter, trace_options, callback);
267 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
268 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
269 base::Unretained(this),
270 category_filter,
271 base::debug::TraceLog::RECORDING_MODE,
272 trace_options,
273 on_enable_recording_done_callback));
274 return true;
277 void TracingControllerImpl::OnEnableRecordingDone(
278 const std::string& category_filter,
279 int trace_options,
280 const EnableRecordingDoneCallback& callback) {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
283 // Notify all child processes.
284 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
285 it != trace_message_filters_.end(); ++it) {
286 it->get()->SendBeginTracing(category_filter,
287 static_cast<TraceLog::Options>(trace_options));
290 if (!callback.is_null())
291 callback.Run();
294 bool TracingControllerImpl::DisableRecording(
295 const base::FilePath& result_file_path,
296 const TracingFileResultCallback& callback) {
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
299 if (!can_disable_recording())
300 return false;
302 options_ = TracingController::Options();
303 // Disable local trace early to avoid traces during end-tracing process from
304 // interfering with the process.
305 base::Closure on_disable_recording_done_callback =
306 base::Bind(&TracingControllerImpl::OnDisableRecordingDone,
307 base::Unretained(this),
308 result_file_path, callback);
309 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
310 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
311 base::Unretained(this),
312 on_disable_recording_done_callback));
313 return true;
316 void TracingControllerImpl::OnDisableRecordingDone(
317 const base::FilePath& result_file_path,
318 const TracingFileResultCallback& callback) {
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321 pending_disable_recording_done_callback_ = callback;
323 #if defined(OS_ANDROID)
324 if (pending_get_categories_done_callback_.is_null())
325 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
326 #endif
328 if (!callback.is_null() || !result_file_path.empty())
329 result_file_.reset(new ResultFile(result_file_path));
331 // Count myself (local trace) in pending_disable_recording_ack_count_,
332 // acked below.
333 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
334 pending_disable_recording_filters_ = trace_message_filters_;
336 #if defined(OS_CHROMEOS) || defined(OS_WIN)
337 if (is_system_tracing_) {
338 // Disable system tracing.
339 is_system_tracing_ = false;
340 ++pending_disable_recording_ack_count_;
342 #if defined(OS_CHROMEOS)
343 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
344 RequestStopSystemTracing(
345 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
346 base::Unretained(this)));
347 #elif defined(OS_WIN)
348 EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
349 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
350 base::Unretained(this)));
351 #endif
353 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
355 // Handle special case of zero child processes by immediately flushing the
356 // trace log. Once the flush has completed the caller will be notified that
357 // tracing has ended.
358 if (pending_disable_recording_ack_count_ == 1) {
359 // Flush asynchronously now, because we don't have any children to wait for.
360 TraceLog::GetInstance()->Flush(
361 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
362 base::Unretained(this)));
365 // Notify all child processes.
366 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
367 it != trace_message_filters_.end(); ++it) {
368 it->get()->SendEndTracing();
372 bool TracingControllerImpl::EnableMonitoring(
373 const std::string& category_filter,
374 TracingController::Options options,
375 const EnableMonitoringDoneCallback& callback) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
378 if (!can_enable_monitoring())
379 return false;
380 OnMonitoringStateChanged(true);
382 #if defined(OS_ANDROID)
383 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
384 #endif
386 options_ = options;
387 int trace_options = 0;
388 if (options & ENABLE_SAMPLING)
389 trace_options |= TraceLog::ENABLE_SAMPLING;
391 base::Closure on_enable_monitoring_done_callback =
392 base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
393 base::Unretained(this),
394 category_filter, trace_options, callback);
395 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
396 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
397 base::Unretained(this),
398 category_filter,
399 base::debug::TraceLog::MONITORING_MODE,
400 trace_options,
401 on_enable_monitoring_done_callback));
402 return true;
405 void TracingControllerImpl::OnEnableMonitoringDone(
406 const std::string& category_filter,
407 int trace_options,
408 const EnableMonitoringDoneCallback& callback) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
411 // Notify all child processes.
412 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
413 it != trace_message_filters_.end(); ++it) {
414 it->get()->SendEnableMonitoring(category_filter,
415 static_cast<TraceLog::Options>(trace_options));
418 if (!callback.is_null())
419 callback.Run();
422 bool TracingControllerImpl::DisableMonitoring(
423 const DisableMonitoringDoneCallback& callback) {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 if (!can_disable_monitoring())
427 return false;
429 options_ = TracingController::Options();
430 base::Closure on_disable_monitoring_done_callback =
431 base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
432 base::Unretained(this), callback);
433 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
434 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
435 base::Unretained(this),
436 on_disable_monitoring_done_callback));
437 return true;
440 void TracingControllerImpl::OnDisableMonitoringDone(
441 const DisableMonitoringDoneCallback& callback) {
442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
444 OnMonitoringStateChanged(false);
446 // Notify all child processes.
447 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
448 it != trace_message_filters_.end(); ++it) {
449 it->get()->SendDisableMonitoring();
452 if (!callback.is_null())
453 callback.Run();
456 void TracingControllerImpl::GetMonitoringStatus(
457 bool* out_enabled,
458 std::string* out_category_filter,
459 TracingController::Options* out_options) {
460 *out_enabled = is_monitoring_;
461 *out_category_filter =
462 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString();
463 *out_options = options_;
466 bool TracingControllerImpl::CaptureMonitoringSnapshot(
467 const base::FilePath& result_file_path,
468 const TracingFileResultCallback& callback) {
469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
471 if (!can_disable_monitoring())
472 return false;
474 if (callback.is_null() && result_file_path.empty())
475 return false;
477 pending_capture_monitoring_snapshot_done_callback_ = callback;
478 monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
480 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
481 // acked below.
482 pending_capture_monitoring_snapshot_ack_count_ =
483 trace_message_filters_.size() + 1;
484 pending_capture_monitoring_filters_ = trace_message_filters_;
486 // Handle special case of zero child processes by immediately flushing the
487 // trace log. Once the flush has completed the caller will be notified that
488 // the capture snapshot has ended.
489 if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
490 // Flush asynchronously now, because we don't have any children to wait for.
491 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
492 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
493 base::Unretained(this)));
496 // Notify all child processes.
497 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
498 it != trace_message_filters_.end(); ++it) {
499 it->get()->SendCaptureMonitoringSnapshot();
502 #if defined(OS_ANDROID)
503 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
504 #endif
506 return true;
509 bool TracingControllerImpl::GetTraceBufferPercentFull(
510 const GetTraceBufferPercentFullCallback& callback) {
511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
513 if (!can_get_trace_buffer_percent_full() || callback.is_null())
514 return false;
516 pending_trace_buffer_percent_full_callback_ = callback;
518 // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
519 pending_trace_buffer_percent_full_ack_count_ =
520 trace_message_filters_.size() + 1;
521 pending_trace_buffer_percent_full_filters_ = trace_message_filters_;
522 maximum_trace_buffer_percent_full_ = 0;
524 // Call OnTraceBufferPercentFullReply unconditionally for the browser process.
525 // This will result in immediate execution of the callback if there are no
526 // child processes.
527 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
528 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
529 base::Unretained(this),
530 scoped_refptr<TraceMessageFilter>(),
531 TraceLog::GetInstance()->GetBufferPercentFull()));
533 // Notify all child processes.
534 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
535 it != trace_message_filters_.end(); ++it) {
536 it->get()->SendGetTraceBufferPercentFull();
538 return true;
541 bool TracingControllerImpl::SetWatchEvent(
542 const std::string& category_name,
543 const std::string& event_name,
544 const WatchEventCallback& callback) {
545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
547 if (callback.is_null())
548 return false;
550 watch_category_name_ = category_name;
551 watch_event_name_ = event_name;
552 watch_event_callback_ = callback;
554 TraceLog::GetInstance()->SetWatchEvent(
555 category_name, event_name,
556 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
557 base::Unretained(this)));
559 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
560 it != trace_message_filters_.end(); ++it) {
561 it->get()->SendSetWatchEvent(category_name, event_name);
563 return true;
566 bool TracingControllerImpl::CancelWatchEvent() {
567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
569 if (!can_cancel_watch_event())
570 return false;
572 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
573 it != trace_message_filters_.end(); ++it) {
574 it->get()->SendCancelWatchEvent();
577 watch_event_callback_.Reset();
578 return true;
581 void TracingControllerImpl::AddTraceMessageFilter(
582 TraceMessageFilter* trace_message_filter) {
583 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
584 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
585 base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
586 base::Unretained(this),
587 make_scoped_refptr(trace_message_filter)));
588 return;
591 trace_message_filters_.insert(trace_message_filter);
592 if (can_cancel_watch_event()) {
593 trace_message_filter->SendSetWatchEvent(watch_category_name_,
594 watch_event_name_);
596 if (can_disable_recording()) {
597 trace_message_filter->SendBeginTracing(
598 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
599 TraceLog::GetInstance()->trace_options());
601 if (can_disable_monitoring()) {
602 trace_message_filter->SendEnableMonitoring(
603 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
604 TraceLog::GetInstance()->trace_options());
608 void TracingControllerImpl::RemoveTraceMessageFilter(
609 TraceMessageFilter* trace_message_filter) {
610 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
611 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
612 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
613 base::Unretained(this),
614 make_scoped_refptr(trace_message_filter)));
615 return;
618 // If a filter is removed while a response from that filter is pending then
619 // simulate the response. Otherwise the response count will be wrong and the
620 // completion callback will never be executed.
621 if (pending_disable_recording_ack_count_ > 0) {
622 TraceMessageFilterSet::const_iterator it =
623 pending_disable_recording_filters_.find(trace_message_filter);
624 if (it != pending_disable_recording_filters_.end()) {
625 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
626 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
627 base::Unretained(this),
628 make_scoped_refptr(trace_message_filter),
629 std::vector<std::string>()));
632 if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
633 TraceMessageFilterSet::const_iterator it =
634 pending_capture_monitoring_filters_.find(trace_message_filter);
635 if (it != pending_capture_monitoring_filters_.end()) {
636 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
637 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
638 base::Unretained(this),
639 make_scoped_refptr(trace_message_filter)));
642 if (pending_trace_buffer_percent_full_ack_count_ > 0) {
643 TraceMessageFilterSet::const_iterator it =
644 pending_trace_buffer_percent_full_filters_.find(trace_message_filter);
645 if (it != pending_trace_buffer_percent_full_filters_.end()) {
646 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
647 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
648 base::Unretained(this),
649 make_scoped_refptr(trace_message_filter),
650 0));
654 trace_message_filters_.erase(trace_message_filter);
657 void TracingControllerImpl::OnDisableRecordingAcked(
658 TraceMessageFilter* trace_message_filter,
659 const std::vector<std::string>& known_category_groups) {
660 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
661 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
662 base::Bind(&TracingControllerImpl::OnDisableRecordingAcked,
663 base::Unretained(this),
664 make_scoped_refptr(trace_message_filter),
665 known_category_groups));
666 return;
669 // Merge known_category_groups with known_category_groups_
670 known_category_groups_.insert(known_category_groups.begin(),
671 known_category_groups.end());
673 if (pending_disable_recording_ack_count_ == 0)
674 return;
676 if (trace_message_filter &&
677 !pending_disable_recording_filters_.erase(trace_message_filter)) {
678 // The response from the specified message filter has already been received.
679 return;
682 if (--pending_disable_recording_ack_count_ == 1) {
683 // All acks from subprocesses have been received. Now flush the local trace.
684 // During or after this call, our OnLocalTraceDataCollected will be
685 // called with the last of the local trace data.
686 TraceLog::GetInstance()->Flush(
687 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
688 base::Unretained(this)));
689 return;
692 if (pending_disable_recording_ack_count_ != 0)
693 return;
695 OnDisableRecordingComplete();
698 void TracingControllerImpl::OnDisableRecordingComplete() {
699 // All acks (including from the subprocesses and the local trace) have been
700 // received.
701 is_recording_ = false;
703 // Trigger callback if one is set.
704 if (!pending_get_categories_done_callback_.is_null()) {
705 pending_get_categories_done_callback_.Run(known_category_groups_);
706 pending_get_categories_done_callback_.Reset();
707 } else if (result_file_) {
708 result_file_->Close(
709 base::Bind(&TracingControllerImpl::OnResultFileClosed,
710 base::Unretained(this)));
714 void TracingControllerImpl::OnResultFileClosed() {
715 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
717 if (!result_file_)
718 return;
720 if (!pending_disable_recording_done_callback_.is_null()) {
721 pending_disable_recording_done_callback_.Run(result_file_->path());
722 pending_disable_recording_done_callback_.Reset();
724 result_file_.reset();
727 #if defined(OS_CHROMEOS) || defined(OS_WIN)
728 void TracingControllerImpl::OnEndSystemTracingAcked(
729 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
732 if (result_file_)
733 result_file_->WriteSystemTrace(events_str_ptr);
735 DCHECK(!is_system_tracing_);
736 std::vector<std::string> category_groups;
737 OnDisableRecordingAcked(NULL, category_groups);
739 #endif
741 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
742 TraceMessageFilter* trace_message_filter) {
743 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
744 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
745 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
746 base::Unretained(this),
747 make_scoped_refptr(trace_message_filter)));
748 return;
751 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
752 return;
754 if (trace_message_filter &&
755 !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
756 // The response from the specified message filter has already been received.
757 return;
760 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
761 // All acks from subprocesses have been received. Now flush the local trace.
762 // During or after this call, our OnLocalMonitoringTraceDataCollected
763 // will be called with the last of the local trace data.
764 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
765 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
766 base::Unretained(this)));
767 return;
770 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
771 return;
773 if (monitoring_snapshot_file_) {
774 monitoring_snapshot_file_->Close(
775 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
776 base::Unretained(this)));
780 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
781 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
783 if (!monitoring_snapshot_file_)
784 return;
786 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
787 pending_capture_monitoring_snapshot_done_callback_.Run(
788 monitoring_snapshot_file_->path());
789 pending_capture_monitoring_snapshot_done_callback_.Reset();
791 monitoring_snapshot_file_.reset();
794 void TracingControllerImpl::OnTraceDataCollected(
795 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
796 // OnTraceDataCollected may be called from any browser thread, either by the
797 // local event trace system or from child processes via TraceMessageFilter.
798 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
799 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
800 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
801 base::Unretained(this), events_str_ptr));
802 return;
805 if (result_file_)
806 result_file_->Write(events_str_ptr);
809 void TracingControllerImpl::OnMonitoringTraceDataCollected(
810 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
811 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
812 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
813 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
814 base::Unretained(this), events_str_ptr));
815 return;
818 if (monitoring_snapshot_file_)
819 monitoring_snapshot_file_->Write(events_str_ptr);
822 void TracingControllerImpl::OnLocalTraceDataCollected(
823 const scoped_refptr<base::RefCountedString>& events_str_ptr,
824 bool has_more_events) {
825 if (events_str_ptr->data().size())
826 OnTraceDataCollected(events_str_ptr);
828 if (has_more_events)
829 return;
831 // Simulate an DisableRecordingAcked for the local trace.
832 std::vector<std::string> category_groups;
833 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
834 OnDisableRecordingAcked(NULL, category_groups);
837 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
838 const scoped_refptr<base::RefCountedString>& events_str_ptr,
839 bool has_more_events) {
840 if (events_str_ptr->data().size())
841 OnMonitoringTraceDataCollected(events_str_ptr);
843 if (has_more_events)
844 return;
846 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
847 OnCaptureMonitoringSnapshotAcked(NULL);
850 void TracingControllerImpl::OnTraceBufferPercentFullReply(
851 TraceMessageFilter* trace_message_filter,
852 float percent_full) {
853 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
854 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
855 base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
856 base::Unretained(this),
857 make_scoped_refptr(trace_message_filter),
858 percent_full));
859 return;
862 if (pending_trace_buffer_percent_full_ack_count_ == 0)
863 return;
865 if (trace_message_filter &&
866 !pending_trace_buffer_percent_full_filters_.erase(trace_message_filter)) {
867 // The response from the specified message filter has already been received.
868 return;
871 maximum_trace_buffer_percent_full_ =
872 std::max(maximum_trace_buffer_percent_full_, percent_full);
874 if (--pending_trace_buffer_percent_full_ack_count_ == 0) {
875 // Trigger callback if one is set.
876 pending_trace_buffer_percent_full_callback_.Run(
877 maximum_trace_buffer_percent_full_);
878 pending_trace_buffer_percent_full_callback_.Reset();
882 void TracingControllerImpl::OnWatchEventMatched() {
883 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
884 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
885 base::Bind(&TracingControllerImpl::OnWatchEventMatched,
886 base::Unretained(this)));
887 return;
890 if (!watch_event_callback_.is_null())
891 watch_event_callback_.Run();
894 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
895 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
896 tracing_uis_.insert(tracing_ui);
899 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
900 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
901 DCHECK(it != tracing_uis_.end());
902 tracing_uis_.erase(it);
905 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
906 if (is_monitoring_ == is_monitoring)
907 return;
909 is_monitoring_ = is_monitoring;
910 #if !defined(OS_ANDROID)
911 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
912 it != tracing_uis_.end(); it++) {
913 (*it)->OnMonitoringStateChanged(is_monitoring);
915 #endif
918 } // namespace content