summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 20:42:33 +0000
committerteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 20:42:33 +0000
commit30e1cb75b8fa46b67cfc7faa146eacdca5e90241 (patch)
tree2b6b293673d938f49843aa6b76143ca7d5950315
parentae5df4b22be0cfee27c09c6a1e4721eb0935eab2 (diff)
downloadchromium_src-30e1cb75b8fa46b67cfc7faa146eacdca5e90241.zip
chromium_src-30e1cb75b8fa46b67cfc7faa146eacdca5e90241.tar.gz
chromium_src-30e1cb75b8fa46b67cfc7faa146eacdca5e90241.tar.bz2
Pepper: Use shared memory for ArrayBufferVar.
This change improves performance for sending ArrayBufferVars between the plugin and the host. It copies the data from the var into a shared memory region and sends the shared memory handle over IPC. This required defining a new message for plugins to request the host to create shared memory. BUG= Review URL: https://chromiumcodereview.appspot.com/11827059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@189089 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/shared_memory_nacl.cc1
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/nacl/nacl_ipc_adapter.cc3
-rw-r--r--chrome/nacl/nacl_ipc_adapter.h1
-rw-r--r--chrome/renderer/pepper/pepper_helper.cc4
-rw-r--r--chrome/renderer/pepper/pepper_shared_memory_message_filter.cc75
-rw-r--r--chrome/renderer/pepper/pepper_shared_memory_message_filter.h53
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.cc11
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.h6
-rw-r--r--ppapi/host/instance_message_filter.cc19
-rw-r--r--ppapi/host/instance_message_filter.h41
-rw-r--r--ppapi/host/ppapi_host.cc20
-rw-r--r--ppapi/host/ppapi_host.h11
-rw-r--r--ppapi/ppapi_host.gypi2
-rw-r--r--ppapi/ppapi_proxy.gypi1
-rw-r--r--ppapi/proxy/handle_converter.cc26
-rw-r--r--ppapi/proxy/plugin_array_buffer_var.cc84
-rw-r--r--ppapi/proxy/plugin_array_buffer_var.h16
-rw-r--r--ppapi/proxy/plugin_var_tracker.cc22
-rw-r--r--ppapi/proxy/plugin_var_tracker.h11
-rw-r--r--ppapi/proxy/ppapi_messages.h11
-rw-r--r--ppapi/proxy/ppb_instance_proxy.cc7
-rw-r--r--ppapi/proxy/ppp_messaging_proxy.cc4
-rw-r--r--ppapi/proxy/serialized_var.cc175
-rw-r--r--ppapi/proxy/serialized_var.h47
-rw-r--r--ppapi/shared_impl/test_globals.h17
-rw-r--r--ppapi/shared_impl/var.h15
-rw-r--r--ppapi/shared_impl/var_tracker.cc13
-rw-r--r--ppapi/shared_impl/var_tracker.h26
-rw-r--r--ppapi/tests/test_post_message.cc6
-rw-r--r--webkit/plugins/ppapi/host_array_buffer_var.cc71
-rw-r--r--webkit/plugins/ppapi/host_array_buffer_var.h11
-rw-r--r--webkit/plugins/ppapi/host_var_tracker.cc42
-rw-r--r--webkit/plugins/ppapi/host_var_tracker.h22
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.cc7
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.h4
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h7
37 files changed, 858 insertions, 36 deletions
diff --git a/base/shared_memory_nacl.cc b/base/shared_memory_nacl.cc
index 63e56e5..291527e 100644
--- a/base/shared_memory_nacl.cc
+++ b/base/shared_memory_nacl.cc
@@ -123,7 +123,6 @@ SharedMemoryHandle SharedMemory::handle() const {
void SharedMemory::Close() {
Unmap();
-
if (mapped_file_ > 0) {
if (close(mapped_file_) < 0)
DPLOG(ERROR) << "close";
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 549985b..42b162f 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -216,6 +216,8 @@
'renderer/pepper/pepper_flash_renderer_host.h',
'renderer/pepper/pepper_helper.cc',
'renderer/pepper/pepper_helper.h',
+ 'renderer/pepper/pepper_shared_memory_message_filter.cc',
+ 'renderer/pepper/pepper_shared_memory_message_filter.h',
'renderer/pepper/ppb_nacl_private_impl.cc',
'renderer/pepper/ppb_nacl_private_impl.h',
'renderer/pepper/ppb_pdf_impl.cc',
diff --git a/chrome/nacl/nacl_ipc_adapter.cc b/chrome/nacl/nacl_ipc_adapter.cc
index a37756c..c615a05 100644
--- a/chrome/nacl/nacl_ipc_adapter.cc
+++ b/chrome/nacl/nacl_ipc_adapter.cc
@@ -15,9 +15,11 @@
#include "build/build_config.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_platform_file.h"
+#include "native_client/src/trusted/desc/nacl_desc_base.h"
#include "native_client/src/trusted/desc/nacl_desc_custom.h"
#include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
#include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
+#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_handle.h"
@@ -460,6 +462,7 @@ int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) {
bool NaClIPCAdapter::SendCompleteMessage(const char* buffer,
size_t buffer_len) {
+ lock_.AssertAcquired();
// The message will have already been validated, so we know it's large enough
// for our header.
const NaClMessageHeader* header =
diff --git a/chrome/nacl/nacl_ipc_adapter.h b/chrome/nacl/nacl_ipc_adapter.h
index 032d98d..515b0fc 100644
--- a/chrome/nacl/nacl_ipc_adapter.h
+++ b/chrome/nacl/nacl_ipc_adapter.h
@@ -8,6 +8,7 @@
#include <map>
#include <queue>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
diff --git a/chrome/renderer/pepper/pepper_helper.cc b/chrome/renderer/pepper/pepper_helper.cc
index c15f893..c36bac0 100644
--- a/chrome/renderer/pepper/pepper_helper.cc
+++ b/chrome/renderer/pepper/pepper_helper.cc
@@ -5,6 +5,7 @@
#include "chrome/renderer/pepper/pepper_helper.h"
#include "chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h"
+#include "chrome/renderer/pepper/pepper_shared_memory_message_filter.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -23,6 +24,9 @@ void PepperHelper::DidCreatePepperPlugin(content::RendererPpapiHost* host) {
host->GetPpapiHost()->AddHostFactoryFilter(
scoped_ptr<ppapi::host::HostFactory>(
new ChromeRendererPepperHostFactory(host)));
+ host->GetPpapiHost()->AddInstanceMessageFilter(
+ scoped_ptr<ppapi::host::InstanceMessageFilter>(
+ new PepperSharedMemoryMessageFilter(host)));
}
} // namespace chrome
diff --git a/chrome/renderer/pepper/pepper_shared_memory_message_filter.cc b/chrome/renderer/pepper/pepper_shared_memory_message_filter.cc
new file mode 100644
index 0000000..c568218
--- /dev/null
+++ b/chrome/renderer/pepper/pepper_shared_memory_message_filter.cc
@@ -0,0 +1,75 @@
+// 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.
+
+#include "chrome/renderer/pepper/pepper_shared_memory_message_filter.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process_util.h"
+#include "base/shared_memory.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "webkit/plugins/ppapi/host_globals.h"
+
+namespace chrome {
+
+PepperSharedMemoryMessageFilter::PepperSharedMemoryMessageFilter(
+ content::RendererPpapiHost* host)
+ : InstanceMessageFilter(host->GetPpapiHost()),
+ host_(host) {
+}
+
+PepperSharedMemoryMessageFilter::~PepperSharedMemoryMessageFilter() {
+}
+
+bool PepperSharedMemoryMessageFilter::OnInstanceMessageReceived(
+ const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PepperSharedMemoryMessageFilter, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_SharedMemory_CreateSharedMemory,
+ OnHostMsgCreateSharedMemory)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool PepperSharedMemoryMessageFilter::Send(IPC::Message* msg) {
+ return host_->GetPpapiHost()->Send(msg);
+}
+
+void PepperSharedMemoryMessageFilter::OnHostMsgCreateSharedMemory(
+ PP_Instance instance,
+ uint32_t size,
+ int* host_handle_id,
+ ppapi::proxy::SerializedHandle* plugin_handle) {
+ plugin_handle->set_null_shmem();
+ *host_handle_id = -1;
+ scoped_ptr<base::SharedMemory> shm(content::RenderThread::Get()->
+ HostAllocateSharedMemoryBuffer(size).Pass());
+ if (!shm.get())
+ return;
+
+ base::SharedMemoryHandle host_shm_handle;
+ shm->ShareToProcess(base::GetCurrentProcessHandle(), &host_shm_handle);
+ *host_handle_id = content::GetHostGlobals()->GetVarTracker()->
+ TrackSharedMemoryHandle(instance, host_shm_handle, size);
+
+ base::PlatformFile host_handle =
+#if defined(OS_WIN)
+ host_shm_handle;
+#elif defined(OS_POSIX)
+ host_shm_handle.fd;
+#else
+ #error Not implemented.
+#endif
+ // We set auto_close to false since we need our file descriptor to
+ // actually be duplicated on linux. The shared memory destructor will
+ // close the original handle for us.
+ plugin_handle->set_shmem(
+ host_->ShareHandleWithRemote(host_handle, false), size);
+}
+
+} // namespace chrome
diff --git a/chrome/renderer/pepper/pepper_shared_memory_message_filter.h b/chrome/renderer/pepper/pepper_shared_memory_message_filter.h
new file mode 100644
index 0000000..5ffcf0b
--- /dev/null
+++ b/chrome/renderer/pepper/pepper_shared_memory_message_filter.h
@@ -0,0 +1,53 @@
+// 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 CHROME_RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
+#define CHROME_RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/host/instance_message_filter.h"
+
+namespace content {
+class RendererPpapiHost;
+}
+
+namespace ppapi {
+namespace proxy {
+class SerializedHandle;
+}
+}
+
+namespace chrome {
+
+// Implements the backend for shared memory messages from a plugin process.
+class PepperSharedMemoryMessageFilter
+ : public ppapi::host::InstanceMessageFilter {
+ public:
+ explicit PepperSharedMemoryMessageFilter(content::RendererPpapiHost* host);
+ virtual ~PepperSharedMemoryMessageFilter();
+
+ // InstanceMessageFilter:
+ virtual bool OnInstanceMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ bool Send(IPC::Message* msg);
+
+ private:
+ // Message handlers.
+ void OnHostMsgCreateSharedMemory(
+ PP_Instance instance,
+ uint32_t size,
+ int* host_shm_handle_id,
+ ppapi::proxy::SerializedHandle* plugin_shm_handle);
+
+ content::RendererPpapiHost* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperSharedMemoryMessageFilter);
+};
+
+} // namespace chrome
+
+#endif // CHROME_RENDERER_PEPPER_PEPPER_SHARED_MEMORY_MESSAGE_FILTER_H_
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc
index cb5497a..fdb5c9c 100644
--- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc
@@ -33,6 +33,7 @@
#include "content/public/common/context_menu_params.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/sandbox_init.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/renderer_restrict_dispatch_group.h"
#include "content/renderer/gamepad_shared_memory_reader.h"
@@ -1608,4 +1609,14 @@ MouseLockDispatcher* PepperPluginDelegateImpl::GetMouseLockDispatcher(
}
}
+IPC::PlatformFileForTransit PepperPluginDelegateImpl::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId target_process_id,
+ bool should_close_source) const {
+ return content::BrokerGetFileHandleForProcess(
+ handle,
+ target_process_id,
+ should_close_source);
+}
+
} // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h
index 5a66214..d8b2e17 100644
--- a/content/renderer/pepper/pepper_plugin_delegate_impl.h
+++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h
@@ -387,6 +387,12 @@ class PepperPluginDelegateImpl
MouseLockDispatcher* GetMouseLockDispatcher(
webkit::ppapi::PluginInstance* instance);
+ // Share a given handle with the target process.
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId target_process_id,
+ bool should_close_source) const OVERRIDE;
+
// Pointer to the RenderView that owns us.
RenderViewImpl* render_view_;
diff --git a/ppapi/host/instance_message_filter.cc b/ppapi/host/instance_message_filter.cc
new file mode 100644
index 0000000..229235f
--- /dev/null
+++ b/ppapi/host/instance_message_filter.cc
@@ -0,0 +1,19 @@
+// 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/host/instance_message_filter.h"
+
+#include "ppapi/host/ppapi_host.h"
+
+namespace ppapi {
+namespace host {
+
+InstanceMessageFilter::InstanceMessageFilter(PpapiHost* host) : host_(host) {
+}
+
+InstanceMessageFilter::~InstanceMessageFilter() {
+}
+
+} // namespace host
+} // namespace ppapi
diff --git a/ppapi/host/instance_message_filter.h b/ppapi/host/instance_message_filter.h
new file mode 100644
index 0000000..2b072e9
--- /dev/null
+++ b/ppapi/host/instance_message_filter.h
@@ -0,0 +1,41 @@
+// 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.
+
+#ifndef PPAPI_HOST_INSTANCE_MESSAGE_FILTER_H_
+#define PPAPI_HOST_INSTANCE_MESSAGE_FILTER_H_
+
+#include "base/basictypes.h"
+#include "ppapi/host/ppapi_host_export.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+namespace host {
+
+class PpapiHost;
+
+class PPAPI_HOST_EXPORT InstanceMessageFilter {
+ public:
+ explicit InstanceMessageFilter(PpapiHost* host);
+ virtual ~InstanceMessageFilter();
+
+ // Processes an instance message from the plugin process. Returns true if the
+ // message was handled. On false, the PpapiHost will forward the message to
+ // the next filter.
+ virtual bool OnInstanceMessageReceived(const IPC::Message& msg) = 0;
+
+ PpapiHost* host() { return host_; }
+
+ private:
+ PpapiHost* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstanceMessageFilter);
+};
+
+} // namespace host
+} // namespace ppapi
+
+#endif // PPAPI_HOST_INSTANCE_MESSAGE_FILTER_H_
diff --git a/ppapi/host/ppapi_host.cc b/ppapi/host/ppapi_host.cc
index 6423f1e..87dfb11 100644
--- a/ppapi/host/ppapi_host.cc
+++ b/ppapi/host/ppapi_host.cc
@@ -8,6 +8,7 @@
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/host_factory.h"
#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/instance_message_filter.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
@@ -33,8 +34,11 @@ PpapiHost::PpapiHost(IPC::Sender* sender,
PpapiHost::~PpapiHost() {
// Delete these explicitly before destruction since then the host is still
- // technically alive in case one of the hosts accesses us from the
+ // technically alive in case one of the filters accesses us from the
// destructor.
+ instance_message_filters_.clear();
+
+ // The resources may also want to use us in their destructors.
resources_.clear();
pending_resource_hosts_.clear();
}
@@ -59,6 +63,15 @@ bool PpapiHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
+ if (!handled) {
+ for (size_t i = 0; i < instance_message_filters_.size(); i++) {
+ if (instance_message_filters_[i]->OnInstanceMessageReceived(msg)) {
+ handled = true;
+ break;
+ }
+ }
+ }
+
return handled;
}
@@ -94,6 +107,11 @@ void PpapiHost::AddHostFactoryFilter(scoped_ptr<HostFactory> filter) {
host_factory_filters_.push_back(filter.release());
}
+void PpapiHost::AddInstanceMessageFilter(
+ scoped_ptr<InstanceMessageFilter> filter) {
+ instance_message_filters_.push_back(filter.release());
+}
+
void PpapiHost::OnHostMsgResourceCall(
const proxy::ResourceMessageCallParams& params,
const IPC::Message& nested_msg) {
diff --git a/ppapi/host/ppapi_host.h b/ppapi/host/ppapi_host.h
index 5e44d1a..c661a9b 100644
--- a/ppapi/host/ppapi_host.h
+++ b/ppapi/host/ppapi_host.h
@@ -30,6 +30,7 @@ namespace host {
class HostFactory;
struct HostMessageContext;
+class InstanceMessageFilter;
struct ReplyMessageContext;
class ResourceHost;
@@ -69,6 +70,10 @@ class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener {
// ownership of the pointer.
void AddHostFactoryFilter(scoped_ptr<HostFactory> filter);
+ // Adds the given message filter to the host. The PpapiHost will take
+ // ownership of the pointer.
+ void AddInstanceMessageFilter(scoped_ptr<InstanceMessageFilter> filter);
+
// Returns null if the resource doesn't exist.
host::ResourceHost* GetResourceHost(PP_Resource resource) const;
@@ -104,6 +109,12 @@ class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener {
// an ObserverList.
ScopedVector<HostFactory> host_factory_filters_;
+ // Filters for instance messages. Note that since we don't support deleting
+ // these dynamically we don't need to worry about modifications during
+ // iteration. If we add that capability, this should be replaced with an
+ // ObserverList.
+ ScopedVector<InstanceMessageFilter> instance_message_filters_;
+
typedef std::map<PP_Resource, linked_ptr<ResourceHost> > ResourceMap;
ResourceMap resources_;
diff --git a/ppapi/ppapi_host.gypi b/ppapi/ppapi_host.gypi
index a2afd58..4031c77 100644
--- a/ppapi/ppapi_host.gypi
+++ b/ppapi/ppapi_host.gypi
@@ -25,6 +25,8 @@
'host/host_factory.h',
'host/host_message_context.cc',
'host/host_message_context.h',
+ 'host/instance_message_filter.cc',
+ 'host/instance_message_filter.h',
'host/message_filter_host.cc',
'host/message_filter_host.h',
'host/ppapi_host.cc',
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 9978a42..838bbc6 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -88,6 +88,7 @@
'proxy/plugin_var_tracker.h',
'proxy/ppapi_command_buffer_proxy.h',
'proxy/ppapi_command_buffer_proxy.cc',
+ 'proxy/ppapi_messages.h',
'proxy/ppapi_message_utils.h',
'proxy/ppb_audio_proxy.cc',
'proxy/ppb_audio_proxy.h',
diff --git a/ppapi/proxy/handle_converter.cc b/ppapi/proxy/handle_converter.cc
index a669062..ef4102c 100644
--- a/ppapi/proxy/handle_converter.cc
+++ b/ppapi/proxy/handle_converter.cc
@@ -4,11 +4,15 @@
#include "ppapi/proxy/handle_converter.h"
+#include <vector>
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/proxy/serialized_var.h"
+
+class NaClDescImcShm;
namespace IPC {
class Message;
@@ -28,9 +32,9 @@ void WriteHandle(int handle_index,
typedef std::vector<ppapi::proxy::SerializedHandle> Handles;
-// We define overload for catching SerializedHandles, so that we can share
-// them correctly to the untrusted side, and another for handling all other
-// parameters. See ConvertHandlesImpl for how these get used.
+// We define overloads for catching SerializedHandles so that we can share
+// them correctly to the untrusted side.
+// See ConvertHandlesImpl for how these get used.
void ConvertHandlesInParam(const ppapi::proxy::SerializedHandle& handle,
Handles* handles,
IPC::Message* msg,
@@ -40,6 +44,20 @@ void ConvertHandlesInParam(const ppapi::proxy::SerializedHandle& handle,
WriteHandle((*handle_index)++, handle, msg);
}
+void ConvertHandlesInParam(const ppapi::proxy::SerializedVar& var,
+ Handles* handles,
+ IPC::Message* msg,
+ int* handle_index) {
+ ppapi::proxy::SerializedHandle *handle = var.GetPluginShmemHandle();
+ if (handle) {
+ handles->push_back(*handle);
+ if (msg) {
+ var.WriteRawVarHeader(msg);
+ WriteHandle((*handle_index)++, *handle, msg);
+ }
+ }
+}
+
// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
// the handles are carried inside the ResourceMessageReplyParams.
// NOTE: We only translate handles from host->NaCl. The only kind of
@@ -218,6 +236,7 @@ bool HandleConverter::ConvertNativeHandlesToPosix(
switch (msg.type()) {
CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel)
CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
+ CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
case IPC_REPLY_ID: {
int id = IPC::SyncMessage::GetMessageId(msg);
@@ -232,6 +251,7 @@ bool HandleConverter::ConvertNativeHandlesToPosix(
CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl)
CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
+ CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
default:
// Do nothing for messages we don't know.
break;
diff --git a/ppapi/proxy/plugin_array_buffer_var.cc b/ppapi/proxy/plugin_array_buffer_var.cc
index c9d302f..e990ed8 100644
--- a/ppapi/proxy/plugin_array_buffer_var.cc
+++ b/ppapi/proxy/plugin_array_buffer_var.cc
@@ -8,28 +8,104 @@
#include <limits>
+#include "base/process_util.h"
+#include "base/shared_memory.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_buffer_api.h"
+
+using base::SharedMemory;
+using base::SharedMemoryHandle;
+using ppapi::proxy::PluginGlobals;
+using ppapi::proxy::PluginResourceTracker;
+
namespace ppapi {
PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes)
- : buffer_(size_in_bytes) {
+ : buffer_(size_in_bytes),
+ plugin_handle_(base::SharedMemory::NULLHandle()),
+ size_in_bytes_(size_in_bytes) {
+}
+
+PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes,
+ SharedMemoryHandle plugin_handle)
+ : plugin_handle_(plugin_handle),
+ size_in_bytes_(size_in_bytes) {
}
PluginArrayBufferVar::~PluginArrayBufferVar() {
+ Unmap();
+
+ if (shmem_.get() == NULL) {
+ // The SharedMemory destuctor can't close the handle for us.
+ if (SharedMemory::IsHandleValid(plugin_handle_))
+ SharedMemory::CloseHandle(plugin_handle_);
+ } else {
+ // Delete SharedMemory, if we have one.
+ shmem_.reset();
+ }
}
void* PluginArrayBufferVar::Map() {
+ if (shmem_.get())
+ return shmem_->memory();
+ if (SharedMemory::IsHandleValid(plugin_handle_)) {
+ shmem_.reset(new SharedMemory(plugin_handle_, false));
+ if (!shmem_->Map(size_in_bytes_)) {
+ shmem_.reset();
+ return NULL;
+ }
+ return shmem_->memory();
+ }
if (buffer_.empty())
return NULL;
return &(buffer_[0]);
}
void PluginArrayBufferVar::Unmap() {
- // We don't actually use shared memory yet, so do nothing.
+ if (shmem_.get())
+ shmem_->Unmap();
}
uint32 PluginArrayBufferVar::ByteLength() {
- return static_cast<uint32>(buffer_.size());
+ return size_in_bytes_;
}
-} // namespace ppapi
+bool PluginArrayBufferVar::CopyToNewShmem(
+ PP_Instance instance,
+ int* host_handle_id,
+ SharedMemoryHandle* plugin_out_handle) {
+ ppapi::proxy::PluginDispatcher* dispatcher =
+ ppapi::proxy::PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return false;
+ ppapi::proxy::SerializedHandle plugin_handle;
+ dispatcher->Send(new PpapiHostMsg_SharedMemory_CreateSharedMemory(
+ instance, ByteLength(), host_handle_id, &plugin_handle));
+ if (!plugin_handle.IsHandleValid() || !plugin_handle.is_shmem() ||
+ *host_handle_id == -1)
+ return false;
+
+ base::SharedMemoryHandle tmp_handle = plugin_handle.shmem();
+ SharedMemory s(tmp_handle, false);
+ if (!s.Map(ByteLength()))
+ return false;
+ memcpy(s.memory(), Map(), ByteLength());
+ s.Unmap();
+
+ // We don't need to keep the shared memory around on the plugin side;
+ // we've already copied all our data into it. We'll make it invalid
+ // just to be safe.
+ *plugin_out_handle = base::SharedMemory::NULLHandle();
+
+ return true;
+}
+
+} // namespace ppapi
diff --git a/ppapi/proxy/plugin_array_buffer_var.h b/ppapi/proxy/plugin_array_buffer_var.h
index 2eed216..bcafe8c 100644
--- a/ppapi/proxy/plugin_array_buffer_var.h
+++ b/ppapi/proxy/plugin_array_buffer_var.h
@@ -8,6 +8,9 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/shared_impl/var.h"
@@ -18,17 +21,28 @@ namespace ppapi {
class PluginArrayBufferVar : public ArrayBufferVar {
public:
explicit PluginArrayBufferVar(uint32 size_in_bytes);
+ PluginArrayBufferVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle plugin_handle);
virtual ~PluginArrayBufferVar();
// ArrayBufferVar implementation.
virtual void* Map() OVERRIDE;
virtual void Unmap() OVERRIDE;
virtual uint32 ByteLength() OVERRIDE;
+ virtual bool CopyToNewShmem(
+ PP_Instance instance,
+ int* host_handle,
+ base::SharedMemoryHandle* plugin_handle) OVERRIDE;
private:
- // TODO(dmichael): Use shared memory for this.
+ // Non-shared memory
std::vector<uint8> buffer_;
+ // Shared memory
+ base::SharedMemoryHandle plugin_handle_;
+ scoped_ptr<base::SharedMemory> shmem_;
+ uint32 size_in_bytes_;
+
DISALLOW_COPY_AND_ASSIGN(PluginArrayBufferVar);
};
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
index 384eb3ec..cff8fa1 100644
--- a/ppapi/proxy/plugin_var_tracker.cc
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -194,6 +194,12 @@ ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
return new PluginArrayBufferVar(size_in_bytes);
}
+ArrayBufferVar* PluginVarTracker::CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) {
+ return new PluginArrayBufferVar(size_in_bytes, handle);
+}
+
void PluginVarTracker::PluginImplementedObjectCreated(
PP_Instance instance,
const PP_Var& created_var,
@@ -369,5 +375,21 @@ scoped_refptr<ProxyObjectVar> PluginVarTracker::FindOrMakePluginVarFromHostVar(
return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar());
}
+int PluginVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle handle,
+ uint32 size_in_bytes) {
+ NOTREACHED();
+ return -1;
+}
+
+bool PluginVarTracker::StopTrackingSharedMemoryHandle(
+ int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) {
+ NOTREACHED();
+ return false;
+}
+
} // namesace proxy
} // namespace ppapi
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
index 3e287be..a8b229397 100644
--- a/ppapi/proxy/plugin_var_tracker.h
+++ b/ppapi/proxy/plugin_var_tracker.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/shared_memory.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
@@ -59,6 +60,13 @@ class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker {
// VarTracker public overrides.
void DidDeleteInstance(PP_Instance instance) OVERRIDE;
+ virtual int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle file,
+ uint32 size_in_bytes) OVERRIDE;
+ virtual bool StopTrackingSharedMemoryHandle(int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) OVERRIDE;
// Notification that a plugin-implemented object (PPP_Class) was created by
// the plugin or deallocated by WebKit over IPC.
@@ -86,6 +94,9 @@ class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker {
virtual void ObjectGettingZeroRef(VarMap::iterator iter) OVERRIDE;
virtual bool DeleteObjectInfoIfNecessary(VarMap::iterator iter) OVERRIDE;
virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) OVERRIDE;
+ virtual ArrayBufferVar* CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) OVERRIDE;
private:
friend struct DefaultSingletonTraits<PluginVarTracker>;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 9ccd930..6ae94ab 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1455,6 +1455,17 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_GetDefaultPrintSettings)
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply,
PP_PrintSettings_Dev /* print_settings */)
+// Shared memory ---------------------------------------------------------------
+// Creates shared memory on the host side, returning a handle to the shared
+// memory on the plugin and keeping the memory mapped in on the host.
+// We return a "host handle_id" that can be mapped back to the
+// handle on the host side by PpapiGlobals::UntrackSharedMemoryHandle().
+IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_SharedMemory_CreateSharedMemory,
+ PP_Instance /* instance */,
+ uint32_t /* size */,
+ int /* host_handle_id */,
+ ppapi::proxy::SerializedHandle /* plugin_handle */)
+
// WebSocket ------------------------------------------------------------------
IPC_MESSAGE_CONTROL0(PpapiHostMsg_WebSocket_Create)
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index 58b1593..bc51675 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -680,7 +680,8 @@ void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
PP_Var message) {
dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
API_ID_PPB_INSTANCE,
- instance, SerializedVarSendInput(dispatcher(), message)));
+ instance, SerializedVarSendInputShmem(dispatcher(), message,
+ instance)));
}
PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance,
@@ -912,7 +913,9 @@ void PPB_Instance_Proxy::OnHostMsgPostMessage(
SerializedVarReceiveInput message) {
EnterInstanceNoLock enter(instance);
if (enter.succeeded())
- enter.functions()->PostMessage(instance, message.Get(dispatcher()));
+ enter.functions()->PostMessage(instance,
+ message.GetForInstance(dispatcher(),
+ instance));
}
void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
diff --git a/ppapi/proxy/ppp_messaging_proxy.cc b/ppapi/proxy/ppp_messaging_proxy.cc
index 690e874..5a12419 100644
--- a/ppapi/proxy/ppp_messaging_proxy.cc
+++ b/ppapi/proxy/ppp_messaging_proxy.cc
@@ -34,7 +34,7 @@ void HandleMessage(PP_Instance instance, PP_Var message_data) {
dispatcher->Send(new PpapiMsg_PPPMessaging_HandleMessage(
API_ID_PPP_MESSAGING,
instance,
- SerializedVarSendInput(dispatcher, message_data)));
+ SerializedVarSendInputShmem(dispatcher, message_data, instance)));
}
static const PPP_Messaging messaging_interface = {
@@ -90,7 +90,7 @@ bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) {
void PPP_Messaging_Proxy::OnMsgHandleMessage(
PP_Instance instance, SerializedVarReceiveInput message_data) {
- PP_Var received_var(message_data.Get(dispatcher()));
+ PP_Var received_var(message_data.GetForInstance(dispatcher(), instance));
// SerializedVarReceiveInput will decrement the reference count, but we want
// to give the recipient a reference.
PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var);
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index 5352e8f..698d920 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -6,20 +6,29 @@
#include "base/logging.h"
#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/dispatcher.h"
#include "ppapi/proxy/interface_proxy.h"
#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
namespace ppapi {
namespace proxy {
+// When sending array buffers, if the size is over 256K, we use shared
+// memory instead of sending the data over IPC. Light testing suggests
+// shared memory is much faster for 256K and larger messages.
+static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
+
// SerializedVar::Inner --------------------------------------------------------
SerializedVar::Inner::Inner()
: serialization_rules_(NULL),
var_(PP_MakeUndefined()),
+ instance_(0),
cleanup_mode_(CLEANUP_NONE) {
#ifndef NDEBUG
has_been_serialized_ = false;
@@ -30,6 +39,7 @@ SerializedVar::Inner::Inner()
SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
: serialization_rules_(serialization_rules),
var_(PP_MakeUndefined()),
+ instance_(0),
cleanup_mode_(CLEANUP_NONE) {
#ifndef NDEBUG
has_been_serialized_ = false;
@@ -65,11 +75,30 @@ void SerializedVar::Inner::SetVar(PP_Var var) {
raw_var_data_.reset(NULL);
}
+void SerializedVar::Inner::SetInstance(PP_Instance instance) {
+ instance_ = instance;
+}
+
void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
var_ = value;
raw_var_data_.reset(NULL);
}
+void SerializedVar::Inner::WriteRawVarHeader(IPC::Message* m) const {
+ // Write raw_var_data_ when we're called from
+ // chrome/nacl/nacl_ipc_adapter.cc.
+ DCHECK(raw_var_data_.get());
+ DCHECK_EQ(PP_VARTYPE_ARRAY_BUFFER, raw_var_data_->type);
+ DCHECK(raw_var_data_->shmem_size != 0);
+
+ // The serialization for this message MUST MATCH the implementation at
+ // SerializedVar::Inner::WriteToMessage for ARRAY_BUFFER_SHMEM_PLUGIN.
+ m->WriteInt(static_cast<int>(raw_var_data_->type));
+ m->WriteInt(ARRAY_BUFFER_SHMEM_PLUGIN);
+ m->WriteInt(raw_var_data_->shmem_size);
+ // NaClIPCAdapter will write the handles for us.
+}
+
void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
// When writing to the IPC messages, a serialization rules handler should
// always have been set.
@@ -124,14 +153,45 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
// handle the invalid string as if it was in process rather than seeing
// what looks like a valid empty ArraryBuffer.
ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var_);
- if (buffer_var) {
- // TODO(dmichael): If it wasn't already Mapped, Unmap it. (Though once
- // we use shared memory, this will probably be
- // completely different anyway).
- m->WriteData(static_cast<const char*>(buffer_var->Map()),
- buffer_var->ByteLength());
- } else {
- m->WriteData(NULL, 0);
+ bool using_shmem = false;
+ if (buffer_var &&
+ buffer_var->ByteLength() >= kMinimumArrayBufferSizeForShmem &&
+ instance_ != 0) {
+ int host_shm_handle_id;
+ base::SharedMemoryHandle plugin_shm_handle;
+ using_shmem = buffer_var->CopyToNewShmem(instance_,
+ &host_shm_handle_id,
+ &plugin_shm_handle);
+ if (using_shmem) {
+ // The serialization for this message MUST MATCH the implementation
+ // at SerializedVar::Inner::WriteRawVarHeader for
+ // ARRAY_BUFFER_SHMEM_PLUGIN.
+ if (host_shm_handle_id != -1) {
+ DCHECK(!base::SharedMemory::IsHandleValid(plugin_shm_handle));
+ DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
+ m->WriteInt(ARRAY_BUFFER_SHMEM_HOST);
+ m->WriteInt(host_shm_handle_id);
+ } else {
+ DCHECK(base::SharedMemory::IsHandleValid(plugin_shm_handle));
+ DCHECK(PpapiGlobals::Get()->IsHostGlobals());
+ m->WriteInt(ARRAY_BUFFER_SHMEM_PLUGIN);
+ m->WriteInt(buffer_var->ByteLength());
+ SerializedHandle handle(plugin_shm_handle,
+ buffer_var->ByteLength());
+ IPC::ParamTraits<SerializedHandle>::Write(m, handle);
+ }
+ }
+ }
+ if (!using_shmem) {
+ if (buffer_var) {
+ m->WriteInt(ARRAY_BUFFER_NO_SHMEM);
+ m->WriteData(static_cast<const char*>(buffer_var->Map()),
+ buffer_var->ByteLength());
+ } else {
+ // TODO(teravest): Introduce an ARRAY_BUFFER_EMPTY message type.
+ m->WriteBool(ARRAY_BUFFER_NO_SHMEM);
+ m->WriteData(NULL, 0);
+ }
}
break;
}
@@ -159,7 +219,6 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
DCHECK(!has_been_deserialized_);
has_been_deserialized_ = true;
#endif
-
// When reading, the dispatcher should be set when we get a Deserialize
// call (which will supply a dispatcher).
int type;
@@ -197,11 +256,40 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
case PP_VARTYPE_ARRAY_BUFFER: {
int length = 0;
const char* message_bytes = NULL;
- success = m->ReadData(iter, &message_bytes, &length);
+ int shmem_type;
+ success = m->ReadInt(iter, &shmem_type);
if (success) {
- raw_var_data_.reset(new RawVarData);
- raw_var_data_->type = PP_VARTYPE_ARRAY_BUFFER;
- raw_var_data_->data.assign(message_bytes, length);
+ if (shmem_type == ARRAY_BUFFER_NO_SHMEM) {
+ success = m->ReadData(iter, &message_bytes, &length);
+ if (success) {
+ raw_var_data_.reset(new RawVarData);
+ raw_var_data_->type = PP_VARTYPE_ARRAY_BUFFER;
+ raw_var_data_->shmem_type = static_cast<ShmemType>(shmem_type);
+ raw_var_data_->shmem_size = 0;
+ raw_var_data_->data.assign(message_bytes, length);
+ }
+ } else if (shmem_type == ARRAY_BUFFER_SHMEM_HOST) {
+ int host_handle_id;
+ success = m->ReadInt(iter, &host_handle_id);
+ if (success) {
+ raw_var_data_.reset(new RawVarData);
+ raw_var_data_->type = PP_VARTYPE_ARRAY_BUFFER;
+ raw_var_data_->shmem_type = static_cast<ShmemType>(shmem_type);
+ raw_var_data_->host_handle_id = host_handle_id;
+ }
+ } else if (shmem_type == ARRAY_BUFFER_SHMEM_PLUGIN) {
+ SerializedHandle plugin_handle;
+ success = m->ReadInt(iter, &length);
+ success &= IPC::ParamTraits<SerializedHandle>::Read(
+ m, iter, &plugin_handle);
+ if (success) {
+ raw_var_data_.reset(new RawVarData);
+ raw_var_data_->type = PP_VARTYPE_ARRAY_BUFFER;
+ raw_var_data_->shmem_type = static_cast<ShmemType>(shmem_type);
+ raw_var_data_->shmem_size = length;
+ raw_var_data_->plugin_handle = plugin_handle;
+ }
+ }
}
break;
}
@@ -237,6 +325,9 @@ void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
}
void SerializedVar::Inner::ConvertRawVarData() {
+#if defined(NACL_WIN64)
+ NOTREACHED();
+#else
if (!raw_var_data_.get())
return;
@@ -248,15 +339,49 @@ void SerializedVar::Inner::ConvertRawVarData() {
break;
}
case PP_VARTYPE_ARRAY_BUFFER: {
- var_ = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
- static_cast<uint32>(raw_var_data_->data.size()),
- raw_var_data_->data.data());
+ if (raw_var_data_->shmem_type == ARRAY_BUFFER_SHMEM_HOST) {
+ base::SharedMemoryHandle host_handle;
+ uint32 size_in_bytes;
+ bool ok =
+ PpapiGlobals::Get()->GetVarTracker()->
+ StopTrackingSharedMemoryHandle(raw_var_data_->host_handle_id,
+ instance_,
+ &host_handle,
+ &size_in_bytes);
+ if (ok) {
+ var_ = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ size_in_bytes, host_handle);
+ } else {
+ LOG(ERROR) << "Couldn't find array buffer id: "
+ << raw_var_data_->host_handle_id;
+ var_ = PP_MakeUndefined();
+ }
+ } else if (raw_var_data_->shmem_type == ARRAY_BUFFER_SHMEM_PLUGIN) {
+ var_ = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ raw_var_data_->shmem_size,
+ raw_var_data_->plugin_handle.shmem());
+ } else {
+ var_ = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ static_cast<uint32>(raw_var_data_->data.size()),
+ raw_var_data_->data.data());
+ }
break;
}
default:
NOTREACHED();
}
raw_var_data_.reset(NULL);
+#endif
+}
+
+SerializedHandle* SerializedVar::Inner::GetPluginShmemHandle() const {
+ if (raw_var_data_.get()) {
+ if (raw_var_data_->type == PP_VARTYPE_ARRAY_BUFFER) {
+ if (raw_var_data_->shmem_size != 0)
+ return &raw_var_data_->plugin_handle;
+ }
+ }
+ return NULL;
}
// SerializedVar ---------------------------------------------------------------
@@ -289,6 +414,17 @@ void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
output->push_back(SerializedVarSendInput(dispatcher, input[i]));
}
+// SerializedVarSendInputShmem -------------------------------------------------
+
+SerializedVarSendInputShmem::SerializedVarSendInputShmem(
+ Dispatcher* dispatcher,
+ const PP_Var& var,
+ const PP_Instance& instance)
+ : SerializedVar(dispatcher->serialization_rules()) {
+ inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
+ inner_->SetInstance(instance);
+}
+
// ReceiveSerializedVarReturnValue ---------------------------------------------
ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
@@ -394,6 +530,13 @@ PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
return serialized_.inner_->GetVar();
}
+
+PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
+ PP_Instance instance) {
+ serialized_.inner_->SetInstance(instance);
+ return Get(dispatcher);
+}
+
// SerializedVarVectorReceiveInput ---------------------------------------------
SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
index 3b74a3e..f283590 100644
--- a/ppapi/proxy/serialized_var.h
+++ b/ppapi/proxy/serialized_var.h
@@ -11,8 +11,12 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/proxy/serialized_structs.h"
#include "ppapi/proxy/var_serialization_rules.h"
class PickleIterator;
@@ -79,11 +83,20 @@ class PPAPI_PROXY_EXPORT SerializedVar {
return inner_->ReadFromMessage(m, iter);
}
+ // Used by chrome/nacl/nacl_ipc_adapter.cc
+ SerializedHandle* GetPluginShmemHandle() const {
+ return inner_->GetPluginShmemHandle();
+ }
+ void WriteRawVarHeader(IPC::Message* m) const {
+ inner_->WriteRawVarHeader(m);
+ }
+
protected:
friend class SerializedVarReceiveInput;
friend class SerializedVarReturnValue;
friend class SerializedVarOutParam;
friend class SerializedVarSendInput;
+ friend class SerializedVarSendInputShmem;
friend class SerializedVarTestConstructor;
friend class SerializedVarVectorReceiveInput;
@@ -103,6 +116,7 @@ class PPAPI_PROXY_EXPORT SerializedVar {
// See outer class's declarations above.
PP_Var GetVar();
void SetVar(PP_Var var);
+ void SetInstance(PP_Instance instance);
// For the SerializedVarTestConstructor, this writes the Var value as if
// it was just received off the wire, without any serialization rules.
@@ -115,6 +129,12 @@ class PPAPI_PROXY_EXPORT SerializedVar {
void SetCleanupModeToEndSendPassRef();
void SetCleanupModeToEndReceiveCallerOwned();
+ // Returns a handle in the underlying data, if it exists.
+ SerializedHandle* GetPluginShmemHandle() const;
+
+ // Writes raw var data, excluding handles.
+ void WriteRawVarHeader(IPC::Message* m) const;
+
private:
enum CleanupMode {
// The serialized var won't do anything special in the destructor
@@ -128,6 +148,13 @@ class PPAPI_PROXY_EXPORT SerializedVar {
END_RECEIVE_CALLER_OWNED
};
+ // Enum for array buffer message types.
+ enum ShmemType {
+ ARRAY_BUFFER_NO_SHMEM,
+ ARRAY_BUFFER_SHMEM_HOST,
+ ARRAY_BUFFER_SHMEM_PLUGIN,
+ };
+
// ReadFromMessage() may be called on the I/O thread, e.g., when reading the
// reply to a sync message. We cannot use the var tracker on the I/O thread,
// which means we cannot create PP_Var for PP_VARTYPE_STRING and
@@ -136,7 +163,11 @@ class PPAPI_PROXY_EXPORT SerializedVar {
// the main thread.
struct RawVarData {
PP_VarType type;
+ ShmemType shmem_type;
std::string data;
+ uint32 shmem_size;
+ int host_handle_id;
+ SerializedHandle plugin_handle;
};
// Converts |raw_var_data_| to |var_|. It is a no-op if |raw_var_data_| is
@@ -158,6 +189,8 @@ class PPAPI_PROXY_EXPORT SerializedVar {
// a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
PP_Var var_;
+ PP_Instance instance_;
+
CleanupMode cleanup_mode_;
#ifndef NDEBUG
@@ -208,6 +241,19 @@ class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar {
SerializedVarSendInput();
};
+// Specialization for optionally sending over shared memory.
+class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar {
+ public:
+ SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var,
+ const PP_Instance& instance);
+
+ private:
+ // Disallow the empty constructor, but keep the default copy constructor
+ // which is required to send the object to the IPC system.
+ SerializedVarSendInputShmem();
+};
+
+
// For the calling side of a function returning a var. The sending side uses
// SerializedVarReturnValue.
//
@@ -324,6 +370,7 @@ class PPAPI_PROXY_EXPORT SerializedVarReceiveInput {
~SerializedVarReceiveInput();
PP_Var Get(Dispatcher* dispatcher);
+ PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
private:
const SerializedVar& serialized_;
diff --git a/ppapi/shared_impl/test_globals.h b/ppapi/shared_impl/test_globals.h
index 68a997a..5579b09 100644
--- a/ppapi/shared_impl/test_globals.h
+++ b/ppapi/shared_impl/test_globals.h
@@ -6,6 +6,7 @@
#define PPAPI_SHARED_IMPL_TEST_GLOBALS_H_
#include "base/compiler_specific.h"
+#include "base/shared_memory.h"
#include "ppapi/shared_impl/callback_tracker.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_tracker.h"
@@ -20,8 +21,24 @@ class TestVarTracker : public VarTracker {
virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) OVERRIDE {
return NULL;
}
+ virtual ArrayBufferVar* CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) OVERRIDE {
+ return NULL;
+ }
virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE {
}
+ virtual int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle handle,
+ uint32 size_in_bytes) OVERRIDE {
+ return -1;
+ }
+ virtual bool StopTrackingSharedMemoryHandle(int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) OVERRIDE {
+ return false;
+ }
};
// Implementation of PpapiGlobals for tests that don't need either the host- or
diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h
index d5e33d5..50c13b9 100644
--- a/ppapi/shared_impl/var.h
+++ b/ppapi/shared_impl/var.h
@@ -9,7 +9,10 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/platform_file.h"
+#include "base/shared_memory.h"
#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace ppapi {
@@ -160,6 +163,18 @@ class PPAPI_SHARED_EXPORT ArrayBufferVar : public Var {
virtual void Unmap() = 0;
virtual uint32 ByteLength() = 0;
+ // Creates a new shared memory region, and copies the data in the
+ // ArrayBufferVar into it. On the plugin side, host_shm_handle_id will be set
+ // to some value that is not -1. On the host side, plugin_shm_handle will be
+ // set to a valid SharedMemoryHandle.
+ //
+ // Returns true if creating the shared memory (and copying) is successful,
+ // false otherwise.
+ virtual bool CopyToNewShmem(
+ PP_Instance instance,
+ int *host_shm_handle_id,
+ base::SharedMemoryHandle *plugin_shm_handle) = 0;
+
// Var override.
virtual ArrayBufferVar* AsArrayBufferVar() OVERRIDE;
virtual PP_VarType GetType() const OVERRIDE;
diff --git a/ppapi/shared_impl/var_tracker.cc b/ppapi/shared_impl/var_tracker.cc
index a704c3a..434121e 100644
--- a/ppapi/shared_impl/var_tracker.cc
+++ b/ppapi/shared_impl/var_tracker.cc
@@ -9,6 +9,8 @@
#include <limits>
#include "base/logging.h"
+#include "base/shared_memory.h"
+#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/id_assignment.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/var.h"
@@ -216,6 +218,17 @@ ArrayBufferVar* VarTracker::MakeArrayBufferVar(uint32 size_in_bytes,
return array_buffer;
}
+PP_Var VarTracker::MakeArrayBufferPPVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) {
+ DCHECK(CalledOnValidThread());
+
+ scoped_refptr<ArrayBufferVar> array_buffer(
+ CreateShmArrayBuffer(size_in_bytes, handle));
+ if (!array_buffer)
+ return PP_MakeNull();
+ return array_buffer->GetPPVar();
+}
+
std::vector<PP_Var> VarTracker::GetLiveVars() {
DCHECK(CalledOnValidThread());
ProxyLock::AssertAcquired();
diff --git a/ppapi/shared_impl/var_tracker.h b/ppapi/shared_impl/var_tracker.h
index 1d0c0d6..32acdeb 100644
--- a/ppapi/shared_impl/var_tracker.h
+++ b/ppapi/shared_impl/var_tracker.h
@@ -10,10 +10,13 @@
#include "base/basictypes.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
+#include "base/shared_memory.h"
#include "base/threading/non_thread_safe.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace ppapi {
@@ -72,6 +75,10 @@ class PPAPI_SHARED_EXPORT VarTracker
PP_Var MakeArrayBufferPPVar(uint32 size_in_bytes);
// Same as above, but copy the contents of |data| in to the new array buffer.
PP_Var MakeArrayBufferPPVar(uint32 size_in_bytes, const void* data);
+ // Same as above, but copy the contents of the shared memory in |h|
+ // into the new array buffer.
+ PP_Var MakeArrayBufferPPVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle h);
// Create an ArrayBuffer and copy the contents of |data| in to it. The
// returned object has 0 reference count in the tracker, and like all
@@ -94,6 +101,22 @@ class PPAPI_SHARED_EXPORT VarTracker
// Called after an instance is deleted to do var cleanup.
virtual void DidDeleteInstance(PP_Instance instance) = 0;
+ // Returns an "id" for a shared memory handle that can be safely sent between
+ // the host and plugin, and resolved back into the original handle on the
+ // host. Not implemented on the plugin side.
+ virtual int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle handle,
+ uint32 size_in_bytes) = 0;
+
+ // Resolves an "id" generated by TrackSharedMemoryHandle back into
+ // a SharedMemory handle and its size on the host.
+ // Not implemented on the plugin side.
+ virtual bool StopTrackingSharedMemoryHandle(
+ int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle *handle,
+ uint32* size_in_bytes) = 0;
+
protected:
struct VarInfo {
VarInfo();
@@ -171,6 +194,9 @@ class PPAPI_SHARED_EXPORT VarTracker
// implemented by the Host and Plugin tracker separately, so that it can be
// a real WebKit ArrayBuffer on the host side.
virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) = 0;
+ virtual ArrayBufferVar* CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) = 0;
DISALLOW_COPY_AND_ASSIGN(VarTracker);
};
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index 68fe633..8b16620 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -261,7 +261,11 @@ std::string TestPostMessage::TestSendingArrayBuffer() {
// TODO(sehr,dmichael): Add testing of longer array buffers when
// crbug.com/110086 is fixed.
- uint32_t sizes[] = { 0, 100, 1000, 10000, 100000 };
+#if defined(OS_LINUX)
+ uint32_t sizes[] = { 0, 100, 1000, 10000, 100000, 1000000 };
+#else
+ uint32_t sizes[] = { 0, 100, 1000, 10000, 100000 };
+#endif
for (size_t i = 0; i < sizeof(sizes)/sizeof(sizes[i]); ++i) {
std::ostringstream size_stream;
size_stream << sizes[i];
diff --git a/webkit/plugins/ppapi/host_array_buffer_var.cc b/webkit/plugins/ppapi/host_array_buffer_var.cc
index c8266df..e3d06a5 100644
--- a/webkit/plugins/ppapi/host_array_buffer_var.cc
+++ b/webkit/plugins/ppapi/host_array_buffer_var.cc
@@ -4,6 +4,17 @@
#include "webkit/plugins/ppapi/host_array_buffer_var.h"
+#include <stdio.h>
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process_util.h"
+#include "ppapi/c/pp_instance.h"
+#include "webkit/plugins/ppapi/host_globals.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
using ppapi::ArrayBufferVar;
using WebKit::WebArrayBuffer;
@@ -11,17 +22,32 @@ namespace webkit {
namespace ppapi {
HostArrayBufferVar::HostArrayBufferVar(uint32 size_in_bytes)
- : buffer_(WebArrayBuffer::create(size_in_bytes, 1 /* element_size */)) {
+ : buffer_(WebArrayBuffer::create(size_in_bytes, 1 /* element_size */)),
+ valid_(true) {
}
HostArrayBufferVar::HostArrayBufferVar(const WebArrayBuffer& buffer)
- : buffer_(buffer) {
+ : buffer_(buffer),
+ valid_(true) {
+}
+
+HostArrayBufferVar::HostArrayBufferVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle handle)
+ : buffer_(WebArrayBuffer::create(size_in_bytes, 1 /* element_size */)) {
+ base::SharedMemory s(handle, true);
+ valid_ = s.Map(size_in_bytes);
+ if (valid_) {
+ memcpy(buffer_.data(), s.memory(), size_in_bytes);
+ s.Unmap();
+ }
}
HostArrayBufferVar::~HostArrayBufferVar() {
}
void* HostArrayBufferVar::Map() {
+ if (!valid_)
+ return NULL;
return buffer_.data();
}
@@ -33,6 +59,45 @@ uint32 HostArrayBufferVar::ByteLength() {
return buffer_.byteLength();
}
+bool HostArrayBufferVar::CopyToNewShmem(
+ PP_Instance instance,
+ int* host_shm_handle_id,
+ base::SharedMemoryHandle* plugin_shm_handle) {
+ webkit::ppapi::PluginInstance* i =
+ webkit::ppapi::HostGlobals::Get()->GetInstance(instance);
+ scoped_ptr<base::SharedMemory> shm(i->delegate()->CreateAnonymousSharedMemory(
+ ByteLength()));
+ if (!shm.get())
+ return false;
+
+ shm->Map(ByteLength());
+ memcpy(shm->memory(), Map(), ByteLength());
+ shm->Unmap();
+
+ // Duplicate the handle here; the SharedMemory destructor closes
+ // its handle on us.
+ HostGlobals* hg = HostGlobals::Get();
+ PluginModule* pm = hg->GetModule(hg->GetModuleForInstance(instance));
+ base::ProcessId p = pm->GetPeerProcessId();
+ if (p == base::kNullProcessId) {
+ // In-process, clone for ourselves.
+ p = base::GetCurrentProcId();
+ }
+
+ base::PlatformFile platform_file =
+#if defined(OS_WIN)
+ shm->handle();
+#elif defined(OS_POSIX)
+ shm->handle().fd;
+#else
+#error Not implemented.
+#endif
+
+ *plugin_shm_handle =
+ i->delegate()->ShareHandleWithRemote(platform_file, p, false);
+ *host_shm_handle_id = -1;
+ return true;
+}
+
} // namespace ppapi
} // namespace webkit
-
diff --git a/webkit/plugins/ppapi/host_array_buffer_var.h b/webkit/plugins/ppapi/host_array_buffer_var.h
index 803069a..646adf8 100644
--- a/webkit/plugins/ppapi/host_array_buffer_var.h
+++ b/webkit/plugins/ppapi/host_array_buffer_var.h
@@ -5,6 +5,9 @@
#ifndef PPAPI_WEBKIT_PLUGINS_PPAPI_HOST_ARRAY_BUFFER_VAR_H_
#define PPAPI_WEBKIT_PLUGINS_PPAPI_HOST_ARRAY_BUFFER_VAR_H_
+#include "base/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/var.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h"
@@ -16,17 +19,25 @@ class HostArrayBufferVar : public ::ppapi::ArrayBufferVar {
public:
explicit HostArrayBufferVar(uint32 size_in_bytes);
explicit HostArrayBufferVar(const WebKit::WebArrayBuffer& buffer);
+ explicit HostArrayBufferVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle handle);
virtual ~HostArrayBufferVar();
// ArrayBufferVar implementation.
virtual void* Map() OVERRIDE;
virtual void Unmap() OVERRIDE;
virtual uint32 ByteLength() OVERRIDE;
+ virtual bool CopyToNewShmem(
+ PP_Instance instance,
+ int* host_shm_handle_id,
+ base::SharedMemoryHandle* plugin_shm_handle) OVERRIDE;
WebKit::WebArrayBuffer& webkit_buffer() { return buffer_; }
private:
WebKit::WebArrayBuffer buffer_;
+ // Tracks whether the data in the buffer is valid.
+ bool valid_;
DISALLOW_COPY_AND_ASSIGN(HostArrayBufferVar);
};
diff --git a/webkit/plugins/ppapi/host_var_tracker.cc b/webkit/plugins/ppapi/host_var_tracker.cc
index adeeaa1..5d53499 100644
--- a/webkit/plugins/ppapi/host_var_tracker.cc
+++ b/webkit/plugins/ppapi/host_var_tracker.cc
@@ -16,7 +16,7 @@ using ppapi::NPObjectVar;
namespace webkit {
namespace ppapi {
-HostVarTracker::HostVarTracker() {
+HostVarTracker::HostVarTracker() : last_shared_memory_map_id_(0) {
}
HostVarTracker::~HostVarTracker() {
@@ -26,6 +26,12 @@ ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
return new HostArrayBufferVar(size_in_bytes);
}
+ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) {
+ return new HostArrayBufferVar(size_in_bytes, handle);
+}
+
void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) {
DCHECK(CalledOnValidThread());
@@ -127,5 +133,39 @@ void HostVarTracker::ForceReleaseNPObject(::ppapi::NPObjectVar* object_var) {
DeleteObjectInfoIfNecessary(iter);
}
+int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle handle,
+ uint32 size_in_bytes) {
+ SharedMemoryMapEntry entry;
+ entry.instance = instance;
+ entry.handle = handle;
+ entry.size_in_bytes = size_in_bytes;
+
+ // Find a free id for our map.
+ while (shared_memory_map_.find(last_shared_memory_map_id_) !=
+ shared_memory_map_.end()) {
+ ++last_shared_memory_map_id_;
+ }
+ shared_memory_map_[last_shared_memory_map_id_] = entry;
+ return last_shared_memory_map_id_;
+}
+
+bool HostVarTracker::StopTrackingSharedMemoryHandle(
+ int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) {
+ SharedMemoryMap::iterator it = shared_memory_map_.find(id);
+ if (it == shared_memory_map_.end())
+ return false;
+ if (it->second.instance != instance)
+ return false;
+
+ *handle = it->second.handle;
+ *size_in_bytes = it->second.size_in_bytes;
+ shared_memory_map_.erase(it);
+ return true;
+}
+
} // namespace ppapi
} // namespace webkit
diff --git a/webkit/plugins/ppapi/host_var_tracker.h b/webkit/plugins/ppapi/host_var_tracker.h
index 7629f9a..138920c 100644
--- a/webkit/plugins/ppapi/host_var_tracker.h
+++ b/webkit/plugins/ppapi/host_var_tracker.h
@@ -14,7 +14,7 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "ppapi/c/pp_instance.h"
-#include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/var_tracker.h"
#include "webkit/plugins/webkit_plugins_export.h"
@@ -58,10 +58,20 @@ class HostVarTracker : public ::ppapi::VarTracker {
// VarTracker public implementation.
virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE;
+ virtual int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle file,
+ uint32 size_in_bytes) OVERRIDE;
+ virtual bool StopTrackingSharedMemoryHandle(int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) OVERRIDE;
+
private:
// VarTracker private implementation.
virtual ::ppapi::ArrayBufferVar* CreateArrayBuffer(
uint32 size_in_bytes) OVERRIDE;
+ virtual ::ppapi::ArrayBufferVar* CreateShmArrayBuffer(
+ uint32 size_in_bytes, base::SharedMemoryHandle handle) OVERRIDE;
// Clear the reference count of the given object and remove it from
// live_vars_.
@@ -81,6 +91,16 @@ class HostVarTracker : public ::ppapi::VarTracker {
InstanceMap;
InstanceMap instance_map_;
+ // Tracks all shared memory handles used for transmitting array buffers.
+ struct SharedMemoryMapEntry {
+ PP_Instance instance;
+ base::SharedMemoryHandle handle;
+ uint32 size_in_bytes;
+ };
+ typedef std::map<int, SharedMemoryMapEntry> SharedMemoryMap;
+ SharedMemoryMap shared_memory_map_;
+ uint32_t last_shared_memory_map_id_;
+
DISALLOW_COPY_AND_ASSIGN(HostVarTracker);
};
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc
index c465618..137c061 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.cc
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc
@@ -382,5 +382,12 @@ int MockPluginDelegate::EnumerateDevices(
void MockPluginDelegate::StopEnumerateDevices(int request_id) {
}
+IPC::PlatformFileForTransit MockPluginDelegate::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId target_process_id,
+ bool should_close_source) const {
+ return IPC::InvalidPlatformFileForTransit();
+}
+
} // namespace ppapi
} // namespace webkit
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h
index 5f47647..b26ad9f 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.h
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.h
@@ -167,6 +167,10 @@ class MockPluginDelegate : public PluginDelegate {
virtual int EnumerateDevices(PP_DeviceType_Dev type,
const EnumerateDevicesCallback& callback);
virtual void StopEnumerateDevices(int request_id);
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId target_process_id,
+ bool should_close_source) const;
};
} // namespace ppapi
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index 164326b..1c861e8 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -17,6 +17,7 @@
#include "base/sync_socket.h"
#include "base/time.h"
#include "googleurl/src/gurl.h"
+#include "ipc/ipc_platform_file.h"
#include "media/video/capture/video_capture.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/dev/pp_video_dev.h"
@@ -650,6 +651,12 @@ class PluginDelegate {
// Stop enumerating devices of the specified |request_id|. The |request_id|
// is the return value of EnumerateDevicesCallback.
virtual void StopEnumerateDevices(int request_id) = 0;
+
+ // Share a given handle with the target process.
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId target_process_id,
+ bool should_close_source) const = 0;
};
} // namespace ppapi