summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/c/dev/ppb_testing_dev.h10
-rw-r--r--ppapi/ppapi_tests.gypi1
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc1
-rw-r--r--ppapi/proxy/ppb_testing_proxy.cc7
-rw-r--r--ppapi/tests/pp_thread.h117
-rw-r--r--ppapi/tests/test_case.h18
-rw-r--r--ppapi/tests/test_post_message.cc82
-rw-r--r--ppapi/tests/test_post_message.h3
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc13
9 files changed, 240 insertions, 12 deletions
diff --git a/ppapi/c/dev/ppb_testing_dev.h b/ppapi/c/dev/ppb_testing_dev.h
index ec70102..066b50f 100644
--- a/ppapi/c/dev/ppb_testing_dev.h
+++ b/ppapi/c/dev/ppb_testing_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010 The Chromium Authors. All rights reserved.
+/* 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.
*/
@@ -12,8 +12,10 @@
struct PP_Point;
+// TODO(dmichael): Delete support for 0.6.
#define PPB_TESTING_DEV_INTERFACE_0_6 "PPB_Testing(Dev);0.6"
-#define PPB_TESTING_DEV_INTERFACE PPB_TESTING_DEV_INTERFACE_0_6
+#define PPB_TESTING_DEV_INTERFACE_0_7 "PPB_Testing(Dev);0.7"
+#define PPB_TESTING_DEV_INTERFACE PPB_TESTING_DEV_INTERFACE_0_7
// This interface contains functions used for unit testing. Do not use in
// production code. They are not guaranteed to be available in normal plugin
@@ -68,6 +70,10 @@ struct PPB_Testing_Dev {
// associated with this plugin instance. Used for detecting leaks. Returns
// (uint32_t)-1 on failure.
uint32_t (*GetLiveObjectsForInstance)(PP_Instance instance);
+
+ // Returns PP_TRUE if the plugin is running out-of-process, PP_FALSE
+ // otherwise.
+ PP_Bool (*IsOutOfProcess)();
};
#endif /* PPAPI_C_DEV_PPB_TESTING_DEV_H_ */
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index a8a59c2..b3dcb05 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -72,6 +72,7 @@
'tests/all_cpp_includes.h',
'tests/arch_dependent_sizes_32.h',
'tests/arch_dependent_sizes_64.h',
+ 'tests/pp_thread.h',
'tests/test_broker.cc',
'tests/test_broker.h',
'tests/test_buffer.cc',
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 7412462..58a1017 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -109,7 +109,6 @@ bool PluginDispatcher::IsPlugin() const {
}
bool PluginDispatcher::Send(IPC::Message* msg) {
- DCHECK(MessageLoop::current());
TRACE_EVENT2("ppapi proxy", "PluginDispatcher::Send",
"Class", IPC_MESSAGE_ID_CLASS(msg->type()),
"Line", IPC_MESSAGE_ID_LINE(msg->type()));
diff --git a/ppapi/proxy/ppb_testing_proxy.cc b/ppapi/proxy/ppb_testing_proxy.cc
index 942521c..564f68f 100644
--- a/ppapi/proxy/ppb_testing_proxy.cc
+++ b/ppapi/proxy/ppb_testing_proxy.cc
@@ -63,11 +63,16 @@ uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
return result;
}
+PP_Bool IsOutOfProcess() {
+ return PP_TRUE;
+}
+
const PPB_Testing_Dev testing_interface = {
&ReadImageData,
&RunMessageLoop,
&QuitMessageLoop,
- &GetLiveObjectsForInstance
+ &GetLiveObjectsForInstance,
+ &IsOutOfProcess
};
InterfaceProxy* CreateTestingProxy(Dispatcher* dispatcher,
diff --git a/ppapi/tests/pp_thread.h b/ppapi/tests/pp_thread.h
new file mode 100644
index 0000000..f168d8c
--- /dev/null
+++ b/ppapi/tests/pp_thread.h
@@ -0,0 +1,117 @@
+/* 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 PPAPI_TESTS_PP_THREAD_H_
+#define PPAPI_TESTS_PP_THREAD_H_
+
+#include "ppapi/c/pp_macros.h"
+
+/* These precompiler names were copied from chromium's build_config.h. */
+#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || defined(__sun) || defined(__native_client__)
+#define PPAPI_HAS_POSIX_THREADS 1
+#elif defined (_MSC_VER)
+#define PPAPI_HAS_WINDOWS_THREADS 1
+#endif
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+#include <pthread.h>
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+#include <process.h>
+#include <windows.h>
+#endif
+
+/**
+ * @file
+ * This file provides platform-independent wrappers around threads. This is for
+ * use by PPAPI wrappers and tests which need to run on multiple platforms to
+ * support both trusted platforms (Windows, Mac, Linux) and untrusted (Native
+ * Client). Apps that use PPAPI only with Native Client should generally use the
+ * Native Client POSIX implementation instead.
+ *
+ * TODO(dmichael): Move this file to ppapi/c and delete this comment, if we end
+ * up needing platform independent threads in PPAPI C or C++. This file was
+ * written using inline functions and PPAPI naming conventions with the intent
+ * of making it possible to put it in to ppapi/c. Currently, however, it's only
+ * used in ppapi/tests, so is not part of the published API.
+ */
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+typedef pthread_t PP_ThreadType;
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+typedef uintptr_t PP_ThreadType;
+#endif
+
+typedef void (PP_ThreadFunction)(void* data);
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg);
+PP_INLINE void PP_JoinThread(PP_ThreadType thread);
+
+#if defined(PPAPI_HAS_POSIX_THREADS)
+/* Because POSIX thread functions return void* and Windows thread functions do
+ * not, we make PPAPI thread functions have the least capability (no returns).
+ * This struct wraps the user data & function so that we can use the correct
+ * function type on POSIX platforms.
+ */
+struct PP_ThreadFunctionArgWrapper {
+ void* user_data;
+ PP_ThreadFunction* user_function;
+};
+
+PP_INLINE void* PP_POSIXThreadFunctionThunk(void* posix_thread_arg) {
+ PP_ThreadFunctionArgWrapper* arg_wrapper =
+ (PP_ThreadFunctionArgWrapper*)posix_thread_arg;
+ arg_wrapper->user_function(arg_wrapper->user_data);
+ free(posix_thread_arg);
+ return NULL;
+}
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg) {
+ PP_ThreadFunctionArgWrapper* arg_wrapper =
+ (PP_ThreadFunctionArgWrapper*)malloc(sizeof(PP_ThreadFunctionArgWrapper));
+ arg_wrapper->user_function = function;
+ arg_wrapper->user_data = thread_arg;
+ return (pthread_create(thread,
+ NULL,
+ PP_POSIXThreadFunctionThunk,
+ arg_wrapper) == 0);
+}
+
+PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
+ void* exit_status;
+ pthread_join(thread, &exit_status);
+}
+
+#elif defined(PPAPI_HAS_WINDOWS_THREADS)
+typedef DWORD (PP_WindowsThreadFunction)(void* data);
+
+PP_INLINE bool PP_CreateThread(PP_ThreadType* thread,
+ PP_ThreadFunction function,
+ void* thread_arg) {
+ if (!thread)
+ return false;
+ *thread = ::_beginthread(function,
+ 0, /* Use default stack size. */
+ thread_arg);
+ return (*thread != NULL);
+}
+
+PP_INLINE void PP_JoinThread(PP_ThreadType thread) {
+ ::WaitForSingleObject((HANDLE)thread, INFINITE);
+}
+
+#endif
+
+
+/**
+ * @}
+ */
+
+#endif /* PPAPI_TESTS_PP_THREAD_H_ */
+
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h
index 0a3cdc6..06ebcb1 100644
--- a/ppapi/tests/test_case.h
+++ b/ppapi/tests/test_case.h
@@ -130,18 +130,24 @@ class TestCaseFactory {
// RunTest function. This assumes the function name is TestFoo where Foo is the
// test |name|.
#define RUN_TEST(name) \
- force_async_ = false; \
- instance_->LogTest(#name, Test##name());
+ do { \
+ force_async_ = false; \
+ instance_->LogTest(#name, Test##name()); \
+ } while (false)
// Like RUN_TEST above but forces functions taking callbacks to complete
// asynchronously on success or error.
#define RUN_TEST_FORCEASYNC(name) \
- force_async_ = true; \
- instance_->LogTest(#name"ForceAsync", Test##name());
+ do { \
+ force_async_ = true; \
+ instance_->LogTest(#name"ForceAsync", Test##name()); \
+ } while (false)
#define RUN_TEST_FORCEASYNC_AND_NOT(name) \
- RUN_TEST_FORCEASYNC(name); \
- RUN_TEST(name);
+ do { \
+ RUN_TEST_FORCEASYNC(name); \
+ RUN_TEST(name); \
+ } while (false)
// Helper macros for checking values in tests, and returning a location
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index 10bc7a0..f19a3b1 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -11,6 +11,7 @@
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/var.h"
+#include "ppapi/tests/pp_thread.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"
@@ -28,6 +29,25 @@ const bool kTestBool = true;
const int32_t kTestInt = 42;
const double kTestDouble = 42.0;
const int32_t kThreadsToRun = 10;
+const int32_t kMessagesToSendPerThread = 50;
+
+// The struct that invoke_post_message_thread_func expects for its argument.
+// It includes the instance on which to invoke PostMessage, and the value to
+// pass to PostMessage.
+struct InvokePostMessageThreadArg {
+ InvokePostMessageThreadArg(pp::Instance* i, const pp::Var& v)
+ : instance(i), value_to_send(v) {}
+ pp::Instance* instance;
+ pp::Var value_to_send;
+};
+
+void InvokePostMessageThreadFunc(void* user_data) {
+ InvokePostMessageThreadArg* arg =
+ static_cast<InvokePostMessageThreadArg*>(user_data);
+ for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
+ arg->instance->PostMessage(arg->value_to_send);
+ delete arg;
+}
} // namespace
@@ -40,6 +60,8 @@ void TestPostMessage::RunTest() {
RUN_TEST(MessageEvent);
RUN_TEST(NoHandler);
RUN_TEST(ExtraParam);
+ if (testing_interface_->IsOutOfProcess())
+ RUN_TEST(NonMainThread);
}
void TestPostMessage::HandleMessage(const pp::Var& message_data) {
@@ -254,3 +276,63 @@ std::string TestPostMessage::TestExtraParam() {
PASS();
}
+std::string TestPostMessage::TestNonMainThread() {
+ ASSERT_TRUE(ClearListeners());
+ ASSERT_TRUE(AddEchoingListener("message_event.data"));
+ message_data_.clear();
+
+ // Set up a thread for each integer from 0 to (kThreadsToRun - 1). Make each
+ // thread send the number that matches its index kMessagesToSendPerThread
+ // times. For good measure, call postMessage from the main thread
+ // kMessagesToSendPerThread times. At the end, we make sure we got all the
+ // values we expected.
+ PP_ThreadType threads[kThreadsToRun];
+ for (int32_t i = 0; i < kThreadsToRun; ++i) {
+ // Set up a thread to send a value of i.
+ void* arg = new InvokePostMessageThreadArg(instance_, pp::Var(i));
+ PP_CreateThread(&threads[i], &InvokePostMessageThreadFunc, arg);
+ }
+ // Invoke PostMessage right now to send a value of (kThreadsToRun).
+ for (int32_t i = 0; i < kMessagesToSendPerThread; ++i)
+ instance_->PostMessage(pp::Var(kThreadsToRun));
+
+ // Now join all threads.
+ for (int32_t i = 0; i < kThreadsToRun; ++i)
+ PP_JoinThread(threads[i]);
+
+ // PostMessage is asynchronous, so we should not receive a response yet.
+ ASSERT_EQ(message_data_.size(), 0);
+
+ // Make sure we got all values that we expected. Note that because it's legal
+ // for the JavaScript engine to treat our integers as floating points, we
+ // can't just use std::find or equality comparison. So we instead, we convert
+ // each incoming value to an integer, and count them in received_counts.
+ int32_t expected_num = (kThreadsToRun + 1) * kMessagesToSendPerThread;
+ // Count how many we receive per-index.
+ std::vector<int32_t> expected_counts(kThreadsToRun + 1,
+ kMessagesToSendPerThread);
+ std::vector<int32_t> received_counts(kThreadsToRun + 1, 0);
+ for (int32_t i = 0; i < expected_num; ++i) {
+ // Run the message loop to get the next expected message.
+ testing_interface_->RunMessageLoop(instance_->pp_instance());
+ // Make sure we got another message in.
+ ASSERT_EQ(message_data_.size(), 1);
+ pp::Var latest_var(message_data_.back());
+ message_data_.clear();
+
+ ASSERT_TRUE(latest_var.is_int() || latest_var.is_double());
+ int32_t received_value = -1;
+ if (latest_var.is_int()) {
+ received_value = latest_var.AsInt();
+ } else if (latest_var.is_double()) {
+ received_value = static_cast<int32_t>(latest_var.AsDouble() + 0.5);
+ }
+ ASSERT_TRUE(received_value >= 0);
+ ASSERT_TRUE(received_value <= kThreadsToRun);
+ ++received_counts[received_value];
+ }
+ ASSERT_EQ(received_counts, expected_counts);
+
+ PASS();
+}
+
diff --git a/ppapi/tests/test_post_message.h b/ppapi/tests/test_post_message.h
index df7256b..f081880 100644
--- a/ppapi/tests/test_post_message.h
+++ b/ppapi/tests/test_post_message.h
@@ -53,6 +53,9 @@ class TestPostMessage : public TestCase {
// nothing happens.
std::string TestExtraParam();
+ // Test sending messages off of the main thread.
+ std::string TestNonMainThread();
+
typedef std::vector<pp::Var> VarVector;
// This is used to store pp::Var objects we receive via a call to
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
index b5da771..c4a73e5 100644
--- a/webkit/plugins/ppapi/plugin_module.cc
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -200,11 +200,16 @@ uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
return ResourceTracker::Get()->GetLiveObjectsForInstance(instance_id);
}
+PP_Bool IsOutOfProcess() {
+ return PP_FALSE;
+}
+
const PPB_Testing_Dev testing_interface = {
&ReadImageData,
&RunMessageLoop,
&QuitMessageLoop,
- &GetLiveObjectsForInstance
+ &GetLiveObjectsForInstance,
+ &IsOutOfProcess
};
// GetInterface ----------------------------------------------------------------
@@ -364,7 +369,11 @@ const void* GetInterface(const char* name) {
// Only support the testing interface when the command line switch is
// specified. This allows us to prevent people from (ab)using this interface
// in production code.
- if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0) {
+ // TODO(dmichael): Remove support for 0.6. Note that 0.7 only adds a function
+ // to the end, so returning an 0.7 struct for use by clients of 0.6 just
+ // works in practice.
+ if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0 ||
+ strcmp(name, PPB_TESTING_DEV_INTERFACE_0_6) == 0) {
if (CommandLine::ForCurrentProcess()->HasSwitch("enable-pepper-testing"))
return &testing_interface;
}