diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 01:50:40 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 01:50:40 +0000 |
commit | 47cb253f15ca0e9dfcef8dd4b42bb5bc443c522f (patch) | |
tree | a71128d32bc0af6005739c13a99e851ad400d614 /ppapi/proxy | |
parent | 3af832f9c543e7866d375ba326fe659b6f3df939 (diff) | |
download | chromium_src-47cb253f15ca0e9dfcef8dd4b42bb5bc443c522f.zip chromium_src-47cb253f15ca0e9dfcef8dd4b42bb5bc443c522f.tar.gz chromium_src-47cb253f15ca0e9dfcef8dd4b42bb5bc443c522f.tar.bz2 |
Implementation of URLLoader using PluginResource/ResourceHost.
This change is essentially the same as: https://codereview.chromium.org/11416363
Here's the description from that CL:
"This doesn't use the resource call/reply infrastructure, but rather pipes WebKit callbacks to the
plugin via unsolicited callbacks. This eliminates state tracking in the host which makes things
simpler.
This fixes some bugs in Close() as well to fix the below-mentioned bug."
Other things contained in the original CL:
- Add a GetPluginPID method to RendererPpapiHost. This is needed when the loader host Opens()
a request.
- Add a HandleDocumentLoad method to PluginDelegate and implements it in PepperPluginDelegateImpl.
This creates the host for both in- and out-of-process proxies.
- Removes the GetURLLoaderBufferedBytes function from the PPB_Proxy_Private interface.
- Removes the HandleDocumentLoad implementation in the PPP_Instance_Proxy class.
- Removes the document_loader_ field from webkit::ppapi::WebPluginImpl and changes the
implementation to forward document load notifications to the PluginInstance.
- Changes the PluginInstance to manage the document loader.
This CL differs from the original in two ways.
First, the trusted interface keeps the RegisterStatusCallback function. The NaCl plugin relies on
this to generate progress messages back to the embedding page.
Second, PluginInstance is changed to recognize when it's a NaCl instance, and to defer calling
the plugin delegate's HandleDocumentLoad method until after the proxy is switched. In the meantime,
it saves document events in a special loader object. When the proxy is switched, the delegate's
HandleDocumentLoad method is called and the response and document events are then replayed
through the new loader resource.
BUG=69457
R=brettw@chromium.org
Review URL: https://codereview.chromium.org/14371021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200412 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/interface_list.cc | 2 | ||||
-rw-r--r-- | ppapi/proxy/plugin_resource.h | 2 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 109 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_proxy_test.cc | 6 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.cc | 652 | ||||
-rw-r--r-- | ppapi/proxy/ppb_url_loader_proxy.h | 92 | ||||
-rw-r--r-- | ppapi/proxy/ppp_instance_proxy.cc | 72 | ||||
-rw-r--r-- | ppapi/proxy/ppp_instance_proxy.h | 6 | ||||
-rw-r--r-- | ppapi/proxy/resource_creation_proxy.cc | 9 | ||||
-rw-r--r-- | ppapi/proxy/resource_creation_proxy.h | 2 | ||||
-rw-r--r-- | ppapi/proxy/url_loader_resource.cc | 392 | ||||
-rw-r--r-- | ppapi/proxy/url_loader_resource.h | 146 | ||||
-rw-r--r-- | ppapi/proxy/url_response_info_resource.h | 2 |
13 files changed, 645 insertions, 847 deletions
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 4bd8b40..963daf3 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -104,7 +104,6 @@ #include "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h" #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" #include "ppapi/proxy/ppb_testing_proxy.h" -#include "ppapi/proxy/ppb_url_loader_proxy.h" #include "ppapi/proxy/ppb_var_deprecated_proxy.h" #include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/proxy/ppb_x509_certificate_private_proxy.h" @@ -244,7 +243,6 @@ InterfaceList::InterfaceList() { // Do not add more stuff here, they should be added to interface_list*.h // TODO(brettw) remove these. AddPPB(PPB_Instance_Proxy::GetInfoPrivate(), PERMISSION_PRIVATE); - AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo(), PERMISSION_PRIVATE); AddPPB(PPB_Var_Deprecated_Proxy::GetInfo(), PERMISSION_DEV); // TODO(tomfinegan): Figure out where to put these once we refactor things diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h index 1535278..9448326 100644 --- a/ppapi/proxy/plugin_resource.h +++ b/ppapi/proxy/plugin_resource.h @@ -131,6 +131,8 @@ class PPAPI_PROXY_EXPORT PluginResource : public Resource { IPC::Message* reply_msg, ResourceMessageReplyParams* reply_params); + const Connection& connection() { return connection_; } + private: IPC::Sender* GetSender(Destination dest) { return dest == RENDERER ? connection_.renderer_sender : diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 622cfb3..b7169d3 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -589,10 +589,10 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_DidChangeView, IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus, PP_Instance /* instance */, PP_Bool /* has_focus */) -IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleDocumentLoad, - PP_Instance /* instance */, - ppapi::HostResource /* url_loader */, - PP_Bool /* result */) +IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_HandleDocumentLoad, + PP_Instance /* instance */, + int /* pending_loader_host_id */, + ppapi::URLResponseInfoData /* response */) // PPP_Messaging. IPC_MESSAGE_ROUTED2(PpapiMsg_PPPMessaging_HandleMessage, @@ -631,19 +631,6 @@ IPC_MESSAGE_ROUTED2(PpapiMsg_PPPTextInput_RequestSurroundingText, PP_Instance /* instance */, uint32_t /* desired_number_of_characters */) -// PPB_URLLoader -// (Messages from browser to plugin to notify it of changes in state.) -// -// NOTE: The ReadResponseBody_Ack message is a custom generated message -// with the following fields appended: -// ppapi::HostResource -// response data (array of bytes stored via WriteData) -// int result -// -IPC_MESSAGE_ROUTED0(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack) -IPC_MESSAGE_ROUTED2(PpapiMsg_PPBURLLoader_CallbackComplete, - ppapi::HostResource /* loader */, - int32_t /* result */) #if !defined(OS_NACL) && !defined(NACL_WIN64) // PPB_Broker. IPC_MESSAGE_ROUTED3( @@ -722,11 +709,6 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPBTCPSocket_SetBoolOptionACK, uint32 /* socket_id */, bool /* succeeded */) -// PPB_URLLoader_Trusted -IPC_MESSAGE_ROUTED1( - PpapiMsg_PPBURLLoader_UpdateProgress, - ppapi::proxy::PPBURLLoader_UpdateProgress_Params /* params */) - // PPB_TCPServerSocket_Private. // |socket_resource| should not be used as Resource in browser. The @@ -1002,30 +984,6 @@ IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_UpdateSurroundingText, uint32_t /* caret */, uint32_t /* anchor */) -// PPB_URLLoader. -IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create, - PP_Instance /* instance */, - ppapi::HostResource /* result */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_Open, - ppapi::HostResource /* loader */, - ppapi::URLRequestInfoData /* request_data */) -IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_FollowRedirect, - ppapi::HostResource /* loader */) -IPC_SYNC_MESSAGE_ROUTED1_2( - PpapiHostMsg_PPBURLLoader_GetResponseInfo, - ppapi::HostResource /* loader */, - bool /* success */, - ppapi::URLResponseInfoData /* result */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_ReadResponseBody, - ppapi::HostResource /* loader */, - int32_t /* bytes_to_read */) -IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile, - ppapi::HostResource /* loader */) -IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_Close, - ppapi::HostResource /* loader */) -IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess, - ppapi::HostResource /* loader */) - // PPB_Var. IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBVar_AddRefObject, int64 /* object_id */, @@ -1511,7 +1469,63 @@ IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_GetDefaultPrintSettings) IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply, PP_PrintSettings_Dev /* print_settings */) +// URLLoader ------------------------------------------------------------------ + +IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_Create) + +// These messages correspond to PPAPI calls and all should get a +// CallbackComplete message. +IPC_MESSAGE_CONTROL1(PpapiHostMsg_URLLoader_Open, + ppapi::URLRequestInfoData /* request_data */) + +// The plugin can tell the host to defer a load to hold off on sending more +// data because the buffer in the plugin is full. When defers_loading is set to +// false, data streaming will resume. +// +// When auditing redirects (no auto follow) the load will be automatically +// deferred each time we get a redirect. The plugin will reset this to false +// by sending this message when it wants to continue following the redirect. +// +// When streaming data, the host may still send more data after this call (for +// example, it could already be in-flight at the time of this request). +IPC_MESSAGE_CONTROL1(PpapiHostMsg_URLLoader_SetDeferLoading, + bool /* defers_loading */) + +// Closes the URLLoader. There is no reply. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_Close) + +// Requests that cross-site restrictions be ignored. The plugin must have +// the private permission set. Otherwise this message will be ignored by the +// renderer. There is no reply. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_GrantUniversalAccess) + +// Push notification that a response is available. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_URLLoader_ReceivedResponse, + ppapi::URLResponseInfoData /* response */) + +// Push notification with load data from the renderer. It is a custom generated +// message with the response data (array of bytes stored via WriteData) +// appended. +IPC_MESSAGE_CONTROL0(PpapiPluginMsg_URLLoader_SendData) + +// Push notification indicating that all data has been sent, either via +// SendData or by streaming it to a file. Note that since this is a push +// notification, we don't use the result field of the ResourceMessageReply. +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_URLLoader_FinishedLoading, + int32_t /* result */) + +// Push notification from the renderer to the plugin to tell it about download +// and upload progress. This will only be sent if the plugin has requested +// progress updates, and only the fields requested by the plugin will be +// valid. +IPC_MESSAGE_CONTROL4(PpapiPluginMsg_URLLoader_UpdateProgress, + int64_t /* bytes_sent */, + int64_t /* total_bytes_to_be_sent */, + int64_t /* bytes_received */, + int64_t /* total_bytes_to_be_received */) + // Shared memory --------------------------------------------------------------- + // Creates shared memory on the host side, returning a handle to the shared // memory on the plugin and keeping the memory mapped in on the host. // We return a "host handle_id" that can be mapped back to the @@ -1522,7 +1536,8 @@ IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_SharedMemory_CreateSharedMemory, int /* host_handle_id */, ppapi::proxy::SerializedHandle /* plugin_handle */) -// WebSocket ------------------------------------------------------------------ +// WebSocket ------------------------------------------------------------------- + IPC_MESSAGE_CONTROL0(PpapiHostMsg_WebSocket_Create) // Establishes the connection to a server. This message requires diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc index 19f41bb..2df72cc 100644 --- a/ppapi/proxy/ppapi_proxy_test.cc +++ b/ppapi/proxy/ppapi_proxy_test.cc @@ -41,11 +41,6 @@ void SetReserveInstanceIDCallback(PP_Module module, // worry about Instance uniqueness in tests, so we can ignore the call. } -int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) { - NOTREACHED(); - return 0; -} - void AddRefModule(PP_Module module) {} void ReleaseModule(PP_Module module) {} PP_Bool IsInModuleDestructor(PP_Module module) { return PP_FALSE; } @@ -54,7 +49,6 @@ PPB_Proxy_Private ppb_proxy_private = { &PluginCrashed, &GetInstanceForResource, &SetReserveInstanceIDCallback, - &GetURLLoaderBufferedBytes, &AddRefModule, &ReleaseModule, &IsInModuleDestructor diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc deleted file mode 100644 index 425b61f..0000000 --- a/ppapi/proxy/ppb_url_loader_proxy.cc +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright (c) 2012 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 <algorithm> -#include <deque> -#include <vector> - -#include "base/bind.h" -#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/ppb_url_loader.h" -#include "ppapi/c/private/ppb_proxy_private.h" -#include "ppapi/c/trusted/ppb_url_loader_trusted.h" -#include "ppapi/proxy/enter_proxy.h" -#include "ppapi/proxy/host_dispatcher.h" -#include "ppapi/proxy/plugin_dispatcher.h" -#include "ppapi/proxy/plugin_resource_tracker.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/ppb_file_ref_proxy.h" -#include "ppapi/shared_impl/scoped_pp_resource.h" -#include "ppapi/shared_impl/tracked_callback.h" -#include "ppapi/thunk/enter.h" -#include "ppapi/thunk/ppb_url_loader_api.h" -#include "ppapi/thunk/ppb_url_request_info_api.h" -#include "ppapi/thunk/resource_creation_api.h" -#include "ppapi/thunk/thunk.h" - -#if defined(OS_LINUX) -#include <sys/shm.h> -#endif - -using ppapi::thunk::EnterResourceNoLock; -using ppapi::thunk::PPB_URLLoader_API; -using ppapi::thunk::ResourceCreationAPI; - -namespace ppapi { -namespace proxy { - -namespace { - -// The maximum size we'll read into the plugin without being explicitly -// asked for a larger buffer. -const int32_t kMaxReadBufferSize = 16777216; // 16MB - -#if !defined(OS_NACL) -// 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); - if (!dispatcher) - return; - - PPBURLLoader_UpdateProgress_Params params; - params.instance = pp_instance; - params.resource.SetHostResource(pp_instance, pp_resource); - params.bytes_sent = bytes_sent; - params.total_bytes_to_be_sent = total_bytes_to_be_sent; - params.bytes_received = bytes_received; - params.total_bytes_to_be_received = total_bytes_to_be_received; - dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress( - API_ID_PPB_URL_LOADER, params)); -} -#endif // !defined(OS_NACL) - -InterfaceProxy* CreateURLLoaderProxy(Dispatcher* dispatcher) { - return new PPB_URLLoader_Proxy(dispatcher); -} - -} // namespace - -// URLLoader ------------------------------------------------------------------- - -class URLLoader : public Resource, public PPB_URLLoader_API { - public: - URLLoader(const HostResource& resource); - virtual ~URLLoader(); - - // Resource overrides. - virtual PPB_URLLoader_API* AsPPB_URLLoader_API() OVERRIDE; - - // PPB_URLLoader_API implementation. - virtual int32_t Open(PP_Resource request_id, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Open(const URLRequestInfoData& data, - int requestor_pid, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t FollowRedirect( - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual PP_Bool GetUploadProgress(int64_t* bytes_sent, - int64_t* total_bytes_to_be_sent) OVERRIDE; - virtual PP_Bool GetDownloadProgress( - int64_t* bytes_received, - int64_t* total_bytes_to_be_received) OVERRIDE; - virtual PP_Resource GetResponseInfo() OVERRIDE; - virtual int32_t ReadResponseBody( - void* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t FinishStreamingToFile( - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual void Close() OVERRIDE; - virtual void GrantUniversalAccess() OVERRIDE; - virtual void RegisterStatusCallback( - PP_URLLoaderTrusted_StatusCallback cb) OVERRIDE; - virtual bool GetResponseInfoData(URLResponseInfoData* data) OVERRIDE; - - // Called when the browser has new up/download progress to report. - void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params); - - // Called when the browser responds to our ReadResponseBody request. - void ReadResponseBodyAck(int32_t result, const char* data); - - // Called when any callback other than the read callback has been executed. - void CallbackComplete(int32_t result); - - private: - // Reads the give bytes out of the buffer_, placing them in the given output - // buffer, and removes the bytes from the buffer. - // - // The size must be not more than the current size of the buffer. - void PopBuffer(void* output_buffer, int32_t output_size); - - PluginDispatcher* GetDispatcher() const { - return PluginDispatcher::GetForResource(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_; - - // Current completion callback for the current phase of loading. We have only - // one thing (open, follow redirect, read, etc.) outstanding at once. - scoped_refptr<TrackedCallback> current_callback_; - - // When an asynchronous read is pending, this will contain the buffer to put - // the data. The current_callback_ will identify the read callback. - void* current_read_buffer_; - int32_t current_read_buffer_size_; - - // A buffer of all the data that's been sent to us from the host that we - // have yet to send out to the plugin. - std::deque<char> 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(const HostResource& resource) - : Resource(OBJECT_IS_PROXY, resource), - bytes_sent_(-1), - total_bytes_to_be_sent_(-1), - bytes_received_(-1), - total_bytes_to_be_received_(-1), - current_read_buffer_(NULL), - current_read_buffer_size_(0), - response_info_(0) { -} - -URLLoader::~URLLoader() { - if (response_info_) - PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(response_info_); -} - -PPB_URLLoader_API* URLLoader::AsPPB_URLLoader_API() { - return this; -} - -int32_t URLLoader::Open(PP_Resource request_id, - scoped_refptr<TrackedCallback> callback) { - EnterResourceNoLock<thunk::PPB_URLRequestInfo_API> enter(request_id, true); - if (enter.failed()) { - Log(PP_LOGLEVEL_ERROR, "PPB_URLLoader.Open: The URL you're requesting is " - " on a different security origin than your plugin. To request " - " cross-origin resources, see " - " PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS."); - return PP_ERROR_BADRESOURCE; - } - return Open(enter.object()->GetData(), 0, callback); -} - -int32_t URLLoader::Open(const URLRequestInfoData& data, - int requestor_pid, - scoped_refptr<TrackedCallback> callback) { - DCHECK_EQ(0, requestor_pid); // Used in-process only. - - if (TrackedCallback::IsPending(current_callback_)) - return PP_ERROR_INPROGRESS; - - current_callback_ = callback; - - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Open( - API_ID_PPB_URL_LOADER, host_resource(), data)); - return PP_OK_COMPLETIONPENDING; -} - -int32_t URLLoader::FollowRedirect(scoped_refptr<TrackedCallback> callback) { - if (TrackedCallback::IsPending(current_callback_)) - return PP_ERROR_INPROGRESS; - - current_callback_ = callback; - - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect( - API_ID_PPB_URL_LOADER, host_resource())); - return PP_OK_COMPLETIONPENDING; -} - -PP_Bool URLLoader::GetUploadProgress(int64_t* bytes_sent, - int64_t* total_bytes_to_be_sent) { - if (bytes_sent_ == -1) { - *bytes_sent = 0; - *total_bytes_to_be_sent = 0; - return PP_FALSE; - } - *bytes_sent = bytes_sent_; - *total_bytes_to_be_sent = total_bytes_to_be_sent_; - return PP_TRUE; -} - -PP_Bool URLLoader::GetDownloadProgress( - int64_t* bytes_received, - int64_t* total_bytes_to_be_received) { - if (bytes_received_ == -1) { - *bytes_received = 0; - *total_bytes_to_be_received = 0; - return PP_FALSE; - } - *bytes_received = bytes_received_; - *total_bytes_to_be_received = total_bytes_to_be_received_; - return PP_TRUE; -} - -PP_Resource URLLoader::GetResponseInfo() { - if (!response_info_) { - bool success = false; - URLResponseInfoData data; - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo( - API_ID_PPB_URL_LOADER, host_resource(), &success, &data)); - if (!success) - return 0; - - // Create a proxy resource for the the file ref host resource if needed. - PP_Resource body_as_file_ref = 0; - if (!data.body_as_file_ref.resource.is_null()) { - body_as_file_ref = - PPB_FileRef_Proxy::DeserializeFileRef(data.body_as_file_ref); - } - - // Assumes ownership of body_as_file_ref. - thunk::EnterResourceCreationNoLock enter(pp_instance()); - response_info_ = enter.functions()->CreateURLResponseInfo( - pp_instance(), data, body_as_file_ref); - } - - // The caller expects to get a ref, and we want to keep holding ours. - PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(response_info_); - return response_info_; -} - -int32_t URLLoader::ReadResponseBody(void* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) { - if (!buffer || bytes_to_read <= 0) - return PP_ERROR_BADARGUMENT; // Must specify an output buffer. - if (TrackedCallback::IsPending(current_callback_)) - return PP_ERROR_INPROGRESS; // Can only have one request pending. - - if (buffer_.size()) { - // Special case: we've already buffered some data that we can synchronously - // return to the caller. Do so without making IPCs. - int32_t bytes_to_return = - std::min(bytes_to_read, static_cast<int32_t>(buffer_.size())); - PopBuffer(buffer, bytes_to_return); - return bytes_to_return; - } - - current_callback_ = callback; - current_read_buffer_ = buffer; - current_read_buffer_size_ = bytes_to_read; - - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody( - API_ID_PPB_URL_LOADER, host_resource(), bytes_to_read)); - return PP_OK_COMPLETIONPENDING; -} - -int32_t URLLoader::FinishStreamingToFile( - scoped_refptr<TrackedCallback> callback) { - if (TrackedCallback::IsPending(current_callback_)) - return PP_ERROR_INPROGRESS; - - current_callback_ = callback; - - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile( - API_ID_PPB_URL_LOADER, host_resource())); - return PP_OK_COMPLETIONPENDING; -} - -void URLLoader::Close() { - GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Close( - API_ID_PPB_URL_LOADER, host_resource())); -} - -void URLLoader::GrantUniversalAccess() { - GetDispatcher()->Send( - new PpapiHostMsg_PPBURLLoader_GrantUniversalAccess( - API_ID_PPB_URL_LOADER, host_resource())); -} - -void URLLoader::RegisterStatusCallback( - PP_URLLoaderTrusted_StatusCallback cb) { - // Not implemented in the proxied version, this is for implementing the - // proxy itself in the host. -} - -bool URLLoader::GetResponseInfoData(URLResponseInfoData* data) { - // Not implemented in the proxied version, this is for implementing the - // proxy itself in the host. - return false; -} - -void URLLoader::UpdateProgress( - const PPBURLLoader_UpdateProgress_Params& params) { - bytes_sent_ = params.bytes_sent; - total_bytes_to_be_sent_ = params.total_bytes_to_be_sent; - bytes_received_ = params.bytes_received; - total_bytes_to_be_received_ = params.total_bytes_to_be_received; -} - -void URLLoader::ReadResponseBodyAck(int32 result, const char* data) { - if (!TrackedCallback::IsPending(current_callback_) || !current_read_buffer_) { - NOTREACHED(); - return; - } - - if (result >= 0) { - DCHECK_EQ(0U, buffer_.size()); - - int32_t bytes_to_return = std::min(current_read_buffer_size_, result); - std::copy(data, - data + bytes_to_return, - static_cast<char*>(current_read_buffer_)); - - if (result > bytes_to_return) { - // Save what remains to be copied when ReadResponseBody is called again. - buffer_.insert(buffer_.end(), - data + bytes_to_return, - data + result); - } - - result = bytes_to_return; - } - - current_callback_->Run(result); -} - -void URLLoader::CallbackComplete(int32_t result) { - current_callback_->Run(result); -} - -void URLLoader::PopBuffer(void* output_buffer, int32_t output_size) { - CHECK(output_size <= static_cast<int32_t>(buffer_.size())); - std::copy(buffer_.begin(), - buffer_.begin() + output_size, - static_cast<char*>(output_buffer)); - buffer_.erase(buffer_.begin(), - buffer_.begin() + output_size); -} - -// PPB_URLLoader_Proxy --------------------------------------------------------- - -PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher) - : InterfaceProxy(dispatcher), - callback_factory_(this) { -} - -PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() { -} - -// static -PP_Resource PPB_URLLoader_Proxy::TrackPluginResource( - const HostResource& url_loader_resource) { - return (new URLLoader(url_loader_resource))->GetReference(); -} - -// static -const InterfaceProxy::Info* PPB_URLLoader_Proxy::GetTrustedInfo() { - static const Info info = { - thunk::GetPPB_URLLoaderTrusted_0_3_Thunk(), - PPB_URLLOADERTRUSTED_INTERFACE_0_3, - API_ID_NONE, // URL_LOADER is the canonical one. - false, - &CreateURLLoaderProxy - }; - return &info; -} - -// static -PP_Resource PPB_URLLoader_Proxy::CreateProxyResource(PP_Instance pp_instance) { - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(pp_instance); - if (!dispatcher) - return 0; - - HostResource result; - dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create( - API_ID_PPB_URL_LOADER, pp_instance, &result)); - if (result.is_null()) - return 0; - return PPB_URLLoader_Proxy::TrackPluginResource(result); -} - -bool PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy, msg) -#if !defined(OS_NACL) - 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(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess, - OnMsgGrantUniversalAccess) -#endif // !defined(OS_NACL) - - IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress, - OnMsgUpdateProgress) - IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack, - OnMsgReadResponseBodyAck) - IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_CallbackComplete, - OnMsgCallbackComplete) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - // TODO(brettw) handle bad messages! - return handled; -} - -#if !defined(OS_NACL) -void PPB_URLLoader_Proxy::PrepareURLLoaderForSendingToPlugin( - PP_Resource resource) { - // So the plugin can query load status, we need to register our status - // callback before sending any URLLoader to the plugin. - EnterResourceNoLock<PPB_URLLoader_API> enter(resource, false); - if (enter.succeeded()) - enter.object()->RegisterStatusCallback(&UpdateResourceLoadStatus); - else - NOTREACHED(); // Only called internally, resource should be valid. -} - -void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance, - HostResource* result) { - thunk::EnterResourceCreation enter(instance); - if (enter.succeeded()) { - result->SetHostResource(instance, - enter.functions()->CreateURLLoader(instance)); - PrepareURLLoaderForSendingToPlugin(result->host_resource()); - } -} - -void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader, - const URLRequestInfoData& data) { - int peer_pid = dispatcher()->channel()->peer_pid(); - - EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( - loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); - enter.SetResult(enter.object()->Open(data, peer_pid, enter.callback())); - // TODO(brettw) bug 73236 register for the status callbacks. -} - -void PPB_URLLoader_Proxy::OnMsgFollowRedirect( - const HostResource& loader) { - EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( - loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); - if (enter.succeeded()) - enter.SetResult(enter.object()->FollowRedirect(enter.callback())); -} - -void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(const HostResource& loader, - bool* success, - URLResponseInfoData* result) { - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); - if (enter.succeeded()) - *success = enter.object()->GetResponseInfoData(result); - else - *success = false; -} - -void PPB_URLLoader_Proxy::OnMsgReadResponseBody( - const HostResource& 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; - } - - // Read more than requested if there are bytes available for synchronous - // reading. This prevents us from getting too far behind due to IPC message - // latency. Any extra data will get buffered in the plugin. - int32_t synchronously_available_bytes = - static_cast<HostDispatcher*>(dispatcher())->ppb_proxy()-> - GetURLLoaderBufferedBytes(loader.host_resource()); - if (bytes_to_read < kMaxReadBufferSize) { - // Grow the amount to read so we read ahead synchronously, if possible. - bytes_to_read = - std::max(bytes_to_read, - std::min(synchronously_available_bytes, kMaxReadBufferSize)); - } - - // 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.) - IPC::Message* message = - new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack(API_ID_PPB_URL_LOADER); - IPC::ParamTraits<HostResource>::Write(message, loader); - - char* ptr = message->BeginWriteData(bytes_to_read); - if (!ptr) { - // TODO(brettw) have a way to check for out-of-memory. - } - - EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( - loader, callback_factory_, &PPB_URLLoader_Proxy::OnReadCallback, message); - if (enter.succeeded()) { - enter.SetResult(enter.object()->ReadResponseBody(ptr, bytes_to_read, - enter.callback())); - } -} - -void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile( - const HostResource& loader) { - EnterHostFromHostResourceForceCallback<PPB_URLLoader_API> enter( - loader, callback_factory_, &PPB_URLLoader_Proxy::OnCallback, loader); - if (enter.succeeded()) - enter.SetResult(enter.object()->FinishStreamingToFile(enter.callback()));; -} - -void PPB_URLLoader_Proxy::OnMsgClose(const HostResource& loader) { - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); - if (enter.succeeded()) - enter.object()->Close(); -} - -void PPB_URLLoader_Proxy::OnMsgGrantUniversalAccess( - const HostResource& loader) { - EnterHostFromHostResource<PPB_URLLoader_API> enter(loader); - if (enter.succeeded()) - enter.object()->GrantUniversalAccess(); -} -#endif // !defined(OS_NACL) - -// Called in the Plugin. -void PPB_URLLoader_Proxy::OnMsgUpdateProgress( - const PPBURLLoader_UpdateProgress_Params& params) { - EnterPluginFromHostResource<PPB_URLLoader_API> enter(params.resource); - if (enter.succeeded()) - static_cast<URLLoader*>(enter.object())->UpdateProgress(params); -} - -// Called in the Plugin. -void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck( - const IPC::Message& message) { - PickleIterator iter(message); - - HostResource host_resource; - if (!IPC::ParamTraits<HostResource>::Read(&message, &iter, &host_resource)) { - NOTREACHED() << "Expecting HostResource"; - return; - } - - const char* data; - int data_len; - if (!iter.ReadData(&data, &data_len)) { - NOTREACHED() << "Expecting data"; - return; - } - - int result; - if (!iter.ReadInt(&result)) { - NOTREACHED() << "Expecting result"; - return; - } - - if (result >= 0 && result != data_len) { - NOTREACHED() << "Data size mismatch"; - return; - } - - EnterPluginFromHostResource<PPB_URLLoader_API> enter(host_resource); - if (enter.succeeded()) - static_cast<URLLoader*>(enter.object())->ReadResponseBodyAck(result, data); -} - -// Called in the plugin. -void PPB_URLLoader_Proxy::OnMsgCallbackComplete( - const HostResource& host_resource, - int32_t result) { - EnterPluginFromHostResource<PPB_URLLoader_API> enter(host_resource); - if (enter.succeeded()) - static_cast<URLLoader*>(enter.object())->CallbackComplete(result); -} - -#if !defined(OS_NACL) -void PPB_URLLoader_Proxy::OnReadCallback(int32_t result, - IPC::Message* message) { - int32_t bytes_read = 0; - if (result > 0) - bytes_read = result; // Positive results indicate bytes read. - - message->TrimWriteData(bytes_read); - message->WriteInt(result); - - dispatcher()->Send(message); -} - -void PPB_URLLoader_Proxy::OnCallback(int32_t result, - const HostResource& resource) { - dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete( - API_ID_PPB_URL_LOADER, resource, result)); -} -#endif // !defined(OS_NACL) - -} // namespace proxy -} // namespace ppapi diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h deleted file mode 100644 index f4c5bc5..0000000 --- a/ppapi/proxy/ppb_url_loader_proxy.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 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 "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/c/ppb_url_loader.h" -#include "ppapi/c/trusted/ppb_url_loader_trusted.h" -#include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_completion_callback_factory.h" -#include "ppapi/shared_impl/host_resource.h" -#include "ppapi/utility/completion_callback_factory.h" - -namespace ppapi { - -struct URLRequestInfoData; -struct URLResponseInfoData; - -namespace proxy { - -struct PPBURLLoader_UpdateProgress_Params; - -class PPB_URLLoader_Proxy : public InterfaceProxy { - public: - PPB_URLLoader_Proxy(Dispatcher* dispatcher); - virtual ~PPB_URLLoader_Proxy(); - - static const Info* GetTrustedInfo(); - - static PP_Resource CreateProxyResource(PP_Instance instance); - - // 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 PP_Resource TrackPluginResource( - const HostResource& url_loader_resource); - - // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); - - // URLLoader objects are sent from places other than just URLLoader.Create, - // in particular when doing a full-frame plugin. This function does the - // necessary setup in the host before the resource is sent. Call this any - // time you're sending a new URLLoader that the plugin hasn't seen yet. - void PrepareURLLoaderForSendingToPlugin(PP_Resource resource); - - static const ApiID kApiID = API_ID_PPB_URL_LOADER; - - private: - // Plugin->renderer message handlers. - void OnMsgCreate(PP_Instance instance, - HostResource* result); - void OnMsgOpen(const HostResource& loader, - const URLRequestInfoData& data); - void OnMsgFollowRedirect(const HostResource& loader); - void OnMsgGetResponseInfo(const HostResource& loader, - bool* success, - URLResponseInfoData* result); - void OnMsgReadResponseBody(const HostResource& loader, - int32_t bytes_to_read); - void OnMsgFinishStreamingToFile(const HostResource& loader); - void OnMsgClose(const HostResource& loader); - void OnMsgGrantUniversalAccess(const HostResource& loader); - - // Renderer->plugin message handlers. - void OnMsgUpdateProgress( - const PPBURLLoader_UpdateProgress_Params& params); - void OnMsgReadResponseBodyAck(const IPC::Message& message); - void OnMsgCallbackComplete(const HostResource& host_resource, int32_t result); - - // Handles callbacks for read complete messages. Takes ownership of the - // message pointer. - void OnReadCallback(int32_t result, IPC::Message* message); - - // Handles callback for everything but reads. - void OnCallback(int32_t result, const HostResource& resource); - - ProxyCompletionCallbackFactory<PPB_URLLoader_Proxy> callback_factory_; -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PPB_URL_LOADER_PROXY_H_ diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc index eb1d4e4..a7a0699 100644 --- a/ppapi/proxy/ppp_instance_proxy.cc +++ b/ppapi/proxy/ppp_instance_proxy.cc @@ -13,11 +13,14 @@ #include "ppapi/c/ppp_instance.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_globals.h" +#include "ppapi/proxy/plugin_proxy_delegate.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/ppb_url_loader_proxy.h" +#include "ppapi/proxy/url_loader_resource.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppb_view_shared.h" +#include "ppapi/shared_impl/resource_tracker.h" #include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_flash_fullscreen_api.h" @@ -83,36 +86,11 @@ void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { instance, has_focus)); } -PP_Bool HandleDocumentLoad(PP_Instance instance, - PP_Resource url_loader) { - PP_Bool result = PP_FALSE; - HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance); - - // Set up the URLLoader for proxying. - - PPB_URLLoader_Proxy* url_loader_proxy = static_cast<PPB_URLLoader_Proxy*>( - dispatcher->GetInterfaceProxy(API_ID_PPB_URL_LOADER)); - url_loader_proxy->PrepareURLLoaderForSendingToPlugin(url_loader); - - // PluginResourceTracker in the plugin process assumes that resources that it - // tracks have been addrefed on behalf of the plugin at the renderer side. So - // we explicitly do it for |url_loader| here. - // - // Please also see comments in PPP_Instance_Proxy::OnMsgHandleDocumentLoad() - // about releasing of this extra reference. - const PPB_Core* core = reinterpret_cast<const PPB_Core*>( - dispatcher->local_get_interface()(PPB_CORE_INTERFACE)); - if (!core) { - NOTREACHED(); - return PP_FALSE; - } - core->AddRefResource(url_loader); - - HostResource serialized_loader; - serialized_loader.SetHostResource(instance, url_loader); - dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad( - API_ID_PPP_INSTANCE, instance, serialized_loader, &result)); - return result; +PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) { + // This should never get called. Out-of-process document loads are handled + // specially. + NOTREACHED(); + return PP_FALSE; } static const PPP_Instance_1_1 instance_interface = { @@ -253,19 +231,25 @@ void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance, void PPP_Instance_Proxy::OnPluginMsgHandleDocumentLoad( PP_Instance instance, - const HostResource& url_loader, - PP_Bool* result) { - PP_Resource plugin_loader = - PPB_URLLoader_Proxy::TrackPluginResource(url_loader); - *result = combined_interface_->HandleDocumentLoad(instance, plugin_loader); - - // This balances the one reference that TrackPluginResource() initialized it - // with. The plugin will normally take an additional reference which will keep - // the resource alive in the plugin (and the one reference in the renderer - // representing all plugin references). - // Once all references at the plugin side are released, the renderer side will - // be notified and release the reference added in HandleDocumentLoad() above. - PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(plugin_loader); + int pending_loader_host_id, + const URLResponseInfoData& data) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + if (!dispatcher) + return; + Connection connection(PluginGlobals::Get()->GetBrowserSender(), + dispatcher); + + scoped_refptr<URLLoaderResource> loader_resource( + new URLLoaderResource(connection, instance, + pending_loader_host_id, data)); + + PP_Resource loader_pp_resource = loader_resource->GetReference(); + if (!combined_interface_->HandleDocumentLoad(instance, loader_pp_resource)) + loader_resource->Close(); + // We don't pass a ref into the plugin, if it wants one, it will have taken + // an additional one. + PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource( + loader_pp_resource); } } // namespace proxy diff --git a/ppapi/proxy/ppp_instance_proxy.h b/ppapi/proxy/ppp_instance_proxy.h index 1b599d0..85ae55c 100644 --- a/ppapi/proxy/ppp_instance_proxy.h +++ b/ppapi/proxy/ppp_instance_proxy.h @@ -20,6 +20,7 @@ struct PP_Rect; namespace ppapi { +struct URLResponseInfoData; struct ViewData; namespace proxy { @@ -50,8 +51,9 @@ class PPP_Instance_Proxy : public InterfaceProxy { PP_Bool flash_fullscreen); void OnPluginMsgDidChangeFocus(PP_Instance instance, PP_Bool has_focus); void OnPluginMsgHandleDocumentLoad(PP_Instance instance, - const HostResource& url_loader, - PP_Bool* result); + int pending_loader_host_id, + const URLResponseInfoData& data); + scoped_ptr<PPP_Instance_Combined> combined_interface_; }; diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index 8bbe862..50c7d6f 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -33,13 +33,13 @@ #include "ppapi/proxy/ppb_network_monitor_private_proxy.h" #include "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h" #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" -#include "ppapi/proxy/ppb_url_loader_proxy.h" #include "ppapi/proxy/ppb_video_decoder_proxy.h" #include "ppapi/proxy/ppb_x509_certificate_private_proxy.h" #include "ppapi/proxy/printing_resource.h" #include "ppapi/proxy/talk_resource.h" #include "ppapi/proxy/truetype_font_resource.h" #include "ppapi/proxy/udp_socket_private_resource.h" +#include "ppapi/proxy/url_loader_resource.h" #include "ppapi/proxy/url_request_info_resource.h" #include "ppapi/proxy/url_response_info_resource.h" #include "ppapi/proxy/video_capture_resource.h" @@ -82,6 +82,11 @@ PP_Resource ResourceCreationProxy::CreateFileRef(PP_Instance instance, return PPB_FileRef_Proxy::CreateProxyResource(instance, file_system, path); } +PP_Resource ResourceCreationProxy::CreateFileRef( + const PPB_FileRef_CreateInfo& create_info) { + return PPB_FileRef_Proxy::DeserializeFileRef(create_info); +} + PP_Resource ResourceCreationProxy::CreateFileSystem( PP_Instance instance, PP_FileSystemType type) { @@ -166,7 +171,7 @@ PP_Resource ResourceCreationProxy::CreateTrueTypeFont( } PP_Resource ResourceCreationProxy::CreateURLLoader(PP_Instance instance) { - return PPB_URLLoader_Proxy::CreateProxyResource(instance); + return (new URLLoaderResource(GetConnection(), instance))->GetReference(); } PP_Resource ResourceCreationProxy::CreateURLRequestInfo( diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h index 0597c11..74a0888 100644 --- a/ppapi/proxy/resource_creation_proxy.h +++ b/ppapi/proxy/resource_creation_proxy.h @@ -41,6 +41,8 @@ class ResourceCreationProxy : public InterfaceProxy, virtual PP_Resource CreateFileRef(PP_Instance instance, PP_Resource file_system, const char* path) OVERRIDE; + virtual PP_Resource CreateFileRef( + const PPB_FileRef_CreateInfo& create_info) OVERRIDE; virtual PP_Resource CreateFileSystem(PP_Instance instance, PP_FileSystemType type) OVERRIDE; virtual PP_Resource CreateIsolatedFileSystem( diff --git a/ppapi/proxy/url_loader_resource.cc b/ppapi/proxy/url_loader_resource.cc new file mode 100644 index 0000000..5ee8d95 --- /dev/null +++ b/ppapi/proxy/url_loader_resource.cc @@ -0,0 +1,392 @@ +// Copyright (c) 2013 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/url_loader_resource.h" + +#include "base/logging.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_url_loader.h" +#include "ppapi/proxy/dispatch_reply_message.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_file_ref_proxy.h" +#include "ppapi/proxy/url_request_info_resource.h" +#include "ppapi/proxy/url_response_info_resource.h" +#include "ppapi/shared_impl/ppapi_globals.h" +#include "ppapi/shared_impl/url_response_info_data.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/resource_creation_api.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_URLLoader_API; +using ppapi::thunk::PPB_URLRequestInfo_API; + +#ifdef _MSC_VER +// Do not warn about use of std::copy with raw pointers. +#pragma warning(disable : 4996) +#endif + +namespace ppapi { +namespace proxy { + +URLLoaderResource::URLLoaderResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + mode_(MODE_WAITING_TO_OPEN), + status_callback_(NULL), + bytes_sent_(0), + total_bytes_to_be_sent_(-1), + bytes_received_(0), + total_bytes_to_be_received_(-1), + user_buffer_(NULL), + user_buffer_size_(0), + done_status_(PP_OK_COMPLETIONPENDING), + is_streaming_to_file_(false), + is_asynchronous_load_suspended_(false) { + SendCreate(RENDERER, PpapiHostMsg_URLLoader_Create()); +} + +URLLoaderResource::URLLoaderResource(Connection connection, + PP_Instance instance, + int pending_main_document_loader_id, + const ppapi::URLResponseInfoData& data) + : PluginResource(connection, instance), + mode_(MODE_OPENING), + status_callback_(NULL), + bytes_sent_(0), + total_bytes_to_be_sent_(-1), + bytes_received_(0), + total_bytes_to_be_received_(-1), + user_buffer_(NULL), + user_buffer_size_(0), + done_status_(PP_OK_COMPLETIONPENDING), + is_streaming_to_file_(false), + is_asynchronous_load_suspended_(false) { + AttachToPendingHost(RENDERER, pending_main_document_loader_id); + SaveResponseInfo(data); +} + +URLLoaderResource::~URLLoaderResource() { +} + +PPB_URLLoader_API* URLLoaderResource::AsPPB_URLLoader_API() { + return this; +} + +int32_t URLLoaderResource::Open(PP_Resource request_id, + scoped_refptr<TrackedCallback> callback) { + EnterResourceNoLock<PPB_URLRequestInfo_API> enter_request(request_id, true); + if (enter_request.failed()) { + Log(PP_LOGLEVEL_ERROR, + "PPB_URLLoader.Open: invalid request resource ID. (Hint to C++ wrapper" + " users: use the ResourceRequest constructor that takes an instance or" + " else the request will be null.)"); + return PP_ERROR_BADARGUMENT; + } + return Open(enter_request.object()->GetData(), 0, callback); +} + +int32_t URLLoaderResource::Open( + const ::ppapi::URLRequestInfoData& request_data, + int requestor_pid, + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + if (mode_ != MODE_WAITING_TO_OPEN) + return PP_ERROR_INPROGRESS; + + request_data_ = request_data; + + mode_ = MODE_OPENING; + is_asynchronous_load_suspended_ = false; + + RegisterCallback(callback); + Post(RENDERER, PpapiHostMsg_URLLoader_Open(request_data)); + return PP_OK_COMPLETIONPENDING; +} + +int32_t URLLoaderResource::FollowRedirect( + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + if (mode_ != MODE_OPENING) + return PP_ERROR_INPROGRESS; + + SetDefersLoading(false); // Allow the redirect to continue. + RegisterCallback(callback); + return PP_OK_COMPLETIONPENDING; +} + +PP_Bool URLLoaderResource::GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) { + if (!request_data_.record_upload_progress) { + *bytes_sent = 0; + *total_bytes_to_be_sent = 0; + return PP_FALSE; + } + *bytes_sent = bytes_sent_; + *total_bytes_to_be_sent = total_bytes_to_be_sent_; + return PP_TRUE; +} + +PP_Bool URLLoaderResource::GetDownloadProgress( + int64_t* bytes_received, + int64_t* total_bytes_to_be_received) { + if (!request_data_.record_download_progress) { + *bytes_received = 0; + *total_bytes_to_be_received = 0; + return PP_FALSE; + } + *bytes_received = bytes_received_; + *total_bytes_to_be_received = total_bytes_to_be_received_; + return PP_TRUE; +} + +PP_Resource URLLoaderResource::GetResponseInfo() { + if (response_info_.get()) + return response_info_->GetReference(); + return 0; +} + +int32_t URLLoaderResource::ReadResponseBody( + void* buffer, + int32_t bytes_to_read, + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + if (!response_info_.get() || + !response_info_->data().body_as_file_ref.resource.is_null()) + return PP_ERROR_FAILED; + if (bytes_to_read <= 0 || !buffer) + return PP_ERROR_BADARGUMENT; + + user_buffer_ = static_cast<char*>(buffer); + user_buffer_size_ = bytes_to_read; + + if (!buffer_.empty()) + return FillUserBuffer(); + + // We may have already reached EOF. + if (done_status_ != PP_OK_COMPLETIONPENDING) { + user_buffer_ = NULL; + user_buffer_size_ = 0; + return done_status_; + } + + RegisterCallback(callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t URLLoaderResource::FinishStreamingToFile( + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + if (!response_info_.get() || + response_info_->data().body_as_file_ref.resource.is_null()) + return PP_ERROR_FAILED; + + // We may have already reached EOF. + if (done_status_ != PP_OK_COMPLETIONPENDING) + return done_status_; + + is_streaming_to_file_ = true; + if (is_asynchronous_load_suspended_) + SetDefersLoading(false); + + // Wait for didFinishLoading / didFail. + RegisterCallback(callback); + return PP_OK_COMPLETIONPENDING; +} + +void URLLoaderResource::Close() { + mode_ = MODE_LOAD_COMPLETE; + done_status_ = PP_ERROR_ABORTED; + + Post(RENDERER, PpapiHostMsg_URLLoader_Close()); + + // Abort the callbacks, the plugin doesn't want to be called back after this. + // TODO(brettw) this should fix bug 69457, mark it fixed. ============ + if (TrackedCallback::IsPending(pending_callback_)) + pending_callback_->PostAbort(); +} + +void URLLoaderResource::GrantUniversalAccess() { + Post(RENDERER, PpapiHostMsg_URLLoader_GrantUniversalAccess()); +} + +void URLLoaderResource::RegisterStatusCallback( + PP_URLLoaderTrusted_StatusCallback callback) { + status_callback_ = callback; +} + +void URLLoaderResource::OnReplyReceived( + const ResourceMessageReplyParams& params, + const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(URLLoaderResource, msg) + case PpapiPluginMsg_URLLoader_SendData::ID: + // Special message, manually dispatch since we don't want the automatic + // unpickling. + OnPluginMsgSendData(params, msg); + break; + + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_URLLoader_ReceivedResponse, + OnPluginMsgReceivedResponse) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_URLLoader_FinishedLoading, + OnPluginMsgFinishedLoading) + PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( + PpapiPluginMsg_URLLoader_UpdateProgress, + OnPluginMsgUpdateProgress) + IPC_END_MESSAGE_MAP() +} + +void URLLoaderResource::OnPluginMsgReceivedResponse( + const ResourceMessageReplyParams& params, + const URLResponseInfoData& data) { + SaveResponseInfo(data); + RunCallback(PP_OK); +} + +void URLLoaderResource::OnPluginMsgSendData( + const ResourceMessageReplyParams& params, + const IPC::Message& message) { + PickleIterator iter(message); + const char* data; + int data_length; + if (!iter.ReadData(&data, &data_length)) { + NOTREACHED() << "Expecting data"; + return; + } + + mode_ = MODE_STREAMING_DATA; + buffer_.insert(buffer_.end(), data, data + data_length); + + // To avoid letting the network stack download an entire stream all at once, + // defer loading when we have enough buffer. + // Check for this before we run the callback, even though that could move + // data out of the buffer. Doing anything after the callback is unsafe. + DCHECK(request_data_.prefetch_buffer_lower_threshold < + request_data_.prefetch_buffer_upper_threshold); + if (!is_streaming_to_file_ && + !is_asynchronous_load_suspended_ && + (buffer_.size() >= static_cast<size_t>( + request_data_.prefetch_buffer_upper_threshold))) { + DVLOG(1) << "Suspending async load - buffer size: " << buffer_.size(); + SetDefersLoading(true); + } + + if (user_buffer_) + RunCallback(FillUserBuffer()); + else + DCHECK(!TrackedCallback::IsPending(pending_callback_)); +} + +void URLLoaderResource::OnPluginMsgFinishedLoading( + const ResourceMessageReplyParams& params, + int32_t result) { + mode_ = MODE_LOAD_COMPLETE; + done_status_ = result; + user_buffer_ = NULL; + user_buffer_size_ = 0; + + // If the client hasn't called any function that takes a callback since + // the initial call to Open, or called ReadResponseBody and got a + // synchronous return, then the callback will be NULL. + if (TrackedCallback::IsPending(pending_callback_)) + RunCallback(done_status_); +} + +void URLLoaderResource::OnPluginMsgUpdateProgress( + const ResourceMessageReplyParams& params, + int64_t bytes_sent, + int64_t total_bytes_to_be_sent, + int64_t bytes_received, + int64_t total_bytes_to_be_received) { + bytes_sent_ = bytes_sent; + total_bytes_to_be_sent_ = total_bytes_to_be_sent; + bytes_received_ = bytes_received; + total_bytes_to_be_received_ = total_bytes_to_be_received; + + if (status_callback_) + status_callback_(pp_instance(), pp_resource(), + bytes_sent_, total_bytes_to_be_sent_, + bytes_received_, total_bytes_to_be_received_); +} + +void URLLoaderResource::SetDefersLoading(bool defers_loading) { + Post(RENDERER, PpapiHostMsg_URLLoader_SetDeferLoading(defers_loading)); +} + +int32_t URLLoaderResource::ValidateCallback( + scoped_refptr<TrackedCallback> callback) { + DCHECK(callback); + if (TrackedCallback::IsPending(pending_callback_)) + return PP_ERROR_INPROGRESS; + return PP_OK; +} + +void URLLoaderResource::RegisterCallback( + scoped_refptr<TrackedCallback> callback) { + DCHECK(!TrackedCallback::IsPending(pending_callback_)); + pending_callback_ = callback; +} + +void URLLoaderResource::RunCallback(int32_t result) { + // This may be null when this is a main document loader. + if (!pending_callback_.get()) + return; + + // If |user_buffer_| was set as part of registering a callback, the paths + // which trigger that callack must have cleared it since the callback is now + // free to delete it. + DCHECK(!user_buffer_); + + // As a second line of defense, clear the |user_buffer_| in case the + // callbacks get called in an unexpected order. + user_buffer_ = NULL; + user_buffer_size_ = 0; + pending_callback_->Run(result); +} + +void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) { + // Create a proxy resource for the the file ref host resource if needed. + PP_Resource body_as_file_ref = 0; + if (!data.body_as_file_ref.resource.is_null()) { + thunk::EnterResourceCreationNoLock enter(pp_instance()); + body_as_file_ref = + enter.functions()->CreateFileRef(data.body_as_file_ref); + } + response_info_ = new URLResponseInfoResource( + connection(), pp_instance(), data, body_as_file_ref); +} + +size_t URLLoaderResource::FillUserBuffer() { + DCHECK(user_buffer_); + DCHECK(user_buffer_size_); + + size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_); + std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_); + buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy); + + // If the buffer is getting too empty, resume asynchronous loading. + if (is_asynchronous_load_suspended_ && + buffer_.size() <= static_cast<size_t>( + request_data_.prefetch_buffer_lower_threshold)) { + DVLOG(1) << "Resuming async load - buffer size: " << buffer_.size(); + SetDefersLoading(false); + } + + // Reset for next time. + user_buffer_ = NULL; + user_buffer_size_ = 0; + return bytes_to_copy; +} + +} // namespace proxy +} // namespace ppapi
\ No newline at end of file diff --git a/ppapi/proxy/url_loader_resource.h b/ppapi/proxy/url_loader_resource.h new file mode 100644 index 0000000..685ccfe --- /dev/null +++ b/ppapi/proxy/url_loader_resource.h @@ -0,0 +1,146 @@ +// Copyright (c) 2013 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_URL_LOADER_RESOURCE_H_ +#define PPAPI_PROXY_URL_LOADER_RESOURCE_H_ + +#include <deque> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/c/trusted/ppb_url_loader_trusted.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/url_request_info_data.h" +#include "ppapi/thunk/ppb_url_loader_api.h" + +namespace ppapi { +namespace proxy { + +class URLResponseInfoResource; + +class PPAPI_PROXY_EXPORT URLLoaderResource + : public PluginResource, + public NON_EXPORTED_BASE(thunk::PPB_URLLoader_API) { + public: + // Constructor for plugin-initiated loads. + URLLoaderResource(Connection connection, + PP_Instance instance); + + // Constructor for renderer-initiated (document) loads. The loader ID is the + // pending host ID for the already-created host in the renderer, and the + // response data is the response for the already-opened connection. + URLLoaderResource(Connection connection, + PP_Instance instance, + int pending_main_document_loader_id, + const URLResponseInfoData& data); + + virtual ~URLLoaderResource(); + + // Resource override. + thunk::PPB_URLLoader_API* AsPPB_URLLoader_API() OVERRIDE; + + // PPB_URLLoader_API implementation. + virtual int32_t Open(PP_Resource request_id, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Open(const URLRequestInfoData& data, + int requestor_pid, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t FollowRedirect( + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual PP_Bool GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) OVERRIDE; + virtual PP_Bool GetDownloadProgress( + int64_t* bytes_received, + int64_t* total_bytes_to_be_received) OVERRIDE; + virtual PP_Resource GetResponseInfo() OVERRIDE; + virtual int32_t ReadResponseBody( + void* buffer, + int32_t bytes_to_read, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t FinishStreamingToFile( + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual void Close() OVERRIDE; + virtual void GrantUniversalAccess() OVERRIDE; + virtual void RegisterStatusCallback( + PP_URLLoaderTrusted_StatusCallback callback) OVERRIDE; + + // PluginResource implementation. + virtual void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) OVERRIDE; + + private: + enum Mode { + // The plugin has not called Open() yet. + MODE_WAITING_TO_OPEN, + + // The plugin is waiting for the Open() or FollowRedirect callback. + MODE_OPENING, + + // We've started to receive data and may receive more. + MODE_STREAMING_DATA, + + // All data has been streamed or there was an error. + MODE_LOAD_COMPLETE + }; + + // IPC message handlers. + void OnPluginMsgReceivedResponse(const ResourceMessageReplyParams& params, + const URLResponseInfoData& data); + void OnPluginMsgSendData(const ResourceMessageReplyParams& params, + const IPC::Message& message); + void OnPluginMsgFinishedLoading(const ResourceMessageReplyParams& params, + int32_t result); + void OnPluginMsgUpdateProgress(const ResourceMessageReplyParams& params, + int64_t bytes_sent, + int64_t total_bytes_to_be_sent, + int64_t bytes_received, + int64_t total_bytes_to_be_received); + + // Sends the defers loading message to the renderer to block or unblock the + // load. + void SetDefersLoading(bool defers_loading); + + int32_t ValidateCallback(scoped_refptr<TrackedCallback> callback); + + // Sets up |callback| as the pending callback. This should only be called once + // it is certain that |PP_OK_COMPLETIONPENDING| will be returned. + void RegisterCallback(scoped_refptr<TrackedCallback> callback); + + void RunCallback(int32_t result); + + // Saves the given response info to response_info_, handling file refs if + // necessary. This does not issue any callbacks. + void SaveResponseInfo(const URLResponseInfoData& data); + + size_t FillUserBuffer(); + + Mode mode_; + URLRequestInfoData request_data_; + + scoped_refptr<TrackedCallback> pending_callback_; + + PP_URLLoaderTrusted_StatusCallback status_callback_; + + std::deque<char> buffer_; + int64_t bytes_sent_; + int64_t total_bytes_to_be_sent_; + int64_t bytes_received_; + int64_t total_bytes_to_be_received_; + char* user_buffer_; + size_t user_buffer_size_; + int32_t done_status_; + bool is_streaming_to_file_; + bool is_asynchronous_load_suspended_; + + // The response info if we've received it. + scoped_refptr<URLResponseInfoResource> response_info_; + + DISALLOW_COPY_AND_ASSIGN(URLLoaderResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_URL_LOADER_RESOURCE_H_
\ No newline at end of file diff --git a/ppapi/proxy/url_response_info_resource.h b/ppapi/proxy/url_response_info_resource.h index f05b32c..dfb1f8f 100644 --- a/ppapi/proxy/url_response_info_resource.h +++ b/ppapi/proxy/url_response_info_resource.h @@ -37,6 +37,8 @@ class PPAPI_PROXY_EXPORT URLResponseInfoResource virtual PP_Var GetProperty(PP_URLResponseProperty property) OVERRIDE; virtual PP_Resource GetBodyAsFileRef() OVERRIDE; + const URLResponseInfoData& data() const { return data_; } + private: URLResponseInfoData data_; |