diff options
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_ |