summaryrefslogtreecommitdiffstats
path: root/content/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'content/renderer')
-rw-r--r--content/renderer/pepper/content_renderer_pepper_host_factory.cc4
-rw-r--r--content/renderer/pepper/mock_renderer_ppapi_host.cc5
-rw-r--r--content/renderer/pepper/mock_renderer_ppapi_host.h1
-rw-r--r--content/renderer/pepper/pepper_in_process_resource_creation.cc8
-rw-r--r--content/renderer/pepper/pepper_in_process_resource_creation.h2
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.cc66
-rw-r--r--content/renderer/pepper/pepper_plugin_delegate_impl.h3
-rw-r--r--content/renderer/pepper/pepper_url_loader_host.cc380
-rw-r--r--content/renderer/pepper/pepper_url_loader_host.h138
-rw-r--r--content/renderer/pepper/renderer_ppapi_host_impl.cc6
-rw-r--r--content/renderer/pepper/renderer_ppapi_host_impl.h7
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_;