summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 02:38:24 +0000
committeryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 02:38:24 +0000
commit7ef6b79bd40c9e7ce84b05a7b8cc3ed28a0ddc72 (patch)
tree035507f07c0928c6ca8043fa7d01f64817bed3eb
parentfd8609d8bd5255ab0a46b7169921a98de7837025 (diff)
downloadchromium_src-7ef6b79bd40c9e7ce84b05a7b8cc3ed28a0ddc72.zip
chromium_src-7ef6b79bd40c9e7ce84b05a7b8cc3ed28a0ddc72.tar.gz
chromium_src-7ef6b79bd40c9e7ce84b05a7b8cc3ed28a0ddc72.tar.bz2
Pepper: Introduce ThreadAwareCallback.
Some PPB interfaces have methods that set a custom callback. Usually, the callback has to be called on the same thread as the one it was set on. ThreadAwareCallback keeps track of the target thread, and posts a task to run on it if requested from a different thread. BUG=None TEST=newly added unittests. Review URL: https://chromiumcodereview.appspot.com/11859015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177319 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/component_updater/test/component_installers_unittest.cc4
-rw-r--r--ppapi/ppapi_shared.gypi2
-rw-r--r--ppapi/ppapi_tests.gypi1
-rw-r--r--ppapi/proxy/device_enumeration_resource_helper.cc20
-rw-r--r--ppapi/proxy/device_enumeration_resource_helper.h4
-rw-r--r--ppapi/proxy/plugin_globals.cc4
-rw-r--r--ppapi/proxy/plugin_globals.h2
-rw-r--r--ppapi/proxy/ppapi_proxy_test.cc154
-rw-r--r--ppapi/proxy/ppapi_proxy_test.h76
-rw-r--r--ppapi/proxy/ppb_message_loop_proxy.h3
-rw-r--r--ppapi/proxy/ppb_var_unittest.cc28
-rw-r--r--ppapi/shared_impl/DEPS3
-rw-r--r--ppapi/shared_impl/ppapi_globals.cc2
-rw-r--r--ppapi/shared_impl/ppapi_globals.h6
-rw-r--r--ppapi/shared_impl/test_globals.cc4
-rw-r--r--ppapi/shared_impl/test_globals.h2
-rw-r--r--ppapi/shared_impl/thread_aware_callback.cc63
-rw-r--r--ppapi/shared_impl/thread_aware_callback.h115
-rw-r--r--ppapi/shared_impl/thread_aware_callback_unittest.cc218
-rw-r--r--webkit/plugins/ppapi/host_globals.cc5
-rw-r--r--webkit/plugins/ppapi/host_globals.h2
21 files changed, 650 insertions, 68 deletions
diff --git a/chrome/browser/component_updater/test/component_installers_unittest.cc b/chrome/browser/component_updater/test/component_installers_unittest.cc
index e7a4ee1..807f659 100644
--- a/chrome/browser/component_updater/test/component_installers_unittest.cc
+++ b/chrome/browser/component_updater/test/component_installers_unittest.cc
@@ -43,8 +43,8 @@ TEST(ComponentInstallerTest, PepperFlashCheck) {
MessageLoop message_loop;
content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
- ppapi::PpapiGlobals::ForTest for_test;
- ppapi::TestGlobals test_globals(for_test);
+ ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test;
+ ppapi::TestGlobals test_globals(per_thread_for_test);
ppapi::PpapiGlobals::SetPpapiGlobalsOnThreadForTest(&test_globals);
// The test directory is chrome/test/data/components/flapper.
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 67c8a02..ad03525 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -95,6 +95,8 @@
'shared_impl/scoped_pp_resource.h',
'shared_impl/scoped_pp_var.cc',
'shared_impl/scoped_pp_var.h',
+ 'shared_impl/thread_aware_callback.cc',
+ 'shared_impl/thread_aware_callback.h',
'shared_impl/time_conversion.cc',
'shared_impl/time_conversion.h',
'shared_impl/tracked_callback.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index a229107..98ba36a 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -158,6 +158,7 @@
'proxy/serialized_var_unittest.cc',
'proxy/websocket_resource_unittest.cc',
'shared_impl/resource_tracker_unittest.cc',
+ 'shared_impl/thread_aware_callback_unittest.cc',
'shared_impl/time_conversion_unittest.cc',
'shared_impl/tracked_callback_unittest.cc',
'shared_impl/var_tracker_unittest.cc',
diff --git a/ppapi/proxy/device_enumeration_resource_helper.cc b/ppapi/proxy/device_enumeration_resource_helper.cc
index 2b51c27..2729406 100644
--- a/ppapi/proxy/device_enumeration_resource_helper.cc
+++ b/ppapi/proxy/device_enumeration_resource_helper.cc
@@ -30,7 +30,6 @@ DeviceEnumerationResourceHelper::DeviceEnumerationResourceHelper(
: owner_(owner),
pending_enumerate_devices_(false),
monitor_callback_id_(0),
- monitor_callback_(NULL),
monitor_user_data_(NULL) {
}
@@ -90,14 +89,19 @@ int32_t DeviceEnumerationResourceHelper::MonitorDeviceChange(
PP_MonitorDeviceChangeCallback callback,
void* user_data) {
monitor_callback_id_++;
- monitor_callback_ = callback;
monitor_user_data_ = user_data;
-
if (callback) {
+ monitor_callback_.reset(
+ ThreadAwareCallback<PP_MonitorDeviceChangeCallback>::Create(callback));
+ if (!monitor_callback_.get())
+ return PP_ERROR_NO_MESSAGE_LOOP;
+
owner_->Post(PluginResource::RENDERER,
PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange(
monitor_callback_id_));
} else {
+ monitor_callback_.reset(NULL);
+
owner_->Post(PluginResource::RENDERER,
PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange());
}
@@ -120,7 +124,7 @@ bool DeviceEnumerationResourceHelper::HandleReply(
void DeviceEnumerationResourceHelper::LastPluginRefWasDeleted() {
// Make sure that no further notifications are sent to the plugin.
monitor_callback_id_++;
- monitor_callback_ = NULL;
+ monitor_callback_.reset(NULL);
monitor_user_data_ = NULL;
// There is no need to do anything with pending callback of
@@ -178,7 +182,7 @@ void DeviceEnumerationResourceHelper::OnPluginMsgNotifyDeviceChange(
return;
}
- CHECK(monitor_callback_);
+ CHECK(monitor_callback_.get());
scoped_array<PP_Resource> elements;
uint32_t size = devices.size();
@@ -191,10 +195,8 @@ void DeviceEnumerationResourceHelper::OnPluginMsgNotifyDeviceChange(
}
}
- // TODO(yzshen): make sure |monitor_callback_| is called on the same thread as
- // the one on which MonitorDeviceChange() is called.
- CallWhileUnlocked(base::Bind(monitor_callback_, monitor_user_data_, size,
- elements.get()));
+ monitor_callback_->RunOnTargetThread(monitor_user_data_, size,
+ elements.get());
for (size_t index = 0; index < size; ++index)
PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(elements[index]);
}
diff --git a/ppapi/proxy/device_enumeration_resource_helper.h b/ppapi/proxy/device_enumeration_resource_helper.h
index 6c266eb..a2574ec 100644
--- a/ppapi/proxy/device_enumeration_resource_helper.h
+++ b/ppapi/proxy/device_enumeration_resource_helper.h
@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "ppapi/c/dev/ppb_device_ref_dev.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/thread_aware_callback.h"
namespace IPC {
class Message;
@@ -74,7 +75,8 @@ class PPAPI_PROXY_EXPORT DeviceEnumerationResourceHelper
bool pending_enumerate_devices_;
uint32_t monitor_callback_id_;
- PP_MonitorDeviceChangeCallback monitor_callback_;
+ scoped_ptr<ThreadAwareCallback<PP_MonitorDeviceChangeCallback> >
+ monitor_callback_;
void* monitor_user_data_;
DISALLOW_COPY_AND_ASSIGN(DeviceEnumerationResourceHelper);
diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc
index 2913aa2..2e18ac5f 100644
--- a/ppapi/proxy/plugin_globals.cc
+++ b/ppapi/proxy/plugin_globals.cc
@@ -62,8 +62,8 @@ PluginGlobals::PluginGlobals()
plugin_globals_ = this;
}
-PluginGlobals::PluginGlobals(ForTest for_test)
- : ppapi::PpapiGlobals(for_test),
+PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test)
+ : ppapi::PpapiGlobals(per_thread_for_test),
plugin_proxy_delegate_(NULL),
callback_tracker_(new CallbackTracker) {
#if defined(ENABLE_PEPPER_THREADING)
diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h
index b323903..9b50295 100644
--- a/ppapi/proxy/plugin_globals.h
+++ b/ppapi/proxy/plugin_globals.h
@@ -30,7 +30,7 @@ class PluginProxyDelegate;
class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals {
public:
PluginGlobals();
- PluginGlobals(PpapiGlobals::ForTest);
+ explicit PluginGlobals(PpapiGlobals::PerThreadForTest);
virtual ~PluginGlobals();
// Getter for the global singleton. Generally, you should use
diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc
index 1af1dfc..1a475c0 100644
--- a/ppapi/proxy/ppapi_proxy_test.cc
+++ b/ppapi/proxy/ppapi_proxy_test.cc
@@ -7,14 +7,17 @@
#include <sstream>
#include "base/bind.h"
-#include "base/compiler_specific.h"
+#include "base/bind_helpers.h"
#include "base/message_loop_proxy.h"
#include "base/observer_list.h"
#include "base/process_util.h"
+#include "base/run_loop.h"
#include "ipc/ipc_sync_channel.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_message_loop_proxy.h"
+#include "ppapi/shared_impl/proxy_lock.h"
namespace ppapi {
namespace proxy {
@@ -149,7 +152,9 @@ bool ProxyTestHarnessBase::SupportsInterface(const char* name) {
// PluginProxyTestHarness ------------------------------------------------------
-PluginProxyTestHarness::PluginProxyTestHarness() {
+PluginProxyTestHarness::PluginProxyTestHarness(
+ GlobalsConfiguration globals_config)
+ : globals_config_(globals_config) {
}
PluginProxyTestHarness::~PluginProxyTestHarness() {
@@ -164,10 +169,9 @@ Dispatcher* PluginProxyTestHarness::GetDispatcher() {
}
void PluginProxyTestHarness::SetUpHarness() {
- plugin_globals_.reset(new PluginGlobals(PpapiGlobals::ForTest()));
-
// These must be first since the dispatcher set-up uses them.
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ CreatePluginGlobals();
+
resource_tracker().DidCreateInstance(pp_instance());
plugin_dispatcher_.reset(new PluginDispatcher(
@@ -190,10 +194,9 @@ void PluginProxyTestHarness::SetUpHarnessWithChannel(
base::MessageLoopProxy* ipc_message_loop,
base::WaitableEvent* shutdown_event,
bool is_client) {
- plugin_globals_.reset(new PluginGlobals(PpapiGlobals::ForTest()));
-
// These must be first since the dispatcher set-up uses them.
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ CreatePluginGlobals();
+
resource_tracker().DidCreateInstance(pp_instance());
plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);
@@ -218,6 +221,15 @@ void PluginProxyTestHarness::TearDownHarness() {
plugin_globals_.reset();
}
+void PluginProxyTestHarness::CreatePluginGlobals() {
+ if (globals_config_ == PER_THREAD_GLOBALS) {
+ plugin_globals_.reset(new PluginGlobals(PpapiGlobals::PerThreadForTest()));
+ PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ } else {
+ plugin_globals_.reset(new PluginGlobals());
+ }
+}
+
base::MessageLoopProxy*
PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
return ipc_message_loop_;
@@ -270,7 +282,7 @@ void PluginProxyTestHarness::PluginDelegateMock::SetActiveURL(
// PluginProxyTest -------------------------------------------------------------
-PluginProxyTest::PluginProxyTest() {
+PluginProxyTest::PluginProxyTest() : PluginProxyTestHarness(SINGLETON_GLOBALS) {
}
PluginProxyTest::~PluginProxyTest() {
@@ -284,6 +296,102 @@ void PluginProxyTest::TearDown() {
TearDownHarness();
}
+// PluginProxyMultiThreadTest --------------------------------------------------
+
+PluginProxyMultiThreadTest::PluginProxyMultiThreadTest() {
+}
+
+PluginProxyMultiThreadTest::~PluginProxyMultiThreadTest() {
+}
+
+void PluginProxyMultiThreadTest::RunTest() {
+ main_thread_message_loop_proxy_ =
+ PpapiGlobals::Get()->GetMainThreadMessageLoop();
+ ASSERT_EQ(main_thread_message_loop_proxy_.get(),
+ base::MessageLoopProxy::current());
+ nested_main_thread_message_loop_.reset(new base::RunLoop());
+
+ secondary_thread_.reset(new base::DelegateSimpleThread(
+ this, "PluginProxyMultiThreadTest"));
+
+ {
+ ProxyAutoLock auto_lock;
+
+ // MessageLoopResource assumes that the proxy lock has been acquired.
+ secondary_thread_message_loop_ = new MessageLoopResource(pp_instance());
+
+ // TODO(yzshen): The comment of PPB_MessageLoop says that it would return
+ // PP_OK_COMPLETIONPENDING. Either fix the comment or the implementation.
+ ASSERT_EQ(PP_OK,
+ secondary_thread_message_loop_->PostWork(
+ PP_MakeCompletionCallback(
+ &PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread,
+ this),
+ 0));
+ }
+
+ SetUpTestOnMainThread();
+
+ secondary_thread_->Start();
+ nested_main_thread_message_loop_->Run();
+ secondary_thread_->Join();
+
+ {
+ ProxyAutoLock auto_lock;
+
+ // The destruction requires a valid PpapiGlobals instance, so we should
+ // explicitly release it.
+ secondary_thread_message_loop_ = NULL;
+ }
+
+ secondary_thread_.reset(NULL);
+ nested_main_thread_message_loop_.reset(NULL);
+ main_thread_message_loop_proxy_ = NULL;
+}
+
+void PluginProxyMultiThreadTest::CheckOnThread(ThreadType thread_type) {
+ ProxyAutoLock auto_lock;
+ if (thread_type == MAIN_THREAD) {
+ ASSERT_TRUE(MessageLoopResource::GetCurrent()->is_main_thread_loop());
+ } else {
+ ASSERT_EQ(secondary_thread_message_loop_.get(),
+ MessageLoopResource::GetCurrent());
+ }
+}
+
+void PluginProxyMultiThreadTest::PostQuitForMainThread() {
+ main_thread_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&PluginProxyMultiThreadTest::QuitNestedLoop,
+ base::Unretained(this)));
+}
+
+void PluginProxyMultiThreadTest::PostQuitForSecondaryThread() {
+ ProxyAutoLock auto_lock;
+ secondary_thread_message_loop_->PostQuit(PP_TRUE);
+}
+
+void PluginProxyMultiThreadTest::Run() {
+ ProxyAutoLock auto_lock;
+ ASSERT_EQ(PP_OK, secondary_thread_message_loop_->AttachToCurrentThread());
+ ASSERT_EQ(PP_OK, secondary_thread_message_loop_->Run());
+}
+
+void PluginProxyMultiThreadTest::QuitNestedLoop() {
+ nested_main_thread_message_loop_->Quit();
+}
+
+// static
+void PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread(
+ void* user_data,
+ int32_t result) {
+ EXPECT_EQ(PP_OK, result);
+ PluginProxyMultiThreadTest* thiz =
+ static_cast<PluginProxyMultiThreadTest*>(user_data);
+ thiz->CheckOnThread(SECONDARY_THREAD);
+ thiz->SetUpTestOnSecondaryThread();
+}
+
// HostProxyTestHarness --------------------------------------------------------
class HostProxyTestHarness::MockSyncMessageStatusReceiver
@@ -293,8 +401,9 @@ class HostProxyTestHarness::MockSyncMessageStatusReceiver
virtual void EndBlockOnSyncMessage() OVERRIDE {}
};
-HostProxyTestHarness::HostProxyTestHarness()
- : status_receiver_(new MockSyncMessageStatusReceiver) {
+HostProxyTestHarness::HostProxyTestHarness(GlobalsConfiguration globals_config)
+ : globals_config_(globals_config),
+ status_receiver_(new MockSyncMessageStatusReceiver) {
}
HostProxyTestHarness::~HostProxyTestHarness() {
@@ -309,10 +418,9 @@ Dispatcher* HostProxyTestHarness::GetDispatcher() {
}
void HostProxyTestHarness::SetUpHarness() {
- host_globals_.reset(new ppapi::TestGlobals(PpapiGlobals::ForTest()));
-
// These must be first since the dispatcher set-up uses them.
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ CreateHostGlobals();
+
host_dispatcher_.reset(new HostDispatcher(
pp_module(),
&MockGetInterface,
@@ -327,10 +435,9 @@ void HostProxyTestHarness::SetUpHarnessWithChannel(
base::MessageLoopProxy* ipc_message_loop,
base::WaitableEvent* shutdown_event,
bool is_client) {
- host_globals_.reset(new ppapi::TestGlobals(PpapiGlobals::ForTest()));
-
// These must be first since the dispatcher set-up uses them.
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ CreateHostGlobals();
+
delegate_mock_.Init(ipc_message_loop, shutdown_event);
host_dispatcher_.reset(new HostDispatcher(
@@ -351,6 +458,15 @@ void HostProxyTestHarness::TearDownHarness() {
host_globals_.reset();
}
+void HostProxyTestHarness::CreateHostGlobals() {
+ if (globals_config_ == PER_THREAD_GLOBALS) {
+ host_globals_.reset(new TestGlobals(PpapiGlobals::PerThreadForTest()));
+ PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ } else {
+ host_globals_.reset(new TestGlobals());
+ }
+}
+
base::MessageLoopProxy*
HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
return ipc_message_loop_;
@@ -373,7 +489,7 @@ HostProxyTestHarness::DelegateMock::ShareHandleWithRemote(
// HostProxyTest ---------------------------------------------------------------
-HostProxyTest::HostProxyTest() {
+HostProxyTest::HostProxyTest() : HostProxyTestHarness(SINGLETON_GLOBALS) {
}
HostProxyTest::~HostProxyTest() {
@@ -391,6 +507,8 @@ void HostProxyTest::TearDown() {
TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
: test_mode_(test_mode),
+ host_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
+ plugin_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
io_thread_("TwoWayTest_IOThread"),
plugin_thread_("TwoWayTest_PluginThread"),
remote_harness_(NULL),
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h
index e8c15c1..0882790 100644
--- a/ppapi/proxy/ppapi_proxy_test.h
+++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -5,9 +5,12 @@
#include <map>
#include <string>
-#include "base/message_loop.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/host_dispatcher.h"
@@ -20,13 +23,25 @@
#include "ppapi/shared_impl/test_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace base {
+class MessageLoopProxy;
+class RunLoop;
+}
+
namespace ppapi {
namespace proxy {
+class MessageLoopResource;
+
// Base class for plugin and host test harnesses. Tests will not use this
// directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
class ProxyTestHarnessBase {
public:
+ enum GlobalsConfiguration {
+ PER_THREAD_GLOBALS,
+ SINGLETON_GLOBALS
+ };
+
ProxyTestHarnessBase();
virtual ~ProxyTestHarnessBase();
@@ -78,7 +93,7 @@ class ProxyTestHarnessBase {
// Test harness for the plugin side of the proxy.
class PluginProxyTestHarness : public ProxyTestHarnessBase {
public:
- PluginProxyTestHarness();
+ explicit PluginProxyTestHarness(GlobalsConfiguration globals_config);
virtual ~PluginProxyTestHarness();
PluginDispatcher* plugin_dispatcher() { return plugin_dispatcher_.get(); }
@@ -144,6 +159,9 @@ class PluginProxyTestHarness : public ProxyTestHarnessBase {
};
private:
+ void CreatePluginGlobals();
+
+ GlobalsConfiguration globals_config_;
scoped_ptr<PluginGlobals> plugin_globals_;
scoped_ptr<PluginDispatcher> plugin_dispatcher_;
@@ -162,9 +180,58 @@ class PluginProxyTest : public PluginProxyTestHarness, public testing::Test {
MessageLoop message_loop_;
};
+// This class provides support for multi-thread testing. A secondary thread is
+// created with a Pepper message loop.
+// Subclasses need to implement the two SetUpTestOn*Thread() methods to do the
+// actual testing work; and call both PostQuitFor*Thread() when testing is
+// done.
+class PluginProxyMultiThreadTest
+ : public PluginProxyTest,
+ public base::DelegateSimpleThread::Delegate {
+ public:
+ PluginProxyMultiThreadTest();
+ virtual ~PluginProxyMultiThreadTest();
+
+ // Called before the secondary thread is started, but after all the member
+ // variables, including |secondary_thread_| and
+ // |secondary_thread_message_loop_|, are initialized.
+ virtual void SetUpTestOnMainThread() = 0;
+
+ virtual void SetUpTestOnSecondaryThread() = 0;
+
+ // TEST_F() should call this method.
+ void RunTest();
+
+ enum ThreadType {
+ MAIN_THREAD,
+ SECONDARY_THREAD
+ };
+ void CheckOnThread(ThreadType thread_type);
+
+ // These can be called on any thread.
+ void PostQuitForMainThread();
+ void PostQuitForSecondaryThread();
+
+ protected:
+ scoped_refptr<MessageLoopResource> secondary_thread_message_loop_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_message_loop_proxy_;
+
+ private:
+ // base::DelegateSimpleThread::Delegate implementation.
+ virtual void Run() OVERRIDE;
+
+ void QuitNestedLoop();
+
+ static void InternalSetUpTestOnSecondaryThread(void* user_data,
+ int32_t result);
+
+ scoped_ptr<base::DelegateSimpleThread> secondary_thread_;
+ scoped_ptr<base::RunLoop> nested_main_thread_message_loop_;
+};
+
class HostProxyTestHarness : public ProxyTestHarnessBase {
public:
- HostProxyTestHarness();
+ explicit HostProxyTestHarness(GlobalsConfiguration globals_config);
virtual ~HostProxyTestHarness();
HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); }
@@ -215,6 +282,9 @@ class HostProxyTestHarness : public ProxyTestHarnessBase {
private:
class MockSyncMessageStatusReceiver;
+ void CreateHostGlobals();
+
+ GlobalsConfiguration globals_config_;
scoped_ptr<ppapi::TestGlobals> host_globals_;
scoped_ptr<HostDispatcher> host_dispatcher_;
DelegateMock delegate_mock_;
diff --git a/ppapi/proxy/ppb_message_loop_proxy.h b/ppapi/proxy/ppb_message_loop_proxy.h
index 5d161c5..3fa7674 100644
--- a/ppapi/proxy/ppb_message_loop_proxy.h
+++ b/ppapi/proxy/ppb_message_loop_proxy.h
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/shared_impl/ppb_message_loop_shared.h"
#include "ppapi/thunk/ppb_message_loop_api.h"
@@ -19,7 +20,7 @@ struct PPB_MessageLoop_1_0;
namespace ppapi {
namespace proxy {
-class MessageLoopResource : public MessageLoopShared {
+class PPAPI_PROXY_EXPORT MessageLoopResource : public MessageLoopShared {
public:
explicit MessageLoopResource(PP_Instance instance);
// Construct the one MessageLoopResource for the main thread. This must be
diff --git a/ppapi/proxy/ppb_var_unittest.cc b/ppapi/proxy/ppb_var_unittest.cc
index 74ed453..bf6147d 100644
--- a/ppapi/proxy/ppb_var_unittest.cc
+++ b/ppapi/proxy/ppb_var_unittest.cc
@@ -10,7 +10,6 @@
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/proxy/ppapi_proxy_test.h"
-#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/ppb_var_shared.h"
namespace {
@@ -97,13 +96,12 @@ class CreateVarThreadDelegate : public base::PlatformThread::Delegate {
// read the var back out to |strings_out[i]|.
CreateVarThreadDelegate(PP_Module pp_module, const std::string* strings_in,
PP_Var* vars_out, std::string* strings_out,
- size_t size, PpapiGlobals* globals)
+ size_t size)
: pp_module_(pp_module), strings_in_(strings_in), vars_out_(vars_out),
- strings_out_(strings_out), size_(size), globals_(globals) {
+ strings_out_(strings_out), size_(size) {
}
virtual ~CreateVarThreadDelegate() {}
virtual void ThreadMain() {
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_);
const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
for (size_t i = 0; i < size_; ++i) {
vars_out_[i] = ppb_var->VarFromUtf8(strings_in_[i].c_str(),
@@ -117,20 +115,16 @@ class CreateVarThreadDelegate : public base::PlatformThread::Delegate {
PP_Var* vars_out_;
std::string* strings_out_;
size_t size_;
- PpapiGlobals* globals_;
};
// A thread that will increment and decrement the reference count of every var
// multiple times.
class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate {
public:
- ChangeRefVarThreadDelegate(const std::vector<PP_Var>& vars,
- PpapiGlobals* globals)
- : vars_(vars), globals_(globals) {
+ ChangeRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) {
}
virtual ~ChangeRefVarThreadDelegate() {}
virtual void ThreadMain() {
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_);
const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
// Increment and decrement the reference count for each var kRefsToAdd
// times. Note that we always AddRef once before doing the matching Release,
@@ -150,19 +144,15 @@ class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate {
}
private:
std::vector<PP_Var> vars_;
- PpapiGlobals* globals_;
};
// A thread that will decrement the reference count of every var once.
class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate {
public:
- RemoveRefVarThreadDelegate(const std::vector<PP_Var>& vars,
- PpapiGlobals* globals)
- : vars_(vars), globals_(globals) {
+ RemoveRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) {
}
virtual ~RemoveRefVarThreadDelegate() {}
virtual void ThreadMain() {
- PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_);
const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
for (size_t i = 0; i < kNumStrings; ++i) {
ppb_var->Release(vars_[i]);
@@ -170,7 +160,6 @@ class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate {
}
private:
std::vector<PP_Var> vars_;
- PpapiGlobals* globals_;
};
} // namespace
@@ -197,8 +186,7 @@ TEST_F(PPB_VarTest, DISABLED_Threads) {
&vars_[slice_start],
&strings_out[slice_start],
std::min(strings_per_thread,
- kNumStrings - slice_start),
- GetGlobals()));
+ kNumStrings - slice_start)));
}
// Now run then join all the threads.
for (size_t i = 0; i < kNumThreads; ++i)
@@ -213,8 +201,7 @@ TEST_F(PPB_VarTest, DISABLED_Threads) {
std::vector<base::PlatformThreadHandle> change_ref_var_threads(kNumThreads);
std::vector<ChangeRefVarThreadDelegate> change_ref_var_delegates;
for (size_t i = 0; i < kNumThreads; ++i)
- change_ref_var_delegates.push_back(
- ChangeRefVarThreadDelegate(vars_, GetGlobals()));
+ change_ref_var_delegates.push_back(ChangeRefVarThreadDelegate(vars_));
for (size_t i = 0; i < kNumThreads; ++i) {
base::PlatformThread::Create(0, &change_ref_var_delegates[i],
&change_ref_var_threads[i]);
@@ -237,8 +224,7 @@ TEST_F(PPB_VarTest, DISABLED_Threads) {
std::vector<base::PlatformThreadHandle> remove_ref_var_threads(kNumThreads);
std::vector<RemoveRefVarThreadDelegate> remove_ref_var_delegates;
for (size_t i = 0; i < kNumThreads; ++i)
- remove_ref_var_delegates.push_back(
- RemoveRefVarThreadDelegate(vars_, GetGlobals()));
+ remove_ref_var_delegates.push_back(RemoveRefVarThreadDelegate(vars_));
for (size_t i = 0; i < kNumThreads; ++i) {
base::PlatformThread::Create(0, &remove_ref_var_delegates[i],
&remove_ref_var_threads[i]);
diff --git a/ppapi/shared_impl/DEPS b/ppapi/shared_impl/DEPS
index 823b983..9f93141 100644
--- a/ppapi/shared_impl/DEPS
+++ b/ppapi/shared_impl/DEPS
@@ -14,4 +14,7 @@ include_rules = [
"-ppapi/cpp",
"-ppapi/proxy",
+
+ # For testing purpose.
+ "+ppapi/proxy/ppapi_proxy_test.h",
]
diff --git a/ppapi/shared_impl/ppapi_globals.cc b/ppapi/shared_impl/ppapi_globals.cc
index 270d7e8..be10d4c 100644
--- a/ppapi/shared_impl/ppapi_globals.cc
+++ b/ppapi/shared_impl/ppapi_globals.cc
@@ -26,7 +26,7 @@ PpapiGlobals::PpapiGlobals() {
main_loop_proxy_ = base::MessageLoopProxy::current();
}
-PpapiGlobals::PpapiGlobals(ForTest) {
+PpapiGlobals::PpapiGlobals(PerThreadForTest) {
DCHECK(!ppapi_globals_);
main_loop_proxy_ = base::MessageLoopProxy::current();
}
diff --git a/ppapi/shared_impl/ppapi_globals.h b/ppapi/shared_impl/ppapi_globals.h
index 0573c98..84b90e7 100644
--- a/ppapi/shared_impl/ppapi_globals.h
+++ b/ppapi/shared_impl/ppapi_globals.h
@@ -43,8 +43,8 @@ class PPAPI_SHARED_EXPORT PpapiGlobals {
// purposes. This avoids setting the global static ppapi_globals_. For unit
// tests that use this feature, the "test" PpapiGlobals should be constructed
// using this method. See SetPpapiGlobalsOnThreadForTest for more information.
- struct ForTest {};
- explicit PpapiGlobals(ForTest);
+ struct PerThreadForTest {};
+ explicit PpapiGlobals(PerThreadForTest);
virtual ~PpapiGlobals();
@@ -64,7 +64,7 @@ class PPAPI_SHARED_EXPORT PpapiGlobals {
// the same process, e.g. for having 1 thread emulate the "host" and 1 thread
// emulate the "plugin".
//
- // PpapiGlobals object must have been constructed using the "ForTest"
+ // PpapiGlobals object must have been constructed using the "PerThreadForTest"
// parameter.
static void SetPpapiGlobalsOnThreadForTest(PpapiGlobals* ptr);
diff --git a/ppapi/shared_impl/test_globals.cc b/ppapi/shared_impl/test_globals.cc
index cf19286..913d53c 100644
--- a/ppapi/shared_impl/test_globals.cc
+++ b/ppapi/shared_impl/test_globals.cc
@@ -11,8 +11,8 @@ TestGlobals::TestGlobals()
callback_tracker_(new CallbackTracker) {
}
-TestGlobals::TestGlobals(PpapiGlobals::ForTest for_test)
- : ppapi::PpapiGlobals(for_test),
+TestGlobals::TestGlobals(PpapiGlobals::PerThreadForTest per_thread_for_test)
+ : ppapi::PpapiGlobals(per_thread_for_test),
callback_tracker_(new CallbackTracker) {
}
diff --git a/ppapi/shared_impl/test_globals.h b/ppapi/shared_impl/test_globals.h
index ea23ec7..68a997a 100644
--- a/ppapi/shared_impl/test_globals.h
+++ b/ppapi/shared_impl/test_globals.h
@@ -29,7 +29,7 @@ class TestVarTracker : public VarTracker {
class TestGlobals : public PpapiGlobals {
public:
TestGlobals();
- TestGlobals(PpapiGlobals::ForTest);
+ explicit TestGlobals(PpapiGlobals::PerThreadForTest);
virtual ~TestGlobals();
// PpapiGlobals implementation.
diff --git a/ppapi/shared_impl/thread_aware_callback.cc b/ppapi/shared_impl/thread_aware_callback.cc
new file mode 100644
index 0000000..9b1063b
--- /dev/null
+++ b/ppapi/shared_impl/thread_aware_callback.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 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 "ppapi/shared_impl/thread_aware_callback.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_message_loop_shared.h"
+
+namespace ppapi {
+namespace internal {
+
+class ThreadAwareCallbackBase::Core : public base::RefCountedThreadSafe<Core> {
+ public:
+ Core() : aborted_(false) {
+ }
+
+ void MarkAsAborted() { aborted_ = true; }
+
+ void RunIfNotAborted(const base::Closure& closure) {
+ if (!aborted_)
+ CallWhileUnlocked(closure);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<Core>;
+ ~Core() {
+ }
+
+ bool aborted_;
+};
+
+ThreadAwareCallbackBase::ThreadAwareCallbackBase()
+ : target_loop_(PpapiGlobals::Get()->GetCurrentMessageLoop()),
+ core_(new Core()) {
+ DCHECK(target_loop_.get());
+}
+
+ThreadAwareCallbackBase::~ThreadAwareCallbackBase() {
+ core_->MarkAsAborted();
+}
+
+// static
+bool ThreadAwareCallbackBase::HasTargetLoop() {
+ return !!PpapiGlobals::Get()->GetCurrentMessageLoop();
+}
+
+void ThreadAwareCallbackBase::InternalRunOnTargetThread(
+ const base::Closure& closure) {
+ if (target_loop_ != PpapiGlobals::Get()->GetCurrentMessageLoop()) {
+ target_loop_->PostClosure(
+ FROM_HERE,
+ RunWhileLocked(base::Bind(&Core::RunIfNotAborted, core_, closure)),
+ 0);
+ } else {
+ CallWhileUnlocked(closure);
+ }
+}
+
+} // namespace internal
+} // namespace ppapi
diff --git a/ppapi/shared_impl/thread_aware_callback.h b/ppapi/shared_impl/thread_aware_callback.h
new file mode 100644
index 0000000..b954eec
--- /dev/null
+++ b/ppapi/shared_impl/thread_aware_callback.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2013 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 PPAPI_SHARED_IMPL_THREAD_AWARE_CALLBACK_H_
+#define PPAPI_SHARED_IMPL_THREAD_AWARE_CALLBACK_H_
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+
+class MessageLoopShared;
+
+namespace internal {
+
+class PPAPI_SHARED_EXPORT ThreadAwareCallbackBase {
+ protected:
+ ThreadAwareCallbackBase();
+ ~ThreadAwareCallbackBase();
+
+ static bool HasTargetLoop();
+
+ void InternalRunOnTargetThread(const base::Closure& closure);
+
+ private:
+ class Core;
+
+ scoped_refptr<MessageLoopShared> target_loop_;
+ scoped_refptr<Core> core_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadAwareCallbackBase);
+};
+
+} // namespace internal
+
+// Some PPB interfaces have methods that set a custom callback. Usually, the
+// callback has to be called on the same thread as the one it was set on.
+// ThreadAwareCallback keeps track of the target thread, and posts a task to run
+// on it if requested from a different thread.
+//
+// Please note that:
+// - Unlike TrackedCallback, there is no restriction on how many times the
+// callback will be called.
+// - When a ThreadAwareCallback object is destroyed, all pending tasks to run
+// the callback will be ignored. It is designed this way so that when the
+// resource is destroyed or the callback is cancelled by the plugin, we can
+// simply delete the ThreadAwareCallback object to prevent touching the
+// callback later.
+// - When RunOnTargetThread() is called on the target thread, the callback runs
+// immediately.
+template <class FuncType>
+class ThreadAwareCallback : public internal::ThreadAwareCallbackBase {
+ public:
+ // The caller takes ownership of the returned object.
+ // NULL is returned if the current thread doesn't have an associated Pepper
+ // message loop, or |func| is NULL.
+ static ThreadAwareCallback* Create(FuncType func) {
+ if (!func || !HasTargetLoop())
+ return NULL;
+ return new ThreadAwareCallback(func);
+ }
+
+ ~ThreadAwareCallback() {
+ }
+
+ void RunOnTargetThread() {
+ InternalRunOnTargetThread(base::Bind(func_));
+ }
+
+ template <class P1>
+ void RunOnTargetThread(const P1& p1) {
+ InternalRunOnTargetThread(base::Bind(func_, p1));
+ }
+
+ template <class P1, class P2>
+ void RunOnTargetThread(const P1& p1, const P2& p2) {
+ InternalRunOnTargetThread(base::Bind(func_, p1, p2));
+ }
+
+ template <class P1, class P2, class P3>
+ void RunOnTargetThread(const P1& p1, const P2& p2, const P3& p3) {
+ InternalRunOnTargetThread(base::Bind(func_, p1, p2, p3));
+ }
+
+ template <class P1, class P2, class P3, class P4>
+ void RunOnTargetThread(const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4) {
+ InternalRunOnTargetThread(base::Bind(func_, p1, p2, p3, p4));
+ }
+
+ template <class P1, class P2, class P3, class P4, class P5>
+ void RunOnTargetThread(const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4,
+ const P5& p5) {
+ InternalRunOnTargetThread(base::Bind(func_, p1, p2, p3, p4, p5));
+ }
+
+ private:
+ explicit ThreadAwareCallback(FuncType func) : func_(func) {
+ }
+
+ FuncType func_;
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_THREAD_AWARE_CALLBACK_H_
diff --git a/ppapi/shared_impl/thread_aware_callback_unittest.cc b/ppapi/shared_impl/thread_aware_callback_unittest.cc
new file mode 100644
index 0000000..f86048a7
--- /dev/null
+++ b/ppapi/shared_impl/thread_aware_callback_unittest.cc
@@ -0,0 +1,218 @@
+// Copyright (c) 2012 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 "ppapi/shared_impl/thread_aware_callback.h"
+
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ppapi {
+
+namespace {
+
+class TestParameter {
+ public:
+ TestParameter() : value_(0) {
+ }
+
+ int value_;
+};
+
+int called_num = 0;
+
+void TestCallback_0() {
+ ++called_num;
+}
+
+void TestCallback_1(int p1) {
+ ++called_num;
+}
+
+void TestCallback_2(int p1, const double* p2) {
+ ++called_num;
+}
+
+void TestCallback_3(int p1, const double* p2, bool* p3) {
+ ++called_num;
+}
+
+void TestCallback_4(int p1, const double* p2, bool* p3, TestParameter p4) {
+ ++called_num;
+}
+
+void TestCallback_5(int p1,
+ const double* p2,
+ bool* p3,
+ TestParameter p4,
+ const TestParameter& p5) {
+ ++called_num;
+}
+
+typedef proxy::PluginProxyTest ThreadAwareCallbackTest;
+
+// Test that a callback created on the main thread will run on the main thread,
+// even when requested from a different thread.
+class ThreadAwareCallbackMultiThreadTest
+ : public proxy::PluginProxyMultiThreadTest {
+ public:
+ ThreadAwareCallbackMultiThreadTest() : main_thread_callback_called_(false) {
+ }
+ virtual ~ThreadAwareCallbackMultiThreadTest() {
+ CHECK(main_thread_callback_called_);
+ }
+
+ // proxy::PluginProxyMultiThreadTest implementation.
+ virtual void SetUpTestOnMainThread() OVERRIDE {
+ ProxyAutoLock auto_lock;
+
+ main_thread_callback_.reset(
+ ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody));
+ }
+
+ virtual void SetUpTestOnSecondaryThread() OVERRIDE {
+ {
+ ProxyAutoLock auto_lock;
+ main_thread_callback_->RunOnTargetThread(this);
+ }
+
+ PostQuitForSecondaryThread();
+ PostQuitForMainThread();
+ }
+
+ private:
+ typedef void (*CallbackFunc)(ThreadAwareCallbackMultiThreadTest*);
+
+ static void MainThreadCallbackBody(ThreadAwareCallbackMultiThreadTest* thiz) {
+ thiz->CheckOnThread(MAIN_THREAD);
+ thiz->main_thread_callback_called_ = true;
+
+ {
+ ProxyAutoLock auto_lock;
+ // We have to destroy it prior to the PluginGlobals instance held by the
+ // base class. Otherwise it has a ref to Pepper message loop for the main
+ // thread and the PluginGlobals destructor will complain.
+ thiz->main_thread_callback_.reset(NULL);
+ }
+ }
+
+ scoped_ptr<ThreadAwareCallback<CallbackFunc> > main_thread_callback_;
+ bool main_thread_callback_called_;
+};
+
+// Test that when a ThreadAwareCallback instance is destroyed, pending tasks to
+// run the callback will be ignored.
+class ThreadAwareCallbackAbortTest : public proxy::PluginProxyMultiThreadTest {
+ public:
+ ThreadAwareCallbackAbortTest() {
+ }
+ virtual ~ThreadAwareCallbackAbortTest() {
+ }
+
+ // proxy::PluginProxyMultiThreadTest implementation.
+ virtual void SetUpTestOnMainThread() OVERRIDE {
+ ProxyAutoLock auto_lock;
+
+ main_thread_callback_.reset(
+ ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody));
+ }
+
+ virtual void SetUpTestOnSecondaryThread() OVERRIDE {
+ {
+ ProxyAutoLock auto_lock;
+ main_thread_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&ThreadAwareCallbackAbortTest::DeleteCallback,
+ base::Unretained(this)));
+ // |main_thread_callback_| is still valid, even if DeleteCallback() can be
+ // called before this following statement. That is because |auto_lock| is
+ // still held by this method, which prevents DeleteCallback() from
+ // deleting the callback.
+ main_thread_callback_->RunOnTargetThread(this);
+ }
+
+ PostQuitForSecondaryThread();
+ PostQuitForMainThread();
+ }
+
+ private:
+ typedef void (*CallbackFunc)(ThreadAwareCallbackAbortTest*);
+
+ static void MainThreadCallbackBody(ThreadAwareCallbackAbortTest* thiz) {
+ // The callback should not be called.
+ ASSERT_TRUE(false);
+ }
+
+ void DeleteCallback() {
+ ProxyAutoLock auto_lock;
+ main_thread_callback_.reset(NULL);
+ }
+
+ scoped_ptr<ThreadAwareCallback<CallbackFunc> > main_thread_callback_;
+};
+
+} // namespace
+
+TEST_F(ThreadAwareCallbackTest, Basics) {
+ // ThreadAwareCallback should only be used when the proxy lock has been
+ // acquired.
+ ProxyAutoLock auto_lock;
+
+ double double_arg = 0.0;
+ bool bool_arg = false;
+ TestParameter object_arg;
+
+ // Exercise all the template code.
+ called_num = 0;
+ typedef void (*FuncType_0)();
+ scoped_ptr<ThreadAwareCallback<FuncType_0> > callback_0(
+ ThreadAwareCallback<FuncType_0>::Create(TestCallback_0));
+ callback_0->RunOnTargetThread();
+
+ typedef void (*FuncType_1)(int);
+ scoped_ptr<ThreadAwareCallback<FuncType_1> > callback_1(
+ ThreadAwareCallback<FuncType_1>::Create(TestCallback_1));
+ callback_1->RunOnTargetThread(1);
+
+ typedef void (*FuncType_2)(int, const double*);
+ scoped_ptr<ThreadAwareCallback<FuncType_2> > callback_2(
+ ThreadAwareCallback<FuncType_2>::Create(TestCallback_2));
+ callback_2->RunOnTargetThread(1, &double_arg);
+
+ typedef void (*FuncType_3)(int, const double*, bool*);
+ scoped_ptr<ThreadAwareCallback<FuncType_3> > callback_3(
+ ThreadAwareCallback<FuncType_3>::Create(TestCallback_3));
+ callback_3->RunOnTargetThread(1, &double_arg, &bool_arg);
+
+ typedef void (*FuncType_4)(int, const double*, bool*, TestParameter);
+ scoped_ptr<ThreadAwareCallback<FuncType_4> > callback_4(
+ ThreadAwareCallback<FuncType_4>::Create(TestCallback_4));
+ callback_4->RunOnTargetThread(1, &double_arg, &bool_arg, object_arg);
+
+ typedef void (*FuncType_5)(int,
+ const double*,
+ bool*,
+ TestParameter,
+ const TestParameter&);
+ scoped_ptr<ThreadAwareCallback<FuncType_5> > callback_5(
+ ThreadAwareCallback<FuncType_5>::Create(TestCallback_5));
+ callback_5->RunOnTargetThread(1, &double_arg, &bool_arg, object_arg,
+ object_arg);
+
+ EXPECT_EQ(6, called_num);
+}
+
+TEST_F(ThreadAwareCallbackMultiThreadTest, RunOnTargetThread) {
+ RunTest();
+}
+
+TEST_F(ThreadAwareCallbackAbortTest, NotRunIfAborted) {
+ RunTest();
+}
+
+} // namespace ppapi
diff --git a/webkit/plugins/ppapi/host_globals.cc b/webkit/plugins/ppapi/host_globals.cc
index b337689..32fac79 100644
--- a/webkit/plugins/ppapi/host_globals.cc
+++ b/webkit/plugins/ppapi/host_globals.cc
@@ -79,8 +79,9 @@ HostGlobals::HostGlobals() : ::ppapi::PpapiGlobals() {
host_globals_ = this;
}
-HostGlobals::HostGlobals(::ppapi::PpapiGlobals::ForTest for_test)
- : ::ppapi::PpapiGlobals(for_test) {
+HostGlobals::HostGlobals(
+ ::ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test)
+ : ::ppapi::PpapiGlobals(per_thread_for_test) {
DCHECK(!host_globals_);
}
diff --git a/webkit/plugins/ppapi/host_globals.h b/webkit/plugins/ppapi/host_globals.h
index 0427b2a..31c22ed 100644
--- a/webkit/plugins/ppapi/host_globals.h
+++ b/webkit/plugins/ppapi/host_globals.h
@@ -22,7 +22,7 @@ class PluginModule;
class HostGlobals : public ::ppapi::PpapiGlobals {
public:
HostGlobals();
- HostGlobals(::ppapi::PpapiGlobals::ForTest);
+ explicit HostGlobals(::ppapi::PpapiGlobals::PerThreadForTest);
virtual ~HostGlobals();
// Getter for the global singleton. Generally, you should use