summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/dispatch_reply_message.h25
-rw-r--r--ppapi/proxy/gamepad_resource.cc87
-rw-r--r--ppapi/proxy/gamepad_resource.h10
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc21
-rw-r--r--ppapi/proxy/plugin_dispatcher.h7
-rw-r--r--ppapi/proxy/ppapi_messages.h10
-rw-r--r--ppapi/proxy/resource_message_params.cc41
-rw-r--r--ppapi/proxy/resource_message_params.h35
8 files changed, 199 insertions, 37 deletions
diff --git a/ppapi/proxy/dispatch_reply_message.h b/ppapi/proxy/dispatch_reply_message.h
index 443c523..0dc3739 100644
--- a/ppapi/proxy/dispatch_reply_message.h
+++ b/ppapi/proxy/dispatch_reply_message.h
@@ -63,16 +63,23 @@ inline void DispatchResourceReply(ObjT* obj, Method method,
#define PPAPI_DISPATCH_RESOURCE_REPLY(msg_class, member_func) \
case msg_class::ID: { \
- TRACK_RUN_IN_IPC_HANDLER(member_func); \
- msg_class::Schema::Param p; \
- if (msg_class::Read(&ipc_message__, &p)) { \
- ppapi::proxy::DispatchResourceReply( \
- this, \
- &_IpcMessageHandlerClass::member_func, \
- params, p); \
- } \
+ TRACK_RUN_IN_IPC_HANDLER(member_func); \
+ msg_class::Schema::Param p; \
+ if (msg_class::Read(&ipc_message__, &p)) { \
+ ppapi::proxy::DispatchResourceReply( \
+ this, \
+ &_IpcMessageHandlerClass::member_func, \
+ params, p); \
} \
- break;
+ break; \
+ }
+
+#define PPAPI_DISPATCH_RESOURCE_REPLY_0(msg_class, member_func) \
+ case msg_class::ID: { \
+ TRACK_RUN_IN_IPC_HANDLER(member_func); \
+ member_func(params); \
+ break; \
+ }
} // namespace proxy
} // namespace ppapi
diff --git a/ppapi/proxy/gamepad_resource.cc b/ppapi/proxy/gamepad_resource.cc
index 21ee02d..446c11c 100644
--- a/ppapi/proxy/gamepad_resource.cc
+++ b/ppapi/proxy/gamepad_resource.cc
@@ -6,16 +6,47 @@
#include <string.h>
-#include "ppapi/c/ppb_gamepad.h"
+#include "base/threading/platform_thread.h"
#include "ppapi/proxy/dispatch_reply_message.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_gamepad_shared.h"
namespace ppapi {
namespace proxy {
+namespace {
+
+// This is the read logic from content/common/gamepad_seqlock.h
+base::subtle::Atomic32 ReadBegin(const base::subtle::Atomic32* sequence) {
+ base::subtle::Atomic32 version;
+ for (;;) {
+ version = base::subtle::NoBarrier_Load(sequence);
+
+ // If the counter is even, then the associated data might be in a
+ // consistent state, so we can try to read.
+ if ((version & 1) == 0)
+ break;
+
+ // Otherwise, the writer is in the middle of an update. Retry the read.
+ base::PlatformThread::YieldCurrentThread();
+ }
+ return version;
+}
+
+bool ReadRetry(const base::subtle::Atomic32* sequence,
+ base::subtle::Atomic32 version) {
+ // If the sequence number was updated then a read should be re-attempted.
+ // -- Load fence, read membarrier
+ return base::subtle::Release_Load(sequence) != version;
+}
+
+} // namespace
+
GamepadResource::GamepadResource(Connection connection, PP_Instance instance)
: PluginResource(connection, instance),
buffer_(NULL) {
+ memset(&last_read_, 0, sizeof(last_read_));
+
SendCreateToBrowser(PpapiHostMsg_Gamepad_Create());
CallBrowser(PpapiHostMsg_Gamepad_RequestMemory());
}
@@ -28,30 +59,56 @@ void GamepadResource::Sample(PP_GamepadsSampleData* data) {
// Browser hasn't sent back our shared memory, give the plugin gamepad
// data corresponding to "not connected".
memset(data, 0, sizeof(PP_GamepadsSampleData));
- } else {
- memcpy(data, buffer_, sizeof(PP_GamepadsSampleData));
+ return;
}
+
+ // ==========
+ // DANGER
+ // ==========
+ //
+ // This logic is duplicated in the renderer as well. If you change it, that
+ // also needs to be in sync. See gamepad_shared_memory_reader.cc.
+
+ // Only try to read this many times before failing to avoid waiting here
+ // very long in case of contention with the writer.
+ const int kMaximumContentionCount = 10;
+ int contention_count = -1;
+ base::subtle::Atomic32 version;
+ WebKitGamepads read_into;
+ do {
+ version = ReadBegin(&buffer_->sequence);
+ memcpy(&read_into, &buffer_->buffer, sizeof(read_into));
+ ++contention_count;
+ if (contention_count == kMaximumContentionCount)
+ break;
+ } while (ReadRetry(&buffer_->sequence, version));
+
+ // In the event of a read failure, just leave the last read data as-is (the
+ // hardware thread is taking unusally long).
+ if (contention_count < kMaximumContentionCount)
+ ConvertWebKitGamepadData(read_into, &last_read_);
+
+ memcpy(data, &last_read_, sizeof(PP_GamepadsSampleData));
}
void GamepadResource::OnReplyReceived(const ResourceMessageReplyParams& params,
const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(GamepadResource, msg)
- PPAPI_DISPATCH_RESOURCE_REPLY(PpapiPluginMsg_Gamepad_SendMemory,
- OnPluginMsgSendMemory)
+ PPAPI_DISPATCH_RESOURCE_REPLY_0(PpapiPluginMsg_Gamepad_SendMemory,
+ OnPluginMsgSendMemory)
IPC_END_MESSAGE_MAP()
}
void GamepadResource::OnPluginMsgSendMemory(
- const ResourceMessageReplyParams& params,
- base::SharedMemoryHandle shared_memory_handle) {
- /* TODO(brettw) implement this when we have shared gamepad code. It would be
- something like this:
- shared_memory_.reset(
- new base::SharedMemory(shared_memory_handle, true));
- CHECK(shared_memory_->Map(sizeof(GamepadHardwareBuffer)));
- void *memory = shared_memory_->memory();
- // Use the memory...
- */
+ const ResourceMessageReplyParams& params) {
+ // On failure, the handle will be null and the CHECK below will be tripped.
+ base::SharedMemoryHandle handle;
+ params.GetSharedMemoryHandleAtIndex(0, &handle);
+
+ shared_memory_.reset(new base::SharedMemory(handle, true));
+ CHECK(shared_memory_->Map(sizeof(ContentGamepadHardwareBuffer)));
+ buffer_ = static_cast<const ContentGamepadHardwareBuffer*>(
+ shared_memory_->memory());
}
} // namespace proxy
diff --git a/ppapi/proxy/gamepad_resource.h b/ppapi/proxy/gamepad_resource.h
index 61d66b0..f2398ff 100644
--- a/ppapi/proxy/gamepad_resource.h
+++ b/ppapi/proxy/gamepad_resource.h
@@ -9,8 +9,10 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "ppapi/c/ppb_gamepad.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/ppb_gamepad_shared.h"
#include "ppapi/thunk/ppb_gamepad_api.h"
struct PP_GamepadsSampleData;
@@ -41,11 +43,13 @@ class PPAPI_PROXY_EXPORT GamepadResource
virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
const IPC::Message& msg) OVERRIDE;
- void OnPluginMsgSendMemory(const ResourceMessageReplyParams& params,
- base::SharedMemoryHandle shared_memory_handle);
+ void OnPluginMsgSendMemory(const ResourceMessageReplyParams& params);
scoped_ptr<base::SharedMemory> shared_memory_;
- void* buffer_;
+ const ContentGamepadHardwareBuffer* buffer_;
+
+ // Last data returned so we can use this in the event of a read failure.
+ PP_GamepadsSampleData last_read_;
DISALLOW_COPY_AND_ASSIGN(GamepadResource);
};
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 0e406db..d48dbfb 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -260,6 +260,19 @@ thunk::ResourceCreationAPI* PluginDispatcher::GetResourceCreationAPI() {
GetInterfaceProxy(API_ID_RESOURCE_CREATION));
}
+// static
+void PluginDispatcher::DispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg) {
+ Resource* resource = PpapiGlobals::Get()->GetResourceTracker()->GetResource(
+ reply_params.pp_resource());
+ if (!resource) {
+ NOTREACHED();
+ return;
+ }
+ resource->OnReplyReceived(reply_params, nested_msg);
+}
+
void PluginDispatcher::ForceFreeAllInstances() {
if (!g_instance_to_dispatcher)
return;
@@ -281,13 +294,7 @@ void PluginDispatcher::ForceFreeAllInstances() {
void PluginDispatcher::OnMsgResourceReply(
const ppapi::proxy::ResourceMessageReplyParams& reply_params,
const IPC::Message& nested_msg) {
- Resource* resource = PpapiGlobals::Get()->GetResourceTracker()->GetResource(
- reply_params.pp_resource());
- if (!resource) {
- NOTREACHED();
- return;
- }
- resource->OnReplyReceived(reply_params, nested_msg);
+ DispatchResourceReply(reply_params, nested_msg);
}
void PluginDispatcher::OnMsgSupportsInterface(
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
index ba46464..66b5e2d 100644
--- a/ppapi/proxy/plugin_dispatcher.h
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -147,6 +147,13 @@ class PPAPI_PROXY_EXPORT PluginDispatcher
uint32 plugin_dispatcher_id() const { return plugin_dispatcher_id_; }
bool incognito() const { return incognito_; }
+ // Dispatches the given resource message to the appropriate resource in the
+ // plugin process. This should be wired to the various channels that messages
+ // come in from various other processes.
+ static void DispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg);
+
private:
friend class PluginDispatcherTest;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index a532aff..8528a2d 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1551,9 +1551,15 @@ IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileChooser_ShowReply,
// Gamepad.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create)
+
+// Requests that the gamepad host send the shared memory handle to the plugin
+// process.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_RequestMemory)
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Gamepad_SendMemory,
- base::SharedMemoryHandle /* handle */)
+
+// Reply to a RequestMemory call. This supplies the shared memory handle. The
+// actual handle is passed in the ReplyParams struct.
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Gamepad_SendMemory)
+
// Printing.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_Create)
IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_GetDefaultPrintSettings)
diff --git a/ppapi/proxy/resource_message_params.cc b/ppapi/proxy/resource_message_params.cc
index 5c70e49..6d3fa02 100644
--- a/ppapi/proxy/resource_message_params.cc
+++ b/ppapi/proxy/resource_message_params.cc
@@ -27,12 +27,51 @@ ResourceMessageParams::~ResourceMessageParams() {
void ResourceMessageParams::Serialize(IPC::Message* msg) const {
IPC::ParamTraits<PP_Resource>::Write(msg, pp_resource_);
IPC::ParamTraits<int32_t>::Write(msg, sequence_);
+ IPC::ParamTraits<std::vector<SerializedHandle> >::Write(msg, handles_);
}
bool ResourceMessageParams::Deserialize(const IPC::Message* msg,
PickleIterator* iter) {
return IPC::ParamTraits<PP_Resource>::Read(msg, iter, &pp_resource_) &&
- IPC::ParamTraits<int32_t>::Read(msg, iter, &sequence_);
+ IPC::ParamTraits<int32_t>::Read(msg, iter, &sequence_) &&
+ IPC::ParamTraits<std::vector<SerializedHandle> >::Read(
+ msg, iter, &handles_);
+}
+
+const SerializedHandle* ResourceMessageParams::GetHandleOfTypeAtIndex(
+ size_t index,
+ SerializedHandle::Type type) const {
+ if (handles_.size() <= index)
+ return NULL;
+ if (handles_[index].type() != type)
+ return NULL;
+ return &handles_[index];
+}
+
+bool ResourceMessageParams::GetSharedMemoryHandleAtIndex(
+ size_t index,
+ base::SharedMemoryHandle* handle) const {
+ const SerializedHandle* serialized = GetHandleOfTypeAtIndex(
+ index, SerializedHandle::SHARED_MEMORY);
+ if (!serialized)
+ return false;
+ *handle = serialized->shmem();
+ return true;
+}
+
+bool ResourceMessageParams::GetSocketHandleAtIndex(
+ size_t index,
+ IPC::PlatformFileForTransit* handle) const {
+ const SerializedHandle* serialized = GetHandleOfTypeAtIndex(
+ index, SerializedHandle::SOCKET);
+ if (!serialized)
+ return false;
+ *handle = serialized->descriptor();
+ return true;
+}
+
+void ResourceMessageParams::AppendHandle(const SerializedHandle& handle) {
+ handles_.push_back(handle);
}
ResourceMessageCallParams::ResourceMessageCallParams()
diff --git a/ppapi/proxy/resource_message_params.h b/ppapi/proxy/resource_message_params.h
index ad1c96a..bc52234 100644
--- a/ppapi/proxy/resource_message_params.h
+++ b/ppapi/proxy/resource_message_params.h
@@ -5,9 +5,12 @@
#ifndef PPAPI_PROXY_RESOURCE_MESSAGE_PARAMS_H_
#define PPAPI_PROXY_RESOURCE_MESSAGE_PARAMS_H_
+#include <vector>
+
#include "ipc/ipc_message_utils.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/serialized_structs.h"
namespace ppapi {
namespace proxy {
@@ -20,6 +23,33 @@ class PPAPI_PROXY_EXPORT ResourceMessageParams {
PP_Resource pp_resource() const { return pp_resource_; }
int32_t sequence() const { return sequence_; }
+ const std::vector<SerializedHandle> handles() const { return handles_; }
+
+ // Returns a pointer to the handle at the given index if it exists and is of
+ // the given type. If the index doesn't exist or the handle isn't of the
+ // given type, returns NULL. Note that the pointer will be into an internal
+ // vector so will be invalidated if the params are mutated.
+ const SerializedHandle* GetHandleOfTypeAtIndex(
+ size_t index,
+ SerializedHandle::Type type) const;
+
+ // Helper functions to return shared memory handles passed in the params
+ // struct. If the index has a valid handle of the given type, it will be
+ // placed in the output parameter and the function will return true. If the
+ // handle doesn't exist or is a different type, the functions will return
+ // false and the output parameter will be untouched.
+ //
+ // Note that the handle could still be a "null" or invalid handle of
+ // the right type and the functions will succeed.
+ bool GetSharedMemoryHandleAtIndex(size_t index,
+ base::SharedMemoryHandle* handle) const;
+ bool GetSocketHandleAtIndex(size_t index,
+ IPC::PlatformFileForTransit* handle) const;
+
+ // Appends the given handle to the list of handles sent with the call or
+ // reply.
+ void AppendHandle(const SerializedHandle& handle);
+
protected:
ResourceMessageParams();
ResourceMessageParams(PP_Resource resource, int32_t sequence);
@@ -44,6 +74,11 @@ class PPAPI_PROXY_EXPORT ResourceMessageParams {
// confusion within the plugin and within callbacks on the same resource,
// there shouldn't be a security problem.
int32_t sequence_;
+
+ // A list of all handles transferred in the message. Handles go here so that
+ // the NaCl adapter can extract them generally when it rewrites them to
+ // go between Windows and NaCl (Posix) apps.
+ std::vector<SerializedHandle> handles_;
};
// Parameters common to all ResourceMessage "Call" requests.