summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi')
-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
+