diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-24 05:18:15 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-24 05:18:15 +0000 |
commit | 12aff51ce1c9e3ac9f5f75b99aceedaee3ad21c9 (patch) | |
tree | cbcd76eac73bd63d88c190eadde9650c4d38081c | |
parent | b1d9a46a20a2f7257acd9c0a6ff1a5e6dfb61e0e (diff) | |
download | chromium_src-12aff51ce1c9e3ac9f5f75b99aceedaee3ad21c9.zip chromium_src-12aff51ce1c9e3ac9f5f75b99aceedaee3ad21c9.tar.gz chromium_src-12aff51ce1c9e3ac9f5f75b99aceedaee3ad21c9.tar.bz2 |
Revert r200412 and r204024
BUG=268778
R=yzshen@chromium.org
Review URL: https://codereview.chromium.org/23187007
git-svn-id: svn://svn.chromium.org/chrome/branches/1547/src@219422 0039d316-1c4b-4281-b951-d872f2087c98
52 files changed, 1697 insertions, 1468 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 842c224..19ff962 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -252,8 +252,6 @@ 'renderer/pepper/pepper_truetype_font_linux.cc', 'renderer/pepper/pepper_truetype_font_mac.mm', 'renderer/pepper/pepper_truetype_font_win.cc', - 'renderer/pepper/pepper_url_loader_host.cc', - 'renderer/pepper/pepper_url_loader_host.h', 'renderer/pepper/pepper_video_capture_host.cc', 'renderer/pepper/pepper_video_capture_host.h', 'renderer/pepper/pepper_websocket_host.cc', diff --git a/content/public/renderer/renderer_ppapi_host.h b/content/public/renderer/renderer_ppapi_host.h index 8d2e585..c8528d7 100644 --- a/content/public/renderer/renderer_ppapi_host.h +++ b/content/public/renderer/renderer_ppapi_host.h @@ -95,10 +95,6 @@ class RendererPpapiHost { virtual WebKit::WebPluginContainer* GetContainerForInstance( PP_Instance instance) const = 0; - // Returns the PID of the child process containing the plugin. If running - // in-process, this returns base::kNullProcessId. - virtual base::ProcessId GetPluginPID() const = 0; - // Returns true if the given instance is considered to be currently // processing a user gesture or the plugin module has the "override user // gesture" flag set (in which case it can always do things normally diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc index d7872c9..f3ebccd 100644 --- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc +++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc @@ -14,7 +14,6 @@ #include "content/renderer/pepper/pepper_file_system_host.h" #include "content/renderer/pepper/pepper_graphics_2d_host.h" #include "content/renderer/pepper/pepper_truetype_font_host.h" -#include "content/renderer/pepper/pepper_url_loader_host.h" #include "content/renderer/pepper/pepper_video_capture_host.h" #include "content/renderer/pepper/pepper_video_destination_host.h" #include "content/renderer/pepper/pepper_video_source_host.h" @@ -98,9 +97,6 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost( PepperGraphics2DHost::Create(host_, instance, params.pp_resource(), size, is_always_opaque)); } - case PpapiHostMsg_URLLoader_Create::ID: - return scoped_ptr<ResourceHost>(new PepperURLLoaderHost( - host_, false, instance, params.pp_resource())); case PpapiHostMsg_WebSocket_Create::ID: return scoped_ptr<ResourceHost>(new PepperWebSocketHost( host_, instance, params.pp_resource())); diff --git a/content/renderer/pepper/mock_renderer_ppapi_host.cc b/content/renderer/pepper/mock_renderer_ppapi_host.cc index 5a2da54..147c01e 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/content/renderer/pepper/mock_renderer_ppapi_host.cc @@ -47,11 +47,6 @@ WebKit::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance( return NULL; } -base::ProcessId MockRendererPpapiHost::GetPluginPID() const { - NOTIMPLEMENTED(); - return base::kNullProcessId; -} - bool MockRendererPpapiHost::HasUserGesture(PP_Instance instance) const { return has_user_gesture_; } diff --git a/content/renderer/pepper/mock_renderer_ppapi_host.h b/content/renderer/pepper/mock_renderer_ppapi_host.h index 3194d3f..08f7514 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.h +++ b/content/renderer/pepper/mock_renderer_ppapi_host.h @@ -45,7 +45,6 @@ class MockRendererPpapiHost : public RendererPpapiHost { PP_Instance instance) const OVERRIDE; virtual WebKit::WebPluginContainer* GetContainerForInstance( PP_Instance instance) const OVERRIDE; - virtual base::ProcessId GetPluginPID() const OVERRIDE; virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE; virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE; virtual gfx::Point PluginPointToRenderView( diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.cc b/content/renderer/pepper/pepper_in_process_resource_creation.cc index 127a957..5ec0ef0c 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.cc +++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc @@ -22,7 +22,6 @@ #include "ppapi/proxy/graphics_2d_resource.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/printing_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/websocket_resource.h" @@ -117,13 +116,6 @@ PP_Resource PepperInProcessResourceCreation::CreateTrueTypeFont( return 0; } -PP_Resource PepperInProcessResourceCreation::CreateURLLoader( - PP_Instance instance) { - return (new ppapi::proxy::URLLoaderResource( - host_impl_->in_process_router()->GetPluginConnection(), - instance))->GetReference(); -} - PP_Resource PepperInProcessResourceCreation::CreateURLRequestInfo( PP_Instance instance) { return (new ppapi::proxy::URLRequestInfoResource( @@ -131,6 +123,15 @@ PP_Resource PepperInProcessResourceCreation::CreateURLRequestInfo( instance, ::ppapi::URLRequestInfoData()))->GetReference(); } +PP_Resource PepperInProcessResourceCreation::CreateURLResponseInfo( + PP_Instance instance, + const ::ppapi::URLResponseInfoData& data, + PP_Resource file_ref_resource) { + return (new ppapi::proxy::URLResponseInfoResource( + host_impl_->in_process_router()->GetPluginConnection(), + instance, data, file_ref_resource))->GetReference(); +} + PP_Resource PepperInProcessResourceCreation::CreateWebSocket( PP_Instance instance) { return (new ppapi::proxy::WebSocketResource( diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h index 330196f..847320b 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.h +++ b/content/renderer/pepper/pepper_in_process_resource_creation.h @@ -61,10 +61,12 @@ class PepperInProcessResourceCreation virtual PP_Resource CreateTrueTypeFont( PP_Instance instance, const struct PP_TrueTypeFontDesc_Dev* desc) OVERRIDE; - virtual PP_Resource CreateURLLoader( - PP_Instance instance) OVERRIDE; virtual PP_Resource CreateURLRequestInfo( PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateURLResponseInfo( + PP_Instance instance, + const ::ppapi::URLResponseInfoData& data, + PP_Resource file_ref_resource) OVERRIDE; virtual PP_Resource CreateWebSocket( PP_Instance instance) OVERRIDE; diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index 16a6155..ee1b8c9 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -48,14 +48,12 @@ #include "content/renderer/pepper/pepper_graphics_2d_host.h" #include "content/renderer/pepper/pepper_hung_plugin_filter.h" #include "content/renderer/pepper/pepper_in_process_resource_creation.h" -#include "content/renderer/pepper/pepper_in_process_router.h" #include "content/renderer/pepper/pepper_platform_audio_input_impl.h" #include "content/renderer/pepper/pepper_platform_audio_output_impl.h" #include "content/renderer/pepper/pepper_platform_context_3d_impl.h" #include "content/renderer/pepper/pepper_platform_image_2d_impl.h" #include "content/renderer/pepper/pepper_platform_video_capture_impl.h" #include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h" -#include "content/renderer/pepper/pepper_url_loader_host.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" @@ -71,16 +69,11 @@ #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/url_loader_resource.h" -#include "ppapi/shared_impl/api_id.h" #include "ppapi/shared_impl/file_path.h" #include "ppapi/shared_impl/platform_file.h" -#include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppapi_permissions.h" #include "ppapi/shared_impl/ppapi_preferences.h" #include "ppapi/shared_impl/ppb_device_ref_shared.h" -#include "ppapi/shared_impl/ppp_instance_combined.h" -#include "ppapi/shared_impl/resource_tracker.h" #include "ppapi/shared_impl/socket_option_data.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h" @@ -100,7 +93,6 @@ #include "webkit/plugins/ppapi/ppb_tcp_server_socket_private_impl.h" #include "webkit/plugins/ppapi/ppb_tcp_socket_private_impl.h" #include "webkit/plugins/ppapi/resource_helper.h" -#include "webkit/plugins/ppapi/url_response_info_util.h" #include "webkit/plugins/webplugininfo.h" using WebKit::WebView; @@ -1327,64 +1319,6 @@ void PepperPluginDelegateImpl::SaveURLAs(const GURL& url) { render_view_->routing_id(), url, referrer)); } -void PepperPluginDelegateImpl::HandleDocumentLoad( - webkit::ppapi::PluginInstance* instance, - const WebKit::WebURLResponse& response) { - DCHECK(!instance->document_loader()); - - PP_Instance pp_instance = instance->pp_instance(); - RendererPpapiHostImpl* host_impl = static_cast<RendererPpapiHostImpl*>( - instance->module()->GetEmbedderState()); - - // Create a loader resource host for this load. Note that we have to set - // the document_loader before issuing the in-process - // PPP_Instance.HandleDocumentLoad call below, since this may reentrantly - // call into the instance and expect it to be valid. - PepperURLLoaderHost* loader_host = - new PepperURLLoaderHost(host_impl, true, pp_instance, 0); - instance->set_document_loader(loader_host); - loader_host->didReceiveResponse(NULL, response); - - // This host will be pending until the resource object attaches to it. - int pending_host_id = host_impl->GetPpapiHost()->AddPendingResourceHost( - scoped_ptr<ppapi::host::ResourceHost>(loader_host)); - DCHECK(pending_host_id); - ppapi::URLResponseInfoData data = - webkit::ppapi::DataFromWebURLResponse(pp_instance, response); - - if (host_impl->in_process_router()) { - // Running in-process, we can just create the resource and call the - // PPP_Instance function directly. - scoped_refptr<ppapi::proxy::URLLoaderResource> loader_resource( - new ppapi::proxy::URLLoaderResource( - host_impl->in_process_router()->GetPluginConnection(), - pp_instance, pending_host_id, data)); - - PP_Resource loader_pp_resource = loader_resource->GetReference(); - if (!instance->instance_interface()->HandleDocumentLoad( - instance->pp_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. - ppapi::PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource( - loader_pp_resource); - - // Danger! If the plugin doesn't take a ref in HandleDocumentLoad, the - // resource host will be destroyed as soon as our scoped_refptr for the - // resource goes out of scope. - // - // Null it out so people don't accidentally add code below that uses it. - loader_host = NULL; - } else { - // Running out-of-process. Initiate an IPC call to notify the plugin - // process. - ppapi::proxy::HostDispatcher* dispatcher = - ppapi::proxy::HostDispatcher::GetForInstance(pp_instance); - dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad( - ppapi::API_ID_PPP_INSTANCE, pp_instance, pending_host_id, data)); - } -} - base::SharedMemory* PepperPluginDelegateImpl::CreateAnonymousSharedMemory( size_t size) { return RenderThread::Get()->HostAllocateSharedMemoryBuffer(size).release(); diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h index 974c7fb..c40ac89 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h @@ -332,9 +332,6 @@ class PepperPluginDelegateImpl PP_DeviceType_Dev type, const EnumerateDevicesCallback& callback) OVERRIDE; virtual void StopEnumerateDevices(int request_id) OVERRIDE; - virtual void HandleDocumentLoad( - webkit::ppapi::PluginInstance* instance, - const WebKit::WebURLResponse& response) OVERRIDE; // RenderViewObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/content/renderer/pepper/pepper_url_loader_host.cc b/content/renderer/pepper/pepper_url_loader_host.cc deleted file mode 100644 index 9636a58..0000000 --- a/content/renderer/pepper/pepper_url_loader_host.cc +++ /dev/null @@ -1,380 +0,0 @@ -// 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 "content/renderer/pepper/pepper_url_loader_host.h" - -#include "content/public/renderer/renderer_ppapi_host.h" -#include "net/base/net_errors.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/host/dispatch_host_message.h" -#include "ppapi/host/host_message_context.h" -#include "ppapi/host/ppapi_host.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/ppapi_globals.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLLoader.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebKit.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" -#include "third_party/WebKit/public/web/WebSecurityOrigin.h" -#include "third_party/WebKit/public/web/WebURLLoaderOptions.h" -#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" -#include "webkit/plugins/ppapi/url_request_info_util.h" -#include "webkit/plugins/ppapi/url_response_info_util.h" - -using WebKit::WebFrame; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; - -#ifdef _MSC_VER -// Do not warn about use of std::copy with raw pointers. -#pragma warning(disable : 4996) -#endif - -namespace content { - -PepperURLLoaderHost::PepperURLLoaderHost(RendererPpapiHost* host, - bool main_document_loader, - PP_Instance instance, - PP_Resource resource) - : ResourceHost(host->GetPpapiHost(), instance, resource), - renderer_ppapi_host_(host), - main_document_loader_(main_document_loader), - has_universal_access_(false), - bytes_sent_(0), - total_bytes_to_be_sent_(-1), - bytes_received_(0), - total_bytes_to_be_received_(-1) { - DCHECK((main_document_loader && !resource) || - (!main_document_loader && resource)); -} - -PepperURLLoaderHost::~PepperURLLoaderHost() { - // Normally deleting this object will delete the loader which will implicitly - // cancel the load. But this won't happen for the main document loader. So it - // would be nice to issue a Close() here. - // - // However, the PDF plugin will cancel the document load and then close the - // resource (which is reasonable). It then makes a second request to load the - // document so it can set the "want progress" flags (which is unreasonable -- - // we should probably provide download progress on document loads). - // - // But a Close() on the main document (even if the request is already - // canceled) will cancel all pending subresources, of which the second - // request is one, and the load will fail. Even if we fixed the PDF reader to - // change the timing or to send progress events to avoid the second request, - // we don't want to cancel other loads when the main one is closed. - // - // "Leaking" the main document load here by not closing it will only affect - // plugins handling main document loads (which are very few, mostly only PDF) - // that dereference without explicitly closing the main document load (which - // PDF doesn't do -- it explicitly closes it before issuing the second - // request). And the worst thing that will happen is that any remaining data - // will get queued inside WebKit. - if (main_document_loader_) { - // The PluginInstance has a non-owning pointer to us. - webkit::ppapi::PluginInstance* instance_object = - renderer_ppapi_host_->GetPluginInstance(pp_instance()); - if (instance_object) { - DCHECK(instance_object->document_loader() == this); - instance_object->set_document_loader(NULL); - } - } - - // There is a path whereby the destructor for the loader_ member can - // invoke InstanceWasDeleted() upon this URLLoaderResource, thereby - // re-entering the scoped_ptr destructor with the same scoped_ptr object - // via loader_.reset(). Be sure that loader_ is first NULL then destroy - // the scoped_ptr. See http://crbug.com/159429. - scoped_ptr<WebKit::WebURLLoader> for_destruction_only(loader_.release()); - - for (size_t i = 0; i < pending_replies_.size(); i++) - delete pending_replies_[i]; -} - -int32_t PepperURLLoaderHost::OnResourceMessageReceived( - const IPC::Message& msg, - ppapi::host::HostMessageContext* context) { - IPC_BEGIN_MESSAGE_MAP(PepperURLLoaderHost, msg) - PPAPI_DISPATCH_HOST_RESOURCE_CALL( - PpapiHostMsg_URLLoader_Open, - OnHostMsgOpen) - PPAPI_DISPATCH_HOST_RESOURCE_CALL( - PpapiHostMsg_URLLoader_SetDeferLoading, - OnHostMsgSetDeferLoading) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( - PpapiHostMsg_URLLoader_Close, - OnHostMsgClose); - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( - PpapiHostMsg_URLLoader_GrantUniversalAccess, - OnHostMsgGrantUniversalAccess) - IPC_END_MESSAGE_MAP() - return PP_ERROR_FAILED; -} - -void PepperURLLoaderHost::willSendRequest( - WebURLLoader* loader, - WebURLRequest& new_request, - const WebURLResponse& redirect_response) { - if (!request_data_.follow_redirects) { - SaveResponse(redirect_response); - SetDefersLoading(true); - } -} - -void PepperURLLoaderHost::didSendData( - WebURLLoader* loader, - unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent) { - // TODO(darin): Bounds check input? - bytes_sent_ = static_cast<int64_t>(bytes_sent); - total_bytes_to_be_sent_ = static_cast<int64_t>(total_bytes_to_be_sent); - UpdateProgress(); -} - -void PepperURLLoaderHost::didReceiveResponse(WebURLLoader* loader, - const WebURLResponse& response) { - // Sets -1 if the content length is unknown. Send before issuing callback. - total_bytes_to_be_received_ = response.expectedContentLength(); - UpdateProgress(); - - SaveResponse(response); -} - -void PepperURLLoaderHost::didDownloadData(WebURLLoader* loader, - int data_length) { - bytes_received_ += data_length; - UpdateProgress(); -} - -void PepperURLLoaderHost::didReceiveData(WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length) { - // Note that |loader| will be NULL for document loads. - bytes_received_ += data_length; - UpdateProgress(); - - PpapiPluginMsg_URLLoader_SendData* message = - new PpapiPluginMsg_URLLoader_SendData; - message->WriteData(data, data_length); - SendUpdateToPlugin(message); -} - -void PepperURLLoaderHost::didFinishLoading(WebURLLoader* loader, - double finish_time) { - // Note that |loader| will be NULL for document loads. - SendUpdateToPlugin(new PpapiPluginMsg_URLLoader_FinishedLoading(PP_OK)); -} - -void PepperURLLoaderHost::didFail(WebURLLoader* loader, - const WebURLError& error) { - // Note that |loader| will be NULL for document loads. - int32_t pp_error = PP_ERROR_FAILED; - if (error.domain.equals(WebString::fromUTF8(net::kErrorDomain))) { - // TODO(bbudge): Extend pp_errors.h to cover interesting network errors - // from the net error domain. - switch (error.reason) { - case net::ERR_ACCESS_DENIED: - case net::ERR_NETWORK_ACCESS_DENIED: - pp_error = PP_ERROR_NOACCESS; - break; - } - } else { - // It's a WebKit error. - pp_error = PP_ERROR_NOACCESS; - } - - SendUpdateToPlugin(new PpapiPluginMsg_URLLoader_FinishedLoading(pp_error)); -} - -void PepperURLLoaderHost::DidConnectPendingHostToResource() { - for (size_t i = 0; i < pending_replies_.size(); i++) { - host()->SendUnsolicitedReply(pp_resource(), *pending_replies_[i]); - delete pending_replies_[i]; - } - pending_replies_.clear(); -} - -int32_t PepperURLLoaderHost::OnHostMsgOpen( - ppapi::host::HostMessageContext* context, - const ppapi::URLRequestInfoData& request_data) { - // An "Open" isn't a resource Call so has no reply, but failure to open - // implies a load failure. To make it harder to forget to send the load - // failed reply from the open handler, we instead catch errors and convert - // them to load failed messages. - int32_t ret = InternalOnHostMsgOpen(context, request_data); - DCHECK(ret != PP_OK_COMPLETIONPENDING); - - if (ret != PP_OK) - SendUpdateToPlugin(new PpapiPluginMsg_URLLoader_FinishedLoading(ret)); - return PP_OK; -} - -// Since this is wrapped by OnHostMsgOpen, we can return errors here and they -// will be translated into a FinishedLoading call automatically. -int32_t PepperURLLoaderHost::InternalOnHostMsgOpen( - ppapi::host::HostMessageContext* context, - const ppapi::URLRequestInfoData& request_data) { - // Main document loads are already open, so don't allow people to open them - // again. - if (main_document_loader_) - return PP_ERROR_INPROGRESS; - - // Create a copy of the request data since CreateWebURLRequest will populate - // the file refs. - ppapi::URLRequestInfoData filled_in_request_data = request_data; - - if (webkit::ppapi::URLRequestRequiresUniversalAccess( - filled_in_request_data) && - !has_universal_access_) { - ppapi::PpapiGlobals::Get()->LogWithSource( - pp_instance(), PP_LOGLEVEL_ERROR, std::string(), - "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_NOACCESS; - } - - if (loader_.get()) - return PP_ERROR_INPROGRESS; - - WebFrame* frame = GetFrame(); - if (!frame) - return PP_ERROR_FAILED; - WebURLRequest web_request; - if (!webkit::ppapi::CreateWebURLRequest(&filled_in_request_data, frame, - &web_request)) - return PP_ERROR_FAILED; - web_request.setRequestorProcessID(renderer_ppapi_host_->GetPluginPID()); - - WebURLLoaderOptions options; - if (has_universal_access_) { - options.allowCredentials = true; - options.crossOriginRequestPolicy = - WebURLLoaderOptions::CrossOriginRequestPolicyAllow; - } else { - // All other HTTP requests are untrusted. - options.untrustedHTTP = true; - if (filled_in_request_data.allow_cross_origin_requests) { - // Allow cross-origin requests with access control. The request specifies - // if credentials are to be sent. - options.allowCredentials = filled_in_request_data.allow_credentials; - options.crossOriginRequestPolicy = - WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; - } else { - // Same-origin requests can always send credentials. - options.allowCredentials = true; - } - } - - loader_.reset(frame->createAssociatedURLLoader(options)); - if (!loader_.get()) - return PP_ERROR_FAILED; - - // Don't actually save the request until we know we're going to load. - request_data_ = filled_in_request_data; - loader_->loadAsynchronously(web_request, this); - - // Although the request is technically pending, this is not a "Call" message - // so we don't return COMPLETIONPENDING. - return PP_OK; -} - -int32_t PepperURLLoaderHost::OnHostMsgSetDeferLoading( - ppapi::host::HostMessageContext* context, - bool defers_loading) { - SetDefersLoading(defers_loading); - return PP_OK; -} - -int32_t PepperURLLoaderHost::OnHostMsgClose( - ppapi::host::HostMessageContext* context) { - Close(); - return PP_OK; -} - -int32_t PepperURLLoaderHost::OnHostMsgGrantUniversalAccess( - ppapi::host::HostMessageContext* context) { - // Only plugins with private permission can bypass same origin. - if (!host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) - return PP_ERROR_FAILED; - has_universal_access_ = true; - return PP_OK; -} - -void PepperURLLoaderHost::SendUpdateToPlugin(IPC::Message* msg) { - if (pp_resource()) { - host()->SendUnsolicitedReply(pp_resource(), *msg); - delete msg; - } else { - pending_replies_.push_back(msg); - } -} - -void PepperURLLoaderHost::Close() { - if (loader_.get()) - loader_->cancel(); - else if (main_document_loader_) - GetFrame()->stopLoading(); -} - -WebKit::WebFrame* PepperURLLoaderHost::GetFrame() { - webkit::ppapi::PluginInstance* instance_object = - renderer_ppapi_host_->GetPluginInstance(pp_instance()); - if (!instance_object) - return NULL; - return instance_object->container()->element().document().frame(); -} - -void PepperURLLoaderHost::SetDefersLoading(bool defers_loading) { - if (loader_.get()) - loader_->setDefersLoading(defers_loading); - - // TODO(brettw) bug 96770: We need a way to set the defers loading flag on - // main document loads (when the loader_ is null). -} - -void PepperURLLoaderHost::SaveResponse(const WebURLResponse& response) { - if (!main_document_loader_) { - // When we're the main document loader, we send the response data up front, - // so we don't want to trigger any callbacks in the plugin which aren't - // expected. We should not be getting redirects so the response sent - // up-front should be valid (plugin document loads happen after all - // redirects are processed since WebKit has to know the MIME type). - SendUpdateToPlugin( - new PpapiPluginMsg_URLLoader_ReceivedResponse( - webkit::ppapi::DataFromWebURLResponse(pp_instance(), response))); - } -} - -void PepperURLLoaderHost::UpdateProgress() { - bool record_download = request_data_.record_download_progress; - bool record_upload = request_data_.record_upload_progress; - if (record_download || record_upload) { - // Here we go through some effort to only send the exact information that - // the requestor wanted in the request flags. It would be just as - // efficient to send all of it, but we don't want people to rely on - // getting download progress when they happen to set the upload progress - // flag. - ppapi::proxy::ResourceMessageReplyParams params; - SendUpdateToPlugin(new PpapiPluginMsg_URLLoader_UpdateProgress( - record_upload ? bytes_sent_ : -1, - record_upload ? total_bytes_to_be_sent_ : -1, - record_download ? bytes_received_ : -1, - record_download ? total_bytes_to_be_received_ : -1)); - } -} - -} // namespace content
\ No newline at end of file diff --git a/content/renderer/pepper/pepper_url_loader_host.h b/content/renderer/pepper/pepper_url_loader_host.h deleted file mode 100644 index 88a8e26..0000000 --- a/content/renderer/pepper/pepper_url_loader_host.h +++ /dev/null @@ -1,138 +0,0 @@ -// 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 CONTENT_RENDERER_PEPPER_PEPPER_URL_LOADER_HOST_H_ -#define CONTENT_RENDERER_PEPPER_PEPPER_URL_LOADER_HOST_H_ - -#include <vector> - -#include "content/common/content_export.h" -#include "ppapi/host/resource_host.h" -#include "ppapi/proxy/resource_message_params.h" -#include "ppapi/shared_impl/url_request_info_data.h" -#include "ppapi/shared_impl/url_response_info_data.h" -#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" - -namespace WebKit { -class WebFrame; -class WebURLLoader; -} - -namespace content { - -class RendererPpapiHost; - -class PepperURLLoaderHost - : public ppapi::host::ResourceHost, - public WebKit::WebURLLoaderClient { - public: - // If main_document_loader is true, PP_Resource must be 0 since it will be - // pending until the plugin resource attaches to it. - PepperURLLoaderHost(RendererPpapiHost* host, - bool main_document_loader, - PP_Instance instance, - PP_Resource resource); - virtual ~PepperURLLoaderHost(); - - // ResourceHost implementation. - virtual int32_t OnResourceMessageReceived( - const IPC::Message& msg, - ppapi::host::HostMessageContext* context) OVERRIDE; - - // WebKit::WebURLLoaderClient implementation. - virtual void willSendRequest(WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& new_request, - const WebKit::WebURLResponse& redir_response); - virtual void didSendData(WebKit::WebURLLoader* loader, - unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent); - virtual void didReceiveResponse(WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); - virtual void didDownloadData(WebKit::WebURLLoader* loader, - int data_length); - virtual void didReceiveData(WebKit::WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader, - double finish_time); - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error); - - private: - // ResourceHost protected overrides. - virtual void DidConnectPendingHostToResource() OVERRIDE; - - // IPC messages - int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context, - const ppapi::URLRequestInfoData& request_data); - int32_t InternalOnHostMsgOpen(ppapi::host::HostMessageContext* context, - const ppapi::URLRequestInfoData& request_data); - int32_t OnHostMsgSetDeferLoading(ppapi::host::HostMessageContext* context, - bool defers_loading); - int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context); - int32_t OnHostMsgGrantUniversalAccess( - ppapi::host::HostMessageContext* context); - - // Sends or queues an unsolicited message to the plugin resource. This - // handles the case where we have created a pending host resource and the - // plugin has not connected to us yet. Such messages will be queued until the - // plugin resource connects. - // - // Takes ownership of the given pointer. - void SendUpdateToPlugin(IPC::Message* msg); - - void Close(); - - // Returns the frame for the current request. - WebKit::WebFrame* GetFrame(); - - // Calls SetDefersLoading on the current load. This encapsulates the logic - // differences between document loads and regular ones. - void SetDefersLoading(bool defers_loading); - - // Converts a WebURLResponse to a URLResponseInfo and saves it. - void SaveResponse(const WebKit::WebURLResponse& response); - - // Sends the UpdateProgress message (if necessary) to the plugin. - void UpdateProgress(); - - // Non-owning pointer. - RendererPpapiHost* renderer_ppapi_host_; - - // If true, then the plugin instance is a full-frame plugin and we're just - // wrapping the main document's loader (i.e. loader_ is null). - bool main_document_loader_; - - // The data that generated the request. - ppapi::URLRequestInfoData request_data_; - - // Set to true when this loader can ignore same originl policy. - bool has_universal_access_; - - // The loader associated with this request. MAY BE NULL. - // - // This will be NULL if the load hasn't been opened yet, or if this is a main - // document loader (when registered as a mime type). Therefore, you should - // always NULL check this value before using it. In the case of a main - // document load, you would call the functions on the document to cancel the - // load, etc. since there is no loader. - scoped_ptr<WebKit::WebURLLoader> loader_; - - int64_t bytes_sent_; - int64_t total_bytes_to_be_sent_; - int64_t bytes_received_; - int64_t total_bytes_to_be_received_; - - // Messages sent while the resource host is pending. These will be forwarded - // to the plugin when the plugin side connects. The pointers are owned by - // this object and must be deleted. - std::vector<IPC::Message*> pending_replies_; - - DISALLOW_COPY_AND_ASSIGN(PepperURLLoaderHost); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_PEPPER_PEPPER_URL_LOADER_HOST_H_
\ No newline at end of file diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc index 587dc1f..948a9f3 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc @@ -191,12 +191,6 @@ WebKit::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance( return instance_object->container(); } -base::ProcessId RendererPpapiHostImpl::GetPluginPID() const { - if (dispatcher_) - return dispatcher_->channel()->peer_pid(); - return base::kNullProcessId; -} - bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const { PluginInstance* instance_object = GetAndValidateInstance(instance); if (!instance_object) diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.h b/content/renderer/pepper/renderer_ppapi_host_impl.h index ac9b9c9..d09ff1c 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.h +++ b/content/renderer/pepper/renderer_ppapi_host_impl.h @@ -82,7 +82,7 @@ class RendererPpapiHostImpl CreateInProcessResourceCreationAPI( webkit::ppapi::PluginInstance* instance); - // RendererPpapiHost implementation. + // RendererPpapiHost. virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE; virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE; virtual webkit::ppapi::PluginInstance* GetPluginInstance( @@ -91,7 +91,6 @@ class RendererPpapiHostImpl PP_Instance instance) const OVERRIDE; virtual WebKit::WebPluginContainer* GetContainerForInstance( PP_Instance instance) const OVERRIDE; - virtual base::ProcessId GetPluginPID() const OVERRIDE; virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE; virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE; virtual gfx::Point PluginPointToRenderView( @@ -124,9 +123,7 @@ class RendererPpapiHostImpl webkit::ppapi::PluginModule* module_; // Non-owning pointer. - // The dispatcher we use to send messagse when the plugin is out-of-process. - // Will be null when running in-process. Non-owning pointer. - ppapi::proxy::HostDispatcher* dispatcher_; + ppapi::proxy::HostDispatcher* dispatcher_; // Non-owning pointer. scoped_ptr<ppapi::host::PpapiHost> ppapi_host_; diff --git a/ppapi/api/ppp_instance.idl b/ppapi/api/ppp_instance.idl index f178b7a..a5026ae 100644 --- a/ppapi/api/ppp_instance.idl +++ b/ppapi/api/ppp_instance.idl @@ -207,7 +207,7 @@ interface PPP_Instance { /** * HandleDocumentLoad() is called after initialize for a full-frame - * instance that was instantiated based on the MIME type of a DOMWindow + * module that was instantiated based on the MIME type of a DOMWindow * navigation. This situation only applies to modules that are pre-registered * to handle certain MIME types. If you haven't specifically registered to * handle a MIME type or aren't positive this applies to you, your @@ -230,8 +230,7 @@ interface PPP_Instance { * @param[in] url_loader An open <code>PPB_URLLoader</code> instance. * * @return <code>PP_TRUE</code> if the data was handled, - * <code>PP_FALSE</code> otherwise. If you return false, the load will be - * canceled for you. + * <code>PP_FALSE</code> otherwise. */ PP_Bool HandleDocumentLoad( /* A PP_Instance identifying one instance of a module. */ diff --git a/ppapi/c/ppp_instance.h b/ppapi/c/ppp_instance.h index d2641f9..bdc2883 100644 --- a/ppapi/c/ppp_instance.h +++ b/ppapi/c/ppp_instance.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From ppp_instance.idl modified Thu Apr 25 13:07:47 2013. */ +/* From ppp_instance.idl modified Thu Jun 28 15:08:39 2012. */ #ifndef PPAPI_C_PPP_INSTANCE_H_ #define PPAPI_C_PPP_INSTANCE_H_ @@ -146,7 +146,7 @@ struct PPP_Instance_1_1 { void (*DidChangeFocus)(PP_Instance instance, PP_Bool has_focus); /** * HandleDocumentLoad() is called after initialize for a full-frame - * instance that was instantiated based on the MIME type of a DOMWindow + * module that was instantiated based on the MIME type of a DOMWindow * navigation. This situation only applies to modules that are pre-registered * to handle certain MIME types. If you haven't specifically registered to * handle a MIME type or aren't positive this applies to you, your @@ -169,8 +169,7 @@ struct PPP_Instance_1_1 { * @param[in] url_loader An open <code>PPB_URLLoader</code> instance. * * @return <code>PP_TRUE</code> if the data was handled, - * <code>PP_FALSE</code> otherwise. If you return false, the load will be - * canceled for you. + * <code>PP_FALSE</code> otherwise. */ PP_Bool (*HandleDocumentLoad)(PP_Instance instance, PP_Resource url_loader); }; diff --git a/ppapi/c/private/ppb_proxy_private.h b/ppapi/c/private/ppb_proxy_private.h index b185c2c..eac3f57 100644 --- a/ppapi/c/private/ppb_proxy_private.h +++ b/ppapi/c/private/ppb_proxy_private.h @@ -10,7 +10,7 @@ #include "ppapi/c/pp_module.h" #include "ppapi/c/pp_resource.h" -#define PPB_PROXY_PRIVATE_INTERFACE "PPB_Proxy_Private;6" +#define PPB_PROXY_PRIVATE_INTERFACE "PPB_Proxy_Private;5" // Exposes functions needed by the out-of-process proxy to call into the // renderer PPAPI implementation. @@ -34,6 +34,11 @@ struct PPB_Proxy_Private { PP_Module module, PP_Bool (*is_seen)(PP_Module, PP_Instance)); + // Returns the number of bytes synchronously readable out of the URLLoader's + // buffer. Returns 0 on failure or if the url loader doesn't have any data + // now. + int32_t (*GetURLLoaderBufferedBytes)(PP_Resource url_loader); + // Allows adding additional refcounts to the PluginModule that owns the // proxy dispatcher (and all interface proxies). For every AddRef call // there must be a corresponding release call. diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 0895a8c..4d8fa6eb 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -135,6 +135,8 @@ 'proxy/ppb_tcp_socket_private_proxy.h', 'proxy/ppb_testing_proxy.cc', 'proxy/ppb_testing_proxy.h', + 'proxy/ppb_url_loader_proxy.cc', + 'proxy/ppb_url_loader_proxy.h', 'proxy/ppb_var_deprecated_proxy.cc', 'proxy/ppb_var_deprecated_proxy.h', 'proxy/ppb_video_decoder_proxy.cc', @@ -188,8 +190,6 @@ 'proxy/udp_socket_resource.h', 'proxy/udp_socket_resource_base.cc', 'proxy/udp_socket_resource_base.h', - 'proxy/url_loader_resource.cc', - 'proxy/url_loader_resource.h', 'proxy/url_request_info_resource.cc', 'proxy/url_request_info_resource.h', 'proxy/url_response_info_resource.cc', diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 0c84ae8..0c591e73 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -111,6 +111,7 @@ #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" #include "ppapi/proxy/ppb_tcp_socket_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" @@ -250,6 +251,7 @@ 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/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 7452807..d97cc32 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -610,10 +610,10 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_DidChangeView, IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus, PP_Instance /* instance */, PP_Bool /* has_focus */) -IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_HandleDocumentLoad, - PP_Instance /* instance */, - int /* pending_loader_host_id */, - ppapi::URLResponseInfoData /* response */) +IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleDocumentLoad, + PP_Instance /* instance */, + ppapi::HostResource /* url_loader */, + PP_Bool /* result */) // PPP_Messaging. IPC_MESSAGE_ROUTED2(PpapiMsg_PPPMessaging_HandleMessage, @@ -652,6 +652,19 @@ 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( @@ -729,6 +742,11 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPBTCPSocket_SetOptionACK, uint32 /* socket_id */, int32_t /* result */) +// 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 @@ -1005,6 +1023,30 @@ 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 */, @@ -1614,61 +1656,6 @@ IPC_MESSAGE_CONTROL1(PpapiPluginMsg_UDPSocket_SendToReply, int32_t /* bytes_written */) IPC_MESSAGE_CONTROL0(PpapiHostMsg_UDPSocket_Close) -// 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 diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc index c3cca4d..cb891ac 100644 --- a/ppapi/proxy/ppapi_proxy_test.cc +++ b/ppapi/proxy/ppapi_proxy_test.cc @@ -41,6 +41,11 @@ 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; } @@ -49,6 +54,7 @@ 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 new file mode 100644 index 0000000..425b61f --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.cc @@ -0,0 +1,652 @@ +// 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 new file mode 100644 index 0000000..f4c5bc5 --- /dev/null +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -0,0 +1,92 @@ +// 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 a7a0699..eb1d4e4 100644 --- a/ppapi/proxy/ppp_instance_proxy.cc +++ b/ppapi/proxy/ppp_instance_proxy.cc @@ -13,14 +13,11 @@ #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/url_loader_resource.h" +#include "ppapi/proxy/ppb_url_loader_proxy.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" @@ -86,11 +83,36 @@ void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { instance, has_focus)); } -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; +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; } static const PPP_Instance_1_1 instance_interface = { @@ -231,25 +253,19 @@ void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance, void PPP_Instance_Proxy::OnPluginMsgHandleDocumentLoad( PP_Instance instance, - 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); + 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); } } // namespace proxy diff --git a/ppapi/proxy/ppp_instance_proxy.h b/ppapi/proxy/ppp_instance_proxy.h index 85ae55c..1b599d0 100644 --- a/ppapi/proxy/ppp_instance_proxy.h +++ b/ppapi/proxy/ppp_instance_proxy.h @@ -20,7 +20,6 @@ struct PP_Rect; namespace ppapi { -struct URLResponseInfoData; struct ViewData; namespace proxy { @@ -51,9 +50,8 @@ class PPP_Instance_Proxy : public InterfaceProxy { PP_Bool flash_fullscreen); void OnPluginMsgDidChangeFocus(PP_Instance instance, PP_Bool has_focus); void OnPluginMsgHandleDocumentLoad(PP_Instance instance, - int pending_loader_host_id, - const URLResponseInfoData& data); - + const HostResource& url_loader, + PP_Bool* result); scoped_ptr<PPP_Instance_Combined> combined_interface_; }; diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index 337d620..8f33fba 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -35,6 +35,7 @@ #include "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h" #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" #include "ppapi/proxy/ppb_tcp_socket_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" @@ -42,7 +43,6 @@ #include "ppapi/proxy/truetype_font_resource.h" #include "ppapi/proxy/udp_socket_private_resource.h" #include "ppapi/proxy/udp_socket_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" @@ -85,11 +85,6 @@ 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) { @@ -174,7 +169,7 @@ PP_Resource ResourceCreationProxy::CreateTrueTypeFont( } PP_Resource ResourceCreationProxy::CreateURLLoader(PP_Instance instance) { - return (new URLLoaderResource(GetConnection(), instance))->GetReference(); + return PPB_URLLoader_Proxy::CreateProxyResource(instance); } PP_Resource ResourceCreationProxy::CreateURLRequestInfo( @@ -183,6 +178,15 @@ PP_Resource ResourceCreationProxy::CreateURLRequestInfo( GetConnection(), instance, URLRequestInfoData()))->GetReference(); } +PP_Resource ResourceCreationProxy::CreateURLResponseInfo( + PP_Instance instance, + const URLResponseInfoData& data, + PP_Resource file_ref_resource) { + return (new URLResponseInfoResource(GetConnection(), instance, + data, + file_ref_resource))->GetReference(); +} + PP_Resource ResourceCreationProxy::CreateWheelInputEvent( PP_Instance instance, PP_TimeTicks time_stamp, diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h index 47b40a8..1e7c77b 100644 --- a/ppapi/proxy/resource_creation_proxy.h +++ b/ppapi/proxy/resource_creation_proxy.h @@ -41,8 +41,6 @@ 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( @@ -87,6 +85,10 @@ class ResourceCreationProxy : public InterfaceProxy, virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateURLRequestInfo( PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateURLResponseInfo( + PP_Instance instance, + const URLResponseInfoData& data, + PP_Resource file_ref_resource) OVERRIDE; virtual PP_Resource CreateWheelInputEvent( PP_Instance instance, PP_TimeTicks time_stamp, diff --git a/ppapi/proxy/url_loader_resource.cc b/ppapi/proxy/url_loader_resource.cc deleted file mode 100644 index 5bbc937..0000000 --- a/ppapi/proxy/url_loader_resource.cc +++ /dev/null @@ -1,392 +0,0 @@ -// 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.get()); - 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 deleted file mode 100644 index 685ccfe..0000000 --- a/ppapi/proxy/url_loader_resource.h +++ /dev/null @@ -1,146 +0,0 @@ -// 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 dfb1f8f..f05b32c 100644 --- a/ppapi/proxy/url_response_info_resource.h +++ b/ppapi/proxy/url_response_info_resource.h @@ -37,8 +37,6 @@ 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_; diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h index 65a150e..6812441 100644 --- a/ppapi/shared_impl/api_id.h +++ b/ppapi/shared_impl/api_id.h @@ -46,6 +46,7 @@ enum ApiID { API_ID_PPB_TESTING, API_ID_PPB_TEXT_INPUT, API_ID_PPB_UDPSOCKET_PRIVATE, + API_ID_PPB_URL_LOADER, API_ID_PPB_URL_RESPONSE_INFO, API_ID_PPB_VAR_ARRAY_BUFFER, API_ID_PPB_VAR_DEPRECATED, diff --git a/ppapi/shared_impl/resource.cc b/ppapi/shared_impl/resource.cc index 4fb9a47..2c40961 100644 --- a/ppapi/shared_impl/resource.cc +++ b/ppapi/shared_impl/resource.cc @@ -75,7 +75,6 @@ void Resource::OnReplyReceived(const proxy::ResourceMessageReplyParams& params, } void Resource::Log(PP_LogLevel level, const std::string& message) { -printf("Log:%s\n", message.c_str()); PpapiGlobals::Get()->LogWithSource(pp_instance(), level, std::string(), message); } diff --git a/ppapi/tests/test_url_loader.cc b/ppapi/tests/test_url_loader.cc index d3602d3..0978f0e 100644 --- a/ppapi/tests/test_url_loader.cc +++ b/ppapi/tests/test_url_loader.cc @@ -800,6 +800,7 @@ std::string TestURLLoader::TestUntendedLoad() { event.Wait(); } } + // The loader should now have the data and have finished successfully. std::string body; std::string error = ReadEntireResponseBody(&loader, &body); diff --git a/ppapi/thunk/interfaces_legacy.h b/ppapi/thunk/interfaces_legacy.h index 6e53ea4..e163e80 100644 --- a/ppapi/thunk/interfaces_legacy.h +++ b/ppapi/thunk/interfaces_legacy.h @@ -9,6 +9,8 @@ LEGACY_IFACE(PPB_INPUT_EVENT_INTERFACE_1_0, ::ppapi::thunk::GetPPB_InputEvent_1_0_Thunk()) LEGACY_IFACE(PPB_INSTANCE_PRIVATE_INTERFACE_0_1, ::ppapi::thunk::GetPPB_Instance_Private_0_1_Thunk()) +LEGACY_IFACE(PPB_URLLOADERTRUSTED_INTERFACE_0_3, + ::ppapi::thunk::GetPPB_URLLoaderTrusted_0_3_Thunk()) LEGACY_IFACE(PPB_CORE_INTERFACE_1_0, &core_interface) LEGACY_IFACE(PPB_GPUBLACKLIST_PRIVATE_INTERFACE, PPB_GpuBlacklist_Private_Impl::GetInterface()) @@ -40,4 +42,3 @@ LEGACY_IFACE(PPB_VAR_INTERFACE_1_1, LEGACY_IFACE(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, ::ppapi::PPB_Var_Shared::GetVarArrayBufferInterface1_0()) - diff --git a/ppapi/thunk/interfaces_ppb_private.h b/ppapi/thunk/interfaces_ppb_private.h index 52fcb77..3d6dd32 100644 --- a/ppapi/thunk/interfaces_ppb_private.h +++ b/ppapi/thunk/interfaces_ppb_private.h @@ -49,9 +49,6 @@ PROXIED_IFACE(NoAPIName, PPB_TALK_PRIVATE_INTERFACE_2_0, // This uses the FileIO API which is declared in the public stable file. PROXIED_IFACE(NoAPIName, PPB_FILEIOTRUSTED_INTERFACE_0_4, PPB_FileIOTrusted_0_4) -PROXIED_IFACE(NoAPIName, PPB_URLLOADERTRUSTED_INTERFACE_0_3, - PPB_URLLoaderTrusted_0_3) - // Hack to keep font working. The Font 0.6 API is binary compatible with // BrowserFont 1.0, so just map the string to the same thing. // TODO(brettw) remove support for the old Font API. diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h index d3addcb..05da71f 100644 --- a/ppapi/thunk/interfaces_ppb_public_stable.h +++ b/ppapi/thunk/interfaces_ppb_public_stable.h @@ -24,6 +24,7 @@ PROXIED_API(PPB_Graphics3D) PROXIED_API(PPB_ImageData) PROXIED_API(PPB_Instance) PROXIED_API(PPB_TCPSocket) +PROXIED_API(PPB_URLLoader) // AudioConfig isn't proxied in the normal way, we have only local classes and // serialize it to a struct when we need it on the host side. @@ -74,11 +75,11 @@ PROXIED_IFACE(PPB_Instance, PPB_FULLSCREEN_INTERFACE_1_0, PPB_Fullscreen_1_0) PROXIED_IFACE(PPB_Instance, PPB_MESSAGING_INTERFACE_1_0, PPB_Messaging_1_0) PROXIED_IFACE(PPB_Instance, PPB_MOUSECURSOR_INTERFACE_1_0, PPB_MouseCursor_1_0) PROXIED_IFACE(PPB_Instance, PPB_MOUSELOCK_INTERFACE_1_0, PPB_MouseLock_1_0) +PROXIED_IFACE(PPB_URLLoader, PPB_URLLOADER_INTERFACE_1_0, PPB_URLLoader_1_0) PROXIED_IFACE(NoAPIName, PPB_NETADDRESS_INTERFACE_1_0, PPB_NetAddress_1_0) PROXIED_IFACE(NoAPIName, PPB_NETWORKPROXY_INTERFACE_1_0, PPB_NetworkProxy_1_0) PROXIED_IFACE(PPB_TCPSocket, PPB_TCPSOCKET_INTERFACE_1_0, PPB_TCPSocket_1_0) PROXIED_IFACE(NoAPIName, PPB_UDPSOCKET_INTERFACE_1_0, PPB_UDPSocket_1_0) -PROXIED_IFACE(NoAPIName, PPB_URLLOADER_INTERFACE_1_0, PPB_URLLoader_1_0) PROXIED_IFACE(NoAPIName, PPB_URLREQUESTINFO_INTERFACE_1_0, PPB_URLRequestInfo_1_0) PROXIED_IFACE(NoAPIName, PPB_URLRESPONSEINFO_INTERFACE_1_0, diff --git a/ppapi/thunk/ppb_url_loader_api.h b/ppapi/thunk/ppb_url_loader_api.h index df9b6aa..00d4690 100644 --- a/ppapi/thunk/ppb_url_loader_api.h +++ b/ppapi/thunk/ppb_url_loader_api.h @@ -49,6 +49,14 @@ class PPB_URLLoader_API { virtual void GrantUniversalAccess() = 0; virtual void RegisterStatusCallback( PP_URLLoaderTrusted_StatusCallback cb) = 0; + + // Internal function. This will fill in the given response info data and + // return true on sucesss. If the dowbload was to a file, there will be one + // plugin reference transferred to the caller. On failure, returns false. + // + // If body_as_file_ref is non-zero, this will transfer one plugin reference + // to that object to the caller. + virtual bool GetResponseInfoData(URLResponseInfoData* data) = 0; }; } // namespace thunk diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h index 082f1cc..8671ce3 100644 --- a/ppapi/thunk/resource_creation_api.h +++ b/ppapi/thunk/resource_creation_api.h @@ -33,7 +33,6 @@ struct PP_Size; namespace ppapi { -struct PPB_FileRef_CreateInfo; struct URLRequestInfoData; struct URLResponseInfoData; @@ -52,12 +51,6 @@ class ResourceCreationAPI { virtual PP_Resource CreateFileRef(PP_Instance instance, PP_Resource file_system, const char* path) = 0; - // Like the above version but takes a serialized file ref. The resource - // in the serialized file ref is passed into this, which takes ownership of - // the reference. In the proxy, the return value will be a plugin resource. - // In the impl, the return value will be the same resource ID. - virtual PP_Resource CreateFileRef( - const PPB_FileRef_CreateInfo& serialized) = 0; virtual PP_Resource CreateFileSystem(PP_Instance instance, PP_FileSystemType type) = 0; virtual PP_Resource CreateIsolatedFileSystem(PP_Instance instance, @@ -102,6 +95,14 @@ class ResourceCreationAPI { virtual PP_Resource CreateURLRequestInfo( PP_Instance instance) = 0; + // Passes a reference to the file_ref_resource, which is a process-local + // resource corresponding to the body_as_file_ref host resource in |data|, + // if there is one. + virtual PP_Resource CreateURLResponseInfo( + PP_Instance instance, + const URLResponseInfoData& data, + PP_Resource file_ref_resource) = 0; + virtual PP_Resource CreateWheelInputEvent( PP_Instance instance, PP_TimeTicks time_stamp, diff --git a/ppapi/thunk/thunk.h b/ppapi/thunk/thunk.h index f454be7..5dbab25 100644 --- a/ppapi/thunk/thunk.h +++ b/ppapi/thunk/thunk.h @@ -6,6 +6,7 @@ #define PPAPI_THUNK_THUNK_H_ #include "ppapi/c/private/ppb_instance_private.h" +#include "ppapi/c/trusted/ppb_url_loader_trusted.h" #include "ppapi/thunk/ppapi_thunk_export.h" // Declares a getter for the interface thunk of the form: @@ -38,6 +39,8 @@ namespace thunk { // the appropriate interfaces_*.h file. PPAPI_THUNK_EXPORT const PPB_Instance_Private_0_1* GetPPB_Instance_Private_0_1_Thunk(); +PPAPI_THUNK_EXPORT const PPB_URLLoaderTrusted_0_3* + GetPPB_URLLoaderTrusted_0_3_Thunk(); } // namespace thunk } // namespace ppapi diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc index 242ae86..4295520 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.cc +++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc @@ -413,10 +413,5 @@ bool MockPluginDelegate::IsRunningInProcess(PP_Instance instance) const { return false; } -void MockPluginDelegate::HandleDocumentLoad( - PluginInstance* instance, - const WebKit::WebURLResponse& response) { -} - } // namespace ppapi } // namespace webkit diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h index f4050bd..ffcb7b5 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.h +++ b/webkit/plugins/ppapi/mock_plugin_delegate.h @@ -180,8 +180,6 @@ class MockPluginDelegate : public PluginDelegate { base::ProcessId target_process_id, bool should_close_source) const; virtual bool IsRunningInProcess(PP_Instance instance) const; - virtual void HandleDocumentLoad(PluginInstance* instance, - const WebKit::WebURLResponse& response); }; } // namespace ppapi diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h index 0353afb..6895f82 100644 --- a/webkit/plugins/ppapi/plugin_delegate.h +++ b/webkit/plugins/ppapi/plugin_delegate.h @@ -86,9 +86,6 @@ class WebGamepads; class WebPlugin; struct WebCompositionUnderline; struct WebCursorInfo; -struct WebURLError; -class WebURLLoaderClient; -class WebURLResponse; } namespace webkit_glue { @@ -687,14 +684,6 @@ class PluginDelegate { // Returns true if running in process. virtual bool IsRunningInProcess(PP_Instance instance) const = 0; - - // Notifies the plugin of the document load. This should initiate the call to - // PPP_Instance.HandleDocumentLoad. - // - // The loader object should set itself on the PluginInstance as the document - // loader using set_document_loader. - virtual void HandleDocumentLoad(PluginInstance* instance, - const WebKit::WebURLResponse& response) = 0; }; } // namespace ppapi diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index a15fc5e..9fa5b10 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -40,7 +40,6 @@ #include "ppapi/shared_impl/resource.h" #include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/shared_impl/time_conversion.h" -#include "ppapi/shared_impl/url_request_info_data.h" #include "ppapi/shared_impl/var.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_buffer_api.h" @@ -86,6 +85,7 @@ #include "webkit/plugins/ppapi/ppb_buffer_impl.h" #include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h" #include "webkit/plugins/ppapi/ppb_image_data_impl.h" +#include "webkit/plugins/ppapi/ppb_url_loader_impl.h" #include "webkit/plugins/ppapi/ppp_pdf.h" #include "webkit/plugins/ppapi/url_request_info_util.h" #include "webkit/plugins/sad_plugin.h" @@ -135,11 +135,7 @@ using WebKit::WebPrintParams; using WebKit::WebPrintScalingOption; using WebKit::WebScopedUserGesture; using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderClient; using WebKit::WebURLRequest; -using WebKit::WebURLResponse; using WebKit::WebUserGestureIndicator; using WebKit::WebUserGestureToken; using WebKit::WebView; @@ -324,51 +320,6 @@ PluginInstance* PluginInstance::Create(PluginDelegate* delegate, plugin_url); } -PluginInstance::NaClDocumentLoader::NaClDocumentLoader() - : finished_loading_(false) { -} - -PluginInstance::NaClDocumentLoader::~NaClDocumentLoader(){ -} - -void PluginInstance::NaClDocumentLoader::ReplayReceivedData( - WebURLLoaderClient* document_loader) { - for (std::list<std::string>::iterator it = data_.begin(); - it != data_.end(); ++it) { - document_loader->didReceiveData(NULL, it->c_str(), it->length(), - 0 /* encoded_data_length */); - } - if (finished_loading_) { - document_loader->didFinishLoading(NULL, - 0 /* finish_time */); - } - if (error_.get()) { - document_loader->didFail(NULL, *error_); - } -} - -void PluginInstance::NaClDocumentLoader::didReceiveData( - WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length) { - data_.push_back(std::string(data, data_length)); -} - -void PluginInstance::NaClDocumentLoader::didFinishLoading( - WebURLLoader* loader, - double finish_time) { - DCHECK(!finished_loading_); - finished_loading_ = true; -} - -void PluginInstance::NaClDocumentLoader::didFail( - WebURLLoader* loader, - const WebURLError& error) { - DCHECK(!error_.get()); - error_.reset(new WebURLError(error)); -} - PluginInstance::GamepadImpl::GamepadImpl(PluginDelegate* delegate) : Resource(::ppapi::Resource::Untracked()), delegate_(delegate) { @@ -436,7 +387,6 @@ PluginInstance::PluginInstance( selection_anchor_(0), pending_user_gesture_(0.0), document_loader_(NULL), - nacl_document_load_(false), npp_(new NPP_t) { pp_instance_ = HostGlobals::Get()->AddInstance(this); @@ -447,12 +397,6 @@ PluginInstance::PluginInstance( view_data_.is_page_visible = delegate->IsPageVisible(); resource_creation_ = delegate_->CreateResourceCreationAPI(this); - - // TODO(bbudge) remove this when the trusted NaCl plugin has been removed. - // We must defer certain plugin events for NaCl instances since we switch - // from the in-process to the out-of-process proxy after instantiating them. - if (module->name() == "Native Client") - nacl_document_load_ = true; } PluginInstance::~PluginInstance() { @@ -647,27 +591,13 @@ bool PluginInstance::Initialize(const std::vector<std::string>& arg_names, return success; } -bool PluginInstance::HandleDocumentLoad( - const WebKit::WebURLResponse& response) { - DCHECK(!document_loader_); - if (!nacl_document_load_) { - if (module()->is_crashed()) { - // Don't create a resource for a crashed plugin. - container()->element().document().frame()->stopLoading(); - return false; - } - delegate()->HandleDocumentLoad(this, response); - // If the load was not abandoned, document_loader_ will now be set. It's - // possible that the load was canceled by now and document_loader_ was - // already nulled out. - } else { - // The NaCl proxy isn't available, so save the response and record document - // load notifications for later replay. - nacl_document_response_ = response; - nacl_document_loader_.reset(new NaClDocumentLoader()); - document_loader_ = nacl_document_loader_.get(); - } - return true; +bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) { + if (!document_loader_) + document_loader_ = loader; + DCHECK(loader == document_loader_.get()); + + return PP_ToBool(instance_interface_->HandleDocumentLoad( + pp_instance(), loader->pp_resource())); } bool PluginInstance::SendCompositionEventToPlugin(PP_InputEvent_Type type, @@ -2504,18 +2434,9 @@ PP_NaClResult PluginInstance::ResetAsProxied( view_change_weak_ptr_factory_.InvalidateWeakPtrs(); SendDidChangeView(); - DCHECK(nacl_document_load_); - nacl_document_load_ = false; - if (!nacl_document_response_.isNull()) { - document_loader_ = NULL; - // Pass the response to the new proxy. - HandleDocumentLoad(nacl_document_response_); - nacl_document_response_ = WebKit::WebURLResponse(); - // Replay any document load events we've received to the real loader. - nacl_document_loader_->ReplayReceivedData(document_loader_); - nacl_document_loader_.reset(NULL); - } - + // If we received HandleDocumentLoad, re-send it now via the proxy. + if (document_loader_) + HandleDocumentLoad(document_loader_.get()); return PP_NACL_OK; } diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index 4b73f07..cae0600 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -44,6 +44,7 @@ #include "ppapi/shared_impl/tracked_callback.h" #include "ppapi/thunk/ppb_gamepad_api.h" #include "ppapi/thunk/resource_creation_api.h" +#include "third_party/skia/include/core/SkRefCnt.h" #include "skia/ext/refptr.h" #include "third_party/WebKit/public/platform/WebCanvas.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -68,11 +69,8 @@ class WebInputEvent; class WebLayer; class WebMouseEvent; class WebPluginContainer; -class WebURLLoader; -class WebURLResponse; struct WebCompositionUnderline; struct WebCursorInfo; -struct WebURLError; struct WebPrintParams; } @@ -136,10 +134,6 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : // nonzero. PP_Instance pp_instance() const { return pp_instance_; } - ::ppapi::PPP_Instance_Combined* instance_interface() const { - return instance_interface_.get(); - } - ::ppapi::thunk::ResourceCreationAPI& resource_creation() { return *resource_creation_.get(); } @@ -178,11 +172,11 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : bool full_frame() const { return full_frame_; } const ::ppapi::ViewData& view_data() const { return view_data_; } - // PPP_Instance and PPP_Instance_Private. + // PPP_Instance and PPP_Instance_Private pass-through. bool Initialize(const std::vector<std::string>& arg_names, const std::vector<std::string>& arg_values, bool full_frame); - bool HandleDocumentLoad(const WebKit::WebURLResponse& response); + bool HandleDocumentLoad(PPB_URLLoader_Impl* loader); bool HandleInputEvent(const WebKit::WebInputEvent& event, WebKit::WebCursorInfo* cursor_info); PP_Var GetInstanceObject(); @@ -357,17 +351,6 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : void SimulateImeSetCompositionEvent( const ::ppapi::InputEventData& input_event); - // The document loader is valid when the plugin is "full-frame" and in this - // case is non-NULL as long as the corresponding loader resource is alive. - // This pointer is non-owning, so the loader must use set_document_loader to - // clear itself when it is destroyed. - WebKit::WebURLLoaderClient* document_loader() const { - return document_loader_; - } - void set_document_loader(WebKit::WebURLLoaderClient* loader) { - document_loader_ = loader; - } - ContentDecryptorDelegate* GetContentDecryptorDelegate(); // PPB_Instance_API implementation. @@ -500,31 +483,6 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : private: friend class PpapiUnittest; - // Class to record document load notifications and play them back once the - // real document loader becomes available. Used only by NaCl instances. - class NaClDocumentLoader : public WebKit::WebURLLoaderClient { - public: - NaClDocumentLoader(); - virtual ~NaClDocumentLoader(); - - void ReplayReceivedData(WebURLLoaderClient* document_loader); - - // WebKit::WebURLLoaderClient implementation. - virtual void didReceiveData(WebKit::WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader, - double finish_time); - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error); - - private: - std::list<std::string> data_; - bool finished_loading_; - scoped_ptr<WebKit::WebURLError> error_; - }; - // Implements PPB_Gamepad_API. This is just to avoid having an excessive // number of interfaces implemented by PluginInstance. class GamepadImpl : public ::ppapi::thunk::PPB_Gamepad_API, @@ -818,12 +776,9 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : std::vector<std::string> argn_; std::vector<std::string> argv_; - // Non-owning pointer to the document loader, if any. - WebKit::WebURLLoaderClient* document_loader_; - // State for deferring document loads. Used only by NaCl instances. - WebKit::WebURLResponse nacl_document_response_; - scoped_ptr<NaClDocumentLoader> nacl_document_loader_; - bool nacl_document_load_; + // This is NULL unless HandleDocumentLoad has called. In that case, we store + // the pointer so we can re-send it later if we are reset to talk to NaCl. + scoped_refptr<PPB_URLLoader_Impl> document_loader_; // The ContentDecryptorDelegate forwards PPP_ContentDecryptor_Private // calls and handles PPB_ContentDecryptor_Private calls. diff --git a/webkit/plugins/ppapi/ppapi_webplugin_impl.cc b/webkit/plugins/ppapi/ppapi_webplugin_impl.cc index 26dcbdd..24e152f3 100644 --- a/webkit/plugins/ppapi/ppapi_webplugin_impl.cc +++ b/webkit/plugins/ppapi/ppapi_webplugin_impl.cc @@ -28,6 +28,7 @@ #include "webkit/plugins/ppapi/npobject_var.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/ppb_url_loader_impl.h" using ppapi::NPObjectVar; using WebKit::WebCanvas; @@ -201,26 +202,38 @@ bool WebPluginImpl::handleInputEvent(const WebKit::WebInputEvent& event, void WebPluginImpl::didReceiveResponse( const WebKit::WebURLResponse& response) { - DCHECK(!instance_->document_loader()); - instance_->HandleDocumentLoad(response); + DCHECK(!document_loader_); + + if (instance_->module()->is_crashed()) { + // Don't create a resource for a crashed plugin. + instance_->container()->element().document().frame()->stopLoading(); + return; + } + + document_loader_ = new PPB_URLLoader_Impl(instance_->pp_instance(), true); + document_loader_->didReceiveResponse(NULL, response); + + if (!instance_->HandleDocumentLoad(document_loader_)) + document_loader_ = NULL; } void WebPluginImpl::didReceiveData(const char* data, int data_length) { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); - if (document_loader) - document_loader->didReceiveData(NULL, data, data_length, 0); + if (document_loader_) + document_loader_->didReceiveData(NULL, data, data_length, data_length); } void WebPluginImpl::didFinishLoading() { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); - if (document_loader) - document_loader->didFinishLoading(NULL, 0.0); + if (document_loader_) { + document_loader_->didFinishLoading(NULL, 0); + document_loader_ = NULL; + } } void WebPluginImpl::didFailLoading(const WebKit::WebURLError& error) { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); - if (document_loader) - document_loader->didFail(NULL, error); + if (document_loader_) { + document_loader_->didFail(NULL, error); + document_loader_ = NULL; + } } void WebPluginImpl::didFinishLoadingFrameRequest(const WebKit::WebURL& url, diff --git a/webkit/plugins/ppapi/ppapi_webplugin_impl.h b/webkit/plugins/ppapi/ppapi_webplugin_impl.h index b317daa..b7495cf 100644 --- a/webkit/plugins/ppapi/ppapi_webplugin_impl.h +++ b/webkit/plugins/ppapi/ppapi_webplugin_impl.h @@ -99,6 +99,7 @@ class WebPluginImpl : public WebKit::WebPlugin { // being an embedded resource. bool full_frame_; scoped_refptr<PluginInstance> instance_; + scoped_refptr<PPB_URLLoader_Impl> document_loader_; gfx::Rect plugin_rect_; PP_Var instance_object_; WebKit::WebPluginContainer* container_; diff --git a/webkit/plugins/ppapi/ppb_proxy_impl.cc b/webkit/plugins/ppapi/ppb_proxy_impl.cc index 2910045..070aa7a 100644 --- a/webkit/plugins/ppapi/ppb_proxy_impl.cc +++ b/webkit/plugins/ppapi/ppb_proxy_impl.cc @@ -10,6 +10,7 @@ #include "webkit/plugins/ppapi/host_globals.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/ppb_url_loader_impl.h" using ppapi::PpapiGlobals; using ppapi::thunk::EnterResource; @@ -41,6 +42,13 @@ void SetReserveInstanceIDCallback(PP_Module module, plugin_module->SetReserveInstanceIDCallback(reserve); } +int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) { + EnterResource<PPB_URLLoader_API> enter(url_loader, true); + if (enter.succeeded()) + return static_cast<PPB_URLLoader_Impl*>(enter.object())->buffer_size(); + return 0; +} + void AddRefModule(PP_Module module) { PluginModule* plugin_module = HostGlobals::Get()->GetModule(module); if (plugin_module) @@ -64,6 +72,7 @@ const PPB_Proxy_Private ppb_proxy = { &PluginCrashed, &GetInstanceForResource, &SetReserveInstanceIDCallback, + &GetURLLoaderBufferedBytes, &AddRefModule, &ReleaseModule, &IsInModuleDestructor diff --git a/webkit/plugins/ppapi/ppb_url_loader_impl.cc b/webkit/plugins/ppapi/ppb_url_loader_impl.cc new file mode 100644 index 0000000..e5dce65 --- /dev/null +++ b/webkit/plugins/ppapi/ppb_url_loader_impl.cc @@ -0,0 +1,549 @@ +// 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 "webkit/plugins/ppapi/ppb_url_loader_impl.h" + +#include "base/logging.h" +#include "net/base/net_errors.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppb_url_loader.h" +#include "ppapi/c/trusted/ppb_url_loader_trusted.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/ppb_url_request_info_api.h" +#include "third_party/WebKit/public/platform/WebURLError.h" +#include "third_party/WebKit/public/platform/WebURLLoader.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebPluginContainer.h" +#include "third_party/WebKit/public/web/WebURLLoaderOptions.h" +#include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/plugin_module.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/resource_helper.h" +#include "webkit/plugins/ppapi/url_request_info_util.h" +#include "webkit/plugins/ppapi/url_response_info_util.h" + +using ppapi::Resource; +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_URLLoader_API; +using ppapi::thunk::PPB_URLRequestInfo_API; +using ppapi::TrackedCallback; +using WebKit::WebFrame; +using WebKit::WebString; +using WebKit::WebURL; +using WebKit::WebURLError; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderOptions; +using WebKit::WebURLRequest; +using WebKit::WebURLResponse; + +#ifdef _MSC_VER +// Do not warn about use of std::copy with raw pointers. +#pragma warning(disable : 4996) +#endif + +namespace webkit { +namespace ppapi { + +namespace { + +WebFrame* GetFrameForResource(const Resource* resource) { + PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(resource); + if (!plugin_instance) + return NULL; + return plugin_instance->container()->element().document().frame(); +} + +} // namespace + +PPB_URLLoader_Impl::PPB_URLLoader_Impl(PP_Instance instance, + bool main_document_loader) + : Resource(::ppapi::OBJECT_IS_IMPL, instance), + main_document_loader_(main_document_loader), + pending_callback_(), + 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), + has_universal_access_(false), + status_callback_(NULL) { +} + +PPB_URLLoader_Impl::~PPB_URLLoader_Impl() { + // Removes the resource from the ResourceTracker's tables. This normally + // happens as part of Resource destruction, but if a subclass destructor + // has a risk of re-entering destruction via the ResourceTracker, it can + // call this explicitly to get rid of the table entry before continuing + // with the destruction. If the resource is not in the ResourceTracker's + // tables, silently does nothing. See http://crbug.com/159429. + RemoveFromResourceTracker(); +} + +PPB_URLLoader_API* PPB_URLLoader_Impl::AsPPB_URLLoader_API() { + return this; +} + +void PPB_URLLoader_Impl::InstanceWasDeleted() { + loader_.reset(); +} + +int32_t PPB_URLLoader_Impl::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 PPB_URLLoader_Impl::Open( + const ::ppapi::URLRequestInfoData& request_data, + int requestor_pid, + scoped_refptr<TrackedCallback> callback) { + // Main document loads are already open, so don't allow people to open them + // again. + if (main_document_loader_) + return PP_ERROR_INPROGRESS; + + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + + // Create a copy of the request data since CreateWebURLRequest will populate + // the file refs. + ::ppapi::URLRequestInfoData filled_in_request_data = request_data; + + if (URLRequestRequiresUniversalAccess(filled_in_request_data) && + !has_universal_access_) { + 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_NOACCESS; + } + + if (loader_) + return PP_ERROR_INPROGRESS; + + WebFrame* frame = GetFrameForResource(this); + if (!frame) + return PP_ERROR_FAILED; + WebURLRequest web_request; + if (!CreateWebURLRequest(&filled_in_request_data, frame, &web_request)) + return PP_ERROR_FAILED; + web_request.setRequestorProcessID(requestor_pid); + + // Save a copy of the request info so the plugin can continue to use and + // change it while we're doing the request without affecting us. We must do + // this after CreateWebURLRequest since that fills out the file refs. + request_data_ = filled_in_request_data; + + WebURLLoaderOptions options; + if (has_universal_access_) { + options.allowCredentials = true; + options.crossOriginRequestPolicy = + WebURLLoaderOptions::CrossOriginRequestPolicyAllow; + } else { + // All other HTTP requests are untrusted. + options.untrustedHTTP = true; + if (request_data_.allow_cross_origin_requests) { + // Allow cross-origin requests with access control. The request specifies + // if credentials are to be sent. + options.allowCredentials = request_data_.allow_credentials; + options.crossOriginRequestPolicy = + WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; + } else { + // Same-origin requests can always send credentials. + options.allowCredentials = true; + } + } + + is_asynchronous_load_suspended_ = false; + loader_.reset(frame->createAssociatedURLLoader(options)); + if (!loader_) + return PP_ERROR_FAILED; + + loader_->loadAsynchronously(web_request, this); + + // Notify completion when we receive a redirect or response headers. + RegisterCallback(callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t PPB_URLLoader_Impl::FollowRedirect( + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + + SetDefersLoading(false); // Allow the redirect to continue. + RegisterCallback(callback); + return PP_OK_COMPLETIONPENDING; +} + +PP_Bool PPB_URLLoader_Impl::GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) { + if (!RecordUploadProgress()) { + *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 PPB_URLLoader_Impl::GetDownloadProgress( + int64_t* bytes_received, + int64_t* total_bytes_to_be_received) { + if (!RecordDownloadProgress()) { + *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 PPB_URLLoader_Impl::GetResponseInfo() { + ::ppapi::thunk::EnterResourceCreationNoLock enter(pp_instance()); + if (enter.failed() || !response_info_) + return 0; + + // Since we're the "host" the process-local resource for the file ref is + // the same as the host resource. We pass a ref to the file ref. + if (!response_info_->body_as_file_ref.resource.is_null()) { + ::ppapi::PpapiGlobals::Get()->GetResourceTracker()->AddRefResource( + response_info_->body_as_file_ref.resource.host_resource()); + } + return enter.functions()->CreateURLResponseInfo( + pp_instance(), + *response_info_, + response_info_->body_as_file_ref.resource.host_resource()); +} + +int32_t PPB_URLLoader_Impl::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_->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 PPB_URLLoader_Impl::FinishStreamingToFile( + scoped_refptr<TrackedCallback> callback) { + int32_t rv = ValidateCallback(callback); + if (rv != PP_OK) + return rv; + if (!response_info_.get() || + response_info_->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 PPB_URLLoader_Impl::Close() { + if (loader_) + loader_->cancel(); + else if (main_document_loader_) + GetFrameForResource(this)->stopLoading(); + + // We must not access the buffer provided by the caller from this point on. + user_buffer_ = NULL; + user_buffer_size_ = 0; + if (TrackedCallback::IsPending(pending_callback_)) + pending_callback_->PostAbort(); +} + +void PPB_URLLoader_Impl::GrantUniversalAccess() { + has_universal_access_ = true; +} + +void PPB_URLLoader_Impl::RegisterStatusCallback( + PP_URLLoaderTrusted_StatusCallback cb) { + status_callback_ = cb; +} + +bool PPB_URLLoader_Impl::GetResponseInfoData( + ::ppapi::URLResponseInfoData* data) { + if (!response_info_) + return false; + + *data = *response_info_; + + // We transfer one plugin reference to the FileRef to the caller. + if (!response_info_->body_as_file_ref.resource.is_null()) { + ::ppapi::PpapiGlobals::Get()->GetResourceTracker()->AddRefResource( + response_info_->body_as_file_ref.resource.host_resource()); + } + return true; +} + +void PPB_URLLoader_Impl::willSendRequest( + WebURLLoader* loader, + WebURLRequest& new_request, + const WebURLResponse& redirect_response) { + if (!request_data_.follow_redirects) { + SaveResponse(redirect_response); + SetDefersLoading(true); + RunCallback(PP_OK); + } +} + +void PPB_URLLoader_Impl::didSendData( + WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent) { + // TODO(darin): Bounds check input? + bytes_sent_ = static_cast<int64_t>(bytes_sent); + total_bytes_to_be_sent_ = static_cast<int64_t>(total_bytes_to_be_sent); + UpdateStatus(); +} + +void PPB_URLLoader_Impl::didReceiveResponse(WebURLLoader* loader, + const WebURLResponse& response) { + SaveResponse(response); + + // Sets -1 if the content length is unknown. + total_bytes_to_be_received_ = response.expectedContentLength(); + UpdateStatus(); + + RunCallback(PP_OK); +} + +void PPB_URLLoader_Impl::didDownloadData(WebURLLoader* loader, + int data_length) { + bytes_received_ += data_length; + UpdateStatus(); +} + +void PPB_URLLoader_Impl::didReceiveData(WebURLLoader* loader, + const char* data, + int data_length, + int encoded_data_length) { + // Note that |loader| will be NULL for document loads. + bytes_received_ += data_length; + UpdateStatus(); + + 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 PPB_URLLoader_Impl::didFinishLoading(WebURLLoader* loader, + double finish_time) { + FinishLoading(PP_OK); +} + +void PPB_URLLoader_Impl::didFail(WebURLLoader* loader, + const WebURLError& error) { + int32_t pp_error = PP_ERROR_FAILED; + if (error.domain.equals(WebString::fromUTF8(net::kErrorDomain))) { + // TODO(bbudge): Extend pp_errors.h to cover interesting network errors + // from the net error domain. + switch (error.reason) { + case net::ERR_ABORTED: + pp_error = PP_ERROR_ABORTED; + break; + case net::ERR_ACCESS_DENIED: + case net::ERR_NETWORK_ACCESS_DENIED: + pp_error = PP_ERROR_NOACCESS; + break; + } + } else { + // It's a WebKit error. + pp_error = PP_ERROR_NOACCESS; + } + + FinishLoading(pp_error); +} + +void PPB_URLLoader_Impl::SetDefersLoading(bool defers_loading) { + if (loader_) { + loader_->setDefersLoading(defers_loading); + is_asynchronous_load_suspended_ = defers_loading; + } + + // TODO(brettw) bug 96770: We need a way to set the defers loading flag on + // main document loads (when the loader_ is null). +} + +void PPB_URLLoader_Impl::FinishLoading(int32_t done_status) { + done_status_ = done_status; + 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_); +} + +int32_t PPB_URLLoader_Impl::ValidateCallback( + scoped_refptr<TrackedCallback> callback) { + DCHECK(callback); + + if (TrackedCallback::IsPending(pending_callback_)) + return PP_ERROR_INPROGRESS; + + return PP_OK; +} + +void PPB_URLLoader_Impl::RegisterCallback( + scoped_refptr<TrackedCallback> callback) { + DCHECK(!TrackedCallback::IsPending(pending_callback_)); + + PluginModule* plugin_module = ResourceHelper::GetPluginModule(this); + if (!plugin_module) + return; + + pending_callback_ = callback; +} + +void PPB_URLLoader_Impl::RunCallback(int32_t result) { + // This may be null only when this is a main document loader. + if (!pending_callback_) { + CHECK(main_document_loader_); + 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); +} + +size_t PPB_URLLoader_Impl::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; +} + +void PPB_URLLoader_Impl::SaveResponse(const WebURLResponse& response) { + // DataFromWebURLResponse returns a file ref with one reference to it, which + // we take over via our ScopedPPResource. + response_info_.reset(new ::ppapi::URLResponseInfoData( + DataFromWebURLResponse(pp_instance(), response))); + response_info_file_ref_ = ::ppapi::ScopedPPResource( + ::ppapi::ScopedPPResource::PassRef(), + response_info_->body_as_file_ref.resource.host_resource()); +} + +void PPB_URLLoader_Impl::UpdateStatus() { + if (status_callback_ && + (RecordDownloadProgress() || RecordUploadProgress())) { + // Here we go through some effort to only send the exact information that + // the requestor wanted in the request flags. It would be just as + // efficient to send all of it, but we don't want people to rely on + // getting download progress when they happen to set the upload progress + // flag. + status_callback_( + pp_instance(), pp_resource(), + RecordUploadProgress() ? bytes_sent_ : -1, + RecordUploadProgress() ? total_bytes_to_be_sent_ : -1, + RecordDownloadProgress() ? bytes_received_ : -1, + RecordDownloadProgress() ? total_bytes_to_be_received_ : -1); + } +} + +bool PPB_URLLoader_Impl::RecordDownloadProgress() const { + return request_data_.record_download_progress; +} + +bool PPB_URLLoader_Impl::RecordUploadProgress() const { + return request_data_.record_upload_progress; +} + +} // namespace ppapi +} // namespace webkit + diff --git a/webkit/plugins/ppapi/ppb_url_loader_impl.h b/webkit/plugins/ppapi/ppb_url_loader_impl.h new file mode 100644 index 0000000..586aa9c --- /dev/null +++ b/webkit/plugins/ppapi/ppb_url_loader_impl.h @@ -0,0 +1,176 @@ +// 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 WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_ +#define WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_ + +#include <deque> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/trusted/ppb_url_loader_trusted.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/shared_impl/url_request_info_data.h" +#include "ppapi/thunk/ppb_url_loader_api.h" +#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" + +namespace WebKit { +class WebURL; +} + +namespace webkit { +namespace ppapi { + +class PPB_URLLoader_Impl : public ::ppapi::Resource, + public ::ppapi::thunk::PPB_URLLoader_API, + public WebKit::WebURLLoaderClient { + public: + PPB_URLLoader_Impl(PP_Instance instance, bool main_document_loader); + virtual ~PPB_URLLoader_Impl(); + + // Resource overrides. + virtual ::ppapi::thunk::PPB_URLLoader_API* AsPPB_URLLoader_API() OVERRIDE; + virtual void InstanceWasDeleted() OVERRIDE; + + // PPB_URLLoader_API implementation. + virtual int32_t Open( + PP_Resource request_id, + scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE; + virtual int32_t Open( + const ::ppapi::URLRequestInfoData& data, + int requestor_pid, + scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE; + virtual int32_t FollowRedirect( + scoped_refptr< ::ppapi::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< ::ppapi::TrackedCallback> callback) OVERRIDE; + virtual int32_t FinishStreamingToFile( + scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE; + virtual void Close() OVERRIDE; + virtual void GrantUniversalAccess() OVERRIDE; + virtual void RegisterStatusCallback( + PP_URLLoaderTrusted_StatusCallback cb) OVERRIDE; + virtual bool GetResponseInfoData( + ::ppapi::URLResponseInfoData* data) OVERRIDE; + + // WebKit::WebURLLoaderClient implementation. + virtual void willSendRequest(WebKit::WebURLLoader* loader, + WebKit::WebURLRequest& new_request, + const WebKit::WebURLResponse& redir_response); + virtual void didSendData(WebKit::WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent); + virtual void didReceiveResponse(WebKit::WebURLLoader* loader, + const WebKit::WebURLResponse& response); + virtual void didDownloadData(WebKit::WebURLLoader* loader, + int data_length); + + virtual void didReceiveData(WebKit::WebURLLoader* loader, + const char* data, + int data_length, + int encoded_data_length); + virtual void didFinishLoading(WebKit::WebURLLoader* loader, + double finish_time); + virtual void didFail(WebKit::WebURLLoader* loader, + const WebKit::WebURLError& error); + + // Returns the number of bytes currently available for synchronous reading + // in the loader. + int32_t buffer_size() const { return buffer_.size(); } + + private: + // Check that |callback| is valid (only non-blocking operation is supported) + // and that no callback is already pending. Returns |PP_OK| if okay, else + // |PP_ERROR_...| to be returned to the plugin. + int32_t ValidateCallback(scoped_refptr< ::ppapi::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< ::ppapi::TrackedCallback> callback); + + void RunCallback(int32_t result); + + size_t FillUserBuffer(); + + // Converts a WebURLResponse to a URLResponseInfo and saves it. + void SaveResponse(const WebKit::WebURLResponse& response); + + // Calls the status_callback_ (if any) with the current upload and download + // progress. Call this function if you update any of these values to + // synchronize an out-of-process plugin's state. + void UpdateStatus(); + + // Returns true if the plugin has requested we record download or upload + // progress. When false, we don't need to update the counters. We go out of + // our way not to allow access to this information unless it's requested, + // even when it would be easier just to return it and not check, so that + // plugins don't depend on access without setting the flag. + bool RecordDownloadProgress() const; + bool RecordUploadProgress() const; + + // Calls SetDefersLoading on the current load. This encapsulates the logic + // differences between document loads and regular ones. + void SetDefersLoading(bool defers_loading); + + void FinishLoading(int32_t done_status); + + // If true, then the plugin instance is a full-frame plugin and we're just + // wrapping the main document's loader (i.e. loader_ is null). + bool main_document_loader_; + + // Keep a copy of the request data. We specifically do this instead of + // keeping a reference to the request resource, because the plugin might + // change the request info resource out from under us. + ::ppapi::URLRequestInfoData request_data_; + + // The loader associated with this request. MAY BE NULL. + // + // This will be NULL if the load hasn't been opened yet, or if this is a main + // document loader (when registered as a mime type). Therefore, you should + // always NULL check this value before using it. In the case of a main + // document load, you would call the functions on the document to cancel the + // load, etc. since there is no loader. + scoped_ptr<WebKit::WebURLLoader> loader_; + + scoped_refptr< ::ppapi::TrackedCallback> pending_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_; + + bool has_universal_access_; + + PP_URLLoaderTrusted_StatusCallback status_callback_; + + // When the response info is received, this stores the data. The + // ScopedResource maintains the reference to the file ref (if any) in the + // data object so we don't forget to dereference it. + scoped_ptr< ::ppapi::URLResponseInfoData > response_info_; + ::ppapi::ScopedPPResource response_info_file_ref_; + + DISALLOW_COPY_AND_ASSIGN(PPB_URLLoader_Impl); +}; + +} // namespace ppapi +} // namespace webkit + +#endif // WEBKIT_PLUGINS_PPAPI_PPB_URL_LOADER_IMPL_H_ diff --git a/webkit/plugins/ppapi/resource_creation_impl.cc b/webkit/plugins/ppapi/resource_creation_impl.cc index f84e5fe..dd8188a 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.cc +++ b/webkit/plugins/ppapi/resource_creation_impl.cc @@ -22,6 +22,7 @@ #include "webkit/plugins/ppapi/ppb_scrollbar_impl.h" #include "webkit/plugins/ppapi/ppb_tcp_server_socket_private_impl.h" #include "webkit/plugins/ppapi/ppb_tcp_socket_private_impl.h" +#include "webkit/plugins/ppapi/ppb_url_loader_impl.h" #include "webkit/plugins/ppapi/ppb_video_decoder_impl.h" #include "webkit/plugins/ppapi/ppb_x509_certificate_private_impl.h" #include "webkit/plugins/ppapi/resource_helper.h" @@ -84,13 +85,6 @@ PP_Resource ResourceCreationImpl::CreateFileRef( return res ? res->GetReference() : 0; } -PP_Resource ResourceCreationImpl::CreateFileRef( - const ::ppapi::PPB_FileRef_CreateInfo& serialized) { - // When we're in-process, the host resource in the create info *is* the - // resource, so we don't need to do anything. - return serialized.resource.host_resource(); -} - PP_Resource ResourceCreationImpl::CreateFlashDRM(PP_Instance instance) { return 0; // Not supported in-process. } @@ -275,6 +269,10 @@ PP_Resource ResourceCreationImpl::CreateUDPSocketPrivate(PP_Instance instance) { return 0; // Not supported in-process. } +PP_Resource ResourceCreationImpl::CreateURLLoader(PP_Instance instance) { + return (new PPB_URLLoader_Impl(instance, false))->GetReference(); +} + PP_Resource ResourceCreationImpl::CreateVideoCapture(PP_Instance instance) { return 0; // VideoCapture is not supported in process now. } diff --git a/webkit/plugins/ppapi/resource_creation_impl.h b/webkit/plugins/ppapi/resource_creation_impl.h index d3018fc..ef71d28 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.h +++ b/webkit/plugins/ppapi/resource_creation_impl.h @@ -41,8 +41,6 @@ class WEBKIT_PLUGINS_EXPORT ResourceCreationImpl virtual PP_Resource CreateFileRef(PP_Instance instance, PP_Resource file_system, const char* path) OVERRIDE; - virtual PP_Resource CreateFileRef( - const ::ppapi::PPB_FileRef_CreateInfo& serialized) OVERRIDE; virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateFlashFontFile( PP_Instance instance, @@ -124,6 +122,7 @@ class WEBKIT_PLUGINS_EXPORT ResourceCreationImpl virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoDecoder( PP_Instance instance, diff --git a/webkit/plugins/ppapi/url_response_info_util.h b/webkit/plugins/ppapi/url_response_info_util.h index 346ede6..ff805db 100644 --- a/webkit/plugins/ppapi/url_response_info_util.h +++ b/webkit/plugins/ppapi/url_response_info_util.h @@ -7,7 +7,6 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/shared_impl/url_response_info_data.h" -#include "webkit/plugins/webkit_plugins_export.h" namespace WebKit { class WebURLResponse; @@ -19,7 +18,7 @@ namespace ppapi { // The returned object will have one plugin reference to the "body_as_file_ref" // if it's non-null. It's expected that the result of this function will be // passed to the plugin. -WEBKIT_PLUGINS_EXPORT ::ppapi::URLResponseInfoData DataFromWebURLResponse( +::ppapi::URLResponseInfoData DataFromWebURLResponse( PP_Instance pp_instance, const WebKit::WebURLResponse& response); diff --git a/webkit/plugins/webkit_plugins.gypi b/webkit/plugins/webkit_plugins.gypi index f1a217c..6229552 100644 --- a/webkit/plugins/webkit_plugins.gypi +++ b/webkit/plugins/webkit_plugins.gypi @@ -143,6 +143,8 @@ '../plugins/ppapi/ppb_tcp_socket_private_impl.h', '../plugins/ppapi/ppb_uma_private_impl.cc', '../plugins/ppapi/ppb_uma_private_impl.h', + '../plugins/ppapi/ppb_url_loader_impl.cc', + '../plugins/ppapi/ppb_url_loader_impl.h', '../plugins/ppapi/ppb_var_deprecated_impl.cc', '../plugins/ppapi/ppb_var_deprecated_impl.h', '../plugins/ppapi/ppb_video_decoder_impl.cc', |