summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authordgrogan@chromium.org <dgrogan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-13 08:18:51 +0000
committerdgrogan@chromium.org <dgrogan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-13 08:18:51 +0000
commit0213480a48c9d02f15ad80e5bc670303c65ea11b (patch)
treecbaa434b1c315e5fca93a89cd600d2a475b4f1fe /webkit
parent6b6e7ee27ce2b3beccebbcb3dc8ca75bb1dfa067 (diff)
downloadchromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.zip
chromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.tar.gz
chromium_src-0213480a48c9d02f15ad80e5bc670303c65ea11b.tar.bz2
Track webcore worker message loops in chromium.
BUG=106265 TEST= Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=114157 Review URL: http://codereview.chromium.org/8785013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114192 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/webkit_glue.gypi2
-rw-r--r--webkit/glue/webkitplatformsupport_impl.cc13
-rw-r--r--webkit/glue/webkitplatformsupport_impl.h5
-rw-r--r--webkit/glue/worker_task_runner.cc103
-rw-r--r--webkit/glue/worker_task_runner.h59
-rw-r--r--webkit/glue/worker_task_runner_unittest.cc56
-rw-r--r--webkit/tools/test_shell/test_shell.gypi1
7 files changed, 239 insertions, 0 deletions
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 2c049b8..aa95004 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -436,6 +436,8 @@
'web_io_operators.h',
'window_open_disposition.h',
'window_open_disposition.cc',
+ 'worker_task_runner.cc',
+ 'worker_task_runner.h',
# These files used to be built in the webcore target, but moved here
# since part of glue.
diff --git a/webkit/glue/webkitplatformsupport_impl.cc b/webkit/glue/webkitplatformsupport_impl.cc
index fd3759a..e8ddd15 100644
--- a/webkit/glue/webkitplatformsupport_impl.cc
+++ b/webkit/glue/webkitplatformsupport_impl.cc
@@ -41,6 +41,7 @@
#include "webkit/glue/websocketstreamhandle_impl.h"
#include "webkit/glue/webthread_impl.h"
#include "webkit/glue/weburlloader_impl.h"
+#include "webkit/glue/worker_task_runner.h"
#include "webkit/media/audio_decoder.h"
#include "webkit/plugins/npapi/plugin_instance.h"
#include "webkit/plugins/webplugininfo.h"
@@ -686,4 +687,16 @@ void WebKitPlatformSupportImpl::DestroyCurrentThread(void* thread) {
delete impl;
}
+void WebKitPlatformSupportImpl::didStartWorkerRunLoop(
+ const WebKit::WebWorkerRunLoop& runLoop) {
+ WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
+ worker_task_runner->OnWorkerRunLoopStarted(runLoop);
+}
+
+void WebKitPlatformSupportImpl::didStopWorkerRunLoop(
+ const WebKit::WebWorkerRunLoop& runLoop) {
+ WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
+ worker_task_runner->OnWorkerRunLoopStopped(runLoop);
+}
+
} // namespace webkit_glue
diff --git a/webkit/glue/webkitplatformsupport_impl.h b/webkit/glue/webkitplatformsupport_impl.h
index 75f8baa..02a7266 100644
--- a/webkit/glue/webkitplatformsupport_impl.h
+++ b/webkit/glue/webkitplatformsupport_impl.h
@@ -124,6 +124,11 @@ class WEBKIT_GLUE_EXPORT WebKitPlatformSupportImpl :
void SuspendSharedTimer();
void ResumeSharedTimer();
+ virtual void didStartWorkerRunLoop(
+ const WebKit::WebWorkerRunLoop& runLoop) OVERRIDE;
+ virtual void didStopWorkerRunLoop(
+ const WebKit::WebWorkerRunLoop& runLoop) OVERRIDE;
+
private:
void DoTimeout() {
if (shared_timer_func_ && !shared_timer_suspended_)
diff --git a/webkit/glue/worker_task_runner.cc b/webkit/glue/worker_task_runner.cc
new file mode 100644
index 0000000..3836e61
--- /dev/null
+++ b/webkit/glue/worker_task_runner.cc
@@ -0,0 +1,103 @@
+// 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 "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "webkit/glue/worker_task_runner.h"
+
+using WebKit::WebWorkerRunLoop;
+
+namespace {
+
+class RunClosureTask : public WebWorkerRunLoop::Task {
+ public:
+ RunClosureTask(const base::Closure& task) : task_(task) {}
+ virtual ~RunClosureTask() {}
+ virtual void Run() {
+ task_.Run();
+ }
+ private:
+ base::Closure task_;
+};
+
+} // unnamed namespace
+
+namespace webkit_glue {
+
+struct WorkerTaskRunner::ThreadLocalState {
+ ThreadLocalState(int id, const WebWorkerRunLoop& loop)
+ : id_(id), run_loop_(loop) {
+ }
+ int id_;
+ WebWorkerRunLoop run_loop_;
+ ObserverList<WorkerTaskRunner::Observer> stop_observers_;
+};
+
+WorkerTaskRunner::WorkerTaskRunner() {
+ // Start worker ids at 1, 0 is reserved for the main thread.
+ int id = id_sequence_.GetNext();
+ DCHECK(!id);
+}
+
+void WorkerTaskRunner::PostTask(
+ int id, const base::Closure& closure) {
+ DCHECK(id > 0);
+ base::AutoLock locker(loop_map_lock_);
+ IDToLoopMap::iterator found = loop_map_.find(id);
+ if (found != loop_map_.end())
+ found->second.postTask(new RunClosureTask(closure));
+}
+
+int WorkerTaskRunner::CurrentWorkerId() {
+ if (!current_tls_.Get())
+ return 0;
+ return current_tls_.Get()->id_;
+}
+
+WorkerTaskRunner* WorkerTaskRunner::Instance() {
+ static base::LazyInstance<WorkerTaskRunner,
+ base::LeakyLazyInstanceTraits<WorkerTaskRunner> >
+ worker_task_runner = LAZY_INSTANCE_INITIALIZER;
+ return worker_task_runner.Pointer();
+}
+
+void WorkerTaskRunner::AddStopObserver(Observer* obs) {
+ DCHECK(CurrentWorkerId() > 0);
+ current_tls_.Get()->stop_observers_.AddObserver(obs);
+}
+
+void WorkerTaskRunner::RemoveStopObserver(Observer* obs) {
+ DCHECK(CurrentWorkerId() > 0);
+ current_tls_.Get()->stop_observers_.RemoveObserver(obs);
+}
+
+WorkerTaskRunner::~WorkerTaskRunner() {
+}
+
+void WorkerTaskRunner::OnWorkerRunLoopStarted(const WebWorkerRunLoop& loop) {
+ DCHECK(!current_tls_.Get());
+ int id = id_sequence_.GetNext();
+ current_tls_.Set(new ThreadLocalState(id, loop));
+
+ base::AutoLock locker_(loop_map_lock_);
+ loop_map_[id] = loop;
+}
+
+void WorkerTaskRunner::OnWorkerRunLoopStopped(const WebWorkerRunLoop& loop) {
+ DCHECK(current_tls_.Get());
+ FOR_EACH_OBSERVER(Observer, current_tls_.Get()->stop_observers_,
+ OnWorkerRunLoopStopped());
+ {
+ base::AutoLock locker(loop_map_lock_);
+ DCHECK(loop_map_[CurrentWorkerId()] == loop);
+ loop_map_.erase(CurrentWorkerId());
+ }
+ delete current_tls_.Get();
+ current_tls_.Set(NULL);
+}
+
+} // namespace webkit_glue
diff --git a/webkit/glue/worker_task_runner.h b/webkit/glue/worker_task_runner.h
new file mode 100644
index 0000000..6eea8c0
--- /dev/null
+++ b/webkit/glue/worker_task_runner.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef WEBKIT_GLUE_WORKER_TASK_RUNNER_H_
+#define WEBKIT_GLUE_WORKER_TASK_RUNNER_H_
+#pragma once
+
+#include <map>
+
+#include "base/atomic_sequence_num.h"
+#include "base/callback_forward.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_local.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerRunLoop.h"
+#include "webkit/glue/webkit_glue_export.h"
+
+namespace webkit_glue {
+
+class WEBKIT_GLUE_EXPORT WorkerTaskRunner {
+ public:
+ WorkerTaskRunner();
+
+ void PostTask(int id, const base::Closure& task);
+ int CurrentWorkerId();
+ static WorkerTaskRunner* Instance();
+
+ class Observer {
+ public:
+ virtual ~Observer() {}
+ virtual void OnWorkerRunLoopStopped() = 0;
+ };
+ // Add/Remove an observer that will get notified when the current worker run
+ // loop is stopping. This observer will not get notified when other threads
+ // are stopping. It's only valid to call these on a worker thread.
+ void AddStopObserver(Observer* observer);
+ void RemoveStopObserver(Observer* observer);
+
+ private:
+ friend class WebKitPlatformSupportImpl;
+ friend class WorkerTaskRunnerTest;
+
+ typedef std::map<int, WebKit::WebWorkerRunLoop> IDToLoopMap;
+
+ ~WorkerTaskRunner();
+ void OnWorkerRunLoopStarted(const WebKit::WebWorkerRunLoop& loop);
+ void OnWorkerRunLoopStopped(const WebKit::WebWorkerRunLoop& loop);
+
+ struct ThreadLocalState;
+ base::ThreadLocalPointer<ThreadLocalState> current_tls_;
+
+ base::AtomicSequenceNumber id_sequence_;
+ IDToLoopMap loop_map_;
+ base::Lock loop_map_lock_;
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_WORKER_TASK_RUNNER_H_
diff --git a/webkit/glue/worker_task_runner_unittest.cc b/webkit/glue/worker_task_runner_unittest.cc
new file mode 100644
index 0000000..0ac4f2e
--- /dev/null
+++ b/webkit/glue/worker_task_runner_unittest.cc
@@ -0,0 +1,56 @@
+// 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 "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/worker_task_runner.h"
+
+namespace webkit_glue {
+
+class WorkerTaskRunnerTest : public testing::Test {
+ public:
+ void FakeStart() {
+ task_runner_.OnWorkerRunLoopStarted(WebKit::WebWorkerRunLoop());
+ }
+ void FakeStop() {
+ task_runner_.OnWorkerRunLoopStopped(WebKit::WebWorkerRunLoop());
+ }
+ WorkerTaskRunner task_runner_;
+};
+
+class MockObserver : public WorkerTaskRunner::Observer {
+ public:
+ MOCK_METHOD0(OnWorkerRunLoopStopped, void());
+ void RemoveSelfOnNotify() {
+ ON_CALL(*this, OnWorkerRunLoopStopped()).WillByDefault(
+ testing::Invoke(this, &MockObserver::RemoveSelf));
+ }
+ void RemoveSelf() {
+ runner_->RemoveStopObserver(this);
+ }
+ WorkerTaskRunner* runner_;
+};
+
+TEST_F(WorkerTaskRunnerTest, BasicObservingAndWorkerId) {
+ ASSERT_EQ(0, task_runner_.CurrentWorkerId());
+ MockObserver o;
+ EXPECT_CALL(o, OnWorkerRunLoopStopped()).Times(1);
+ FakeStart();
+ task_runner_.AddStopObserver(&o);
+ ASSERT_LT(0, task_runner_.CurrentWorkerId());
+ FakeStop();
+}
+
+TEST_F(WorkerTaskRunnerTest, CanRemoveSelfDuringNotification) {
+ MockObserver o;
+ o.RemoveSelfOnNotify();
+ o.runner_ = &task_runner_;
+ EXPECT_CALL(o, OnWorkerRunLoopStopped()).Times(1);
+ FakeStart();
+ task_runner_.AddStopObserver(&o);
+ FakeStop();
+}
+
+}
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index 082c502..adfd6d3 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -429,6 +429,7 @@
'../../glue/webframe_unittest.cc',
'../../glue/webkit_glue_unittest.cc',
'../../glue/webview_unittest.cc',
+ '../../glue/worker_task_runner_unittest.cc',
'../../media/buffered_data_source_unittest.cc',
'../../media/buffered_resource_loader_unittest.cc',
'../../media/simple_data_source_unittest.cc',