summaryrefslogtreecommitdiffstats
path: root/content/browser/trace_controller.cc
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-18 22:27:55 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-18 22:27:55 +0000
commitd61e096b7e834877db979e73064b24f40a860ff4 (patch)
treed114570b4eabd7219686a1a19c5f463cd267e45b /content/browser/trace_controller.cc
parentfbfa76496e247f4a57858e4f3c0e6bd517b59352 (diff)
downloadchromium_src-d61e096b7e834877db979e73064b24f40a860ff4.zip
chromium_src-d61e096b7e834877db979e73064b24f40a860ff4.tar.gz
chromium_src-d61e096b7e834877db979e73064b24f40a860ff4.tar.bz2
event trace plumbing for multi-process support
related review: http://codereview.chromium.org/6691013/ BUG=none TEST=none Review URL: http://codereview.chromium.org/6694004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78768 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/trace_controller.cc')
-rw-r--r--content/browser/trace_controller.cc162
1 files changed, 162 insertions, 0 deletions
diff --git a/content/browser/trace_controller.cc b/content/browser/trace_controller.cc
new file mode 100644
index 0000000..e2e046a
--- /dev/null
+++ b/content/browser/trace_controller.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/trace_controller.h"
+
+#include "base/task.h"
+#include "content/browser/browser_message_filter.h"
+#include "content/browser/trace_message_filter.h"
+#include "content/common/child_process_messages.h"
+#include "gpu/common/gpu_trace_event.h"
+
+
+TraceController::TraceController() :
+ pending_ack_count_(0),
+ is_tracing_(false),
+ subscriber_(NULL) {
+ gpu::TraceLog::GetInstance()->SetOutputCallback(
+ NewCallback(this, &TraceController::OnTraceDataCollected));
+}
+
+TraceController::~TraceController() {
+ gpu::TraceLog::GetInstance()->SetOutputCallback(NULL);
+}
+
+//static
+TraceController* TraceController::GetInstance() {
+ return Singleton<TraceController>::get();
+}
+
+bool TraceController::BeginTracing(TraceSubscriber* subscriber) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_begin_tracing() ||
+ (subscriber_ != NULL && subscriber != subscriber_))
+ return false;
+
+ subscriber_ = subscriber;
+
+ // Enable tracing
+ is_tracing_ = true;
+ gpu::TraceLog::GetInstance()->SetEnabled(true);
+
+ // Notify all child processes.
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
+ it->get()->SendBeginTracing();
+ }
+
+ return true;
+}
+
+bool TraceController::EndTracingAsync(TraceSubscriber* subscriber) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_end_tracing() || subscriber != 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 OnEndTracingAck code.
+ // Count myself (local trace) in pending_ack_count_, acked below.
+ pending_ack_count_ = filters_.size() + 1;
+
+ // Handle special case of zero child processes.
+ if (pending_ack_count_ == 1) {
+ // Ack asynchronously now, because we don't have any children to wait for.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TraceController::OnEndTracingAck));
+ }
+
+ // Notify all child processes.
+ for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
+ it->get()->SendEndTracing();
+ }
+
+ return true;
+}
+
+void TraceController::CancelSubscriber(TraceSubscriber* subscriber) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (subscriber == subscriber_) {
+ subscriber_ = NULL;
+ // End tracing if necessary.
+ if (is_tracing_ && pending_ack_count_ == 0)
+ EndTracingAsync(NULL);
+ }
+}
+
+void TraceController::AddFilter(TraceMessageFilter* filter) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TraceController::AddFilter,
+ make_scoped_refptr(filter)));
+ return;
+ }
+
+ filters_.insert(filter);
+ if (is_tracing_enabled()) {
+ filter->SendBeginTracing();
+ }
+}
+
+void TraceController::RemoveFilter(TraceMessageFilter* filter) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TraceController::RemoveFilter,
+ make_scoped_refptr(filter)));
+ return;
+ }
+
+ filters_.erase(filter);
+}
+
+void TraceController::OnEndTracingAck() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TraceController::OnEndTracingAck));
+ return;
+ }
+
+ if (--pending_ack_count_ == 0) {
+ // All acks have been received.
+ is_tracing_ = false;
+
+ // Disable local trace. During this call, our OnTraceDataCollected will be
+ // called with the last of the local trace data. Since we are on the UI
+ // thread, the call to OnTraceDataCollected will be synchronous, so we can
+ // immediately call OnEndTracingComplete below.
+ gpu::TraceLog::GetInstance()->SetEnabled(false);
+
+ // Trigger callback if one is set.
+ if (subscriber_ != NULL) {
+ subscriber_->OnEndTracingComplete();
+ // Clear subscriber so that others can use TraceController.
+ subscriber_ = NULL;
+ }
+ }
+
+ if (pending_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,
+ NewRunnableMethod(this, &TraceController::OnEndTracingAck));
+ }
+}
+
+void TraceController::OnTraceDataCollected(const std::string& data) {
+ // OnTraceDataCollected may be called from any browser thread, either by the
+ // local event trace system or from child processes bia TraceMessageFilter.
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TraceController::OnTraceDataCollected, data));
+ return;
+ }
+
+ if (subscriber_) {
+ subscriber_->OnTraceDataCollected(data);
+ }
+}
+