| 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.
|
|
|