diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-05 22:13:02 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-05 22:13:02 +0000 |
commit | 4c2e935b2b9adc5894b9de72b4a119a8cd173b63 (patch) | |
tree | d5fd2d0d8bd800c89bfa59a9f3e679f55df4ea43 /ppapi/proxy | |
parent | 751bf4bbbfa669bfa9c21eef69c150b8bdbf2250 (diff) | |
download | chromium_src-4c2e935b2b9adc5894b9de72b4a119a8cd173b63.zip chromium_src-4c2e935b2b9adc5894b9de72b4a119a8cd173b63.tar.gz chromium_src-4c2e935b2b9adc5894b9de72b4a119a8cd173b63.tar.bz2 |
Instance interface implementation. These don't build by themselves, this is
part of a larger patch. You can see most of the serialization mechanics already
checked in to the same directory.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/4289005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65260 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/ppb_instance_proxy.cc | 138 | ||||
-rw-r--r-- | ppapi/proxy/ppb_instance_proxy.h | 55 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.cc | 419 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.h | 74 | ||||
-rw-r--r-- | ppapi/proxy/ppp_instance_proxy.cc | 195 | ||||
-rw-r--r-- | ppapi/proxy/ppp_instance_proxy.h | 63 |
6 files changed, 944 insertions, 0 deletions
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc new file mode 100644 index 0000000..024673e --- /dev/null +++ b/ppapi/proxy/ppb_instance_proxy.cc @@ -0,0 +1,138 @@ +// 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_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..b863de3 --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.cc @@ -0,0 +1,419 @@ +// 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/host_dispatcher.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_url_response_info_proxy.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; } + + // Initialized to -1. Will be set to nonnegative values by the UpdateProgress + // message when the values are known. + int64_t bytes_sent_; + int64_t total_bytes_to_be_sent_; + int64_t bytes_received_; + int64_t total_bytes_to_be_received_; + + // When an asynchronous read is pending, this will contain the callback and + // the buffer to put the data. + PP_CompletionCallback current_read_callback_; + char* current_read_buffer_; + + private: + DISALLOW_COPY_AND_ASSIGN(URLLoader); +}; + +URLLoader::URLLoader() + : bytes_sent_(-1), + total_bytes_to_be_sent_(-1), + bytes_received_(-1), + total_bytes_to_be_received_(-1), + current_read_callback_(PP_MakeCompletionCallback(NULL, NULL)), + current_read_buffer_(NULL) { +} + +URLLoader::~URLLoader() { +} + +namespace { + +// Plugin interface implmentation ---------------------------------------------- + +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) + PPB_URLLoader_Proxy::TrackPluginResource(result); + 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) { + URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id); + if (!object || object->bytes_sent_ == -1) { + *bytes_sent = 0; + *total_bytes_to_be_sent = 0; + return false; + } + *bytes_sent = object->bytes_sent_; + *total_bytes_to_be_sent = object->total_bytes_to_be_sent_; + return true; +} + +bool GetDownloadProgress(PP_Resource loader_id, + int64_t* bytes_received, + int64_t* total_bytes_to_be_received) { + URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id); + if (!object || object->bytes_received_ == -1) { + *bytes_received = 0; + *total_bytes_to_be_received = 0; + return false; + } + *bytes_received = object->bytes_received_; + *total_bytes_to_be_received = object->total_bytes_to_be_received_; + return true; +} + +PP_Resource GetResponseInfo(PP_Resource loader_id) { + // If we find that plugins are frequently requesting the response info, we + // can improve performance by caching the PP_Resource in the URLLoader + // object. This way we only have to do IPC for the first request. However, + // it seems that most plugins will only call this once so there's no use + // optimizing this case. + + PP_Resource result; + PluginDispatcher* dispatcher = PluginDispatcher::Get(); + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo( + INTERFACE_ID_PPB_URL_LOADER, loader_id, &result)); + if (dispatcher->plugin_resource_tracker()->PreparePreviouslyTrackedResource( + result)) + return result; + + // Tell the response info to create a tracking object and add it to the + // resource tracker. + PPB_URLResponseInfo_Proxy::TrackPluginResource(result); + return result; +} + +int32_t ReadResponseBody(PP_Resource loader_id, + char* buffer, + int32_t bytes_to_read, + PP_CompletionCallback callback) { + URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id); + if (!object) + return PP_ERROR_BADRESOURCE; + + if (!buffer) + return PP_ERROR_BADARGUMENT; // Must specify an output buffer. + if (object->current_read_callback_.func) + return PP_ERROR_INPROGRESS; // Can only have one request pending. + + // Currently we don't support sync calls to read. We'll need to revisit + // how this works when we allow blocking calls (from background threads). + if (!callback.func) + return PP_ERROR_BADARGUMENT; + + object->current_read_callback_ = callback; + object->current_read_buffer_ = buffer; + + PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody( + INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_to_read)); + 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 +}; + +// Renderer status updates ----------------------------------------------------- + +// Called in the renderer when the byte counts have changed. We send a message +// to the plugin to synchronize its counts so it can respond to status polls +// from the plugin. +void UpdateResourceLoadStatus(PP_Instance pp_instance, + PP_Resource pp_resource, + int64 bytes_sent, + int64 total_bytes_to_be_sent, + int64 bytes_received, + int64 total_bytes_to_be_received) { + Dispatcher* dispatcher = HostDispatcher::GetForInstance(pp_instance); + dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress( + INTERFACE_ID_PPB_URL_LOADER, pp_resource, + bytes_sent, total_bytes_to_be_sent, + bytes_received, total_bytes_to_be_received)); +} + +// Data associated with callbacks for ReadResponseBody. +struct ReadCallbackInfo { + base::WeakPtr<PPB_URLLoader_Proxy> loader; + PP_Resource pp_resource; + std::string read_buffer; +}; + +// Callback for renderer calls to ReadResponseBody. This function will forward +// the result to the plugin and clean up the callback info. +void ReadCallbackHandler(void* user_data, int32_t result) { + scoped_ptr<ReadCallbackInfo> info(static_cast<ReadCallbackInfo*>(user_data)); + if (!info->loader) + return; + + int32_t bytes_read = 0; + if (result > 0) + bytes_read = result; // Positive results indicate bytes read. + info->read_buffer.resize(bytes_read); + + info->loader->dispatcher()->Send( + new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack( + INTERFACE_ID_PPB_URL_LOADER, info->pp_resource, + result, info->read_buffer)); +} + +} // namespace + +// PPB_URLLoader_Proxy --------------------------------------------------------- + +PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher, + const void* target_interface) + : InterfaceProxy(dispatcher, target_interface) { +} + +PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() { +} + +// static +void PPB_URLLoader_Proxy::TrackPluginResource(PP_Resource url_loader_resource) { + linked_ptr<URLLoader> object(new URLLoader); + PluginDispatcher::Get()->plugin_resource_tracker()->AddResource( + url_loader_resource, object); +} + +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_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_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack, + OnMsgReadResponseBodyAck) + 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) { + PP_CompletionCallback callback = ReceiveCallback(serialized_callback); + int32_t result = ppb_url_loader_target()->Open( + loader, request_info, callback); + if (result != PP_ERROR_WOULDBLOCK) + PP_RunCompletionCallback(&callback, result); +} + +void PPB_URLLoader_Proxy::OnMsgFollowRedirect( + PP_Resource loader, + uint32_t serialized_callback) { + PP_CompletionCallback callback = ReceiveCallback(serialized_callback); + int32_t result = ppb_url_loader_target()->FollowRedirect( + loader, callback); + if (result != PP_ERROR_WOULDBLOCK) + PP_RunCompletionCallback(&callback, result); +} + +void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(PP_Resource loader, + PP_Resource* result) { + *result = ppb_url_loader_target()->GetResponseInfo(loader); +} + +void PPB_URLLoader_Proxy::OnMsgReadResponseBody( + PP_Resource loader, + int32_t bytes_to_read) { + // The plugin could be sending us malicious messages, don't accept negative + // sizes. + if (bytes_to_read < 0) { + // TODO(brettw) kill plugin. + bytes_to_read = 0; + } + + // This heap object will get deleted by the callback handler. + // TODO(brettw) this will be leaked if the plugin closes the resource! + // (Also including the plugin unloading and having the resource implicitly + // destroyed. Depending on the cleanup ordering, we may not need the weak + // pointer here.) + ReadCallbackInfo* info = new ReadCallbackInfo; + info->loader = AsWeakPtr(); + info->pp_resource = loader; + info->read_buffer.resize(bytes_to_read); + + int32_t result = ppb_url_loader_target()->ReadResponseBody( + loader, const_cast<char*>(info->read_buffer.c_str()), bytes_to_read, + PP_MakeCompletionCallback(&ReadCallbackHandler, info)); + if (result != PP_ERROR_WOULDBLOCK) { + // Send error (or perhaps success for synchronous reads) back to plugin. + // The callback function is already set up to do this and also delete the + // callback info. + ReadCallbackHandler(info, result); + } +} + +void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( + PP_Resource loader, + uint32_t serialized_callback) { + PP_CompletionCallback callback = ReceiveCallback(serialized_callback); + int32_t result = ppb_url_loader_target()->FinishStreamingToFile( + loader, callback); + if (result != PP_ERROR_WOULDBLOCK) + PP_RunCompletionCallback(&callback, result); +} + +void PPB_URLLoader_Proxy::OnMsgClose(PP_Resource loader) { + ppb_url_loader_target()->Close(loader); +} + +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) { + NOTREACHED(); + 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; +} + +void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck(PP_Resource pp_resource, + int32 result, + const std::string& data) { + URLLoader* object = PluginResource::GetAs<URLLoader>(pp_resource); + if (!object) { + NOTREACHED(); + return; + } + + if (!object->current_read_callback_.func || !object->current_read_buffer_) { + NOTREACHED(); + return; + } + + // In the error case, the string will be empty, so we can always just copy + // out of it before issuing the callback. + memcpy(object->current_read_buffer_, data.c_str(), data.length()); + + // The plugin should be able to make a new request from their callback, so + // we have to clear our copy first. + PP_CompletionCallback temp_callback = object->current_read_callback_; + object->current_read_callback_ = PP_BlockUntilComplete(); + object->current_read_buffer_ = NULL; + PP_RunCompletionCallback(&temp_callback, result); +} + +} // 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..cc35677 --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -0,0 +1,74 @@ +// 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 "base/weak_ptr.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 base::SupportsWeakPtr<PPB_URLLoader_Proxy> { + public: + PPB_URLLoader_Proxy(Dispatcher* dispatcher, const void* target_interface); + virtual ~PPB_URLLoader_Proxy(); + + // URLLoader objects are normally allocated by the Create function, but + // they are also provided to PPP_Instance.OnMsgHandleDocumentLoad. This + // function allows the proxy for DocumentLoad to create the correct plugin + // proxied info for the given browser-supplied URLLoader resource ID. + static void TrackPluginResource(PP_Resource url_loader_resource); + + 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 OnMsgGetResponseInfo(PP_Resource loader, + PP_Resource* result); + void OnMsgReadResponseBody(PP_Resource loader, + int32_t bytes_to_read); + 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); + void OnMsgReadResponseBodyAck(PP_Resource pp_resource, + int32_t result, + const std::string& data); +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PPB_URL_LOADER_PROXY_H_ diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc new file mode 100644 index 0000000..0b5a889 --- /dev/null +++ b/ppapi/proxy/ppp_instance_proxy.cc @@ -0,0 +1,195 @@ +// 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_messages.h" +#include "ppapi/proxy/ppb_url_loader_proxy.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::max(static_cast<size_t>(1), argn.size())); + std::vector<const char*> argv_array; + 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) { + PPB_URLLoader_Proxy::TrackPluginResource(url_loader); + *result = ppp_instance_target()->HandleDocumentLoad( + instance, url_loader); +} + +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_ |