diff options
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/dispatch_reply_message.h | 25 | ||||
-rw-r--r-- | ppapi/proxy/gamepad_resource.cc | 87 | ||||
-rw-r--r-- | ppapi/proxy/gamepad_resource.h | 10 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.cc | 21 | ||||
-rw-r--r-- | ppapi/proxy/plugin_dispatcher.h | 7 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 10 | ||||
-rw-r--r-- | ppapi/proxy/resource_message_params.cc | 41 | ||||
-rw-r--r-- | ppapi/proxy/resource_message_params.h | 35 |
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. |