Index: content/browser/tracing/trace_controller_impl.cc |
diff --git a/content/browser/tracing/trace_controller_impl.cc b/content/browser/tracing/trace_controller_impl.cc |
index 53e4ea5cae05fb44b09f45c02cda83f42f08acf9..97d105a32d56e103e999249366493854afe93115 100644 |
--- a/content/browser/tracing/trace_controller_impl.cc |
+++ b/content/browser/tracing/trace_controller_impl.cc |
@@ -53,9 +53,11 @@ TraceController* TraceController::GetInstance() { |
TraceControllerImpl::TraceControllerImpl() : |
subscriber_(NULL), |
pending_end_ack_count_(0), |
+ pending_show_continuous_sampling_ack_count_(0), |
pending_bpf_ack_count_(0), |
maximum_bpf_(0.0f), |
is_tracing_(false), |
+ is_continuous_sampling_tracing_(false), |
is_get_category_groups_(false), |
category_filter_( |
base::debug::CategoryFilter::kDefaultCategoryFilterString) { |
@@ -138,14 +140,13 @@ bool TraceControllerImpl::BeginTracing(TraceSubscriber* subscriber, |
base::debug::CategoryFilter(category_patterns), options); |
OnTracingBegan(subscriber); |
- |
return true; |
} |
bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- if (!can_end_tracing() || subscriber != subscriber_) |
+ if (!can_end_tracing(subscriber)) |
return false; |
// There could be a case where there are no child processes and filters_ |
@@ -173,6 +174,70 @@ bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { |
return true; |
} |
+bool TraceControllerImpl::BeginContinuousSamplingTracing( |
+ TraceSubscriber* subscriber) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (!can_begin_continuous_sampling_tracing(subscriber)) |
+ return false; |
+ |
+ is_continuous_sampling_tracing_ = true; |
+ continuous_sampling_subscriber_ = subscriber; |
+ |
+ // Notify all child processes. |
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { |
+ it->get()->SendBeginContinuousSamplingTracing(); |
+ } |
+ return true; |
+} |
+ |
+bool TraceControllerImpl::EndContinuousSamplingTracing( |
+ TraceSubscriber* subscriber) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (!can_end_continuous_sampling_tracing(subscriber)) |
+ return false; |
+ |
+ is_continuous_sampling_tracing_ = false; |
+ continuous_sampling_subscriber_ = NULL; |
+ |
+ // Notify all child processes. |
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { |
+ it->get()->SendEndContinuousSamplingTracing(); |
+ } |
+ return true; |
+} |
+ |
+bool TraceControllerImpl::ShowContinuousSamplingTracingAsync( |
+ TraceSubscriber* subscriber) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (!can_end_continuous_sampling_tracing(subscriber)) |
+ return false; |
+ |
+ // There could be a case where there are no child processes and filters_ |
+ // is empty. In that case we can immediately tell the subscriber that tracing |
+ // has ended. To avoid recursive calls back to the subscriber, we will just |
+ // use the existing asynchronous OnShowContinuousSamplingTracingAck code. |
+ // Count myself (local trace) in pending_show_continuous_sampling_ack_count_, |
+ // acked below. |
+ pending_show_continuous_sampling_ack_count_ = filters_.size() + 1; |
+ |
+ // Handle special case of zero child processes. |
+ if (pending_show_continuous_sampling_ack_count_ == 1) { |
+ // Ack asynchronously now, because we don't have any children to wait for. |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck, |
+ base::Unretained(this))); |
+ } |
+ |
+ // Notify all child processes. |
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { |
+ it->get()->SendShowContinuousSamplingTracing(); |
+ } |
+ return true; |
+} |
+ |
bool TraceControllerImpl::GetTraceBufferPercentFullAsync( |
TraceSubscriber* subscriber) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -238,7 +303,7 @@ void TraceControllerImpl::CancelSubscriber(TraceSubscriber* subscriber) { |
if (subscriber == subscriber_) { |
subscriber_ = NULL; |
// End tracing if necessary. |
- if (is_tracing_ && pending_end_ack_count_ == 0) |
+ if (is_tracing_enabled()) |
EndTracingAsync(NULL); |
} |
} |
@@ -258,6 +323,9 @@ void TraceControllerImpl::AddFilter(TraceMessageFilter* filter) { |
if (!watch_category_.empty()) |
filter->SendSetWatchEvent(watch_category_, watch_name_); |
} |
+ if (is_continuous_sampling_tracing_enabled()) { |
+ filter->SendBeginContinuousSamplingTracing(); |
+ } |
} |
void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) { |
@@ -273,7 +341,6 @@ void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) { |
void TraceControllerImpl::OnTracingBegan(TraceSubscriber* subscriber) { |
is_tracing_ = true; |
- |
subscriber_ = subscriber; |
category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter(); |
@@ -356,6 +423,60 @@ void TraceControllerImpl::OnTraceDataCollected( |
subscriber_->OnTraceDataCollected(events_str_ptr); |
} |
+void TraceControllerImpl::OnShowContinuousSamplingTracingAck() { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck, |
+ base::Unretained(this))); |
+ return; |
+ } |
+ |
+ if (pending_show_continuous_sampling_ack_count_ == 0) |
+ return; |
+ |
+ if (--pending_show_continuous_sampling_ack_count_ == 0) { |
+ // During this call, our OnContinuousSamplingTraceDataCollected will be |
+ // called with the last of the local trace data. Since we are on the UI |
+ // thread, the call to OnContinuousSamplingTraceDataCollected will be |
+ // synchronous, so we can immediately call |
+ // OnShowContinuousSamplingTracingComplete below. |
+ TraceLog::GetInstance()->FlushContinuousSamplingTracing( |
+ base::Bind(&TraceControllerImpl::OnContinuousSamplingTraceDataCollected, |
+ base::Unretained(this))); |
+ |
+ if (continuous_sampling_subscriber_) |
+ continuous_sampling_subscriber_-> |
+ OnShowContinuousSamplingTracingComplete(); |
+ } |
+ |
+ if (pending_show_continuous_sampling_ack_count_ == 1) { |
+ // The last ack represents local trace, so we need to ack it now. Note that |
+ // this code only executes if there were child processes. |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck, |
+ base::Unretained(this))); |
+ } |
+} |
+ |
+void TraceControllerImpl::OnContinuousSamplingTraceDataCollected( |
+ const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
+ // OnContinuousSamplingTraceDataCollected may be called from |
+ // any browser thread, either by the local event trace system or |
+ // from child processes via TraceMessageFilter. |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&TraceControllerImpl:: |
+ OnContinuousSamplingTraceDataCollected, |
+ base::Unretained(this), events_str_ptr)); |
+ return; |
+ } |
+ |
+ // Drop trace events if we are just getting categories. |
+ if (continuous_sampling_subscriber_) |
+ continuous_sampling_subscriber_-> |
+ OnContinuousSamplingTraceDataCollected(events_str_ptr); |
+} |
+ |
void TraceControllerImpl::OnTraceNotification(int notification) { |
// OnTraceNotification may be called from any browser thread, either by the |
// local event trace system or from child processes via TraceMessageFilter. |