diff options
Diffstat (limited to 'content/renderer')
11 files changed, 618 insertions, 2 deletions
diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc index 715725b..79b7c4f 100644 --- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc +++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc @@ -12,6 +12,7 @@ #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" @@ -74,6 +75,9 @@ 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 68aa8c8..8c61ccd 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/content/renderer/pepper/mock_renderer_ppapi_host.cc @@ -53,6 +53,11 @@ MockRendererPpapiHost::GetPlatformGraphics2D(PP_Resource resource) { 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 47f5861..4476760 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.h +++ b/content/renderer/pepper/mock_renderer_ppapi_host.h @@ -47,6 +47,7 @@ class MockRendererPpapiHost : public RendererPpapiHost { PP_Instance instance) const OVERRIDE; virtual webkit::ppapi::PluginDelegate::PlatformGraphics2D* GetPlatformGraphics2D(PP_Resource resource) 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 d695697..0738056 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.cc +++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc @@ -22,6 +22,7 @@ #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" @@ -114,6 +115,13 @@ 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( diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h index 847320b..8903afd 100644 --- a/content/renderer/pepper/pepper_in_process_resource_creation.h +++ b/content/renderer/pepper/pepper_in_process_resource_creation.h @@ -61,6 +61,8 @@ 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( diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index 110e1bc..a3625b8 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -46,12 +46,14 @@ #include "content/renderer/pepper/pepper_file_system_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" @@ -67,11 +69,16 @@ #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/thunk/enter.h" #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" @@ -91,6 +98,7 @@ #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; @@ -1335,6 +1343,64 @@ 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 2f178ef..c694d54 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h @@ -321,6 +321,9 @@ 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 new file mode 100644 index 0000000..b88ccdf --- /dev/null +++ b/content/renderer/pepper/pepper_url_loader_host.cc @@ -0,0 +1,380 @@ +// 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/Source/Platform/chromium/public/WebURLError.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebURLLoader.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebURLResponse.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/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 new file mode 100644 index 0000000..111194a --- /dev/null +++ b/content/renderer/pepper/pepper_url_loader_host.h @@ -0,0 +1,138 @@ +// 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/Source/Platform/chromium/public/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 32ce540..641d68e 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc @@ -201,6 +201,12 @@ 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 4d3d0b4..d1256ac 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. + // RendererPpapiHost implementation. virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE; virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE; virtual webkit::ppapi::PluginInstance* GetPluginInstance( @@ -93,6 +93,7 @@ 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( @@ -121,7 +122,9 @@ class RendererPpapiHostImpl webkit::ppapi::PluginModule* module_; // Non-owning pointer. - ppapi::proxy::HostDispatcher* dispatcher_; // 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_; scoped_ptr<ppapi::host::PpapiHost> ppapi_host_; |