Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Unified Diff: ppapi/proxy/ppb_url_loader_proxy.cc

Issue 4289005: Instance interface implementation. These don't build by themselves, this is... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ppapi/proxy/ppb_url_loader_proxy.h ('k') | ppapi/proxy/ppp_instance_proxy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ppapi/proxy/ppb_url_loader_proxy.cc
===================================================================
--- ppapi/proxy/ppb_url_loader_proxy.cc (revision 0)
+++ ppapi/proxy/ppb_url_loader_proxy.cc (revision 0)
@@ -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
Property changes on: ppapi/proxy/ppb_url_loader_proxy.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « ppapi/proxy/ppb_url_loader_proxy.h ('k') | ppapi/proxy/ppp_instance_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698