| Index: ppapi/proxy/ppb_url_loader_proxy.cc
|
| ===================================================================
|
| --- ppapi/proxy/ppb_url_loader_proxy.cc (revision 72517)
|
| +++ ppapi/proxy/ppb_url_loader_proxy.cc (working copy)
|
| @@ -16,6 +16,7 @@
|
| #include "ppapi/proxy/host_dispatcher.h"
|
| #include "ppapi/proxy/plugin_dispatcher.h"
|
| #include "ppapi/proxy/plugin_resource.h"
|
| +#include "ppapi/proxy/plugin_resource_tracker.h"
|
| #include "ppapi/proxy/ppapi_messages.h"
|
| #include "ppapi/proxy/ppb_url_response_info_proxy.h"
|
|
|
| @@ -28,12 +29,14 @@
|
|
|
| class URLLoader : public PluginResource {
|
| public:
|
| - URLLoader(PP_Instance instance);
|
| + URLLoader(PP_Instance instance, SerializedResource resource);
|
| virtual ~URLLoader();
|
|
|
| // Resource overrides.
|
| virtual URLLoader* AsURLLoader() { return this; }
|
|
|
| + PP_Resource GetResponseInfo();
|
| +
|
| // Initialized to -1. Will be set to nonnegative values by the UpdateProgress
|
| // message when the values are known.
|
| int64_t bytes_sent_;
|
| @@ -46,32 +49,63 @@
|
| PP_CompletionCallback current_read_callback_;
|
| char* current_read_buffer_;
|
|
|
| + // Cached copy of the response info. When nonzero, we're holding a reference
|
| + // to this resource.
|
| + PP_Resource response_info_;
|
| +
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(URLLoader);
|
| };
|
|
|
| -URLLoader::URLLoader(PP_Instance instance)
|
| - : PluginResource(instance),
|
| +URLLoader::URLLoader(PP_Instance instance, SerializedResource resource)
|
| + : PluginResource(instance, resource),
|
| 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) {
|
| + current_read_buffer_(NULL),
|
| + response_info_(0) {
|
| }
|
|
|
| URLLoader::~URLLoader() {
|
| + if (response_info_)
|
| + PluginResourceTracker::GetInstance()->ReleaseResource(response_info_);
|
| }
|
|
|
| +PP_Resource URLLoader::GetResponseInfo() {
|
| + if (!response_info_) {
|
| + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance());
|
| + if (!dispatcher)
|
| + return 0;
|
| +
|
| + SerializedResource response_id;
|
| + dispatcher->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
|
| + INTERFACE_ID_PPB_URL_LOADER, host_resource(), &response_id));
|
| + if (response_id.is_null())
|
| + return 0;
|
| +
|
| + response_info_ = PPB_URLResponseInfo_Proxy::CreateResponseForResource(
|
| + instance(), response_id);
|
| + }
|
| +
|
| + // The caller expects to get a ref, and we want to keep holding ours.
|
| + PluginResourceTracker::GetInstance()->AddRefResource(response_info_);
|
| + return response_info_;
|
| +}
|
| +
|
| namespace {
|
|
|
| -// Converts the given loader ID to the dispatcher associated with it, or NULL
|
| -// if it couldn't be found.
|
| -PluginDispatcher* DispatcherFromURLLoader(PP_Resource loader_id) {
|
| - URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id);
|
| - if (!object)
|
| - return NULL;
|
| - return PluginDispatcher::GetForInstance(object->instance());
|
| +// Converts the given loader ID to the dispatcher associated with it and the
|
| +// loader object. Returns true if the object was found.
|
| +bool RoutingDataFromURLLoader(PP_Resource loader_id,
|
| + URLLoader** loader_object,
|
| + PluginDispatcher** dispatcher) {
|
| + *loader_object = PluginResource::GetAs<URLLoader>(loader_id);
|
| + if (!*loader_object)
|
| + return false;
|
| + *dispatcher = PluginDispatcher::GetForInstance((*loader_object)->instance());
|
| + return !!*dispatcher;
|
| }
|
|
|
| // Plugin PPB_URLLoader implmentation ------------------------------------------
|
| @@ -81,12 +115,12 @@
|
| if (!dispatcher)
|
| return 0;
|
|
|
| - PP_Resource result = 0;
|
| + SerializedResource result;
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create(
|
| INTERFACE_ID_PPB_URL_LOADER, instance_id, &result));
|
| - if (result)
|
| - PPB_URLLoader_Proxy::TrackPluginResource(instance_id, result);
|
| - return result;
|
| + if (result.is_null())
|
| + return 0;
|
| + return PPB_URLLoader_Proxy::TrackPluginResource(instance_id, result);
|
| }
|
|
|
| PP_Bool IsURLLoader(PP_Resource resource) {
|
| @@ -97,24 +131,31 @@
|
| int32_t Open(PP_Resource loader_id,
|
| PP_Resource request_id,
|
| PP_CompletionCallback callback) {
|
| - PluginDispatcher* dispatcher = DispatcherFromURLLoader(loader_id);
|
| - if (!dispatcher)
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| return PP_ERROR_BADRESOURCE;
|
| + PluginResource* request_object =
|
| + PluginResourceTracker::GetInstance()->GetResourceObject(request_id);
|
| + if (!request_object)
|
| + return PP_ERROR_BADRESOURCE;
|
|
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Open(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id, request_id,
|
| + INTERFACE_ID_PPB_URL_LOADER, loader_object->host_resource(),
|
| + request_object->host_resource(),
|
| dispatcher->callback_tracker().SendCallback(callback)));
|
| return PP_ERROR_WOULDBLOCK;
|
| }
|
|
|
| int32_t FollowRedirect(PP_Resource loader_id,
|
| PP_CompletionCallback callback) {
|
| - PluginDispatcher* dispatcher = DispatcherFromURLLoader(loader_id);
|
| - if (!dispatcher)
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| return PP_ERROR_BADRESOURCE;
|
|
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id,
|
| + INTERFACE_ID_PPB_URL_LOADER, loader_object->host_resource(),
|
| dispatcher->callback_tracker().SendCallback(callback)));
|
| return PP_ERROR_WOULDBLOCK;
|
| }
|
| @@ -151,46 +192,21 @@
|
| URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id);
|
| if (!object)
|
| return 0;
|
| -
|
| - // 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::GetForInstance(
|
| - object->instance());
|
| - if (!dispatcher)
|
| - return PP_ERROR_BADRESOURCE;
|
| -
|
| - dispatcher->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id, &result));
|
| - if (PluginResourceTracker::GetInstance()->
|
| - PreparePreviouslyTrackedResource(result))
|
| - return result;
|
| -
|
| - // Tell the response info to create a tracking object and add it to the
|
| - // resource tracker.
|
| - PPB_URLResponseInfo_Proxy::TrackPluginResource(object->instance(), result);
|
| - return result;
|
| + return object->GetResponseInfo();
|
| }
|
|
|
| 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)
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| return PP_ERROR_BADRESOURCE;
|
| - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
|
| - object->instance());
|
| - if (!dispatcher)
|
| - return PP_ERROR_BADRESOURCE;
|
|
|
| if (!buffer)
|
| return PP_ERROR_BADARGUMENT; // Must specify an output buffer.
|
| - if (object->current_read_callback_.func)
|
| + if (loader_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
|
| @@ -198,33 +214,36 @@
|
| if (!callback.func)
|
| return PP_ERROR_BADARGUMENT;
|
|
|
| - object->current_read_callback_ = callback;
|
| - object->current_read_buffer_ = buffer;
|
| + loader_object->current_read_callback_ = callback;
|
| + loader_object->current_read_buffer_ = buffer;
|
|
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_to_read));
|
| + INTERFACE_ID_PPB_URL_LOADER, loader_object->instance(),
|
| + loader_object->host_resource(), bytes_to_read));
|
| return PP_ERROR_WOULDBLOCK;
|
| }
|
|
|
| int32_t FinishStreamingToFile(PP_Resource loader_id,
|
| PP_CompletionCallback callback) {
|
| - PluginDispatcher* dispatcher = DispatcherFromURLLoader(loader_id);
|
| - if (!dispatcher)
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| return PP_ERROR_BADRESOURCE;
|
|
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id,
|
| + INTERFACE_ID_PPB_URL_LOADER, loader_object->host_resource(),
|
| dispatcher->callback_tracker().SendCallback(callback)));
|
| return PP_ERROR_WOULDBLOCK;
|
| }
|
|
|
| void Close(PP_Resource loader_id) {
|
| - PluginDispatcher* dispatcher = DispatcherFromURLLoader(loader_id);
|
| - if (!dispatcher)
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| return;
|
|
|
| dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Close(
|
| - INTERFACE_ID_PPB_URL_LOADER, loader_id));
|
| + INTERFACE_ID_PPB_URL_LOADER, loader_object->host_resource()));
|
| }
|
|
|
| const PPB_URLLoader ppb_urlloader = {
|
| @@ -242,10 +261,15 @@
|
|
|
| // Plugin URLLoaderTrusted implementation --------------------------------------
|
|
|
| -void GrantUniversalAccess(PP_Resource loader) {
|
| - PluginDispatcher::Get()->Send(
|
| +void GrantUniversalAccess(PP_Resource loader_id) {
|
| + URLLoader* loader_object;
|
| + PluginDispatcher* dispatcher;
|
| + if (!RoutingDataFromURLLoader(loader_id, &loader_object, &dispatcher))
|
| + return;
|
| +
|
| + dispatcher->Send(
|
| new PpapiHostMsg_PPBURLLoaderTrusted_GrantUniversalAccess(
|
| - INTERFACE_ID_PPB_URL_LOADER_TRUSTED, loader));
|
| + INTERFACE_ID_PPB_URL_LOADER_TRUSTED, loader_object->host_resource()));
|
| }
|
|
|
| const PPB_URLLoaderTrusted ppb_urlloader_trusted = {
|
| @@ -258,7 +282,8 @@
|
| // PPB_URLLoader_Proxy ---------------------------------------------------------
|
|
|
| struct PPB_URLLoader_Proxy::ReadCallbackInfo {
|
| - PP_Resource pp_resource;
|
| + PP_Instance instance;
|
| + SerializedResource resource;
|
| std::string read_buffer;
|
| };
|
|
|
| @@ -272,11 +297,11 @@
|
| }
|
|
|
| // static
|
| -void PPB_URLLoader_Proxy::TrackPluginResource(PP_Instance instance,
|
| - PP_Resource url_loader_resource) {
|
| - linked_ptr<URLLoader> object(new URLLoader(instance));
|
| - PluginResourceTracker::GetInstance()->AddResource(url_loader_resource,
|
| - object);
|
| +PP_Resource PPB_URLLoader_Proxy::TrackPluginResource(
|
| + PP_Instance instance,
|
| + SerializedResource url_loader_resource) {
|
| + linked_ptr<URLLoader> object(new URLLoader(instance, url_loader_resource));
|
| + return PluginResourceTracker::GetInstance()->AddResource(object);
|
| }
|
|
|
| const void* PPB_URLLoader_Proxy::GetSourceInterface() const {
|
| @@ -316,37 +341,39 @@
|
| }
|
|
|
| void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance,
|
| - PP_Resource* result) {
|
| - *result = ppb_url_loader_target()->Create(instance);
|
| + SerializedResource* result) {
|
| + result->set_host_resource(ppb_url_loader_target()->Create(instance));
|
| }
|
|
|
| -void PPB_URLLoader_Proxy::OnMsgOpen(PP_Resource loader,
|
| - PP_Resource request_info,
|
| +void PPB_URLLoader_Proxy::OnMsgOpen(SerializedResource loader,
|
| + SerializedResource request_info,
|
| uint32_t serialized_callback) {
|
| PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
|
| int32_t result = ppb_url_loader_target()->Open(
|
| - loader, request_info, callback);
|
| + loader.host_resource(), request_info.host_resource(), callback);
|
| if (result != PP_ERROR_WOULDBLOCK)
|
| PP_RunCompletionCallback(&callback, result);
|
| }
|
|
|
| void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
|
| - PP_Resource loader,
|
| + SerializedResource loader,
|
| uint32_t serialized_callback) {
|
| PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
|
| int32_t result = ppb_url_loader_target()->FollowRedirect(
|
| - loader, callback);
|
| + loader.host_resource(), 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::OnMsgGetResponseInfo(SerializedResource loader,
|
| + SerializedResource* result) {
|
| + result->set_host_resource(
|
| + ppb_url_loader_target()->GetResponseInfo(loader.host_resource()));
|
| }
|
|
|
| void PPB_URLLoader_Proxy::OnMsgReadResponseBody(
|
| - PP_Resource loader,
|
| + PP_Instance instance,
|
| + SerializedResource loader,
|
| int32_t bytes_to_read) {
|
| // The plugin could be sending us malicious messages, don't accept negative
|
| // sizes.
|
| @@ -361,15 +388,17 @@
|
| // destroyed. Depending on the cleanup ordering, we may not need the weak
|
| // pointer here.)
|
| ReadCallbackInfo* info = new ReadCallbackInfo;
|
| - info->pp_resource = loader;
|
| + info->instance = instance;
|
| + info->resource = loader;
|
| + // TODO(brettw) have a way to check for out-of-memory.
|
| info->read_buffer.resize(bytes_to_read);
|
|
|
| CompletionCallback callback = callback_factory_.NewCallback(
|
| &PPB_URLLoader_Proxy::OnReadCallback, info);
|
|
|
| int32_t result = ppb_url_loader_target()->ReadResponseBody(
|
| - loader, const_cast<char*>(info->read_buffer.c_str()), bytes_to_read,
|
| - callback.pp_completion_callback());
|
| + loader.host_resource(), const_cast<char*>(info->read_buffer.c_str()),
|
| + bytes_to_read, callback.pp_completion_callback());
|
| 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
|
| @@ -379,45 +408,51 @@
|
| }
|
|
|
| void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile(
|
| - PP_Resource loader,
|
| + SerializedResource loader,
|
| uint32_t serialized_callback) {
|
| PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
|
| int32_t result = ppb_url_loader_target()->FinishStreamingToFile(
|
| - loader, callback);
|
| + loader.host_resource(), 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::OnMsgClose(SerializedResource loader) {
|
| + ppb_url_loader_target()->Close(loader.host_resource());
|
| }
|
|
|
| +// Called in the Plugin.
|
| 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();
|
| + const PPBURLLoader_UpdateProgress_Params& params) {
|
| + PP_Resource plugin_resource =
|
| + PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
|
| + params.instance, params.resource);
|
| + if (!plugin_resource)
|
| return;
|
| - }
|
| + URLLoader* object = PluginResource::GetAs<URLLoader>(plugin_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;
|
| + object->bytes_sent_ = params.bytes_sent;
|
| + object->total_bytes_to_be_sent_ = params.total_bytes_to_be_sent;
|
| + object->bytes_received_ = params.bytes_received;
|
| + object->total_bytes_to_be_received_ = params.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();
|
| +// Called in the Plugin.
|
| +void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck(
|
| + PP_Instance instance,
|
| + SerializedResource host_resource,
|
| + int32 result,
|
| + const std::string& data) {
|
| + PP_Resource plugin_resource =
|
| + PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
|
| + instance, host_resource);
|
| + if (!plugin_resource)
|
| return;
|
| - }
|
| + URLLoader* object = PluginResource::GetAs<URLLoader>(plugin_resource);
|
| + if (!object)
|
| + return;
|
|
|
| if (!object->current_read_callback_.func || !object->current_read_buffer_) {
|
| NOTREACHED();
|
| @@ -444,7 +479,7 @@
|
| info->read_buffer.resize(bytes_read);
|
|
|
| dispatcher()->Send(new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack(
|
| - INTERFACE_ID_PPB_URL_LOADER, info->pp_resource,
|
| + INTERFACE_ID_PPB_URL_LOADER, info->instance, info->resource,
|
| result, info->read_buffer));
|
|
|
| delete info;
|
| @@ -480,8 +515,9 @@
|
| return handled;
|
| }
|
|
|
| -void PPB_URLLoaderTrusted_Proxy::OnMsgGrantUniversalAccess(PP_Resource loader) {
|
| - ppb_url_loader_trusted_target()->GrantUniversalAccess(loader);
|
| +void PPB_URLLoaderTrusted_Proxy::OnMsgGrantUniversalAccess(
|
| + SerializedResource loader) {
|
| + ppb_url_loader_trusted_target()->GrantUniversalAccess(loader.host_resource());
|
| }
|
|
|
| } // namespace proxy
|
|
|