| Index: ppapi/proxy/ppb_url_loader_proxy.cc | 
| =================================================================== | 
| --- ppapi/proxy/ppb_url_loader_proxy.cc	(revision 72840) | 
| +++ 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(const HostResource& 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(const HostResource& resource) | 
| +    : PluginResource(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; | 
| + | 
| +    HostResource 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( | 
| +        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; | 
| +  HostResource 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(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->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,7 @@ | 
| // PPB_URLLoader_Proxy --------------------------------------------------------- | 
|  | 
| struct PPB_URLLoader_Proxy::ReadCallbackInfo { | 
| -  PP_Resource pp_resource; | 
| +  HostResource resource; | 
| std::string read_buffer; | 
| }; | 
|  | 
| @@ -272,11 +296,10 @@ | 
| } | 
|  | 
| // 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( | 
| +    const HostResource& url_loader_resource) { | 
| +  linked_ptr<URLLoader> object(new URLLoader(url_loader_resource)); | 
| +  return PluginResourceTracker::GetInstance()->AddResource(object); | 
| } | 
|  | 
| const void* PPB_URLLoader_Proxy::GetSourceInterface() const { | 
| @@ -316,37 +339,38 @@ | 
| } | 
|  | 
| void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance, | 
| -                                      PP_Resource* result) { | 
| -  *result = ppb_url_loader_target()->Create(instance); | 
| +                                      HostResource* result) { | 
| +  result->SetHostResource(instance, ppb_url_loader_target()->Create(instance)); | 
| } | 
|  | 
| -void PPB_URLLoader_Proxy::OnMsgOpen(PP_Resource loader, | 
| -                                    PP_Resource request_info, | 
| +void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader, | 
| +                                    const HostResource& 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, | 
| +    const HostResource& 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(const HostResource& loader, | 
| +                                               HostResource* result) { | 
| +  result->SetHostResource(loader.instance(), | 
| +      ppb_url_loader_target()->GetResponseInfo(loader.host_resource())); | 
| } | 
|  | 
| void PPB_URLLoader_Proxy::OnMsgReadResponseBody( | 
| -    PP_Resource loader, | 
| +    const HostResource& loader, | 
| int32_t bytes_to_read) { | 
| // The plugin could be sending us malicious messages, don't accept negative | 
| // sizes. | 
| @@ -361,15 +385,16 @@ | 
| // destroyed. Depending on the cleanup ordering, we may not need the weak | 
| // pointer here.) | 
| ReadCallbackInfo* info = new ReadCallbackInfo; | 
| -  info->pp_resource = loader; | 
| +  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 +404,50 @@ | 
| } | 
|  | 
| void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( | 
| -    PP_Resource loader, | 
| +    const HostResource& 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(const HostResource& 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.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( | 
| +    const HostResource& host_resource, | 
| +    int32 result, | 
| +    const std::string& data) { | 
| +  PP_Resource plugin_resource = | 
| +      PluginResourceTracker::GetInstance()->PluginResourceForHostResource( | 
| +          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,8 +474,7 @@ | 
| info->read_buffer.resize(bytes_read); | 
|  | 
| dispatcher()->Send(new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack( | 
| -      INTERFACE_ID_PPB_URL_LOADER, info->pp_resource, | 
| -      result, info->read_buffer)); | 
| +      INTERFACE_ID_PPB_URL_LOADER, info->resource, result, info->read_buffer)); | 
|  | 
| delete info; | 
| } | 
| @@ -480,8 +509,9 @@ | 
| return handled; | 
| } | 
|  | 
| -void PPB_URLLoaderTrusted_Proxy::OnMsgGrantUniversalAccess(PP_Resource loader) { | 
| -  ppb_url_loader_trusted_target()->GrantUniversalAccess(loader); | 
| +void PPB_URLLoaderTrusted_Proxy::OnMsgGrantUniversalAccess( | 
| +    const HostResource& loader) { | 
| +  ppb_url_loader_trusted_target()->GrantUniversalAccess(loader.host_resource()); | 
| } | 
|  | 
| }  // namespace proxy | 
|  |