summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-05 22:13:02 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-05 22:13:02 +0000
commit4c2e935b2b9adc5894b9de72b4a119a8cd173b63 (patch)
treed5fd2d0d8bd800c89bfa59a9f3e679f55df4ea43 /ppapi/proxy
parent751bf4bbbfa669bfa9c21eef69c150b8bdbf2250 (diff)
downloadchromium_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.cc138
-rw-r--r--ppapi/proxy/ppb_instance_proxy.h55
-rw-r--r--ppapi/proxy/ppb_url_loader_proxy.cc419
-rw-r--r--ppapi/proxy/ppb_url_loader_proxy.h74
-rw-r--r--ppapi/proxy/ppp_instance_proxy.cc195
-rw-r--r--ppapi/proxy/ppp_instance_proxy.h63
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_