summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 03:22:33 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 03:22:33 +0000
commitc2932f5e2101022f6fe59dabd462ccc328788d4e (patch)
tree0690f2db30f3f1591c8dec15fbd4d0c63c662899 /ppapi/proxy
parent685b7699b2845fd74e601a3a9f74cf3b63c9f38a (diff)
downloadchromium_src-c2932f5e2101022f6fe59dabd462ccc328788d4e.zip
chromium_src-c2932f5e2101022f6fe59dabd462ccc328788d4e.tar.gz
chromium_src-c2932f5e2101022f6fe59dabd462ccc328788d4e.tar.bz2
Core PPAPI proxy files. This includes the dispatcher which is the control point
on each end of the IPC channel. It includes the IPC message definitions. It also includes the base class for the interface proxying, and the core resource and var tracking. BUG=none TEST=none Review=http://codereview.chromium.org/4229002/show git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64874 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/callback_tracker.cc72
-rw-r--r--ppapi/proxy/callback_tracker.h66
-rw-r--r--ppapi/proxy/dispatcher.cc215
-rw-r--r--ppapi/proxy/dispatcher.h187
-rw-r--r--ppapi/proxy/host_dispatcher.cc63
-rw-r--r--ppapi/proxy/host_dispatcher.h61
-rw-r--r--ppapi/proxy/interface_id.h33
-rw-r--r--ppapi/proxy/interface_proxy.cc36
-rw-r--r--ppapi/proxy/interface_proxy.h77
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc88
-rw-r--r--ppapi/proxy/plugin_dispatcher.h76
-rw-r--r--ppapi/proxy/plugin_resource.cc17
-rw-r--r--ppapi/proxy/plugin_resource.h64
-rw-r--r--ppapi/proxy/plugin_resource_tracker.cc87
-rw-r--r--ppapi/proxy/plugin_resource_tracker.h62
-rw-r--r--ppapi/proxy/ppapi_messages.cc13
-rw-r--r--ppapi/proxy/ppapi_messages.h22
-rw-r--r--ppapi/proxy/ppapi_messages_internal.h321
-rw-r--r--ppapi/proxy/ppapi_param_traits.cc190
-rw-r--r--ppapi/proxy/ppapi_param_traits.h86
-rw-r--r--ppapi/proxy/serialized_var.cc457
21 files changed, 2293 insertions, 0 deletions
diff --git a/ppapi/proxy/callback_tracker.cc b/ppapi/proxy/callback_tracker.cc
new file mode 100644
index 0000000..9806497
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 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/proxy/callback_tracker.h"
+
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+struct CallbackData {
+ CallbackTracker* tracker;
+ uint32_t callback_id;
+};
+
+void CallbackProxy(void* user_data, int32_t result) {
+ CallbackData* data = static_cast<CallbackData*>(user_data);
+ data->tracker->SendExecuteSerializedCallback(data->callback_id, result);
+ delete data;
+}
+
+} // namespace
+
+CallbackTracker::CallbackTracker(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher),
+ next_callback_id_(1) {
+}
+
+CallbackTracker::~CallbackTracker() {
+}
+
+uint32_t CallbackTracker::SendCallback(PP_CompletionCallback callback) {
+ // Find the next callback ID we can use (being careful about wraparound).
+ while (callback_map_.find(next_callback_id_) != callback_map_.end())
+ next_callback_id_++;
+ callback_map_[next_callback_id_] = callback;
+ return next_callback_id_++;
+}
+
+PP_CompletionCallback CallbackTracker::ReceiveCallback(
+ uint32_t serialized_callback) {
+ CallbackData* data = new CallbackData;
+ data->tracker = this;
+ data->callback_id = serialized_callback;
+ return PP_MakeCompletionCallback(&CallbackProxy, data);
+}
+
+void CallbackTracker::SendExecuteSerializedCallback(
+ uint32_t serialized_callback,
+ int32_t param) {
+ dispatcher_->Send(new PpapiMsg_ExecuteCallback(serialized_callback, param));
+}
+
+void CallbackTracker::ReceiveExecuteSerializedCallback(
+ uint32_t serialized_callback,
+ int32_t param) {
+ CallbackMap::iterator found = callback_map_.find(serialized_callback);
+ if (found == callback_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ PP_RunCompletionCallback(&found->second, param);
+ callback_map_.erase(found);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/callback_tracker.h b/ppapi/proxy/callback_tracker.h
new file mode 100644
index 0000000..5f8233c1
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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_PROXY_CALLBACK_TRACKER_H_
+#define PPAPI_PROXY_CALLBACK_TRACKER_H_
+
+#include <map>
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_stdint.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+// This object tracks cross-process callbacks. When the plugin sends a callback
+// object to the renderer, we save the information and pass an identifier
+// instead.
+//
+// On the renderer side, this identifier is converted to a new callback in that
+// process. When executed, this new callback sends an IPC message containing the
+// previous identifier back to the plugin.
+//
+// When we receive that message, ExecuteSerializedCallback converts the
+// identifier back to the original callback information and runs the callback.
+class CallbackTracker {
+ public:
+ CallbackTracker(Dispatcher* dispatcher);
+ ~CallbackTracker();
+
+ // Converts the given callback in the context of the plugin to a serialized
+ // ID. This will be passed to ReceiveCallback on the renderer side.
+ uint32_t SendCallback(PP_CompletionCallback callback);
+
+ // Converts the given serialized callback ID to a new completion callback in
+ // the context of the current process. This callback actually will represent
+ // a proxy that will execute the callback in the plugin process.
+ PP_CompletionCallback ReceiveCallback(uint32_t serialized_callback);
+
+ // Sends a request to the remote process to execute the given callback.
+ void SendExecuteSerializedCallback(uint32_t serialized_callback,
+ int32_t param);
+
+ // Executes the given callback ID with the given result in the current
+ // process. This will also destroy the information associated with the
+ // callback and the serialized ID won't be valid any more.
+ void ReceiveExecuteSerializedCallback(uint32_t serialized_callback,
+ int32_t param);
+
+ private:
+ // Pointer to the dispatcher that owns us.
+ Dispatcher* dispatcher_;
+
+ int32_t next_callback_id_;
+
+ // Maps callback IDs to the actual callback objects in the plugin process.
+ typedef std::map<int32_t, PP_CompletionCallback> CallbackMap;
+ CallbackMap callback_map_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_CALLBACK_TRACKER_H_
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
new file mode 100644
index 0000000..e2c6f1e
--- /dev/null
+++ b/ppapi/proxy/dispatcher.cc
@@ -0,0 +1,215 @@
+// Copyright (c) 2010 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/proxy/dispatcher.h"
+
+#include <string.h> // For memset.
+
+#include <map>
+
+#include "base/logging.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/ppb_core_proxy.h"
+#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_instance_proxy.h"
+#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/ppp_instance_proxy.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+Dispatcher::Dispatcher(GetInterfaceFunc local_get_interface)
+ : pp_module_(0),
+ disallow_trusted_interfaces_(true),
+ local_get_interface_(local_get_interface),
+ declared_supported_remote_interfaces_(false),
+ callback_tracker_(this) {
+ memset(id_to_proxy_, 0,
+ static_cast<int>(INTERFACE_ID_COUNT) * sizeof(InterfaceProxy*));
+}
+
+Dispatcher::~Dispatcher() {
+}
+
+bool Dispatcher::InitWithChannel(MessageLoop* ipc_message_loop,
+ const std::string& channel_name,
+ bool is_client,
+ base::WaitableEvent* shutdown_event) {
+ IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT
+ : IPC::Channel::MODE_SERVER;
+ channel_.reset(new IPC::SyncChannel(channel_name, mode, this, NULL,
+ ipc_message_loop, false, shutdown_event));
+ return true;
+}
+
+void Dispatcher::OnMessageReceived(const IPC::Message& msg) {
+ // Control messages.
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ IPC_BEGIN_MESSAGE_MAP(Dispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_DeclareInterfaces,
+ OnMsgDeclareInterfaces)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
+ IPC_MESSAGE_FORWARD(PpapiMsg_ExecuteCallback, &callback_tracker_,
+ CallbackTracker::ReceiveExecuteSerializedCallback)
+ IPC_END_MESSAGE_MAP()
+ return;
+ }
+
+ // Interface-specific messages.
+ if (msg.routing_id() > 0 && msg.routing_id() < INTERFACE_ID_COUNT) {
+ InterfaceProxy* proxy = id_to_proxy_[msg.routing_id()];
+ if (proxy)
+ proxy->OnMessageReceived(msg);
+ else
+ NOTREACHED();
+ // TODO(brettw): kill the plugin if it starts sending invalid messages?
+ }
+}
+
+void Dispatcher::SetSerializationRules(
+ VarSerializationRules* var_serialization_rules) {
+ serialization_rules_.reset(var_serialization_rules);
+}
+
+void Dispatcher::InjectProxy(InterfaceID id,
+ const std::string& name,
+ InterfaceProxy* proxy) {
+ proxies_[name] = linked_ptr<InterfaceProxy>(proxy);
+ id_to_proxy_[id] = proxy;
+}
+
+const void* Dispatcher::GetLocalInterface(const char* interface) {
+ return local_get_interface_(interface);
+}
+
+const void* Dispatcher::GetProxiedInterface(const std::string& interface) {
+ // See if we already know about this interface and have created a host.
+ ProxyMap::const_iterator found = proxies_.find(interface);
+ if (found != proxies_.end())
+ return found->second->GetSourceInterface();
+
+ // When the remote side has sent us a declared list of all interfaces it
+ // supports and we don't have it in our list, we know the requested interface
+ // doesn't exist and we can return failure.
+ if (declared_supported_remote_interfaces_)
+ return NULL;
+
+ if (!RemoteSupportsTargetInterface(interface))
+ return NULL;
+
+ linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interface, NULL));
+ if (!proxy.get())
+ return NULL; // Don't know how to proxy this interface.
+
+ // Save our proxy.
+ proxies_[interface] = proxy;
+ id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
+ return proxy->GetSourceInterface();
+}
+
+bool Dispatcher::Send(IPC::Message* msg) {
+ return channel_->Send(msg);
+}
+
+bool Dispatcher::RemoteSupportsTargetInterface(const std::string& interface) {
+ bool result = false;
+ Send(new PpapiMsg_SupportsInterface(interface, &result));
+ return result;
+}
+
+bool Dispatcher::IsInterfaceTrusted(const std::string& interface) {
+ // FIXME(brettw)
+ (void)interface;
+ return false;
+}
+
+bool Dispatcher::SetupProxyForTargetInterface(const std::string& interface) {
+ // If we already have a proxy that knows about the locally-implemented
+ // interface, we know it's supported and don't need to re-query.
+ ProxyMap::const_iterator found = proxies_.find(interface);
+ if (found != proxies_.end())
+ return true;
+
+ if (disallow_trusted_interfaces_ && IsInterfaceTrusted(interface))
+ return false;
+
+ // Create the proxy if it doesn't exist and set the local interface on it.
+ // This also handles the case where possibly an interface could be supported
+ // by both the local and remote side.
+ const void* interface_functions = local_get_interface_(interface.c_str());
+ if (!interface_functions)
+ return false;
+ InterfaceProxy* proxy = CreateProxyForInterface(interface,
+ interface_functions);
+ if (!proxy)
+ return false;
+
+ proxies_[interface] = linked_ptr<InterfaceProxy>(proxy);
+ id_to_proxy_[proxy->GetInterfaceId()] = proxy;
+ return true;
+}
+
+void Dispatcher::OnMsgSupportsInterface(const std::string& interface_name,
+ bool* result) {
+ *result = SetupProxyForTargetInterface(interface_name);
+}
+
+void Dispatcher::OnMsgDeclareInterfaces(
+ const std::vector<std::string>& interfaces) {
+ // Make proxies for all the interfaces it supports that we also support.
+ for (size_t i = 0; i < interfaces.size(); i++) {
+ // Possibly the plugin could request an interface before the "declare"
+ // message is received, so we could already have an entry for this
+ // interface. In this case, we can just skip to the next one.
+ if (proxies_.find(interfaces[i]) != proxies_.end())
+ continue;
+
+ linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interfaces[i],
+ NULL));
+ if (!proxy.get()) {
+ // Since only the browser declares supported interfaces, we should never
+ // get one we don't support.
+ //NOTREACHED() << "Remote side declaring an unsupported proxy.";
+ continue;
+ }
+ proxies_[interfaces[i]] = proxy;
+ id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
+ }
+}
+
+InterfaceProxy* Dispatcher::CreateProxyForInterface(
+ const std::string& interface_name,
+ const void* interface_functions) {
+ if (interface_name == PPB_CORE_INTERFACE)
+ return new PPB_Core_Proxy(this, interface_functions);
+ if (interface_name == PPB_GRAPHICS_2D_INTERFACE)
+ return new PPB_Graphics2D_Proxy(this, interface_functions);
+ if (interface_name == PPB_IMAGEDATA_INTERFACE)
+ return new PPB_ImageData_Proxy(this, interface_functions);
+ if (interface_name == PPB_INSTANCE_INTERFACE)
+ return new PPB_Instance_Proxy(this, interface_functions);
+ if (interface_name == PPB_VAR_DEPRECATED_INTERFACE)
+ return new PPB_Var_Deprecated_Proxy(this, interface_functions);
+ if (interface_name == PPP_INSTANCE_INTERFACE)
+ return new PPP_Instance_Proxy(this, interface_functions);
+
+ return NULL;
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
new file mode 100644
index 0000000..412b2d8
--- /dev/null
+++ b/ppapi/proxy/dispatcher.h
@@ -0,0 +1,187 @@
+// Copyright (c) 2010 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_PROXY_DISPATCHER_H_
+#define PPAPI_PROXY_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/callback_tracker.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+class MessageLoop;
+struct PPB_Var_Deprecated;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+class SyncChannel;
+}
+
+namespace pp {
+namespace proxy {
+
+class InterfaceProxy;
+class VarSerializationRules;
+
+// An interface proxy can represent either end of a cross-process interface
+// call. The "source" side is where the call is invoked, and the "target" side
+// is where the call ends up being executed.
+//
+// Plugin side | Browser side
+// -------------------------------------|--------------------------------------
+// |
+// "Source" | "Target"
+// InterfaceProxy ----------------------> InterfaceProxy
+// |
+// |
+// "Target" | "Source"
+// InterfaceProxy <---------------------- InterfaceProxy
+// |
+class Dispatcher : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ typedef const void* (*GetInterfaceFunc)(const char*);
+ typedef const int32_t (*InitModuleFunc)(PP_Module, GetInterfaceFunc);
+ typedef const void (*ShutdownModuleFunc)();
+
+ ~Dispatcher();
+
+ bool InitWithChannel(MessageLoop* ipc_message_loop,
+ const std::string& channel_name,
+ bool is_client,
+ base::WaitableEvent* shutdown_event);
+
+ // Returns true if the dispatcher is on the plugin side, or false if it's the
+ // browser side.
+ virtual bool IsPlugin() const = 0;
+
+ VarSerializationRules* serialization_rules() const {
+ return serialization_rules_.get();
+ }
+ PP_Module pp_module() const {
+ return pp_module_;
+ }
+
+ // Wrapper for calling the local GetInterface function.
+ const void* GetLocalInterface(const char* interface);
+
+ // Implements PPP_GetInterface and PPB_GetInterface on the "source" side. It
+ // will check if the remote side supports this interface as a target, and
+ // create a proxy if it does. A local implementation of that interface backed
+ // by the proxy will be returned on success. If the interface is unproxyable
+ // or not supported by the remote side, returns NULL.
+ const void* GetProxiedInterface(const std::string& interface);
+
+ // Called if the remote side is declaring to us which interfaces it supports
+ // so we don't have to query for each one. We'll pre-create proxies for
+ // each of the given interfaces.
+
+ // IPC::Message::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ IPC::SyncChannel* channel() const {
+ return channel_.get();
+ }
+
+ CallbackTracker& callback_tracker() {
+ return callback_tracker_;
+ }
+
+ protected:
+ Dispatcher(GetInterfaceFunc local_get_interface);
+
+ // Setter for the derived classes to set the appropriate var serialization.
+ // Takes ownership of the given pointer, which must be on the heap.
+ void SetSerializationRules(VarSerializationRules* var_serialization_rules);
+
+ void set_pp_module(PP_Module module) {
+ pp_module_ = module;
+ }
+
+ // Allows the PluginDispatcher to add a magic proxy for PPP_Class, bypassing
+ // the normal "do you support this proxy" stuff and the big lookup of
+ // name to proxy object. Takes ownership of the pointer.
+ void InjectProxy(InterfaceID id,
+ const std::string& name,
+ InterfaceProxy* proxy);
+
+ private:
+ typedef std::map< std::string, linked_ptr<InterfaceProxy> > ProxyMap;
+
+ // Message handlers
+ void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
+ void OnMsgDeclareInterfaces(const std::vector<std::string>& interfaces);
+
+ // Allocates a new proxy on the heap corresponding to the given interface
+ // name, or returns NULL if that interface name isn't known proxyable. The
+ // caller owns the returned pointer.
+ //
+ // The interface_functions gives the pointer to the local interfece when this
+ // is a target proxy. When creating a source proxy, set this to NULL.
+ InterfaceProxy* CreateProxyForInterface(
+ const std::string& interface_name,
+ const void* interface_functions);
+
+ // Returns true if the remote side supports the given interface as the
+ // target of an IPC call.
+ bool RemoteSupportsTargetInterface(const std::string& interface);
+
+ // Sets up a proxy as the target for the given interface, if it is supported.
+ // Returns true if this process implements the given interface and it is
+ // proxyable.
+ bool SetupProxyForTargetInterface(const std::string& interface);
+
+ bool IsInterfaceTrusted(const std::string& interface);
+
+ // Set by the derived classed to indicate the module ID corresponding to
+ // this dispatcher.
+ PP_Module pp_module_;
+
+ scoped_ptr<IPC::SyncChannel> channel_;
+
+ bool disallow_trusted_interfaces_;
+
+ GetInterfaceFunc local_get_interface_;
+
+ ProxyMap proxies_;
+ InterfaceProxy* id_to_proxy_[INTERFACE_ID_COUNT];
+
+ // True if the remote side has declared which interfaces it supports in
+ // advance. When set, it means if we don't already have a source proxy for
+ // the requested interface, that the remote side doesn't support it and
+ // we don't need to query.
+ //
+ // This is just an optimization. The browser has a fixed set of interfaces
+ // it supports, and the many plugins will end up querying many of them. By
+ // having the browser just send all of those interfaces in one message, we
+ // can avoid a bunch of IPC chatter to set up each interface.
+ bool declared_supported_remote_interfaces_;
+
+ CallbackTracker callback_tracker_;
+
+ scoped_ptr<VarSerializationRules> serialization_rules_;
+
+ DISALLOW_COPY_AND_ASSIGN(Dispatcher);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_DISPATCHER_H_
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
new file mode 100644
index 0000000..bb70796
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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/proxy/host_dispatcher.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ppapi/proxy/host_var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap;
+InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
+
+} // namespace
+
+HostDispatcher::HostDispatcher(const PPB_Var_Deprecated* var_interface,
+ PP_Module module,
+ GetInterfaceFunc local_get_interface)
+ : Dispatcher(local_get_interface) {
+ SetSerializationRules(new HostVarSerializationRules(var_interface, module));
+}
+
+HostDispatcher::~HostDispatcher() {
+}
+
+// static
+HostDispatcher* HostDispatcher::GetForInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ return NULL;
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found == g_instance_to_dispatcher->end())
+ return NULL;
+ return found->second;
+}
+
+// static
+void HostDispatcher::SetForInstance(PP_Instance instance,
+ HostDispatcher* dispatcher) {
+ if (!g_instance_to_dispatcher)
+ g_instance_to_dispatcher = new InstanceToDispatcherMap;
+ (*g_instance_to_dispatcher)[instance] = dispatcher;
+}
+
+// static
+void HostDispatcher::RemoveForInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ return;
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found != g_instance_to_dispatcher->end())
+ g_instance_to_dispatcher->erase(found);
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
new file mode 100644
index 0000000..94d45d2
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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_PROXY_HOST_DISPATCHER_H_
+#define PPAPI_PROXY_HOST_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+struct PPB_Var_Deprecated;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+class SyncChannel;
+}
+
+namespace pp {
+namespace proxy {
+
+class InterfaceProxy;
+class VarSerialization;
+
+class HostDispatcher : public Dispatcher {
+ public:
+ // Constructor for the renderer side.
+ //
+ // You must call Dispatcher::InitWithChannel after the constructor.
+ HostDispatcher(const PPB_Var_Deprecated* var_interface,
+ PP_Module module,
+ GetInterfaceFunc local_get_interface);
+ ~HostDispatcher();
+
+ // The host side maintains a mapping from PP_Instance to Dispatcher so
+ // that we can send the messages to the right channel.
+ static HostDispatcher* GetForInstance(PP_Instance instance);
+ static void SetForInstance(PP_Instance instance,
+ HostDispatcher* dispatcher);
+ static void RemoveForInstance(PP_Instance instance);
+
+ // Dispatcher overrides.
+ virtual bool IsPlugin() const { return false; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostDispatcher);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_HOST_DISPATCHER_H_
diff --git a/ppapi/proxy/interface_id.h b/ppapi/proxy/interface_id.h
new file mode 100644
index 0000000..8f5ad9b
--- /dev/null
+++ b/ppapi/proxy/interface_id.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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_PROXY_INTERFACE_ID_H_
+#define PPAPI_PROXY_INTERFACE_ID_H_
+
+namespace pp {
+namespace proxy {
+
+// These numbers must be all small integers. They are used in a lookup table
+// to route messages to the appropriate message handler.
+enum InterfaceID {
+ // Zero is reserved for control messages.
+ INTERFACE_ID_PPB_CORE = 1,
+ INTERFACE_ID_PPB_GRAPHICS_2D,
+ INTERFACE_ID_PPB_IMAGE_DATA,
+ INTERFACE_ID_PPB_INSTANCE,
+ INTERFACE_ID_PPB_URL_LOADER,
+ INTERFACE_ID_PPB_VAR,
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+
+ INTERFACE_ID_PPP_CLASS,
+ INTERFACE_ID_PPP_INSTANCE,
+
+ // Must be last to indicate the number of interface IDs.
+ INTERFACE_ID_COUNT
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_INTERFACE_ID_H_
diff --git a/ppapi/proxy/interface_proxy.cc b/ppapi/proxy/interface_proxy.cc
new file mode 100644
index 0000000..7561d5e
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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/proxy/interface_proxy.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/dispatcher.h"
+
+namespace pp {
+namespace proxy {
+
+InterfaceProxy::InterfaceProxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : dispatcher_(dispatcher),
+ target_interface_(target_interface) {
+}
+
+InterfaceProxy::~InterfaceProxy() {
+}
+
+bool InterfaceProxy::Send(IPC::Message* msg) {
+ return dispatcher_->Send(msg);
+}
+
+uint32 InterfaceProxy::SendCallback(PP_CompletionCallback callback) {
+ return dispatcher_->callback_tracker().SendCallback(callback);
+}
+
+PP_CompletionCallback InterfaceProxy::ReceiveCallback(
+ uint32 serialized_callback) {
+ return dispatcher_->callback_tracker().ReceiveCallback(serialized_callback);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/interface_proxy.h b/ppapi/proxy/interface_proxy.h
new file mode 100644
index 0000000..538ebf5
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2010 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_PROXY_INTERFACE_PROXY_H_
+#define PPAPI_PROXY_INTERFACE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_id.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+class InterfaceProxy : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ // Creates the given interface associated with the given dispatcher. The
+ // dispatcher manages our lifetime.
+ //
+ // The target interface pointer, when non-NULL, indicates that this is a
+ // target proxy (see dispatcher.h for a definition). In this case, the proxy
+ // will interpret this pointer to the actual implementation of the interface
+ // in the local process.
+ //
+ // If the target interface is NULL, this proxy will be a "source" interface.
+ InterfaceProxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~InterfaceProxy();
+
+ // See dispatcher.h for definitions of source and target.
+ bool is_source_proxy() const { return !target_interface_; }
+ bool is_target_proxy() const { return !!target_interface_; }
+
+ // When this proxy is the "target" of the IPC communication (see
+ // dispatcher.h), this target_interface pointer will indicate the local
+ // side's interface pointer. This contains the functions that actually
+ // implement the proxied interface.
+ //
+ // This will be NULL when this proxy is a source proxy.
+ const void* target_interface() const { return target_interface_; }
+
+ Dispatcher* dispatcher() { return dispatcher_; }
+
+ // IPC::Message::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // Returns the local implementation of the interface that will proxy it to
+ // the remote side. This is used on the source side only (see dispatcher.h).
+ virtual const void* GetSourceInterface() const = 0;
+
+ // Returns the interface ID associated with this proxy. Implemented by each
+ // derived class to identify itself.
+ virtual InterfaceID GetInterfaceId() const = 0;
+
+ // Sub-classes must implement IPC::Channel::Listener which contains this:
+ //virtual void OnMessageReceived(const IPC::Message& msg);
+
+ protected:
+ uint32 SendCallback(PP_CompletionCallback callback);
+ PP_CompletionCallback ReceiveCallback(uint32 serialized_callback);
+
+ private:
+ Dispatcher* dispatcher_;
+ const void* target_interface_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_INTERFACE_PROXY_H_
+
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
new file mode 100644
index 0000000..1997dc4
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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/proxy/plugin_dispatcher.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_var_serialization_rules.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PluginDispatcher* g_dispatcher = NULL;
+
+const void* GetInterfaceFromDispatcher(const char* interface) {
+ // TODO(brettw) need some kind of lock for multi-thread access.
+ return pp::proxy::PluginDispatcher::Get()->GetProxiedInterface(interface);
+}
+
+} // namespace
+
+PluginDispatcher::PluginDispatcher(GetInterfaceFunc get_interface,
+ InitModuleFunc init_module,
+ ShutdownModuleFunc shutdown_module)
+ : Dispatcher(get_interface),
+ init_module_(init_module),
+ shutdown_module_(shutdown_module),
+ plugin_resource_tracker_(new PluginResourceTracker(this)),
+ plugin_var_tracker_(new PluginVarTracker(this)) {
+ SetSerializationRules(
+ new PluginVarSerializationRules(plugin_var_tracker_.get()));
+
+ // As a plugin, we always support the PPP_Class interface. There's no
+ // GetInterface call or name for it, so we insert it into our table now.
+ InjectProxy(INTERFACE_ID_PPP_CLASS, "$Internal_PPP_Class",
+ new PPP_Class_Proxy(this));
+}
+
+PluginDispatcher::~PluginDispatcher() {
+ if (shutdown_module_)
+ shutdown_module_();
+}
+
+// static
+PluginDispatcher* PluginDispatcher::Get() {
+ return g_dispatcher;
+}
+
+// static
+void PluginDispatcher::SetGlobal(PluginDispatcher* dispatcher) {
+ DCHECK(!dispatcher || !g_dispatcher);
+ g_dispatcher = dispatcher;
+}
+
+void PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ // Handle some plugin-specific control messages.
+ IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_InitializeModule, OnInitializeModule)
+
+ // Forward all other control messages to the superclass.
+ IPC_MESSAGE_UNHANDLED(Dispatcher::OnMessageReceived(msg))
+ IPC_END_MESSAGE_MAP()
+ return;
+ }
+
+ // All non-control messages get handled by the superclass.
+ Dispatcher::OnMessageReceived(msg);
+}
+
+void PluginDispatcher::OnInitializeModule(PP_Module pp_module, bool* result) {
+ set_pp_module(pp_module);
+ *result = init_module_(pp_module, &GetInterfaceFromDispatcher) == PP_OK;
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
new file mode 100644
index 0000000..0a97965
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_DISPATCHER_H_
+#define PPAPI_PROXY_PLUGIN_DISPATCHER_H_
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "ppapi/proxy/callback_tracker.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+class MessageLoop;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher : public Dispatcher {
+ public:
+ // Constructor for the plugin side. The init and shutdown functions will be
+ // will be automatically called when requested by the renderer side. The
+ // module ID will be set upon receipt of the InitializeModule message.
+ //
+ // You must call Dispatcher::InitWithChannel after the constructor.
+ PluginDispatcher(GetInterfaceFunc get_interface,
+ InitModuleFunc init_module,
+ ShutdownModuleFunc shutdown_module);
+ ~PluginDispatcher();
+
+ // The plugin maintains a global Dispatcher pointer. There is only one since
+ // there is only one connection to the browser. Don't call this on the
+ // browser side, see GetForInstnace.
+ static PluginDispatcher* Get();
+ static void SetGlobal(PluginDispatcher* dispatcher);
+
+ // Dispatcher overrides.
+ virtual bool IsPlugin() const { return true; }
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ // Returns the resource tracker for the plugin. In the browser process this
+ // will return NULL.
+ PluginResourceTracker* plugin_resource_tracker() {
+ return plugin_resource_tracker_.get();
+ }
+
+ // Returns the var tracker for the plugin. In the browser process this
+ // will return NULL.
+ PluginVarTracker* plugin_var_tracker() {
+ return plugin_var_tracker_.get();
+ }
+
+ private:
+ void OnInitializeModule(PP_Module pp_module, bool* result);
+
+ InitModuleFunc init_module_;
+ ShutdownModuleFunc shutdown_module_;
+
+ scoped_ptr<PluginResourceTracker> plugin_resource_tracker_;
+ scoped_ptr<PluginVarTracker> plugin_var_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginDispatcher);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_DISPATCHER_H_
diff --git a/ppapi/proxy/plugin_resource.cc b/ppapi/proxy/plugin_resource.cc
new file mode 100644
index 0000000..b1a579e
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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/proxy/plugin_resource.h"
+
+namespace pp {
+namespace proxy {
+
+PluginResource::PluginResource() {
+}
+
+PluginResource::~PluginResource() {
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
new file mode 100644
index 0000000..9a70266
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_RESOURCE_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+
+// If you inherit from resource, make sure you add the class name here.
+#define FOR_ALL_RESOURCES(F) \
+ F(Graphics2D) \
+ F(ImageData) \
+ F(URLLoader)
+
+namespace pp {
+namespace proxy {
+
+// Forward declaration of Resource classes.
+#define DECLARE_RESOURCE_CLASS(RESOURCE) class RESOURCE;
+FOR_ALL_RESOURCES(DECLARE_RESOURCE_CLASS)
+#undef DECLARE_RESOURCE_CLASS
+
+class PluginResource {
+ public:
+ PluginResource();
+ virtual ~PluginResource();
+
+ // Returns NULL if the resource is invalid or is a different type.
+ template<typename T> static T* GetAs(PP_Resource res) {
+ PluginResource* resource =
+ PluginDispatcher::Get()->plugin_resource_tracker()->GetResourceObject(
+ res);
+ return resource ? resource->Cast<T>() : NULL;
+ }
+
+ template <typename T> T* Cast() { return NULL; }
+
+ private:
+ // Type-specific getters for individual resource types. These will return
+ // NULL if the resource does not match the specified type. Used by the Cast()
+ // function.
+ #define DEFINE_TYPE_GETTER(RESOURCE) \
+ virtual RESOURCE* As##RESOURCE() { return NULL; }
+ FOR_ALL_RESOURCES(DEFINE_TYPE_GETTER)
+ #undef DEFINE_TYPE_GETTER
+
+ DISALLOW_COPY_AND_ASSIGN(PluginResource);
+};
+
+// Cast() specializations.
+#define DEFINE_RESOURCE_CAST(Type) \
+ template <> inline Type* PluginResource::Cast<Type>() { \
+ return As##Type(); \
+ }
+FOR_ALL_RESOURCES(DEFINE_RESOURCE_CAST)
+#undef DEFINE_RESOURCE_CAST
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_H_
diff --git a/ppapi/proxy/plugin_resource_tracker.cc b/ppapi/proxy/plugin_resource_tracker.cc
new file mode 100644
index 0000000..a285311
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 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/proxy/plugin_resource_tracker.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(int rc,
+ linked_ptr<PluginResource> r)
+ : ref_count(rc),
+ resource(r) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other)
+ : ref_count(other.ref_count),
+ resource(other.resource) {
+}
+
+PluginResourceTracker::ResourceInfo::~ResourceInfo() {
+}
+
+PluginResourceTracker::ResourceInfo&
+PluginResourceTracker::ResourceInfo::operator=(
+ const ResourceInfo& other) {
+ ref_count = other.ref_count;
+ resource = other.resource;
+ return *this;
+}
+
+PluginResourceTracker::PluginResourceTracker(PluginDispatcher* dispatcher)
+ : dispatcher_(dispatcher) {
+}
+
+PluginResourceTracker::~PluginResourceTracker() {
+}
+
+PluginResource* PluginResourceTracker::GetResourceObject(
+ PP_Resource pp_resource) {
+ ResourceMap::iterator found = resource_map_.find(pp_resource);
+ if (found == resource_map_.end())
+ return NULL;
+ return found->second.resource.get();
+}
+
+void PluginResourceTracker::AddResource(PP_Resource pp_resource,
+ linked_ptr<PluginResource> object) {
+ DCHECK(resource_map_.find(pp_resource) == resource_map_.end());
+ resource_map_[pp_resource] = ResourceInfo(1, object);
+}
+
+void PluginResourceTracker::AddRefResource(PP_Resource resource) {
+ resource_map_[resource].ref_count++;
+}
+
+void PluginResourceTracker::ReleaseResource(PP_Resource resource) {
+ ReleasePluginResourceRef(resource, true);
+}
+
+void PluginResourceTracker::ReleasePluginResourceRef(
+ const PP_Resource& resource,
+ bool notify_browser_on_release) {
+ ResourceMap::iterator found = resource_map_.find(resource);
+ if (found == resource_map_.end())
+ return;
+ found->second.ref_count--;
+ if (found->second.ref_count == 0) {
+ if (notify_browser_on_release) {
+ dispatcher_->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
+ INTERFACE_ID_PPB_CORE, resource));
+ }
+ resource_map_.erase(found);
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_resource_tracker.h b/ppapi/proxy/plugin_resource_tracker.h
new file mode 100644
index 0000000..a9ea963
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 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_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+
+#include <map>
+
+#include "base/linked_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+class PluginResource;
+
+class PluginResourceTracker {
+ public:
+ PluginResourceTracker(PluginDispatcher* dispatcher);
+ ~PluginResourceTracker();
+
+ // Returns the object associated with the given resource ID, or NULL if
+ // there isn't one.
+ PluginResource* GetResourceObject(PP_Resource pp_resource);
+
+ void AddResource(PP_Resource pp_resource, linked_ptr<PluginResource> object);
+
+ void AddRefResource(PP_Resource resource);
+ void ReleaseResource(PP_Resource resource);
+
+ private:
+ struct ResourceInfo {
+ ResourceInfo();
+ ResourceInfo(int ref_count, linked_ptr<PluginResource> r);
+ ResourceInfo(const ResourceInfo& other);
+ ~ResourceInfo();
+
+ ResourceInfo& operator=(const ResourceInfo& other);
+
+ int ref_count;
+ linked_ptr<PluginResource> resource; // May be NULL.
+ };
+
+ void ReleasePluginResourceRef(const PP_Resource& var,
+ bool notify_browser_on_release);
+
+ // Pointer to the dispatcher that owns us.
+ PluginDispatcher* dispatcher_;
+
+ typedef std::map<PP_Resource, ResourceInfo> ResourceMap;
+ ResourceMap resource_map_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
diff --git a/ppapi/proxy/ppapi_messages.cc b/ppapi/proxy/ppapi_messages.cc
new file mode 100644
index 0000000..1cc617b
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2010 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/proxy/ppapi_messages.h"
+
+#include "base/file_path.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ppapi/c/ppb_var.h"
+
+// This actually defines the implementations of all the IPC message functions.
+#define MESSAGES_INTERNAL_IMPL_FILE "ppapi/proxy/ppapi_messages_internal.h"
+#include "ipc/ipc_message_impl_macros.h"
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
new file mode 100644
index 0000000..89ba4e9
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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_PROXY_PPAPI_MESSAGES_H_
+#define PPAPI_PROXY_PPAPI_MESSAGES_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+
+#define MESSAGES_INTERNAL_FILE "ppapi/proxy/ppapi_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // PPAPI_PROXY_PPAPI_MESSAGES_H_
diff --git a/ppapi/proxy/ppapi_messages_internal.h b/ppapi/proxy/ppapi_messages_internal.h
new file mode 100644
index 0000000..f99f4cc
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages_internal.h
@@ -0,0 +1,321 @@
+// Copyright (c) 2010 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard. It is included by backing_store_messages_internal.h
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// This file needs to be included again, even though we're actually included
+// from it via utility_messages.h.
+#include "ipc/ipc_message_macros.h"
+
+// These are from the plugin to the renderer
+IPC_BEGIN_MESSAGES(Ppapi)
+ // Loads the given plugin.
+ IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin,
+ FilePath /* path */,
+ int /* renderer_id */)
+
+ IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_InitializeModule,
+ PP_Module /* module_id */,
+ bool /* result */)
+
+ // Sent in both directions to see if the other side supports the given
+ // interface.
+ IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_SupportsInterface,
+ std::string /* interface_name */,
+ bool /* result */)
+
+ // Way for the renderer to list all interfaces that is supports in advance to
+ // avoid extra IPC traffic.
+ IPC_MESSAGE_CONTROL1(PpapiMsg_DeclareInterfaces,
+ std::vector<std::string> /* interfaces */)
+
+ IPC_MESSAGE_CONTROL2(PpapiMsg_ExecuteCallback,
+ uint32 /* serialized_callback */,
+ int32 /* param */)
+
+ // PPP_Class.
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasMethod,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* method */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_GetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiMsg_PPPClass_EnumerateProperties,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<pp::proxy::SerializedVar> /* props */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED4_1(PpapiMsg_PPPClass_SetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* name */,
+ pp::proxy::SerializedVar /* value */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPClass_RemoveProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED4_2(PpapiMsg_PPPClass_Call,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* method_name */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_Construct,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_MESSAGE_ROUTED2(PpapiMsg_PPPClass_Deallocate,
+ int64 /* ppp_class */,
+ int64 /* object */)
+
+ // PPP_Instance.
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPInstance_DidCreate,
+ PP_Instance /* instance */,
+ std::vector<std::string> /* argn */,
+ std::vector<std::string> /* argv */,
+ bool /* result */)
+ IPC_MESSAGE_ROUTED1(PpapiMsg_PPPInstance_DidDestroy,
+ PP_Instance /* instance */)
+ IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_DidChangeView,
+ PP_Instance /* instance */,
+ PP_Rect /* position */,
+ PP_Rect /* clip */)
+ IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus,
+ PP_Instance /* instance */,
+ bool /* has_focus */)
+ IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleInputEvent,
+ PP_Instance /* instance */,
+ PP_InputEvent /* event */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleDocumentLoad,
+ PP_Instance /* instance */,
+ PP_Resource /* url_loader */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstance_GetInstanceObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+
+
+ // PPB_URLLoader
+ // (Messages from browser to plugin to notify it of changes in state.)
+ IPC_MESSAGE_ROUTED5(PpapiMsg_PPBURLLoader_UpdateProgress,
+ PP_Resource /* resource */,
+ int64 /* bytes_sent */,
+ int64 /* total_bytes_to_be_sent */,
+ int64 /* bytes_received */,
+ int64 /* total_bytes_to_be_received */)
+IPC_END_MESSAGES(Ppapi)
+
+// -----------------------------------------------------------------------------
+// These are from the plugin to the renderer.
+IPC_BEGIN_MESSAGES(PpapiHost)
+ // Reply to PpapiMsg_LoadPlugin.
+ IPC_MESSAGE_CONTROL1(PpapiHostMsg_PluginLoaded,
+ IPC::ChannelHandle /* handle */)
+
+ // PPB_Core.
+ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_AddRefResource, PP_Resource)
+ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource, PP_Resource)
+ IPC_SYNC_MESSAGE_ROUTED0_1(PpapiHostMsg_PPBCore_GetTime,
+ double /* return value -> time */)
+ IPC_SYNC_MESSAGE_ROUTED0_1(PpapiHostMsg_PPBCore_GetTimeTicks,
+ double /* return value -> time */)
+ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBCore_CallOnMainThread,
+ int /* delay_in_msec */,
+ uint32_t /* serialized_callback */,
+ int32_t /* result */)
+
+ // PPB_Graphics2D.
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics2D_Create,
+ PP_Module /* module */,
+ PP_Size /* size */,
+ bool /* is_always_opaque */,
+ PP_Resource /* result */)
+ IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBGraphics2D_PaintImageData,
+ PP_Resource /* graphics_2d */,
+ PP_Resource /* image_data */,
+ PP_Point /* top_left */,
+ bool /* src_rect_specified */,
+ PP_Rect /* src_rect */)
+ IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics2D_Scroll,
+ PP_Resource /* graphics_2d */,
+ bool /* clip_specified */,
+ PP_Rect /* clip */,
+ PP_Point /* amount */)
+ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics2D_ReplaceContents,
+ PP_Resource /* graphics_2d */,
+ PP_Resource /* image_data */)
+ IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics2D_Flush,
+ PP_Resource /* graphics_2d */,
+ uint32_t /* serialized_callback */,
+ int32_t /* result */)
+
+ // PPB_ImageData.
+ IPC_SYNC_MESSAGE_ROUTED0_1(
+ PpapiHostMsg_PPBImageData_GetNativeImageDataFormat,
+ int32 /* result_format */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(
+ PpapiHostMsg_PPBImageData_IsImageDataFormatSupported,
+ int32 /* format */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_Create,
+ PP_Module /* module */,
+ int32 /* format */,
+ PP_Size /* size */,
+ bool /* init_to_zero */,
+ PP_Resource /* result_resource */,
+ std::string /* image_data_desc */,
+ uint64_t /* result_shm_handle */)
+
+ // PPB_Instance.
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetWindowObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_BindGraphics,
+ PP_Instance /* instance */,
+ PP_Resource /* device */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_IsFullFrame,
+ PP_Instance /* instance */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBInstance_ExecuteScript,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* script */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+
+ // PPB_URLLoader.
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create,
+ PP_Instance /* instance */,
+ PP_Resource /* result */)
+ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_Open,
+ PP_Resource /* loader */,
+ PP_Resource /*request_info */,
+ uint32_t /* serialized_callback */)
+ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FollowRedirect,
+ PP_Resource /* loader */,
+ uint32_t /* serialized_callback */)
+ IPC_SYNC_MESSAGE_ROUTED1_3(PpapiHostMsg_PPBURLLoader_GetUploadProgress,
+ PP_Resource /* loader */,
+ int64 /* bytes_sent */,
+ int64 /* total_bytes_to_be_sent */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_3(PpapiHostMsg_PPBURLLoader_GetDownloadProgress,
+ PP_Resource /* loader */,
+ int64 /* bytes_received */,
+ int64 /* total_bytes_to_be_received */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_GetResponseInfo,
+ PP_Resource /* loader */,
+ PP_Resource /* response_info_out */)
+ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
+ PP_Resource /* loader */,
+ int32_t /* bytes_to_read */,
+ uint32_t /* serialized_callback */)
+ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
+ PP_Resource /* loader */,
+ uint32_t /* serialized_callback */)
+ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_Close,
+ PP_Resource /* loader */)
+
+ // PPB_Var.
+ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVar_AddRefObject,
+ int64 /* object_id */)
+ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVar_ReleaseObject,
+ int64 /* object_id */)
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_ConvertType,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* var */,
+ int /* new_type */,
+ pp::proxy::SerializedVar /* exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBVar_DefineProperty,
+ pp::proxy::SerializedVar /* object */,
+ PP_ObjectProperty /* property */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* method */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_GetProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_DeleteProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBVar_EnumerateProperties,
+ pp::proxy::SerializedVar /* object */,
+ std::vector<pp::proxy::SerializedVar> /* props */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* name */,
+ pp::proxy::SerializedVar /* value */,
+ pp::proxy::SerializedVar /* out_exception */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBVar_IsCallable,
+ pp::proxy::SerializedVar /* object */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED4_2(PpapiHostMsg_PPBVar_Call,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* this_object */,
+ pp::proxy::SerializedVar /* method_name */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_CallDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* method_name */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_Construct,
+ pp::proxy::SerializedVar /* object */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+ IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+ pp::proxy::SerializedVar /* var */,
+ int64 /* object_class */,
+ int64 /* object-data */,
+ bool /* result */)
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+ PP_Module /* module */,
+ int64 /* object_class */,
+ int64 /* object_data */,
+ pp::proxy::SerializedVar /* result */)
+
+IPC_END_MESSAGES(PpapiHost)
+
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
new file mode 100644
index 0000000..4bfe23c
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -0,0 +1,190 @@
+// Copyright (c) 2010 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/proxy/ppapi_param_traits.h"
+
+#include <string.h> // For memcpy
+
+#include "ppapi/proxy/serialized_var.h"
+
+namespace IPC {
+
+// static
+void ParamTraits<PP_InputEvent>::Write(Message* m, const param_type& p) {
+ // PP_InputEvent is just POD so we can just memcpy it.
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(PP_InputEvent));
+}
+
+// static
+bool ParamTraits<PP_InputEvent>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ const char* data;
+ int data_size;
+ if (!m->ReadData(iter, &data, &data_size))
+ return false;
+ memcpy(r, data, sizeof(PP_InputEvent));
+ return true;
+}
+
+// static
+void ParamTraits<PP_InputEvent>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_ObjectProperty -----------------------------------------------------------
+
+// static
+void ParamTraits<PP_ObjectProperty>::Write(Message* m, const param_type& p) {
+ // FIXME(brettw);
+}
+
+// static
+bool ParamTraits<PP_ObjectProperty>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ // FIXME(brettw);
+ return true;
+}
+
+// static
+void ParamTraits<PP_ObjectProperty>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Point --------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Point>::Write(Message* m, const param_type& p) {
+ m->WriteInt(p.x);
+ m->WriteInt(p.y);
+}
+
+// static
+bool ParamTraits<PP_Point>::Read(const Message* m, void** iter, param_type* r) {
+ return m->ReadInt(iter, &r->x) && !m->ReadInt(iter, &r->y);
+}
+
+// static
+void ParamTraits<PP_Point>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Rect ---------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Rect>::Write(Message* m, const param_type& p) {
+ m->WriteInt(p.point.x);
+ m->WriteInt(p.point.y);
+ m->WriteInt(p.size.width);
+ m->WriteInt(p.size.height);
+}
+
+// static
+bool ParamTraits<PP_Rect>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ if (!m->ReadInt(iter, &r->point.x) ||
+ !m->ReadInt(iter, &r->point.y) ||
+ !m->ReadInt(iter, &r->size.width) ||
+ !m->ReadInt(iter, &r->size.height))
+ return false;
+ return true;
+}
+
+// static
+void ParamTraits<PP_Rect>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Size ---------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Size>::Write(Message* m, const param_type& p) {
+ m->WriteInt(p.width);
+ m->WriteInt(p.height);
+}
+
+// static
+bool ParamTraits<PP_Size>::Read(const Message* m, void** iter, param_type* r) {
+ return m->ReadInt(iter, &r->width) && m->ReadInt(iter, &r->height);
+}
+
+// static
+void ParamTraits<PP_Size>::Log(const param_type& p, std::string* l) {
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Write(Message* m,
+ const param_type& p) {
+ p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedVar>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// std::vector<SerializedVar> --------------------------------------------------
+
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Write(
+ Message* m,
+ const param_type& p) {
+ WriteParam(m, static_cast<int>(p.size()));
+ for (size_t i = 0; i < p.size(); i++)
+ WriteParam(m, p[i]);
+}
+
+// static
+bool ParamTraits< std::vector<pp::proxy::SerializedVar> >::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ // This part is just a copy of the the default ParamTraits vector Read().
+ int size;
+ // ReadLength() checks for < 0 itself.
+ if (!m->ReadLength(iter, &size))
+ return false;
+ // Resizing beforehand is not safe, see BUG 1006367 for details.
+ if (INT_MAX / sizeof(pp::proxy::SerializedVar) <= static_cast<size_t>(size))
+ return false;
+
+ // The default vector deserializer does resize here and then we deserialize
+ // into those allocated slots. However, the implementation of vector (at
+ // least in GCC's implementation), creates a new empty object using the
+ // default constructor, and then sets the rest of the items to that empty
+ // one using the copy constructor.
+ //
+ // Since we allocate the inner class when you call the default constructor
+ // and transfer the inner class when you do operator=, the entire vector
+ // will end up referring to the same inner class. Deserializing into this
+ // will just end up overwriting the same item over and over, since all the
+ // SerializedVars will refer to the same thing.
+ //
+ // The solution is to make a new SerializedVar for each deserialized item,
+ // and then add it to the vector one at a time. Our copies are efficient so
+ // this is no big deal.
+ r->reserve(size);
+ for (int i = 0; i < size; i++) {
+ pp::proxy::SerializedVar var;
+ if (!ReadParam(m, iter, &var))
+ return false;
+ r->push_back(var);
+ }
+ return true;
+}
+
+// static
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+
+} // namespace IPC
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
new file mode 100644
index 0000000..e8c17d8
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2010 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_PROXY_PPAPI_PARAM_TRAITS_H_
+#define PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
+
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_input_event.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/serialized_var.h" // TODO(brettw) eraseme.
+
+class PP_ObjectProperty;
+
+namespace pp {
+namespace proxy {
+class SerializedVar;
+}
+}
+
+namespace IPC {
+
+template<>
+struct ParamTraits<PP_InputEvent> {
+ typedef PP_InputEvent param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_ObjectProperty> {
+ typedef PP_ObjectProperty param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Point> {
+ typedef PP_Point param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Rect> {
+ typedef PP_Rect param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_Size> {
+ typedef PP_Size param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<pp::proxy::SerializedVar> {
+ typedef pp::proxy::SerializedVar param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+// We need a special implementation of sending a vector of SerializedVars
+// because the behavior of vector doesn't always play nicely with our
+// weird SerializedVar implementation (see "Read" in the .cc file).
+template<>
+struct ParamTraits< std::vector<pp::proxy::SerializedVar> > {
+ typedef std::vector<pp::proxy::SerializedVar> param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+} // namespace IPC
+
+#endif // PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
new file mode 100644
index 0000000..a76f219
--- /dev/null
+++ b/ppapi/proxy/serialized_var.cc
@@ -0,0 +1,457 @@
+// Copyright (c) 2010 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/proxy/serialized_var.h"
+
+#include "base/logging.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+// SerializedVar::Inner --------------------------------------------------------
+
+SerializedVar::Inner::Inner()
+ : serialization_rules_(NULL),
+ var_(PP_MakeUndefined()),
+ cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
+ : serialization_rules_(serialization_rules),
+ var_(PP_MakeUndefined()),
+ cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules,
+ const PP_Var& var)
+ : serialization_rules_(serialization_rules),
+ var_(var),
+ cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::~Inner() {
+ switch (cleanup_mode_) {
+ case END_SEND_PASS_REF:
+ serialization_rules_->EndSendPassRef(var_);
+ break;
+ case END_RECEIVE_CALLER_OWNED:
+ serialization_rules_->EndReceiveCallerOwned(var_);
+ break;
+ default:
+ break;
+ }
+}
+
+PP_Var SerializedVar::Inner::GetVar() const {
+ DCHECK(serialization_rules_);
+
+ // If we're a string var, we should have already converted the string value
+ // to a var ID.
+ DCHECK(var_.type != PP_VARTYPE_STRING || var_.value.as_id != 0);
+ return var_;
+}
+
+PP_Var SerializedVar::Inner::GetIncompleteVar() const {
+ DCHECK(serialization_rules_);
+ return var_;
+}
+
+void SerializedVar::Inner::SetVar(PP_Var var) {
+ // Sanity check, when updating the var we should have received a
+ // serialization rules pointer already.
+ DCHECK(serialization_rules_);
+ var_ = var;
+}
+
+const std::string& SerializedVar::Inner::GetString() const {
+ DCHECK(serialization_rules_);
+ return string_value_;
+}
+
+std::string* SerializedVar::Inner::GetStringPtr() {
+ DCHECK(serialization_rules_);
+ return &string_value_;
+}
+
+void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
+ // When writing to the IPC messages, a serization rules handler should
+ // always have been set.
+ //
+ // When sending a message, it should be difficult to trigger this if you're
+ // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
+ // Make sure you're using the proper "Send" helper class.
+ //
+ // It should be more common to see this when handling an incoming message
+ // that returns a var. This means the message handler didn't write to the
+ // output parameter, or possibly you used the wrong helper class
+ // (normally SerializedVarReturnValue).
+ DCHECK(serialization_rules_);
+
+#ifndef NDEBUG
+ // We should only be serializing something once.
+ DCHECK(!has_been_serialized_);
+ has_been_serialized_ = true;
+#endif
+
+ // If the var is not a string type, we should not have ended up with any
+ // string data.
+ DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty());
+
+ m->WriteInt(static_cast<int>(var_.type));
+ switch (var_.type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL:
+ // These don't need any data associated with them other than the type we
+ // just serialized.
+ break;
+ case PP_VARTYPE_BOOL:
+ m->WriteBool(var_.value.as_bool);
+ break;
+ case PP_VARTYPE_INT32:
+ m->WriteInt(var_.value.as_int);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ IPC::ParamTraits<double>::Write(m, var_.value.as_double);
+ break;
+ case PP_VARTYPE_STRING:
+ // TODO(brettw) in the case of an invalid string ID, it would be nice
+ // to send something to the other side such that a 0 ID would be
+ // generated there. Then the function implementing the interface can
+ // handle the invalid string as if it was in process rather than seeing
+ // what looks like a valid empty string.
+ m->WriteString(string_value_);
+ break;
+ case PP_VARTYPE_OBJECT:
+ m->WriteInt64(var_.value.as_id);
+ break;
+ }
+}
+
+bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) {
+#ifndef NDEBUG
+ // We should only deserialize something once or will end up with leaked
+ // references.
+ //
+ // One place this has happened in the past is using
+ // std::vector<SerializedVar>.resize(). If you're doing this manually instead
+ // of using the helper classes for handling in/out vectors of vars, be
+ // sure you use the same pattern as the SerializedVarVector classes.
+ 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;
+ if (!m->ReadInt(iter, &type))
+ return false;
+
+ bool success = false;
+ switch (type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL:
+ // These don't have any data associated with them other than the type we
+ // just serialized.
+ success = true;
+ break;
+ case PP_VARTYPE_BOOL:
+ success = m->ReadBool(iter, &var_.value.as_bool);
+ break;
+ case PP_VARTYPE_INT32:
+ success = m->ReadInt(iter, &var_.value.as_int);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double);
+ break;
+ case PP_VARTYPE_STRING:
+ success = m->ReadString(iter, &string_value_);
+ var_.value.as_id = 0;
+ break;
+ case PP_VARTYPE_OBJECT:
+ success = m->ReadInt64(iter, &var_.value.as_id);
+ break;
+ default:
+ // Leave success as false.
+ break;
+ }
+
+ // All success cases get here. We avoid writing the type above so that the
+ // output param is untouched (defaults to VARTYPE_UNDEFINED) even in the
+ // failure case.
+ if (success)
+ var_.type = static_cast<PP_VarType>(type);
+ return success;
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+SerializedVar::SerializedVar() : inner_(new Inner) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
+ : inner_(new Inner(serialization_rules)) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules,
+ const PP_Var& var)
+ : inner_(new Inner(serialization_rules, var)) {
+}
+
+SerializedVar::~SerializedVar() {
+}
+
+// SerializedVarSendInput ------------------------------------------------------
+
+SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
+ const PP_Var& var)
+ : SerializedVar(dispatcher->serialization_rules(), var) {
+ dispatcher->serialization_rules()->SendCallerOwned(var, GetStringPtr());
+}
+
+// static
+void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
+ const PP_Var* input,
+ size_t input_count,
+ std::vector<SerializedVar>* output) {
+ output->resize(input_count);
+ for (size_t i = 0; i < input_count; i++) {
+ (*output)[i] = SerializedVar(dispatcher->serialization_rules(), input[i]);
+ dispatcher->serialization_rules()->SendCallerOwned(input[i],
+ (*output)[i].GetStringPtr());
+ }
+}
+
+// ReceiveSerializedVarReturnValue ---------------------------------------------
+
+ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
+}
+
+PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
+ set_serialization_rules(dispatcher->serialization_rules());
+ SetVar(serialization_rules()->ReceivePassRef(GetIncompleteVar(),
+ GetString()));
+ return GetVar();
+}
+
+// ReceiveSerializedException --------------------------------------------------
+
+ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
+ PP_Var* exception)
+ : SerializedVar(dispatcher->serialization_rules()),
+ exception_(exception) {
+}
+
+ReceiveSerializedException::~ReceiveSerializedException() {
+ if (exception_) {
+ // When an output exception is specified, it will take ownership of the
+ // reference.
+ SetVar(serialization_rules()->ReceivePassRef(GetIncompleteVar(),
+ GetString()));
+ *exception_ = GetVar();
+ } else {
+ // When no output exception is specified, the browser thinks we have a ref
+ // to an object that we don't want (this will happen only in the plugin
+ // since the browser will always specify an out exception for the plugin to
+ // write into).
+ //
+ // Strings don't need this handling since we can just avoid creating a
+ // Var from the std::string in the first place.
+ if (GetVar().type == PP_VARTYPE_OBJECT)
+ serialization_rules()->ReleaseObjectRef(GetVar());
+ }
+}
+
+bool ReceiveSerializedException::IsThrown() const {
+ return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
+}
+
+// ReceiveSerializedVarVectorOutParam ------------------------------------------
+
+ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
+ Dispatcher* dispatcher,
+ uint32_t* output_count,
+ PP_Var** output)
+ : dispatcher_(dispatcher),
+ output_count_(output_count),
+ output_(output) {
+}
+
+ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
+ *output_count_ = static_cast<uint32_t>(vector_.size());
+ if (!vector_.size()) {
+ *output_ = NULL;
+ return;
+ }
+
+ *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
+ for (size_t i = 0; i < vector_.size(); i++) {
+ // Here we just mimic what happens when returning a value.
+ ReceiveSerializedVarReturnValue converted;
+ SerializedVar* serialized = &converted;
+ *serialized = vector_[i];
+ (*output_)[i] = converted.Return(dispatcher_);
+ }
+}
+
+std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
+ return &vector_;
+}
+
+// SerializedVarReceiveInput ---------------------------------------------------
+
+SerializedVarReceiveInput::SerializedVarReceiveInput(
+ const SerializedVar& serialized)
+ : serialized_(serialized),
+ dispatcher_(NULL),
+ var_(PP_MakeUndefined()) {
+}
+
+SerializedVarReceiveInput::~SerializedVarReceiveInput() {
+}
+
+PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
+ serialized_.set_serialization_rules(dispatcher->serialization_rules());
+
+ // Ensure that when the serialized var goes out of scope it cleans up the
+ // stuff we're making in BeginReceiveCallerOwned.
+ serialized_.set_cleanup_mode(SerializedVar::END_RECEIVE_CALLER_OWNED);
+
+ serialized_.SetVar(
+ serialized_.serialization_rules()->BeginReceiveCallerOwned(
+ serialized_.GetIncompleteVar(), serialized_.GetStringPtr()));
+ return serialized_.GetVar();
+}
+
+// SerializedVarVectorReceiveInput ---------------------------------------------
+
+SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
+ const std::vector<SerializedVar>& serialized)
+ : serialized_(serialized) {
+}
+
+SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
+ for (size_t i = 0; i < deserialized_.size(); i++) {
+ serialized_[i].serialization_rules()->EndReceiveCallerOwned(
+ deserialized_[i]);
+ }
+}
+
+PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
+ uint32_t* array_size) {
+ deserialized_.resize(serialized_.size());
+ for (size_t i = 0; i < serialized_.size(); i++) {
+ // The vector must be able to clean themselves up after this call is
+ // torn down.
+ serialized_[i].set_serialization_rules(dispatcher->serialization_rules());
+
+ serialized_[i].SetVar(
+ serialized_[i].serialization_rules()->BeginReceiveCallerOwned(
+ serialized_[i].GetIncompleteVar(), serialized_[i].GetStringPtr()));
+ deserialized_[i] = serialized_[i].GetVar();
+ }
+
+ *array_size = static_cast<uint32_t>(serialized_.size());
+ return deserialized_.size() > 0 ? &deserialized_[0] : NULL;
+}
+
+// SerializedVarReturnValue ----------------------------------------------------
+
+SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
+ : serialized_(serialized) {
+}
+
+void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
+ const PP_Var& var) {
+ serialized_->set_serialization_rules(dispatcher->serialization_rules());
+ serialized_->SetVar(var);
+
+ // Var must clean up after our BeginSendPassRef call.
+ serialized_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
+
+ dispatcher->serialization_rules()->BeginSendPassRef(
+ serialized_->GetIncompleteVar(), serialized_->GetStringPtr());
+}
+
+// SerializedVarOutParam -------------------------------------------------------
+
+SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
+ : serialized_(serialized),
+ writable_var_(PP_MakeUndefined()) {
+}
+
+SerializedVarOutParam::~SerializedVarOutParam() {
+ if (serialized_->serialization_rules()) {
+ // When unset, OutParam wasn't called. We'll just leave the var untouched
+ // in that case.
+ serialized_->SetVar(writable_var_);
+ serialized_->serialization_rules()->BeginSendPassRef(
+ writable_var_, serialized_->GetStringPtr());
+
+ // Normally the current object will be created on the stack to wrap a
+ // SerializedVar and won't have a scope around the actual IPC send. So we
+ // need to tell the SerializedVar to do the begin/end send pass ref calls.
+ serialized_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
+ }
+}
+
+PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
+ serialized_->set_serialization_rules(dispatcher->serialization_rules());
+ return &writable_var_;
+}
+
+// SerializedVarVectorOutParam -------------------------------------------------
+
+SerializedVarVectorOutParam::SerializedVarVectorOutParam(
+ std::vector<SerializedVar>* serialized)
+ : dispatcher_(NULL),
+ serialized_(serialized),
+ count_(0),
+ array_(NULL) {
+}
+
+SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
+ DCHECK(dispatcher_);
+
+ // Convert the array written by the pepper code to the serialized structure.
+ // Note we can't use resize here, we have to allocate a new SerializedVar
+ // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
+ serialized_->reserve(count_);
+ for (uint32_t i = 0; i < count_; i++) {
+ // Just mimic what we do for regular OutParams.
+ SerializedVar var;
+ SerializedVarOutParam out(&var);
+ *out.OutParam(dispatcher_) = array_[i];
+ serialized_->push_back(var);
+ }
+
+ // When returning arrays, the pepper code expects the caller to take
+ // ownership of the array.
+ free(array_);
+}
+
+PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
+ DCHECK(!dispatcher_); // Should only be called once.
+ dispatcher_ = dispatcher;
+ return &array_;
+}
+
+} // namespace proxy
+} // namespace pp
+