diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 03:10:13 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 03:10:13 +0000 |
commit | 4bcab1c571c6b11a51e4493e3387733a6c95bbac (patch) | |
tree | 49c5a05d14c81b4061eda1a5f07d46d9545b46cb /ppapi | |
parent | 6ed2a5a54b7bb8ccd33da7bc948fee169f128459 (diff) | |
download | chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.zip chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.tar.gz chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.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 URL: http://codereview.chromium.org/4229002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64869 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
47 files changed, 6325 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/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc new file mode 100644 index 0000000..9ca6a15 --- /dev/null +++ b/ppapi/proxy/host_var_serialization_rules.cc @@ -0,0 +1,91 @@ +// 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_var_serialization_rules.h" + +#include "base/logging.h" +#include "ppapi/c/dev/ppb_var_deprecated.h" + +namespace pp { +namespace proxy { + +HostVarSerializationRules::HostVarSerializationRules( + const PPB_Var_Deprecated* var_interface, + PP_Module pp_module) + : var_interface_(var_interface), + pp_module_(pp_module) { +} + +HostVarSerializationRules::~HostVarSerializationRules() { +} + +void HostVarSerializationRules::SendCallerOwned(const PP_Var& var, + std::string* str_val) { + if (var.type == PP_VARTYPE_STRING) + VarToString(var, str_val); +} + +PP_Var HostVarSerializationRules::BeginReceiveCallerOwned( + const PP_Var& var, + const std::string* str_val) { + if (var.type == PP_VARTYPE_STRING) { + // Convert the string to the context of the current process. + return var_interface_->VarFromUtf8(pp_module_, str_val->c_str(), + static_cast<uint32_t>(str_val->size())); + } + return var; +} + +void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { + if (var.type == PP_VARTYPE_STRING) { + // Destroy the string BeginReceiveCallerOwned created above. + var_interface_->Release(var); + } +} + +PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var, + const std::string& str_val) { + if (var.type == PP_VARTYPE_STRING) { + // Convert the string to the context of the current process. + return var_interface_->VarFromUtf8(pp_module_, str_val.c_str(), + static_cast<uint32_t>(str_val.size())); + } + + // See PluginVarSerialization::BeginSendPassRef for an example. + if (var.type == PP_VARTYPE_OBJECT) + var_interface_->AddRef(var); + return var; +} + +void HostVarSerializationRules::BeginSendPassRef(const PP_Var& var, + std::string* str_val) { + // See PluginVarSerialization::ReceivePassRef for an example. We don't need + // to do anything here other than convert the string. + if (var.type == PP_VARTYPE_STRING) + VarToString(var, str_val); +} + +void HostVarSerializationRules::EndSendPassRef(const PP_Var& var) { + // See PluginVarSerialization::ReceivePassRef for an example. We don't need + // to do anything here. +} + +void HostVarSerializationRules::VarToString(const PP_Var& var, + std::string* str) { + DCHECK(var.type == PP_VARTYPE_STRING); + + // This could be optimized to avoid an extra string copy by going to a lower + // level of the browser's implementation of strings where we already have + // a std::string. + uint32_t len = 0; + const char* data = var_interface_->VarToUtf8(var, &len); + str->assign(data, len); +} + +void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { + var_interface_->Release(var); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h new file mode 100644 index 0000000..92e294f --- /dev/null +++ b/ppapi/proxy/host_var_serialization_rules.h @@ -0,0 +1,51 @@ +// 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_VAR_SERIALIZATION_RULES_H_ +#define PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_ + +#include "base/basictypes.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/proxy/var_serialization_rules.h" + +struct PPB_Var_Deprecated; + +namespace pp { +namespace proxy { + +class VarTracker; + +// Implementation of the VarSerializationRules interface for the host side. +class HostVarSerializationRules : public VarSerializationRules { + public: + HostVarSerializationRules(const PPB_Var_Deprecated* var_interface, + PP_Module pp_module); + ~HostVarSerializationRules(); + + // VarSerialization implementation. + virtual void SendCallerOwned(const PP_Var& var, std::string* str_val); + virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, + const std::string* str_val); + virtual void EndReceiveCallerOwned(const PP_Var& var); + virtual PP_Var ReceivePassRef(const PP_Var& var, + const std::string& str_val); + virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val); + virtual void EndSendPassRef(const PP_Var& var); + virtual void ReleaseObjectRef(const PP_Var& var); + + private: + // Converts the given var (which must be a VARTYPE_STRING) to the given + // string object. + void VarToString(const PP_Var& var, std::string* str); + + const PPB_Var_Deprecated* var_interface_; + PP_Module pp_module_; + + DISALLOW_COPY_AND_ASSIGN(HostVarSerializationRules); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_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/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc new file mode 100644 index 0000000..d01f8d5 --- /dev/null +++ b/ppapi/proxy/plugin_var_serialization_rules.cc @@ -0,0 +1,112 @@ +// 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_var_serialization_rules.h" + +#include "ppapi/proxy/plugin_var_tracker.h" + +namespace pp { +namespace proxy { + +PluginVarSerializationRules::PluginVarSerializationRules( + PluginVarTracker* var_tracker) + : var_tracker_(var_tracker) { +} + +PluginVarSerializationRules::~PluginVarSerializationRules() { +} + +void PluginVarSerializationRules::SendCallerOwned(const PP_Var& var, + std::string* str_val) { + // Nothing to do since we manage the refcount, other than retrieve the string + // to use for IPC. + if (var.type == PP_VARTYPE_STRING) + *str_val = var_tracker_->GetString(var); +} + +PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned( + const PP_Var& var, + const std::string* str_val) { + if (var.type == PP_VARTYPE_STRING) { + // Convert the string to the context of the current process. + PP_Var ret; + ret.type = PP_VARTYPE_STRING; + ret.value.as_id = var_tracker_->MakeString(*str_val); + return ret; + } + + return var; +} + +void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { + if (var.type == PP_VARTYPE_STRING) { + // Destroy the string BeginReceiveCallerOwned created above. + var_tracker_->Release(var); + } +} + +PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, + const std::string& str_val) { + if (var.type == PP_VARTYPE_STRING) { + // Convert the string to the context of the current process. + PP_Var ret; + ret.type = PP_VARTYPE_STRING; + ret.value.as_id = var_tracker_->MakeString(str_val); + return ret; + } + + // Overview of sending an object with "pass ref" from the browser to the + // plugin: + // Example 1 Example 2 + // Plugin Browser Plugin Browser + // Before send 3 2 0 1 + // Browser calls BeginSendPassRef 3 2 0 1 + // Plugin calls ReceivePassRef 4 1 1 1 + // Browser calls EndSendPassRef 4 1 1 1 + // + // In example 1 before the send, the plugin has 3 refs which are represented + // as one ref in the browser (since the plugin only tells the browser when + // it's refcount goes from 1 -> 0). The initial state is that the browser + // plugin code started to return a value, which means it gets another ref + // on behalf of the caller. This needs to be transferred to the plugin and + // folded in to its set of refs it maintains (with one ref representing all + // fo them in the browser). + if (var.type == PP_VARTYPE_OBJECT) + var_tracker_->ReceiveObjectPassRef(var); + return var; +} + +void PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var, + std::string* str_val) { + // Overview of sending an object with "pass ref" from the plugin to the + // browser: + // Example 1 Example 2 + // Plugin Browser Plugin Browser + // Before send 3 1 1 1 + // Plugin calls BeginSendPassRef 3 1 1 1 + // Browser calls ReceivePassRef 3 2 1 2 + // Plugin calls EndSendPassRef 2 2 0 1 + // + // The plugin maintains one ref count in the browser on behalf of the + // entire ref count in the plugin. When the plugin refcount goes to 0, it + // will call the browser to deref the object. This is why in example 2 + // transferring the object ref to the browser involves no net change in the + // browser's refcount. + + if (var.type == PP_VARTYPE_STRING) + *str_val = var_tracker_->GetString(var); +} + +void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var) { + // See BeginSendPassRef for an example of why we release our ref here. + if (var.type == PP_VARTYPE_OBJECT) + var_tracker_->Release(var); +} + +void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { + var_tracker_->Release(var); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/plugin_var_serialization_rules.h b/ppapi/proxy/plugin_var_serialization_rules.h new file mode 100644 index 0000000..f2d8224 --- /dev/null +++ b/ppapi/proxy/plugin_var_serialization_rules.h @@ -0,0 +1,44 @@ +// 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_VAR_SERIALIZATION_RULES_H_ +#define PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_ + +#include "base/basictypes.h" +#include "ppapi/proxy/var_serialization_rules.h" + +namespace pp { +namespace proxy { + +class PluginVarTracker; + +// Implementation of the VarSerialization interface for the plugin. +class PluginVarSerializationRules : public VarSerializationRules { + public: + // This class with use the given non-owning pointer to the var tracker to + // handle object refcounting and string conversion. + PluginVarSerializationRules(PluginVarTracker* tracker); + ~PluginVarSerializationRules(); + + // VarSerialization implementation. + virtual void SendCallerOwned(const PP_Var& var, std::string* str_val); + virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, + const std::string* str_val); + virtual void EndReceiveCallerOwned(const PP_Var& var); + virtual PP_Var ReceivePassRef(const PP_Var& var, + const std::string& str_val); + virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val); + virtual void EndSendPassRef(const PP_Var& var); + virtual void ReleaseObjectRef(const PP_Var& var); + + private: + PluginVarTracker* var_tracker_; + + DISALLOW_COPY_AND_ASSIGN(PluginVarSerializationRules); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_ diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc new file mode 100644 index 0000000..b28fc38 --- /dev/null +++ b/ppapi/proxy/plugin_var_tracker.cc @@ -0,0 +1,134 @@ +// 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_var_tracker.h" + +#include "base/ref_counted.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace pp { +namespace proxy { + +namespace { + +class RefCountedString : public base::RefCounted<RefCountedString> { + public: + RefCountedString() { + } + RefCountedString(const std::string& str) : value_(str) { + } + RefCountedString(const char* data, size_t len) + : value_(data, len) { + } + + const std::string& value() const { return value_; } + + private: + std::string value_; +}; + +// When running in the plugin, this will convert the string ID to the object +// using casting. No validity checking is done. +RefCountedString* PluginStringFromID(int64 id) { + return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id)); +} + +} // namespace + +PluginVarTracker::PluginVarTracker(PluginDispatcher* dispatcher) + : dispatcher_(dispatcher), + browser_var_interface_(NULL) { +} + +void PluginVarTracker::Init() { + browser_var_interface_ = reinterpret_cast<const PPB_Var*>( + dispatcher_->GetLocalInterface(PPB_VAR_INTERFACE)); +} + +int64 PluginVarTracker::MakeString(const std::string& str) { + RefCountedString* out = new RefCountedString(str); + out->AddRef(); + return static_cast<int64>(reinterpret_cast<intptr_t>(out)); +} + +std::string PluginVarTracker::GetString(const PP_Var& var) const { + return PluginStringFromID(var.value.as_id)->value(); +} + +const std::string* PluginVarTracker::GetExistingString( + const PP_Var& var) const { + if (var.type != PP_VARTYPE_STRING) + return NULL; + RefCountedString* str = PluginStringFromID(var.value.as_id); + return &str->value(); +} + +void PluginVarTracker::AddRef(const PP_Var& var) { + if (var.type == PP_VARTYPE_STRING) { + PluginStringFromID(var.value.as_id)->AddRef(); + } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { + int& ref_count = object_ref_count_[var.value.as_id]; + ref_count++; + if (ref_count == 1) { + // We must handle the case where we got requested to AddRef an object + // that we've never seen before. This should tell the browser we've + // taken a ref. This comes up when the browser passes an object as an + // input param and holds a ref for us. We may not have seen that object + // and the plugin handler may want to AddRef and release it internally. + SendAddRefObjectMsg(var.value.as_id); + } + } +} + +void PluginVarTracker::Release(const PP_Var& var) { + if (var.type == PP_VARTYPE_STRING) { + PluginStringFromID(var.value.as_id)->Release(); + } else if (var.type == PP_VARTYPE_OBJECT) { + ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); + if (found == object_ref_count_.end()) + return; // Invalid object. + found->second--; + + if (found->second == 0) { + // Plugin has released all of its refs, tell the browser. + object_ref_count_.erase(found); + SendReleaseObjectMsg(var.value.as_id); + } + } +} + +void PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var) { + // We're the plugin and the renderer just sent us a ref. The renderer has + // addrefed the var in its tracker for us since it's returning it. + // + // - If We don't have a reference to this already, then we just add it to + // our tracker and use that one ref. + // + // - If we do already have a reference to it, that means the renderer now + // has two references on our behalf. We want to transfer that extra + // reference to our list. This means we addref in the plugin, and release + // the extra one in the renderer. + ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); + if (found == object_ref_count_.end()) { + object_ref_count_[var.value.as_id] = 1; + } else { + SendReleaseObjectMsg(var.value.as_id); + found->second++; + } +} + +void PluginVarTracker::SendAddRefObjectMsg(int64_t id) { + dispatcher_->Send(new PpapiHostMsg_PPBVar_AddRefObject( + INTERFACE_ID_PPB_VAR_DEPRECATED, id)); +} + +void PluginVarTracker::SendReleaseObjectMsg(int64_t id) { + dispatcher_->Send(new PpapiHostMsg_PPBVar_ReleaseObject( + INTERFACE_ID_PPB_VAR_DEPRECATED, id)); +} + +} // namesace proxy +} // namespace pp diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h new file mode 100644 index 0000000..b519ee6 --- /dev/null +++ b/ppapi/proxy/plugin_var_tracker.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_VAR_TRACKER_H_ +#define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ + +#include <map> +#include <string> + +#include "ppapi/c/pp_stdint.h" +#include "ppapi/c/pp_var.h" + +struct PPB_Var; + +namespace pp { +namespace proxy { + +class PluginDispatcher; + +// Tracks live strings and objects in the plugin process. We maintain our own +// reference count for these objects. In the case of JS objects, we maintain +// a single ref in the browser process whenever we have a nonzero refcount +// in the plugin process. This allows AddRef and Release to not initiate too +// much IPC chat. +class PluginVarTracker { + public: + // You must call Init() after creation to set up the correct interfaces. We + // do this to avoid having to depend on the dispatcher in the constructor, + // which is probably just being created from our constructor. + PluginVarTracker(PluginDispatcher* dispatcher); + + // Must be called after construction. + void Init(); + + // Allocates a string and returns the ID of it. The refcount will be 1. + int64_t MakeString(const std::string& str); + + // Returns the string associated with the given string var. The var must be + // of type string and must be valid or this function will crash. + std::string GetString(const PP_Var& var) const; + + // Returns a pointer to the given string if it exists, or NULL if the var + // isn't a string var. + const std::string* GetExistingString(const PP_Var& var) const; + + void AddRef(const PP_Var& var); + void Release(const PP_Var& var); + + // Manages tracking for receiving a VARTYPE_OBJECT from the remote side + // (either the plugin or the renderer) that has already had its reference + // count incremented on behalf of the caller. + void ReceiveObjectPassRef(const PP_Var& var); + + private: + // Sends an addref or release message to the browser for the given object ID. + void SendAddRefObjectMsg(int64_t id); + void SendReleaseObjectMsg(int64_t id); + + PluginDispatcher* dispatcher_; + + // When !is_plugin_ (we're in the renderer) this points to the actual var + // interface implementation which is how we create strings and manage + // refcounts. + const PPB_Var* browser_var_interface_; + + // Tracks object references to the reference count of that object on the + // plugin side. + typedef std::map<int64_t, int> ObjectRefCount; + ObjectRefCount object_ref_count_; +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PLUGIN_VAR_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/ppb_core_proxy.cc b/ppapi/proxy/ppb_core_proxy.cc new file mode 100644 index 0000000..a956f7a --- /dev/null +++ b/ppapi/proxy/ppb_core_proxy.cc @@ -0,0 +1,129 @@ +// 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/ppb_core_proxy.h" + +#include <stdlib.h> // For malloc + +#include "base/logging.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/ppb_core.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace pp { +namespace proxy { + +namespace { + +void AddRefResource(PP_Resource resource) { + PluginDispatcher::Get()->plugin_resource_tracker()->AddRefResource(resource); +} + +void ReleaseResource(PP_Resource resource) { + PluginDispatcher::Get()->plugin_resource_tracker()->ReleaseResource(resource); +} + +void* MemAlloc(size_t num_bytes) { + return malloc(num_bytes); +} + +void MemFree(void* ptr) { + free(ptr); +} + +double GetTime() { + double result; + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBCore_GetTime( + INTERFACE_ID_PPB_CORE, &result)); + return result; +} + +double GetTimeTicks() { + double result; + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBCore_GetTimeTicks( + INTERFACE_ID_PPB_CORE, &result)); + return result; +} + +void CallOnMainThread(int delay_in_msec, + PP_CompletionCallback callback, + int32_t result) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + dispatcher->Send(new PpapiHostMsg_PPBCore_CallOnMainThread( + INTERFACE_ID_PPB_CORE, delay_in_msec, + dispatcher->callback_tracker().SendCallback(callback), + result)); +} + +bool IsMainThread() { + NOTIMPLEMENTED(); + return true; +} + +const PPB_Core core_interface = { + &AddRefResource, + &ReleaseResource, + &MemAlloc, + &MemFree, + &GetTime, + &GetTimeTicks, + &CallOnMainThread, + &IsMainThread +}; + +} // namespace + +PPB_Core_Proxy::PPB_Core_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_Core_Proxy::~PPB_Core_Proxy() { +} + +const void* PPB_Core_Proxy::GetSourceInterface() const { + return &core_interface; +} + +InterfaceID PPB_Core_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_CORE; +} + +void PPB_Core_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_Core_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_AddRefResource, OnMsgAddRefResource) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_ReleaseResource, OnMsgReleaseResource) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_GetTime, OnMsgGetTime) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_CallOnMainThread, + OnMsgCallOnMainThread) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! +} + +void PPB_Core_Proxy::OnMsgAddRefResource(PP_Resource resource) { + ppb_core_target()->AddRefResource(resource); +} + +void PPB_Core_Proxy::OnMsgReleaseResource(PP_Resource resource) { + ppb_core_target()->ReleaseResource(resource); +} + +void PPB_Core_Proxy::OnMsgGetTime(double* result) { + *result = 0.0; // FIXME(brettw); +} + +void PPB_Core_Proxy::OnMsgCallOnMainThread(int delay_in_msec, + uint32_t serialized_callback, + int32_t result) { + // TODO(brettw) this doesn't need to go to the other process, we should be + // able to post this to our own message loop and get better performance. + ppb_core_target()->CallOnMainThread(delay_in_msec, + ReceiveCallback(serialized_callback), + result); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_core_proxy.h b/ppapi/proxy/ppb_core_proxy.h new file mode 100644 index 0000000..e7dfa90 --- /dev/null +++ b/ppapi/proxy/ppb_core_proxy.h @@ -0,0 +1,45 @@ +// 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_PPB_CORE_PROXY_H_ +#define PPAPI_PPB_CORE_PROXY_H_ + +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Core; + +namespace pp { +namespace proxy { + +class PPB_Core_Proxy : public InterfaceProxy { + public: + PPB_Core_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_Core_Proxy(); + + const PPB_Core* ppb_core_target() const { + return reinterpret_cast<const PPB_Core*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgAddRefResource(PP_Resource resource); + void OnMsgReleaseResource(PP_Resource resource); + void OnMsgGetTime(double* result); + void OnMsgCallOnMainThread(int delay_in_msec, + uint32_t serialized_callback, + int32_t result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_CORE_PROXY_H_ diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.cc b/ppapi/proxy/ppb_graphics_2d_proxy.cc new file mode 100644 index 0000000..ec0fb09 --- /dev/null +++ b/ppapi/proxy/ppb_graphics_2d_proxy.cc @@ -0,0 +1,202 @@ +// 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/ppb_graphics_2d_proxy.h" + +#include <string.h> // For memcpy + +#include "base/logging.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/ppb_graphics_2d.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace pp { +namespace proxy { + +class Graphics2D : public PluginResource { + public: + Graphics2D(const PP_Size& size, bool is_always_opaque) + : size_(size), is_always_opaque_(is_always_opaque) { + } + + // Resource overrides. + virtual Graphics2D* AsGraphics2D() { return this; } + + const PP_Size& size() const { return size_; } + bool is_always_opaque() const { return is_always_opaque_; } + + private: + PP_Size size_; + bool is_always_opaque_; + + DISALLOW_COPY_AND_ASSIGN(Graphics2D); +}; + +namespace { + +PP_Resource Create(PP_Module module_id, + const PP_Size* size, + bool is_always_opaque) { + PluginDispatcher* dispatcher = PluginDispatcher::Get(); + PP_Resource result = 0; + dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Create( + INTERFACE_ID_PPB_GRAPHICS_2D, module_id, *size, is_always_opaque, + &result)); + if (result) { + linked_ptr<Graphics2D> graphics_2d(new Graphics2D(*size, is_always_opaque)); + dispatcher->plugin_resource_tracker()->AddResource(result, graphics_2d); + } + return result; +} + +bool IsGraphics2D(PP_Resource resource) { + Graphics2D* object = PluginResource::GetAs<Graphics2D>(resource); + return !!object; +} + +bool Describe(PP_Resource graphics_2d, + PP_Size* size, + bool* is_always_opaque) { + Graphics2D* object = PluginResource::GetAs<Graphics2D>(graphics_2d); + if (!object) { + size->width = 0; + size->height = 0; + *is_always_opaque = false; + return false; + } + + *size = object->size(); + *is_always_opaque = object->is_always_opaque(); + return true; +} + +void PaintImageData(PP_Resource graphics_2d, + PP_Resource image_data, + const PP_Point* top_left, + const PP_Rect* src_rect) { + PP_Rect dummy; + memset(&dummy, 0, sizeof(PP_Rect)); + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_PaintImageData( + INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, image_data, *top_left, + !!src_rect, src_rect ? *src_rect : dummy)); +} + +void Scroll(PP_Resource graphics_2d, + const PP_Rect* clip_rect, + const PP_Point* amount) { + PP_Rect dummy; + memset(&dummy, 0, sizeof(PP_Rect)); + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_Scroll( + INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, !!clip_rect, + clip_rect ? *clip_rect : dummy, *amount)); +} + +void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) { + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBGraphics2D_ReplaceContents( + INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, image_data)); +} + +int32_t Flush(PP_Resource graphics_2d, + PP_CompletionCallback callback) { + PluginDispatcher* dispatcher = PluginDispatcher::Get(); + int32_t result = PP_ERROR_FAILED; + dispatcher->Send(new PpapiHostMsg_PPBGraphics2D_Flush( + INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, + dispatcher->callback_tracker().SendCallback(callback), + &result)); + return result; +} + +const PPB_Graphics2D ppb_graphics_2d = { + &Create, + &IsGraphics2D, + &Describe, + &PaintImageData, + &Scroll, + &ReplaceContents, + &Flush +}; + +} // namespace + +PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() { +} + +const void* PPB_Graphics2D_Proxy::GetSourceInterface() const { + return &ppb_graphics_2d; +} + +InterfaceID PPB_Graphics2D_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_GRAPHICS_2D; +} + +void PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_Graphics2D_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Create, + OnMsgCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_PaintImageData, + OnMsgPaintImageData) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Scroll, + OnMsgScroll) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_ReplaceContents, + OnMsgReplaceContents) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush, + OnMsgFlush) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! +} + +void PPB_Graphics2D_Proxy::OnMsgCreate(PP_Module module, + const PP_Size& size, + bool is_always_opaque, + PP_Resource* result) { + *result = ppb_graphics_2d_target()->Create( + module, &size, is_always_opaque); +} + +void PPB_Graphics2D_Proxy::OnMsgPaintImageData(PP_Resource graphics_2d, + PP_Resource image_data, + const PP_Point& top_left, + bool src_rect_specified, + const PP_Rect& src_rect) { + ppb_graphics_2d_target()->PaintImageData( + graphics_2d, image_data, &top_left, + src_rect_specified ? &src_rect : NULL); +} + +void PPB_Graphics2D_Proxy::OnMsgScroll(PP_Resource graphics_2d, + bool clip_specified, + const PP_Rect& clip, + const PP_Point& amount) { + ppb_graphics_2d_target()->Scroll( + graphics_2d, + clip_specified ? &clip : NULL, &amount); +} + +void PPB_Graphics2D_Proxy::OnMsgReplaceContents(PP_Resource graphics_2d, + PP_Resource image_data) { + ppb_graphics_2d_target()->ReplaceContents(graphics_2d, image_data); +} + +void PPB_Graphics2D_Proxy::OnMsgFlush(PP_Resource graphics_2d, + uint32_t serialized_callback, + int32_t* result) { + // TODO(brettw) this should be a non-sync function. Ideally it would call + // the callback with a failure code from here if you weren't allowed to + // call Flush there. + *result = ppb_graphics_2d_target()->Flush( + graphics_2d, ReceiveCallback(serialized_callback)); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.h b/ppapi/proxy/ppb_graphics_2d_proxy.h new file mode 100644 index 0000000..80c698134 --- /dev/null +++ b/ppapi/proxy/ppb_graphics_2d_proxy.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_PPB_GRAPHICS_2D_PROXY_H_ +#define PPAPI_PPB_GRAPHICS_2D_PROXY_H_ + +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_size.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Graphics2D; +struct PP_Point; +struct PP_Rect; + +namespace pp { +namespace proxy { + +class PPB_Graphics2D_Proxy : public InterfaceProxy { + public: + PPB_Graphics2D_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_Graphics2D_Proxy(); + + const PPB_Graphics2D* ppb_graphics_2d_target() const { + return reinterpret_cast<const PPB_Graphics2D*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgCreate(PP_Module module, + const PP_Size& size, + bool is_always_opaque, + PP_Resource* result); + void OnMsgPaintImageData(PP_Resource graphics_2d, + PP_Resource image_data, + const PP_Point& top_left, + bool src_rect_specified, + const PP_Rect& src_rect); + void OnMsgScroll(PP_Resource graphics_2d, + bool clip_specified, + const PP_Rect& clip, + const PP_Point& amount); + void OnMsgReplaceContents(PP_Resource graphics_2d, + PP_Resource image_data); + void OnMsgFlush(PP_Resource graphics_2d, + uint32_t serialized_callback, + int32_t* result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_GRAPHICS_2D_PROXY_H_ diff --git a/ppapi/proxy/ppb_image_data_proxy.cc b/ppapi/proxy/ppb_image_data_proxy.cc new file mode 100644 index 0000000..19d0932 --- /dev/null +++ b/ppapi/proxy/ppb_image_data_proxy.cc @@ -0,0 +1,234 @@ +// 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/ppb_image_data_proxy.h" + +#include <string.h> // For memcpy + +#include <vector> + +#include "base/logging.h" +#include "build/build_config.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/ppb_image_data.h" +#include "ppapi/c/trusted/ppb_image_data_trusted.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_messages.h" + +#if defined(OS_LINUX) +#include <sys/shm.h> +#endif + +namespace pp { +namespace proxy { + +class ImageData : public PluginResource { + public: + ImageData(const PP_ImageDataDesc& desc, uint64_t memory_handle); + virtual ~ImageData(); + + // Resource overrides. + virtual ImageData* AsImageData() { return this; } + + void* Map(); + void Unmap(); + + const PP_ImageDataDesc& desc() const { return desc_; } + + private: + PP_ImageDataDesc desc_; + uint64_t memory_handle_; + + void* mapped_data_; + + DISALLOW_COPY_AND_ASSIGN(ImageData); +}; + +ImageData::ImageData(const PP_ImageDataDesc& desc, + uint64_t memory_handle) + : desc_(desc), + memory_handle_(memory_handle), + mapped_data_(NULL) { +} + +ImageData::~ImageData() { + Unmap(); +} + +void* ImageData::Map() { +#if defined(OS_LINUX) + // On linux, the memory handle is a SysV shared memory segment. + int shmkey = static_cast<int>(memory_handle_); + void* address = shmat(shmkey, NULL, 0); + // Mark for deletion in case we crash so the kernel will clean it up. + shmctl(shmkey, IPC_RMID, 0); + if (address == (void*)-1) + return NULL; + mapped_data_ = address; + return address; +#else + #error write this +#endif +} + +void ImageData::Unmap() { +#if defined(OS_LINUX) + if (mapped_data_) + shmdt(mapped_data_); +#else + #error write this +#endif + mapped_data_ = NULL; +} + +namespace { + +PP_ImageDataFormat GetNativeImageDataFormat() { + int32 format = 0; + PluginDispatcher::Get()->Send( + new PpapiHostMsg_PPBImageData_GetNativeImageDataFormat( + INTERFACE_ID_PPB_IMAGE_DATA, &format)); + return static_cast<PP_ImageDataFormat>(format); +} + +bool IsImageDataFormatSupported(PP_ImageDataFormat format) { + bool supported = false; + PluginDispatcher::Get()->Send( + new PpapiHostMsg_PPBImageData_IsImageDataFormatSupported( + INTERFACE_ID_PPB_IMAGE_DATA, static_cast<int32_t>(format), + &supported)); + return supported; +} + +PP_Resource Create(PP_Module module_id, + PP_ImageDataFormat format, + const PP_Size* size, + bool init_to_zero) { + PP_Resource result = 0; + std::string image_data_desc; + uint64_t shm_handle = -1; + PluginDispatcher::Get()->Send( + new PpapiHostMsg_PPBImageData_Create( + INTERFACE_ID_PPB_IMAGE_DATA, module_id, format, *size, init_to_zero, + &result, &image_data_desc, &shm_handle)); + + if (result && image_data_desc.size() == sizeof(PP_ImageDataDesc)) { + // We serialize the PP_ImageDataDesc just by copying to a string. + PP_ImageDataDesc desc; + memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc)); + + linked_ptr<ImageData> object( + new ImageData(desc, shm_handle)); + PluginDispatcher::Get()->plugin_resource_tracker()->AddResource( + result, object); + } + return result; +} + +bool IsImageData(PP_Resource resource) { + ImageData* object = PluginResource::GetAs<ImageData>(resource); + return !!object; +} + +bool Describe(PP_Resource resource, PP_ImageDataDesc* desc) { + ImageData* object = PluginResource::GetAs<ImageData>(resource); + if (!object) + return false; + memcpy(desc, &object->desc(), sizeof(PP_ImageDataDesc)); + return true; +} + +void* Map(PP_Resource resource) { + ImageData* object = PluginResource::GetAs<ImageData>(resource); + if (!object) + return NULL; + return object->Map(); +} + +void Unmap(PP_Resource resource) { + ImageData* object = PluginResource::GetAs<ImageData>(resource); + if (object) + object->Unmap(); +} + +const PPB_ImageData ppb_imagedata = { + &GetNativeImageDataFormat, + &IsImageDataFormatSupported, + &Create, + &IsImageData, + &Describe, + &Map, + &Unmap, +}; + +} // namespace + +PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_ImageData_Proxy::~PPB_ImageData_Proxy() { +} + +const void* PPB_ImageData_Proxy::GetSourceInterface() const { + return &ppb_imagedata; +} + +InterfaceID PPB_ImageData_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_IMAGE_DATA; +} + +void PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_GetNativeImageDataFormat, + OnMsgGetNativeImageDataFormat) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_IsImageDataFormatSupported, + OnMsgIsImageDataFormatSupported) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnMsgCreate) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! +} + +void PPB_ImageData_Proxy::OnMsgGetNativeImageDataFormat(int32* result) { + *result = ppb_image_data_target()->GetNativeImageDataFormat(); +} + +void PPB_ImageData_Proxy::OnMsgIsImageDataFormatSupported(int32 format, + bool* result) { + *result = ppb_image_data_target()->IsImageDataFormatSupported( + static_cast<PP_ImageDataFormat>(format)); +} + +void PPB_ImageData_Proxy::OnMsgCreate(PP_Module module, + int32_t format, + const PP_Size& size, + bool init_to_zero, + PP_Resource* result, + std::string* image_data_desc, + uint64_t* result_shm_handle) { + *result = ppb_image_data_target()->Create( + module, static_cast<PP_ImageDataFormat>(format), &size, init_to_zero); + *result_shm_handle = 0; + if (*result) { + // The ImageDesc is just serialized as a string. + PP_ImageDataDesc desc; + if (ppb_image_data_target()->Describe(*result, &desc)) { + image_data_desc->resize(sizeof(PP_ImageDataDesc)); + memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); + } + + // Get the shared memory handle. + const PPB_ImageDataTrusted* trusted = + reinterpret_cast<const PPB_ImageDataTrusted*>( + dispatcher()->GetLocalInterface(PPB_IMAGEDATA_TRUSTED_INTERFACE)); + if (trusted) + *result_shm_handle = trusted->GetNativeMemoryHandle(*result); + } +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_image_data_proxy.h b/ppapi/proxy/ppb_image_data_proxy.h new file mode 100644 index 0000000..39e8ad6 --- /dev/null +++ b/ppapi/proxy/ppb_image_data_proxy.h @@ -0,0 +1,50 @@ +// 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_PPB_IMAGE_DATA_PROXY_H_ +#define PPAPI_PPB_IMAGE_DATA_PROXY_H_ + +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_size.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_ImageData; + +namespace pp { +namespace proxy { + +class PPB_ImageData_Proxy : public InterfaceProxy { + public: + PPB_ImageData_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_ImageData_Proxy(); + + const PPB_ImageData* ppb_image_data_target() const { + return reinterpret_cast<const PPB_ImageData*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgGetNativeImageDataFormat(int32* result); + void OnMsgIsImageDataFormatSupported(int32 format, bool* result); + void OnMsgCreate(PP_Module module, + int32_t format, + const PP_Size& size, + bool init_to_zero, + PP_Resource* result, + std::string* image_data_desc, + uint64_t* result_shm_handle); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_IMAGE_DATA_PROXY_H_ diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc new file mode 100644 index 0000000..c81562a --- /dev/null +++ b/ppapi/proxy/ppb_instance_proxy.cc @@ -0,0 +1,139 @@ +// 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/ppb_instance_proxy.h" + +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppb_instance.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_message_helpers.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/serialized_var.h" + +namespace pp { +namespace proxy { + +namespace { + +PP_Var GetWindowObject(PP_Instance instance) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedVarReturnValue result; + dispatcher->Send(new PpapiHostMsg_PPBInstance_GetWindowObject( + INTERFACE_ID_PPB_INSTANCE, instance, &result)); + return result.Return(dispatcher); +} + +PP_Var GetOwnerElementObject(PP_Instance instance) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedVarReturnValue result; + dispatcher->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject( + INTERFACE_ID_PPB_INSTANCE, instance, &result)); + return result.Return(dispatcher); +} + +bool BindGraphics(PP_Instance instance, PP_Resource device) { + bool result; + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBInstance_BindGraphics( + INTERFACE_ID_PPB_INSTANCE, instance, device, &result)); + return result; +} + +bool IsFullFrame(PP_Instance instance) { + bool result; + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame( + INTERFACE_ID_PPB_INSTANCE, instance, &result)); + return result; +} + +PP_Var ExecuteScript(PP_Instance instance, PP_Var script, PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + if (se.IsThrown()) + return PP_MakeUndefined(); + + ReceiveSerializedVarReturnValue result; + dispatcher->Send(new PpapiHostMsg_PPBInstance_ExecuteScript( + INTERFACE_ID_PPB_INSTANCE, instance, + SerializedVarSendInput(dispatcher, script), &se, &result)); + return result.Return(dispatcher); +} + +const PPB_Instance instance_interface = { + &GetWindowObject, + &GetOwnerElementObject, + &BindGraphics, + &IsFullFrame, + &ExecuteScript +}; + +} // namespace + +PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_Instance_Proxy::~PPB_Instance_Proxy() { +} + +const void* PPB_Instance_Proxy::GetSourceInterface() const { + return &instance_interface; +} + +InterfaceID PPB_Instance_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_INSTANCE; +} + +void PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject, + OnMsgGetWindowObject) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject, + OnMsgGetOwnerElementObject) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics, + OnMsgBindGraphics) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame, + OnMsgIsFullFrame) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript, + OnMsgExecuteScript) + IPC_END_MESSAGE_MAP() +} + +void PPB_Instance_Proxy::OnMsgGetWindowObject( + PP_Instance instance, + SerializedVarReturnValue result) { + result.Return(dispatcher(), + ppb_instance_target()->GetWindowObject(instance)); +} + +void PPB_Instance_Proxy::OnMsgGetOwnerElementObject( + PP_Instance instance, + SerializedVarReturnValue result) { + result.Return(dispatcher(), + ppb_instance_target()->GetOwnerElementObject(instance)); +} + +void PPB_Instance_Proxy::OnMsgBindGraphics(PP_Instance instance, + PP_Resource device, + bool* result) { + *result = ppb_instance_target()->BindGraphics(instance, device); +} + +void PPB_Instance_Proxy::OnMsgIsFullFrame(PP_Instance instance, bool* result) { + *result = ppb_instance_target()->IsFullFrame(instance); +} + +void PPB_Instance_Proxy::OnMsgExecuteScript( + PP_Instance instance, + SerializedVarReceiveInput script, + SerializedVarOutParam out_exception, + SerializedVarReturnValue result) { + result.Return(dispatcher(), ppb_instance_target()->ExecuteScript( + instance, + script.Get(dispatcher()), + out_exception.OutParam(dispatcher()))); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h new file mode 100644 index 0000000..64b2b2d --- /dev/null +++ b/ppapi/proxy/ppb_instance_proxy.h @@ -0,0 +1,55 @@ +// 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_PPB_INSTANCE_PROXY_H_ +#define PPAPI_PROXY_PPB_INSTANCE_PROXY_H_ + +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Instance; + +namespace pp { +namespace proxy { + +class SerializedVarReceiveInput; +class SerializedVarOutParam; +class SerializedVarReturnValue; + +class PPB_Instance_Proxy : public InterfaceProxy { + public: + PPB_Instance_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_Instance_Proxy(); + + const PPB_Instance* ppb_instance_target() const { + return reinterpret_cast<const PPB_Instance*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgGetWindowObject(PP_Instance instance, + SerializedVarReturnValue result); + void OnMsgGetOwnerElementObject(PP_Instance instance, + SerializedVarReturnValue result); + void OnMsgBindGraphics(PP_Instance instance, + PP_Resource device, + bool* result); + void OnMsgIsFullFrame(PP_Instance instance, bool* result); + void OnMsgExecuteScript(PP_Instance instance, + SerializedVarReceiveInput script, + SerializedVarOutParam out_exception, + SerializedVarReturnValue result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PPB_INSTANCE_PROXY_H_ diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc new file mode 100644 index 0000000..0ff46e4 --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.cc @@ -0,0 +1,301 @@ +// 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/ppb_url_loader_proxy.h" + +#include <vector> + +#include "base/logging.h" +#include "build/build_config.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/dev/ppb_url_loader_dev.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_messages.h" + +#if defined(OS_LINUX) +#include <sys/shm.h> +#endif + +namespace pp { +namespace proxy { + +class URLLoader : public PluginResource { + public: + URLLoader(); + virtual ~URLLoader(); + + // Resource overrides. + virtual URLLoader* AsURLLoader() { return this; } + + int64_t bytes_sent_; + int64_t total_bytes_to_be_sent_; + int64_t bytes_received_; + int64_t total_bytes_to_be_received_; + + private: + + DISALLOW_COPY_AND_ASSIGN(URLLoader); +}; + +URLLoader::URLLoader() + : bytes_sent_(0), + total_bytes_to_be_sent_(0), + bytes_received_(0), + total_bytes_to_be_received_(0) { +} + +URLLoader::~URLLoader() { +} + +namespace { + +PP_Resource Create(PP_Instance instance_id) { + PluginDispatcher* dispatcher = PluginDispatcher::Get(); + PP_Resource result = 0; + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create( + INTERFACE_ID_PPB_URL_LOADER, instance_id, &result)); + if (result) { + linked_ptr<URLLoader> object(new URLLoader); + dispatcher->plugin_resource_tracker()->AddResource(result, object); + } + return result; +} + +bool IsURLLoader(PP_Resource resource) { + URLLoader* object = PluginResource::GetAs<URLLoader>(resource); + return !!object; +} + +int32_t Open(PP_Resource loader_id, + PP_Resource request_id, + PP_CompletionCallback callback) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Open( + INTERFACE_ID_PPB_URL_LOADER, loader_id, request_id, + dispatcher->callback_tracker().SendCallback(callback))); + return PP_ERROR_WOULDBLOCK; +} + +int32_t FollowRedirect(PP_Resource loader_id, + PP_CompletionCallback callback) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect( + INTERFACE_ID_PPB_URL_LOADER, loader_id, + dispatcher->callback_tracker().SendCallback(callback))); + return PP_ERROR_WOULDBLOCK; +} + +bool GetUploadProgress(PP_Resource loader_id, + int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) { + // TODO(brettw) implement this as a non-blocking call where we get notified + // of updates and just send the local copy. + bool result = false; + PluginDispatcher::Get()->Send( + new PpapiHostMsg_PPBURLLoader_GetUploadProgress( + INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_sent, + total_bytes_to_be_sent, &result)); + return result; +} + +bool GetDownloadProgress(PP_Resource loader_id, + int64_t* bytes_received, + int64_t* total_bytes_to_be_received) { + // TODO(brettw) implement this as a non-blocking call where we get notified + // of updates and just send the local copy. + bool result = false; + PluginDispatcher::Get()->Send( + new PpapiHostMsg_PPBURLLoader_GetDownloadProgress( + INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_received, + total_bytes_to_be_received, &result)); + return result; +} + +PP_Resource GetResponseInfo(PP_Resource loader_id) { + // TODO(brettw) this needs to have proper refcounting handling for the + // result! + /* + PP_Resource result; + Dispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo( + INTERFACE_ID_PPB_URL_LOADER, loader_id, &result)); + */ + return 0; +} + +int32_t ReadResponseBody(PP_Resource loader_id, + char* buffer, + int32_t bytes_to_read, + PP_CompletionCallback callback) { + /* TODO + Dispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody( + INTERFACE_ID_PPB_URL_LOADER, loader_id, )); + */ + return PP_ERROR_WOULDBLOCK; +} + +int32_t FinishStreamingToFile(PP_Resource loader_id, + PP_CompletionCallback callback) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile( + INTERFACE_ID_PPB_URL_LOADER, loader_id, + dispatcher->callback_tracker().SendCallback(callback))); + return PP_ERROR_WOULDBLOCK; +} + +void Close(PP_Resource loader_id) { + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_Close( + INTERFACE_ID_PPB_URL_LOADER, loader_id)); +} + +const PPB_URLLoader_Dev ppb_urlloader = { + &Create, + &IsURLLoader, + &Open, + &FollowRedirect, + &GetUploadProgress, + &GetDownloadProgress, + &GetResponseInfo, + &ReadResponseBody, + &FinishStreamingToFile, + &Close +}; + +} // namespace + +PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() { +} + +const void* PPB_URLLoader_Proxy::GetSourceInterface() const { + return &ppb_urlloader; +} + +InterfaceID PPB_URLLoader_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_URL_LOADER; +} + +void PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Create, + OnMsgCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Open, + OnMsgOpen) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FollowRedirect, + OnMsgFollowRedirect) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetUploadProgress, + OnMsgGetUploadProgress) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetDownloadProgress, + OnMsgGetDownloadProgress) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetResponseInfo, + OnMsgGetResponseInfo) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_ReadResponseBody, + OnMsgReadResponseBody) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile, + OnMsgFinishStreamingToFile) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Close, + OnMsgClose) + + IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress, + OnMsgUpdateProgress) + IPC_END_MESSAGE_MAP() + // TODO(brettw) handle bad messages! +} + +void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance, + PP_Resource* result) { + *result = ppb_url_loader_target()->Create(instance); +} + +void PPB_URLLoader_Proxy::OnMsgOpen(PP_Resource loader, + PP_Resource request_info, + uint32_t serialized_callback) { + // TODO(brettw): need to notify in case the result is not "would block". + ppb_url_loader_target()->Open(loader, request_info, + ReceiveCallback(serialized_callback)); +} + +void PPB_URLLoader_Proxy::OnMsgFollowRedirect( + PP_Resource loader, + uint32_t serialized_callback) { + // TODO(brettw): need to notify in case the result is not "would block". + ppb_url_loader_target()->FollowRedirect(loader, + ReceiveCallback(serialized_callback)); +} + +void PPB_URLLoader_Proxy::OnMsgGetUploadProgress( + PP_Resource loader, + int64* bytes_sent, + int64* total_bytes_to_be_sent, + bool* result) { + *result = ppb_url_loader_target()->GetUploadProgress( + loader, bytes_sent, total_bytes_to_be_sent); +} + +void PPB_URLLoader_Proxy::OnMsgGetDownloadProgress( + PP_Resource loader, + int64* bytes_received, + int64* total_bytes_to_be_received, + bool* result) { + *result = ppb_url_loader_target()->GetDownloadProgress( + loader, bytes_received, total_bytes_to_be_received); +} + +void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(PP_Resource loader, + PP_Resource* result) { + /* TODO(brettw) this will depend on the plugin-side FIXME above. + *result = ppb_url_loader_target()->GetResponseInfo(loader); + */ +} + +void PPB_URLLoader_Proxy::OnMsgReadResponseBody( + PP_Resource loader, + int32_t bytes_to_read, + uint32_t serialized_callback) { + // TODO(brettw): need to notify in case the result is not "would block". + /* TODO(brettw) figure out how to share data. + ppb_url_loader_target()->ReadRseponseBody(loader, bytes_to_read, + ReceiveCallback(serialized_callback)); + */ +} + +void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( + PP_Resource loader, + uint32_t serialized_callback) { + // TODO(brettw): need to notify in case the result is not "would block". + ppb_url_loader_target()->FinishStreamingToFile(loader, + ReceiveCallback(serialized_callback)); +} + +void PPB_URLLoader_Proxy::OnMsgClose(PP_Resource loader) { + ppb_url_loader_target()->Close(loader); +} + +// TODO(brettw) nobody calls this function. We should have some way to register +// for these updates so when WebKit tells the pepper url loader code that +// something changed, we'll get a callback. +void PPB_URLLoader_Proxy::OnMsgUpdateProgress( + PP_Resource resource, + int64_t bytes_sent, + int64_t total_bytes_to_be_sent, + int64_t bytes_received, + int64_t total_bytes_to_be_received) { + URLLoader* object = PluginResource::GetAs<URLLoader>(resource); + if (!object) + return; + + object->bytes_sent_ = bytes_sent; + object->total_bytes_to_be_sent_ = total_bytes_to_be_sent; + object->bytes_received_ = bytes_received; + object->total_bytes_to_be_received_ = total_bytes_to_be_received; +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h new file mode 100644 index 0000000..6978f88 --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -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. + +#ifndef PPAPI_PPB_URL_LOADER_PROXY_H_ +#define PPAPI_PPB_URL_LOADER_PROXY_H_ + +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_size.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_URLLoader_Dev; + +namespace pp { +namespace proxy { + +class PPB_URLLoader_Proxy : public InterfaceProxy { + public: + PPB_URLLoader_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_URLLoader_Proxy(); + + const PPB_URLLoader_Dev* ppb_url_loader_target() const { + return reinterpret_cast<const PPB_URLLoader_Dev*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Plugin->renderer message handlers. + void OnMsgCreate(PP_Instance instance, + PP_Resource* result); + void OnMsgOpen(PP_Resource loader, + PP_Resource request_info, + uint32_t serialized_callback); + void OnMsgFollowRedirect(PP_Resource loader, + uint32_t serialized_callback); + void OnMsgGetUploadProgress(PP_Resource loader, + int64* bytes_sent, + int64* total_bytes_to_be_sent, + bool* result); + void OnMsgGetDownloadProgress(PP_Resource loader, + int64* bytes_received, + int64* total_bytes_to_be_received, + bool* result); + void OnMsgGetResponseInfo(PP_Resource loader, + PP_Resource* result); + void OnMsgReadResponseBody(PP_Resource loader, + int32_t bytes_to_read, + uint32_t serialized_callback); + void OnMsgFinishStreamingToFile(PP_Resource loader, + uint32_t serialized_callback); + void OnMsgClose(PP_Resource loader); + + // Renderer->plugin message handlers. + void OnMsgUpdateProgress(PP_Resource resource, + int64_t bytes_sent, + int64_t total_bytes_to_be_sent, + int64_t bytes_received, + int64_t total_bytes_to_be_received); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_URL_LOADER_PROXY_H_ diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.cc b/ppapi/proxy/ppb_var_deprecated_proxy.cc new file mode 100644 index 0000000..e8ba730 --- /dev/null +++ b/ppapi/proxy/ppb_var_deprecated_proxy.cc @@ -0,0 +1,376 @@ +// 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/ppb_var_deprecated_proxy.h" + +#include <stdlib.h> // For malloc + +#include "base/logging.h" +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppb_core.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/ppapi_message_helpers.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppp_class_proxy.h" +#include "ppapi/proxy/serialized_var.h" + +namespace pp { +namespace proxy { + +namespace { + +// PPP_Var_Deprecated plugin --------------------------------------------------- + +void AddRefVar(PP_Var var) { + PluginDispatcher::Get()->plugin_var_tracker()->AddRef(var); +} + +void ReleaseVar(PP_Var var) { + PluginDispatcher::Get()->plugin_var_tracker()->Release(var); +} + +PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { + PP_Var ret; + ret.type = PP_VARTYPE_STRING; + // TODO(brettw) avoid this extra copy. + ret.value.as_id = PluginDispatcher::Get()->plugin_var_tracker()->MakeString( + std::string(data, len)); + return ret; +} + +const char* VarToUtf8(PP_Var var, uint32_t* len) { + const std::string* str = + PluginDispatcher::Get()->plugin_var_tracker()->GetExistingString(var); + if (str) { + *len = static_cast<uint32_t>(str->size()); + return str->c_str(); + } else { + *len = 0; + return NULL; + } +} + +bool HasProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result; +} + +bool HasMethod(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result; +} + +PP_Var GetProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + ReceiveSerializedVarReturnValue result; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result.Return(dispatcher); +} + +void EnumerateProperties(PP_Var var, + uint32_t* property_count, + PP_Var** properties, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + + ReceiveSerializedVarVectorOutParam out_vector(dispatcher, + property_count, properties); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + out_vector.OutParam(), &se)); + } +} + +void SetProperty(PP_Var var, + PP_Var name, + PP_Var value, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), + SerializedVarSendInput(dispatcher, value), &se)); + } +} + +void RemoveProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } +} + +PP_Var Call(PP_Var object, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedVarReturnValue result; + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect); + + dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, + SerializedVarSendInput(dispatcher, object), + SerializedVarSendInput(dispatcher, method_name), argv_vect, + &se, &result)); + } + return result.Return(dispatcher); +} + +PP_Var Construct(PP_Var object, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedVarReturnValue result; + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect); + + dispatcher->Send(new PpapiHostMsg_PPBVar_Construct( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, object), + argv_vect, &se, &result)); + } + return result.Return(dispatcher); +} + +bool IsInstanceOf(PP_Var var, + const PPP_Class_Deprecated* ppp_class, + void** ppp_class_data) { + bool result = false; + Dispatcher* dispatcher = PluginDispatcher::Get(); + int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class)); + int64 class_data_int = 0; + dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + class_int, &class_data_int, &result)); + *ppp_class_data = + reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int)); + return result; +} + +PP_Var CreateObject(PP_Module module_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + Dispatcher* dispatcher = PluginDispatcher::Get(); + ReceiveSerializedVarReturnValue result; + int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class)); + int64 data_int = + static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data)); + dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, module_id, class_int, data_int, &result)); + return result.Return(dispatcher); +} + +const PPB_Var_Deprecated var_deprecated_interface = { + &AddRefVar, + &ReleaseVar, + &VarFromUtf8, + &VarToUtf8, + &HasProperty, + &HasMethod, + &GetProperty, + &EnumerateProperties, + &SetProperty, + &RemoveProperty, + &Call, + &Construct, + &IsInstanceOf, + &CreateObject +}; + +} // namespace + +PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() { +} + +const void* PPB_Var_Deprecated_Proxy::GetSourceInterface() const { + return &var_deprecated_interface; +} + +InterfaceID PPB_Var_Deprecated_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_VAR_DEPRECATED; +} + +void PPB_Var_Deprecated_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_Var_Deprecated_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty, + OnMsgHasProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated, + OnMsgHasMethodDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty, + OnMsgGetProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty, + OnMsgDeleteProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties, + OnMsgEnumerateProperties) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated, + OnMsgSetPropertyDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated, + OnMsgCallDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct, + OnMsgConstruct) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated, + OnMsgIsInstanceOfDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated, + OnMsgCreateObjectDeprecated) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! +} + +void PPB_Var_Deprecated_Proxy::OnMsgHasProperty( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + *result = ppb_var_target()->HasProperty(var.Get(dispatcher()), + name.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Deprecated_Proxy::OnMsgHasMethodDeprecated( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + *result = ppb_var_target()->HasMethod(var.Get(dispatcher()), + name.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Deprecated_Proxy::OnMsgGetProperty( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + result.Return(dispatcher(), ppb_var_target()->GetProperty( + var.Get(dispatcher()), name.Get(dispatcher()), + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Deprecated_Proxy::OnMsgEnumerateProperties( + SerializedVarReceiveInput var, + SerializedVarVectorOutParam props, + SerializedVarOutParam exception) { + ppb_var_target()->GetAllPropertyNames(var.Get(dispatcher()), + props.CountOutParam(), props.ArrayOutParam(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Deprecated_Proxy::OnMsgSetPropertyDeprecated( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarReceiveInput value, + SerializedVarOutParam exception) { + ppb_var_target()->SetProperty(var.Get(dispatcher()), + name.Get(dispatcher()), + value.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Deprecated_Proxy::OnMsgDeleteProperty( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + ppb_var_target()->RemoveProperty(var.Get(dispatcher()), + name.Get(dispatcher()), + exception.OutParam(dispatcher())); + // This deprecated function doesn't actually return a value, but we re-use + // the message from the non-deprecated interface with the return value. + *result = true; +} + +void PPB_Var_Deprecated_Proxy::OnMsgCallDeprecated( + SerializedVarReceiveInput object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ppb_var_target()->Call( + object.Get(dispatcher()), + method_name.Get(dispatcher()), + arg_count, args, + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Deprecated_Proxy::OnMsgConstruct( + SerializedVarReceiveInput var, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ppb_var_target()->Construct( + var.Get(dispatcher()), arg_count, args, + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Deprecated_Proxy::OnMsgIsInstanceOfDeprecated( + pp::proxy::SerializedVarReceiveInput var, + int64 ppp_class, + int64* ppp_class_data, + bool* result) { + // TODO(brettw) write this. +} + +void PPB_Var_Deprecated_Proxy::OnMsgCreateObjectDeprecated( + PP_Module module_id, + int64 ppp_class, + int64 class_data, + SerializedVarReturnValue result) { + result.Return(dispatcher(), PPP_Class_Proxy::CreateProxiedObject( + ppb_var_target(), dispatcher(), module_id, ppp_class, class_data)); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.h b/ppapi/proxy/ppb_var_deprecated_proxy.h new file mode 100644 index 0000000..9fe123a --- /dev/null +++ b/ppapi/proxy/ppb_var_deprecated_proxy.h @@ -0,0 +1,95 @@ +// 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_PPB_VAR_PROXY_H_ +#define PPAPI_PPB_VAR_PROXY_H_ + +#include <vector> + +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Var_Deprecated; + +namespace pp { +namespace proxy { + +class SerializedVar; +class SerializedVarReceiveInput; +class SerializedVarVectorOutParam; +class SerializedVarVectorReceiveInput; +class SerializedVarOutParam; +class SerializedVarReturnValue; + +class PPB_Var_Deprecated_Proxy : public InterfaceProxy { + public: + PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher, + const void* target_interface); + virtual ~PPB_Var_Deprecated_Proxy(); + + const PPB_Var_Deprecated* ppb_var_target() const { + return reinterpret_cast<const PPB_Var_Deprecated*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgHasProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgHasMethodDeprecated(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgGetProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgEnumerateProperties( + SerializedVarReceiveInput var, + SerializedVarVectorOutParam props, + SerializedVarOutParam exception); + void OnMsgSetPropertyDeprecated(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarReceiveInput value, + SerializedVarOutParam exception); + void OnMsgDeleteProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgCall(SerializedVarReceiveInput object, + SerializedVarReceiveInput this_object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgCallDeprecated(SerializedVarReceiveInput object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgConstruct(SerializedVarReceiveInput var, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgIsInstanceOfDeprecated(pp::proxy::SerializedVarReceiveInput var, + int64 ppp_class, + int64* ppp_class_data, + bool* result); + void OnMsgCreateObjectDeprecated(PP_Module module_id, + int64 ppp_class, + int64 ppp_class_data, + SerializedVarReturnValue result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_VAR_PROXY_H_ diff --git a/ppapi/proxy/ppb_var_proxy.cc b/ppapi/proxy/ppb_var_proxy.cc new file mode 100644 index 0000000..117eb6f --- /dev/null +++ b/ppapi/proxy/ppb_var_proxy.cc @@ -0,0 +1,478 @@ +// 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/ppb_var_proxy.h" + +#include <stdlib.h> // For malloc + +#include "base/logging.h" +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppb_core.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/proxy/dispatcher.h" +#include "ppapi/proxy/ppapi_message_helpers.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/serialized_var.h" + +namespace pp { +namespace proxy { + +namespace { + +void AddRefVar(PP_Var var) { + Dispatcher::Get()->plugin_var_tracker()->AddRef(var); +} + +void ReleaseVar(PP_Var var) { + Dispatcher::Get()->plugin_var_tracker()->Release(var); +} + +PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { + PP_Var ret; + ret.type = PP_VARTYPE_STRING; + // TODO(brettw) avoid this extra copy. + ret.value.as_id = Dispatcher::Get()->plugin_var_tracker()->MakeString( + std::string(data, len)); + return ret; +} + +const char* VarToUtf8(PP_Var var, uint32_t* len) { + const std::string* str = + Dispatcher::Get()->plugin_var_tracker()->GetExistingString(var); + if (str) { + *len = static_cast<uint32_t>(str->size()); + return str->c_str(); + } else { + *len = 0; + return NULL; + } +} + +PP_Var ConvertType(PP_Instance instance, + PP_Var var, + PP_VarType new_type, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + ReceiveSerializedVarReturnValue result(dispatcher); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_ConvertType( + INTERFACE_ID_PPB_VAR_DEPRECATED, instance, + SerializedVarSendInput(dispatcher, var), + static_cast<int>(new_type), &se, &result)); + } + return result.Return(); +} + +bool HasProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result; +} + +bool HasMethodDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result; +} + +PP_Var GetProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + ReceiveSerializedVarReturnValue result(dispatcher); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result.Return(); +} + +void EnumerateProperties(PP_Var var, + uint32_t* property_count, + PP_Var** properties, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + + std::vector<SerializedVar> props; + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + &props, &se)); + } + + // TODO(brettw) factor this out so it can be used by ScriptableObject. + /* + *property_count = static_cast<uint32_t>(props.size()); + if (property_count) { + *properties = static_cast<PP_Var*>( + malloc(*property_count * sizeof(PP_Var*))); + for (size_t i = 0; i < props.size(); i++) { + ReceiveSerializedVarReturnValue converted(dispatcher); + SerializedVar* converted_sv = &convered; + + *static_cast<SerializedVar*>(&converted) = props[i]; + (*properties)[i] = converted.Return(); + } + } else { + *properties = NULL; + } + */ +} + +void SetPropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var value, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), + SerializedVarSendInput(dispatcher, value), &se)); + } +} + +bool DeleteProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } + return result; +} + +void RemovePropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedException se(dispatcher, exception); + bool result = false; + if (!se.IsThrown()) { + dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + SerializedVarSendInput(dispatcher, name), &se, &result)); + } +} + + +PP_Var Call(PP_Var object, + PP_Var this_object, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedVarReturnValue result(dispatcher); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect); + + dispatcher->Send(new PpapiHostMsg_PPBVar_Call( + INTERFACE_ID_PPB_VAR_DEPRECATED, + SerializedVarSendInput(dispatcher, object), + SerializedVarSendInput(dispatcher, this_object), + SerializedVarSendInput(dispatcher, method_name), argv_vect, + &se, &result)); + } + return result.Return(); +} + +PP_Var CallDeprecated(PP_Var object, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedVarReturnValue result(dispatcher); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect); + + dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, + SerializedVarSendInput(dispatcher, object), + SerializedVarSendInput(dispatcher, method_name), argv_vect, + &se, &result)); + } + return result.Return(); +} + +PP_Var Construct(PP_Var object, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedVarReturnValue result(dispatcher); + ReceiveSerializedException se(dispatcher, exception); + if (!se.IsThrown()) { + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect); + + dispatcher->Send(new PpapiHostMsg_PPBVar_Construct( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, object), + argv_vect, &se, &result)); + } + return result.Return(); +} + +bool IsInstanceOfDeprecated(PP_Var var, + const PPP_Class_Deprecated* ppp_class, + void** ppp_class_data) { + bool result = false; + Dispatcher* dispatcher = Dispatcher::Get(); + int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class)); + int64 class_data_int = 0; + dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var), + class_int, &class_data_int, &result)); + *ppp_class_data = + reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int)); + return result; +} + +PP_Var CreateObjectDeprecated(PP_Module module_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + Dispatcher* dispatcher = Dispatcher::Get(); + ReceiveSerializedVarReturnValue result(dispatcher); + int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class)); + int64 data_int = + static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data)); + dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated( + INTERFACE_ID_PPB_VAR_DEPRECATED, module_id, class_int, data_int, &result)); + return result.Return(); +} + +const PPB_Var var_interface = { + &AddRefVar, + &ReleaseVar, + &VarFromUtf8, + &VarToUtf8, + &ConvertType, +}; + + +const PPB_Var_Deprecated var_deprecated_interface = { + &AddRefVar, + &ReleaseVar, + &VarFromUtf8, + &VarToUtf8, + &HasProperty, + &HasMethodDeprecated, + &GetProperty, + &EnumerateProperties, + &SetPropertyDeprecated, + &RemovePropertyDeprecated, + &CallDeprecated, + &Construct, + &IsInstanceOfDeprecated, + &CreateObjectDeprecated +}; + +} // namespace + +PPB_Var_Proxy::PPB_Var_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_Var_Proxy::~PPB_Var_Proxy() { +} + +const void* PPB_Var_Proxy::GetSourceInterface() const { + return &var_deprecated_interface; +} + +InterfaceID PPB_Var_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPB_VAR_DEPRECATED; +} + +void PPB_Var_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPB_Var_Proxy, msg) + // AddRef /Release here + //IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DefineProperty, + // OnMsgDefineProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_ConvertType, + OnMsgConvertType) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty, + OnMsgHasProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated, + OnMsgHasMethodDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty, + OnMsgGetProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty, + OnMsgDeleteProperty) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties, + OnMsgEnumerateProperties) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated, + OnMsgSetPropertyDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsCallable, + OnMsgIsCallable) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Call, + OnMsgCall) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated, + OnMsgCallDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct, + OnMsgConstruct) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated, + OnMsgIsInstanceOfDeprecated) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated, + OnMsgCreateObjectDeprecated) + IPC_END_MESSAGE_MAP() + // FIXME(brettw) handle bad messages! +} + +void PPB_Var_Proxy::OnMsgConvertType(PP_Instance instance, + SerializedVarReceiveInput var, + int new_type, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + // FIXME(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgHasProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + *result = ppb_var_target()->HasProperty(var.Get(dispatcher()), + name.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Proxy::OnMsgHasMethodDeprecated(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + *result = ppb_var_target()->HasMethod(var.Get(dispatcher()), + name.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Proxy::OnMsgGetProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + result.Return(dispatcher(), ppb_var_target()->GetProperty( + var.Get(dispatcher()), name.Get(dispatcher()), + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Proxy::OnMsgEnumerateProperties( + SerializedVarReceiveInput var, + std::vector<pp::proxy::SerializedVar>* props, + SerializedVarOutParam exception) { + // FIXME(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgSetPropertyDeprecated( + SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarReceiveInput value, + SerializedVarOutParam exception) { + ppb_var_target()->SetProperty(var.Get(dispatcher()), + name.Get(dispatcher()), + value.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPB_Var_Proxy::OnMsgIsCallable(SerializedVarReceiveInput object, + bool* result) { + // FIXME(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgDeleteProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result) { + // FIXME(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgCall( + SerializedVarReceiveInput object, + SerializedVarReceiveInput this_object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + // FIXME(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgCallDeprecated( + SerializedVarReceiveInput object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ppb_var_target()->Call( + object.Get(dispatcher()), + method_name.Get(dispatcher()), + arg_count, args, + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Proxy::OnMsgConstruct( + SerializedVarReceiveInput var, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ppb_var_target()->Construct( + var.Get(dispatcher()), arg_count, args, + exception.OutParam(dispatcher()))); +} + +void PPB_Var_Proxy::OnMsgIsInstanceOfDeprecated( + pp::proxy::SerializedVarReceiveInput var, + int64 ppp_class, + int64* ppp_class_data, + bool* result) { + // TODO(brettw) write this. +} + +void PPB_Var_Proxy::OnMsgCreateObjectDeprecated( + PP_Module module_id, + int64 ppp_class, + int64 ppp_class_data, + SerializedVarReturnValue result) { + result.Return(dispatcher(), ppb_var_target()->CreateObject( + module_id, + reinterpret_cast<const PPP_Class_Deprecated*>( + static_cast<intptr_t>(ppp_class)), + reinterpret_cast<void*>(static_cast<intptr_t>(ppp_class_data)))); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppb_var_proxy.h b/ppapi/proxy/ppb_var_proxy.h new file mode 100644 index 0000000..2d58a76 --- /dev/null +++ b/ppapi/proxy/ppb_var_proxy.h @@ -0,0 +1,99 @@ +// 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_PPB_VAR_PROXY_H_ +#define PPAPI_PPB_VAR_PROXY_H_ + +#include <vector> + +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Var_Deprecated; + +namespace pp { +namespace proxy { + +class SerializedVar; +class SerializedVarReceiveInput; +class SerializedVarVectorReceiveInput; +class SerializedVarOutParam; +class SerializedVarReturnValue; + +class PPB_Var_Proxy : public InterfaceProxy { + public: + PPB_Var_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_Var_Proxy(); + + const PPB_Var_Deprecated* ppb_var_target() const { + return reinterpret_cast<const PPB_Var_Deprecated*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgConvertType(PP_Instance instance, + SerializedVarReceiveInput var, + int new_type, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgHasProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgHasMethodDeprecated(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgGetProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgEnumerateProperties( + SerializedVarReceiveInput var, + std::vector<pp::proxy::SerializedVar>* props, + SerializedVarOutParam exception); + void OnMsgSetPropertyDeprecated(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarReceiveInput value, + SerializedVarOutParam exception); + void OnMsgIsCallable(SerializedVarReceiveInput object, bool* result); + void OnMsgDeleteProperty(SerializedVarReceiveInput var, + SerializedVarReceiveInput name, + SerializedVarOutParam exception, + bool* result); + void OnMsgCall(SerializedVarReceiveInput object, + SerializedVarReceiveInput this_object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgCallDeprecated(SerializedVarReceiveInput object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgConstruct(SerializedVarReceiveInput var, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgIsInstanceOfDeprecated(pp::proxy::SerializedVarReceiveInput var, + int64 ppp_class, + int64* ppp_class_data, + bool* result); + void OnMsgCreateObjectDeprecated(PP_Module module_id, + int64 ppp_class, + int64 ppp_class_data, + SerializedVarReturnValue result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_VAR_PROXY_H_ diff --git a/ppapi/proxy/ppp_class_proxy.cc b/ppapi/proxy/ppp_class_proxy.cc new file mode 100644 index 0000000..bc9a0bc --- /dev/null +++ b/ppapi/proxy/ppp_class_proxy.cc @@ -0,0 +1,301 @@ +// 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/ppp_class_proxy.h" + +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/dev/ppp_class_deprecated.h" +#include "ppapi/proxy/dispatcher.h" +#include "ppapi/proxy/interface_id.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/serialized_var.h" + +namespace pp { +namespace proxy { + +namespace { + +// PPP_Class in the browser implementation ------------------------------------- + +// Represents a plugin-implemented class in the browser process. This just +// stores the data necessary to call back the plugin. +struct ObjectProxy { + ObjectProxy(Dispatcher* d, int64 p, int64 ud) + : dispatcher(d), + ppp_class(p), + user_data(ud) { + } + + Dispatcher* dispatcher; + int64 ppp_class; + int64 user_data; +}; + +ObjectProxy* ToObjectProxy(void* data) { + return reinterpret_cast<ObjectProxy*>(data); +} + +bool HasProperty(void* object, PP_Var name, PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + bool result = false; + ReceiveSerializedException se(obj->dispatcher, exception); + obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, name), &se, &result)); + return result; +} + +bool HasMethod(void* object, PP_Var name, PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + bool result = false; + ReceiveSerializedException se(obj->dispatcher, exception); + obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, name), &se, &result)); + return result; +} + +PP_Var GetProperty(void* object, + PP_Var name, + PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + ReceiveSerializedException se(obj->dispatcher, exception); + ReceiveSerializedVarReturnValue result; + obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, name), &se, &result)); + return result.Return(obj->dispatcher); +} + +void GetAllPropertyNames(void* object, + uint32_t* property_count, + PP_Var** properties, + PP_Var* exception) { + // FIXME +} + +void SetProperty(void* object, + PP_Var name, + PP_Var value, + PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + ReceiveSerializedException se(obj->dispatcher, exception); + obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, name), + SerializedVarSendInput(obj->dispatcher, value), &se)); +} + +void RemoveProperty(void* object, + PP_Var name, + PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + ReceiveSerializedException se(obj->dispatcher, exception); + obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, name), &se)); +} + +PP_Var Call(void* object, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + + ReceiveSerializedVarReturnValue result; + ReceiveSerializedException se(obj->dispatcher, exception); + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc, + &argv_vect); + + obj->dispatcher->Send(new PpapiMsg_PPPClass_Call( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data, + SerializedVarSendInput(obj->dispatcher, method_name), argv_vect, + &se, &result)); + return result.Return(obj->dispatcher); +} + +PP_Var Construct(void* object, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + ObjectProxy* obj = ToObjectProxy(object); + + ReceiveSerializedVarReturnValue result; + ReceiveSerializedException se(obj->dispatcher, exception); + std::vector<SerializedVar> argv_vect; + SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc, + &argv_vect); + + obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct( + INTERFACE_ID_PPP_CLASS, + obj->ppp_class, obj->user_data, argv_vect, &se, &result)); + return result.Return(obj->dispatcher); +} + +void Deallocate(void* object) { + ObjectProxy* obj = ToObjectProxy(object); + obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate( + INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data)); + delete obj; +} + +const PPP_Class_Deprecated class_interface = { + &HasProperty, + &HasMethod, + &GetProperty, + &GetAllPropertyNames, + &SetProperty, + &RemoveProperty, + &Call, + &Construct, + &Deallocate +}; + +// Plugin helper functions ----------------------------------------------------- + +// Converts an int64 object from IPC to a PPP_Class* for calling into the +// plugin's implementation. +const PPP_Class_Deprecated* ToPPPClass(int64 value) { + return reinterpret_cast<const PPP_Class_Deprecated*>( + static_cast<intptr_t>(value)); +} + +// Converts an int64 object from IPC to a void* for calling into the plugin's +// implementation as the user data. +void* ToUserData(int64 value) { + return reinterpret_cast<void*>(static_cast<intptr_t>(value)); +} + +} // namespace + +// PPP_Class_Proxy ------------------------------------------------------------- + +PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher) + : InterfaceProxy(dispatcher, NULL) { +} + +PPP_Class_Proxy::~PPP_Class_Proxy() { +} + +// static +PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var, + Dispatcher* dispatcher, + PP_Module module_id, + int64 ppp_class, + int64 class_data) { + ObjectProxy* object_proxy = new ObjectProxy(dispatcher, + ppp_class, class_data); + return var->CreateObject(module_id, &class_interface, object_proxy); +} + +const void* PPP_Class_Proxy::GetSourceInterface() const { + return &class_interface; +} + +InterfaceID PPP_Class_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPP_CLASS; +} + +void PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty, + OnMsgHasProperty) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod, + OnMsgHasMethod) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty, + OnMsgGetProperty) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties, + OnMsgEnumerateProperties) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty, + OnMsgSetProperty) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call, + OnMsgCall) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct, + OnMsgConstruct) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate, + OnMsgDeallocate) + IPC_END_MESSAGE_MAP() +} + +void PPP_Class_Proxy::OnMsgHasProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + bool* result) { + *result = ToPPPClass(ppp_class)->HasProperty(ToUserData(object), + property.Get(dispatcher()), exception.OutParam(dispatcher())); +} + +void PPP_Class_Proxy::OnMsgHasMethod(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + bool* result) { + *result = ToPPPClass(ppp_class)->HasMethod(ToUserData(object), + property.Get(dispatcher()), exception.OutParam(dispatcher())); +} + +void PPP_Class_Proxy::OnMsgGetProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + result.Return(dispatcher(), ToPPPClass(ppp_class)->GetProperty( + ToUserData(object), property.Get(dispatcher()), + exception.OutParam(dispatcher()))); +} + +void PPP_Class_Proxy::OnMsgEnumerateProperties( + int64 ppp_class, int64 object, + std::vector<pp::proxy::SerializedVar>* props, + SerializedVarOutParam exception) { + // FIXME +} + +void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarReceiveInput value, + SerializedVarOutParam exception) { + ToPPPClass(ppp_class)->SetProperty( + ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPP_Class_Proxy::OnMsgRemoveProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception) { + ToPPPClass(ppp_class)->RemoveProperty( + ToUserData(object), property.Get(dispatcher()), + exception.OutParam(dispatcher())); +} + +void PPP_Class_Proxy::OnMsgCall( + int64 ppp_class, int64 object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ToPPPClass(ppp_class)->Call( + ToUserData(object), method_name.Get(dispatcher()), + arg_count, args, exception.OutParam(dispatcher()))); +} + +void PPP_Class_Proxy::OnMsgConstruct( + int64 ppp_class, int64 object, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result) { + uint32_t arg_count = 0; + PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); + result.Return(dispatcher(), ToPPPClass(ppp_class)->Construct( + ToUserData(object), arg_count, args, exception.OutParam(dispatcher()))); +} + +void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) { + ToPPPClass(ppp_class)->Deallocate(ToUserData(object)); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppp_class_proxy.h b/ppapi/proxy/ppp_class_proxy.h new file mode 100644 index 0000000..b22d86a --- /dev/null +++ b/ppapi/proxy/ppp_class_proxy.h @@ -0,0 +1,89 @@ +// 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_PPP_CLASS_PROXY_H_ +#define PPAPI_PROXY_PPP_CLASS_PROXY_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PPB_Var_Deprecated; +struct PPP_Class_Deprecated; + +namespace pp { +namespace proxy { + +class SerializedVar; +class SerializedVarReceiveInput; +class SerializedVarVectorReceiveInput; +class SerializedVarOutParam; +class SerializedVarReturnValue; + +class PPP_Class_Proxy : public InterfaceProxy { + public: + // PPP_Class isn't a normal interface that you can query for, so this + // constructor doesn't take an interface pointer. + PPP_Class_Proxy(Dispatcher* dispatcher); + virtual ~PPP_Class_Proxy(); + + // Creates a proxied object in the browser process. This takes the browser's + // PPB_Var_Deprecated interface to use to create the object. The class and + static PP_Var CreateProxiedObject(const PPB_Var_Deprecated* var, + Dispatcher* dispatcher, + PP_Module module_id, + int64 ppp_class, + int64 class_data); + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // IPC message handlers. + void OnMsgHasProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + bool* result); + void OnMsgHasMethod(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + bool* result); + void OnMsgGetProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgEnumerateProperties( + int64 ppp_class, int64 object, + std::vector<pp::proxy::SerializedVar>* props, + SerializedVarOutParam exception); + void OnMsgSetProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarReceiveInput value, + SerializedVarOutParam exception); + void OnMsgRemoveProperty(int64 ppp_class, int64 object, + SerializedVarReceiveInput property, + SerializedVarOutParam exception); + void OnMsgCall(int64 ppp_class, int64 object, + SerializedVarReceiveInput method_name, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgConstruct(int64 ppp_class, int64 object, + SerializedVarVectorReceiveInput arg_vector, + SerializedVarOutParam exception, + SerializedVarReturnValue result); + void OnMsgDeallocate(int64 ppp_class, int64 object); + + DISALLOW_COPY_AND_ASSIGN(PPP_Class_Proxy); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PPP_CLASS_PROXY_H_ diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc new file mode 100644 index 0000000..770c562 --- /dev/null +++ b/ppapi/proxy/ppp_instance_proxy.cc @@ -0,0 +1,198 @@ +// 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/ppp_instance_proxy.h" + +#include <algorithm> + +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppp_instance.h" +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_message_helpers.h" +#include "ppapi/proxy/ppapi_messages.h" + +namespace pp { +namespace proxy { + +namespace { + +bool DidCreate(PP_Instance instance, + uint32_t argc, + const char* argn[], + const char* argv[]) { + std::vector<std::string> argn_vect; + std::vector<std::string> argv_vect; + for (uint32_t i = 0; i < argc; i++) { + argn_vect.push_back(std::string(argn[i])); + argv_vect.push_back(std::string(argv[i])); + } + + bool result = false; + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_DidCreate(INTERFACE_ID_PPP_INSTANCE, instance, + argn_vect, argv_vect, &result)); + return result; +} + +void DidDestroy(PP_Instance instance) { + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_DidDestroy(INTERFACE_ID_PPP_INSTANCE, instance)); +} + +void DidChangeView(PP_Instance instance, + const PP_Rect* position, + const PP_Rect* clip) { + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_DidChangeView(INTERFACE_ID_PPP_INSTANCE, + instance, *position, *clip)); +} + +void DidChangeFocus(PP_Instance instance, bool has_focus) { + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_DidChangeFocus(INTERFACE_ID_PPP_INSTANCE, + instance, has_focus)); +} + +bool HandleInputEvent(PP_Instance instance, + const PP_InputEvent* event) { + bool result = false; + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_HandleInputEvent(INTERFACE_ID_PPP_INSTANCE, + instance, *event, &result)); + return result; +} + +bool HandleDocumentLoad(PP_Instance instance, + PP_Resource url_loader) { + bool result = false; + HostDispatcher::GetForInstance(instance)->Send( + new PpapiMsg_PPPInstance_HandleDocumentLoad(INTERFACE_ID_PPP_INSTANCE, + instance, url_loader, + &result)); + return result; +} + +PP_Var GetInstanceObject(PP_Instance instance) { + Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance); + ReceiveSerializedVarReturnValue result; + dispatcher->Send(new PpapiMsg_PPPInstance_GetInstanceObject( + instance, INTERFACE_ID_PPP_INSTANCE, &result)); + return result.Return(dispatcher); +} + +static const PPP_Instance instance_interface = { + &DidCreate, + &DidDestroy, + &DidChangeView, + &DidChangeFocus, + &HandleInputEvent, + &HandleDocumentLoad, + &GetInstanceObject +}; + +} // namespace + +PPP_Instance_Proxy::PPP_Instance_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPP_Instance_Proxy::~PPP_Instance_Proxy() { +} + +const void* PPP_Instance_Proxy::GetSourceInterface() const { + return &instance_interface; +} + +InterfaceID PPP_Instance_Proxy::GetInterfaceId() const { + return INTERFACE_ID_PPP_INSTANCE; +} + +void PPP_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate, + OnMsgDidCreate) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy, + OnMsgDidDestroy) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView, + OnMsgDidChangeView) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus, + OnMsgDidChangeFocus) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleInputEvent, + OnMsgHandleInputEvent) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad, + OnMsgHandleDocumentLoad) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_GetInstanceObject, + OnMsgGetInstanceObject) + IPC_END_MESSAGE_MAP() +} + +void PPP_Instance_Proxy::OnMsgDidCreate( + PP_Instance instance, + const std::vector<std::string>& argn, + const std::vector<std::string>& argv, + bool* result) { + *result = false; + if (argn.size() != argv.size()) + return; + + // Make sure the arrays always have at least one element so we can take the + // address below. + std::vector<const char*> argn_array; + std::vector<const char*> argv_array; + argn_array.resize(std::max(static_cast<size_t>(1), argn.size())); + argv_array.resize(std::max(static_cast<size_t>(1), argn.size())); + for (size_t i = 0; i < argn.size(); i++) { + argn_array[i] = argn[i].c_str(); + argv_array[i] = argv[i].c_str(); + } + + DCHECK(ppp_instance_target()); + *result = ppp_instance_target()->DidCreate(instance, + static_cast<uint32_t>(argn.size()), + &argn_array[0], &argv_array[0]); + DCHECK(*result); +} + +void PPP_Instance_Proxy::OnMsgDidDestroy(PP_Instance instance) { + ppp_instance_target()->DidDestroy(instance); +} + +void PPP_Instance_Proxy::OnMsgDidChangeView(PP_Instance instance, + const PP_Rect& position, + const PP_Rect& clip) { + ppp_instance_target()->DidChangeView(instance, &position, &clip); +} + +void PPP_Instance_Proxy::OnMsgDidChangeFocus(PP_Instance instance, + bool has_focus) { + ppp_instance_target()->DidChangeFocus(instance, has_focus); +} + +void PPP_Instance_Proxy::OnMsgHandleInputEvent(PP_Instance instance, + const PP_InputEvent& event, + bool* result) { + *result = ppp_instance_target()->HandleInputEvent(instance, &event); +} + +void PPP_Instance_Proxy::OnMsgHandleDocumentLoad(PP_Instance instance, + PP_Resource url_loader, + bool* result) { + NOTREACHED(); + /* TODO(brettw) write this. We need to convert the PP_Resource to a URL + loader proxy resource + object, but that currently isn't implemented. + *result = ppp_instance_target()->HandleDocumentLoad( + instance, url_loader DO SOMETHING WITH THIS); + */ +} + +void PPP_Instance_Proxy::OnMsgGetInstanceObject( + PP_Instance instance, + SerializedVarReturnValue result) { + result.Return(dispatcher(), + ppp_instance_target()->GetInstanceObject(instance)); +} + +} // namespace proxy +} // namespace pp diff --git a/ppapi/proxy/ppp_instance_proxy.h b/ppapi/proxy/ppp_instance_proxy.h new file mode 100644 index 0000000..9fe40b9 --- /dev/null +++ b/ppapi/proxy/ppp_instance_proxy.h @@ -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. + +#ifndef PPAPI_PROXY_PPP_INSTANCE_PROXY_H_ +#define PPAPI_PROXY_PPP_INSTANCE_PROXY_H_ + +#include <string> +#include <vector> + +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/proxy/interface_proxy.h" + +struct PP_InputEvent; +struct PP_Rect; +struct PPP_Instance; + +namespace pp { +namespace proxy { + +class SerializedVarReturnValue; + +class PPP_Instance_Proxy : public InterfaceProxy { + public: + PPP_Instance_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPP_Instance_Proxy(); + + const PPP_Instance* ppp_instance_target() const { + return reinterpret_cast<const PPP_Instance*>(target_interface()); + } + + // InterfaceProxy implementation. + virtual const void* GetSourceInterface() const; + virtual InterfaceID GetInterfaceId() const; + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + // Message handlers. + void OnMsgDidCreate(PP_Instance instance, + const std::vector<std::string>& argn, + const std::vector<std::string>& argv, + bool* result); + void OnMsgDidDestroy(PP_Instance instance); + void OnMsgDidChangeView(PP_Instance instance, + const PP_Rect& position, + const PP_Rect& clip); + void OnMsgDidChangeFocus(PP_Instance instance, bool has_focus); + void OnMsgHandleInputEvent(PP_Instance instance, + const PP_InputEvent& event, + bool* result); + void OnMsgHandleDocumentLoad(PP_Instance instance, + PP_Resource url_loader, + bool* result); + void OnMsgGetInstanceObject(PP_Instance instance, + SerializedVarReturnValue result); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_PPP_INSTANCE_PROXY_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 + diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h new file mode 100644 index 0000000..4d4230d --- /dev/null +++ b/ppapi/proxy/serialized_var.h @@ -0,0 +1,451 @@ +// 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_SERIALIZED_VAR_H_ +#define PPAPI_PROXY_SERIALIZED_VAR_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/linked_ptr.h" +#include "ppapi/c/pp_var.h" + +namespace IPC { +class Message; +} + +namespace pp { +namespace proxy { + +class Dispatcher; +class VarSerializationRules; + +// This class encapsulates a var so that we can serialize and deserialize it +// The problem is that for strings, serialization and deserialization requires +// knowledge from outside about how to get at or create a string. So this +// object groups the var with a dispatcher so that string values can be set or +// gotten. +// +// Declare IPC messages as using this type, but don't use it directly (it has +// no useful public methods). Instead, instantiate one of the helper classes +// below which are conveniently named for each use case to prevent screwups. +// +// Design background +// ----------------- +// This is sadly super complicated. The IPC must all use the same type and it +// must include a var and a dispatcher (this is a SerializedVar). But there are +// many combinations of proper reference counting for sending and receiving +// different types and when different data is avaliable (like the Dispatcher is +// not available at IPC read time). So SerializedVar has to encapsulate all of +// these modes. +// +// This makes SerializedVar complicate and easy to mess up. To make it +// reasonable to use all functions are protected and there are a use-specific +// classes that encapsulate exactly one type of use in a way that typically +// won't compile if you do the wrong thing. +// +// The IPC system is designed to pass things around and will make copies in +// some cases, so our system must be designed so that this stuff will work. +// This is challenging when the SerializedVar must to some cleanup after the +// message is sent. To work around this, we create an inner class using a +// linked_ptr so all copies of a SerializedVar can share and we can guarantee +// that the actual data will get cleaned up on shutdown. +// +// Constness +// --------- +// SerializedVar basically doesn't support const. Everything is mutable and +// most functions are declared const. This unfortunateness is because of the +// way the IPC system works. When deserializing, it will have a const +// SerializedVar in a Tuple and this will be given to the function. We kind of +// want to modify that to convert strings and do refcounting. +// +// The helper classes used for accessing the SerializedVar have more reasonable +// behavior and will enforce that you don't do stupid things. +class SerializedVar { + public: + enum CleanupMode { + // The serialized var won't do anything special in the destructor (default). + CLEANUP_NONE, + + // The serialized var will call EndSendPassRef in the destructor. + END_SEND_PASS_REF, + + // The serialized var will call EndReceiveCallerOwned in the destructor. + END_RECEIVE_CALLER_OWNED + }; + + SerializedVar(); + ~SerializedVar(); + + // Backend implementation for IPC::ParamTraits<SerializedVar>. + void WriteToMessage(IPC::Message* m) const { + inner_->WriteToMessage(m); + } + bool ReadFromMessage(const IPC::Message* m, void** iter) { + return inner_->ReadFromMessage(m, iter); + } + + protected: + friend class SerializedVarReceiveInput; + friend class SerializedVarReturnValue; + friend class SerializedVarOutParam; + friend class SerializedVarSendInput; + friend class SerializedVarVectorReceiveInput; + + SerializedVar(VarSerializationRules* serialization_rules); + SerializedVar(VarSerializationRules* serialization, const PP_Var& var); + + VarSerializationRules* serialization_rules() const { + return inner_->serialization_rules(); + } + void set_serialization_rules(VarSerializationRules* s) const { + inner_->set_serialization_rules(s); + } + + void set_cleanup_mode(CleanupMode cm) const { + inner_->set_cleanup_mode(cm); + } + + // Returns the completed var for this object. The serialization rules must + // have been set already, and any string conversions must already have + // happened. + PP_Var GetVar() const { + return inner_->GetVar(); + } + + // Returns the var which has not had a string serialization happen yet. This + // is used for actually converting a string PP_Var to the string literal. + PP_Var GetIncompleteVar() const { + return inner_->GetIncompleteVar(); + } + + void SetVar(const PP_Var& var) const { + inner_->SetVar(var); + } + + // When this serialized var is a string var, returns the associated string. + // with the value. This can be called if the var isn't a string, but will + // just return the empty string in this case. + const std::string& GetString() const { + return inner_->GetString(); + } + + // Returns a pointer to the inner string associated with this class. The + // derived classes will use this when converting a PP_Var to the string + // literal. This can be called if the var isn't a string, but the value + // should not be written to (this simplifies the callers who can always pass + // the result of this function call to the VarSerializationRules classes). + std::string* GetStringPtr() const { + return inner_->GetStringPtr(); + } + + private: + class Inner { + public: + Inner(); + Inner(VarSerializationRules* serialization_rules); + Inner(VarSerializationRules* serialization_rules, const PP_Var& var); + ~Inner(); + + VarSerializationRules* serialization_rules() { + return serialization_rules_; + } + void set_serialization_rules(VarSerializationRules* serialization_rules) { + serialization_rules_ = serialization_rules; + } + + void set_cleanup_mode(CleanupMode cm) { cleanup_mode_ = cm; } + + // See outer class's declarations above. + PP_Var GetVar() const; + PP_Var GetIncompleteVar() const; + void SetVar(PP_Var var); + const std::string& GetString() const; + std::string* GetStringPtr(); + + void WriteToMessage(IPC::Message* m) const; + bool ReadFromMessage(const IPC::Message* m, void** iter); + + private: + // Rules for serializing and deserializing vars for this process type. + // This may be NULL, but must be set before trying to serialize to IPC when + // sending, or before converting back to a PP_Var when receiving. + VarSerializationRules* serialization_rules_; + + // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the + // string_value_ contains the string. This means that the caller hasn't + // called Deserialize with a valid Dispatcher yet, which is how we can + // convert the serialized string value to a PP_Var string ID. + // + // This var may not be complete until the serialization rules are set when + // reading from IPC since we'll need that to convert the string_value to + // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING. + PP_Var var_; + + // Holds the literal string value to/from IPC. This will be valid of the + // var_ is VARTYPE_STRING. + std::string string_value_; + + CleanupMode cleanup_mode_; + +#ifndef NDEBUG + // When being sent or received over IPC, we should only be serialized or + // deserialized once. These flags help us assert this is true. + mutable bool has_been_serialized_; + mutable bool has_been_deserialized_; +#endif + + DISALLOW_COPY_AND_ASSIGN(Inner); + }; + + mutable linked_ptr<Inner> inner_; +}; + +// Helpers for message sending side -------------------------------------------- + +// For sending a value to the remote side. +// +// Example for API: +// void MyFunction(PP_Var) +// IPC message: +// IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); +// Sender would be: +// void MyFunctionProxy(PP_Var param) { +// Send(new MyFunctionMsg(SerializedVarSendInput(param)); +// } +class SerializedVarSendInput : public SerializedVar { + public: + SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var); + + // Helper function for serializing a vector of input vars for serialization. + static void ConvertVector(Dispatcher* dispatcher, + const PP_Var* input, + size_t input_count, + std::vector<SerializedVar>* output); + + private: + // Disallow the empty constructor, but keep the default copy constructor + // which is required to send the object to the IPC system. + SerializedVarSendInput(); +}; + +// For the calling side of a function returning a var. The sending side uses +// SerializedVarReturnValue. +// +// Example for API: +// PP_Var MyFunction() +// IPC message: +// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); +// Message handler would be: +// PP_Var MyFunctionProxy() { +// ReceiveSerializedVarReturnValue result; +// Send(new MyFunctionMsg(&result)); +// return result.Return(dispatcher()); +// } +class ReceiveSerializedVarReturnValue : public SerializedVar { + public: + // Note that we can't set the dispatcher in the constructor because the + // data will be overridden when the return value is set. + ReceiveSerializedVarReturnValue(); + + PP_Var Return(Dispatcher* dispatcher); + + private: + DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue); +}; + +// Example for API: +// "void MyFunction(PP_Var* exception);" +// IPC message: +// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); +// Message handler would be: +// void OnMsgMyFunction(PP_Var* exception) { +// ReceiveSerializedException se(dispatcher(), exception) +// Send(new PpapiHostMsg_Foo(&se)); +// } +class ReceiveSerializedException : public SerializedVar { + public: + ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception); + ~ReceiveSerializedException(); + + // Returns true if the exception passed in the constructor is set. Check + // this before actually issuing the IPC. + bool IsThrown() const; + + private: + // The input/output exception we're wrapping. May be NULL. + PP_Var* exception_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException); +}; + +// Helper class for when we're returning a vector of Vars. When it goes out +// of scope it will automatically convert the vector filled by the IPC layer +// into the array specified by the constructor params. +// +// Example for API: +// "void MyFunction(uint32_t* count, PP_Var** vars);" +// IPC message: +// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>); +// Proxy function: +// void MyFunction(uint32_t* count, PP_Var** vars) { +// ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars); +// Send(new MyMsg(vect.OutParam())); +// } +class ReceiveSerializedVarVectorOutParam { + public: + ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher, + uint32_t* output_count, + PP_Var** output); + ~ReceiveSerializedVarVectorOutParam(); + + std::vector<SerializedVar>* OutParam(); + + private: + Dispatcher* dispatcher_; + uint32_t* output_count_; + PP_Var** output_; + + std::vector<SerializedVar> vector_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam); +}; + +// Helpers for message receiving side ------------------------------------------ + +// For receiving a value from the remote side. +// +// Example for API: +// void MyFunction(PP_Var) +// IPC message: +// IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); +// Message handler would be: +// void OnMsgMyFunction(SerializedVarReceiveInput param) { +// MyFunction(param.Get()); +// } +class SerializedVarReceiveInput { + public: + // We rely on the implicit constructor here since the IPC layer will call + // us with a SerializedVar. Pass this object by value, the copy constructor + // will pass along the pointer (as cheap as passing a pointer arg). + SerializedVarReceiveInput(const SerializedVar& serialized); + ~SerializedVarReceiveInput(); + + PP_Var Get(Dispatcher* dispatcher); + + private: + const SerializedVar& serialized_; + + // Since the SerializedVar is const, we can't set its dispatcher (which is + // OK since we don't need to). But since we need it for our own uses, we + // track it here. Will be NULL before Get() is called. + Dispatcher* dispatcher_; + PP_Var var_; +}; + +// For receiving an input vector of vars from the remote side. +// +// Example: +// OnMsgMyFunction(SerializedVarVectorReceiveInput vector) { +// uint32_t size; +// PP_Var* array = vector.Get(dispatcher, &size); +// MyFunction(size, array); +// } +class SerializedVarVectorReceiveInput { + public: + SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized); + ~SerializedVarVectorReceiveInput(); + + // Only call Get() once. It will return a pointer to the converted array and + // place the array size in the out param. Will return NULL when the array is + // empty. + PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size); + + private: + const std::vector<SerializedVar>& serialized_; + + // Filled by Get(). + std::vector<PP_Var> deserialized_; +}; + +// For the receiving side of a function returning a var. The calling side uses +// ReceiveSerializedVarReturnValue. +// +// Example for API: +// PP_Var MyFunction() +// IPC message: +// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); +// Message handler would be: +// void OnMsgMyFunction(SerializedVarReturnValue result) { +// result.Return(dispatcher(), MyFunction()); +// } +class SerializedVarReturnValue { + public: + // We rely on the implicit constructor here since the IPC layer will call + // us with a SerializedVar*. Pass this object by value, the copy constructor + // will pass along the pointer (as cheap as passing a pointer arg). + SerializedVarReturnValue(SerializedVar* serialized); + + void Return(Dispatcher* dispatcher, const PP_Var& var); + + private: + SerializedVar* serialized_; +}; + +// For writing an out param to the remote side. +// +// Example for API: +// "void MyFunction(PP_Var* out);" +// IPC message: +// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); +// Message handler would be: +// void OnMsgMyFunction(SerializedVarOutParam out_param) { +// MyFunction(out_param.OutParam(dispatcher())); +// } +class SerializedVarOutParam { + public: + // We rely on the implicit constructor here since the IPC layer will call + // us with a SerializedVar*. Pass this object by value, the copy constructor + // will pass along the pointer (as cheap as passing a pointer arg). + SerializedVarOutParam(SerializedVar* serialized); + ~SerializedVarOutParam(); + + // Call this function only once. The caller should write its result to the + // returned var pointer before this class goes out of scope. The var's + // initial value will be VARTYPE_UNDEFINED. + PP_Var* OutParam(Dispatcher* dispatcher); + + private: + SerializedVar* serialized_; + + // This is the value actually written by the code and returned by OutParam. + // We'll write this into serialized_ in our destructor. + PP_Var writable_var_; +}; + +// For returning an array of PP_Vars to the other side and transferring +// ownership. +// +class SerializedVarVectorOutParam { + public: + SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized); + ~SerializedVarVectorOutParam(); + + uint32_t* CountOutParam() { return &count_; } + PP_Var** ArrayOutParam(Dispatcher* dispatcher); + + private: + Dispatcher* dispatcher_; + std::vector<SerializedVar>* serialized_; + + uint32_t count_; + PP_Var* array_; +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_SERIALIZED_VAR_H_ + diff --git a/ppapi/proxy/var_serialization_rules.h b/ppapi/proxy/var_serialization_rules.h new file mode 100644 index 0000000..bf00547 --- /dev/null +++ b/ppapi/proxy/var_serialization_rules.h @@ -0,0 +1,85 @@ +// 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_VAR_SERIALIZATION_RULES_H_ +#define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_ + +#include "ppapi/c/pp_var.h" + +#include <string> + +namespace pp { +namespace proxy { + +// Encapsulates the rules for serializing and deserializing vars to and from +// the local process. The renderer and the plugin process each have separate +// bookkeeping rules. +class VarSerializationRules { + public: + virtual ~VarSerializationRules() {} + + // Caller-owned calls -------------------------------------------------------- + // + // A caller-owned call is when doing a function call with a "normal" input + // argument. The caller has a reference to the var, and the caller is + // responsible for freeing that reference. + + // Prepares the given var for sending to the callee. If the var is a string, + // the value of that string will be placed in *str_val. If the var is not + // a string, str_val will beuntouched and may be NULL. + virtual void SendCallerOwned(const PP_Var& var, std::string* str_val) = 0; + + // When receiving a caller-owned variable, normally we don't have to do + // anything. However, in the case of strings, we need to deserialize the + // string from IPC, create a new PP_Var string in the local process, call the + // function, and then destroy the temporary string. These two functions + // handle that process + // + // BeginReceiveCallerOwned takes a var from IPC and an optional pointer to + // the deserialized string (which will be used only when var is a + // VARTYPE_STRING and may be NULL otherwise) and returns a new var + // representing the input in the local process. The output will be the same + // as the input except for strings. + // + // EndReceiveCallerOwned destroys the string created by Begin* and does + // nothing otherwise. It should be called with the result of Begin*. + virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, + const std::string* str_val) = 0; + virtual void EndReceiveCallerOwned(const PP_Var& var) = 0; + + // Passinag refs ------------------------------------------------------------- + // + // A pass-ref transfer is when ownership of a reference is passed from + // onen side to the other. Normally, this happens via return values and + // output arguments, as for exceptions. The code generating the value + // (the function returning it in the case of a return value) will AddRef + // the var on behalf of the consumer of the value. Responsibility for + // Release is on the consumer (the caller of the function in the case of a + // return value). + + // Creates a var in the context of the local process from the given + // deserialized var and deserialized string (which will be used only when var + // is a VARTYPE_STRING and may be NULL otherwise). The input var/string + // should be the result of calling SendPassRef in the remote process. + virtual PP_Var ReceivePassRef(const PP_Var& var, + const std::string& str_val) = 0; + + // Prepares a var to be sent to the remote side. One local reference will + // be passed to the remote side. Call Begin* before doing the send and End* + // after doing the send. See SendCallerOwned for a description of the string. + virtual void BeginSendPassRef(const PP_Var& var, std::string* str_val) = 0; + virtual void EndSendPassRef(const PP_Var& var) = 0; + + // --------------------------------------------------------------------------- + + virtual void ReleaseObjectRef(const PP_Var& var) = 0; + + protected: + VarSerializationRules() {} +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_ |