diff options
-rw-r--r-- | chrome/test/ui/ppapi_uitest.cc | 3 | ||||
-rw-r--r-- | ppapi/tests/test_url_loader.cc | 32 | ||||
-rw-r--r-- | ppapi/tests/test_url_loader.h | 1 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_loader.cc | 66 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_loader.h | 12 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_request_info.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_request_info.h | 3 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_response_info.cc | 24 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_url_response_info.h | 4 |
9 files changed, 132 insertions, 17 deletions
diff --git a/chrome/test/ui/ppapi_uitest.cc b/chrome/test/ui/ppapi_uitest.cc index 9de0e3b..a145c8e 100644 --- a/chrome/test/ui/ppapi_uitest.cc +++ b/chrome/test/ui/ppapi_uitest.cc @@ -109,8 +109,7 @@ TEST_F(PPAPITest, Buffer) { RunTest("Buffer"); } -// http://bugs.chromium.org/51345 -TEST_F(PPAPITest, DISABLED_URLLoader) { +TEST_F(PPAPITest, URLLoader) { RunTestViaHTTP("URLLoader"); } diff --git a/ppapi/tests/test_url_loader.cc b/ppapi/tests/test_url_loader.cc index b1cdd6f..3203f39 100644 --- a/ppapi/tests/test_url_loader.cc +++ b/ppapi/tests/test_url_loader.cc @@ -38,6 +38,7 @@ void TestURLLoader::RunTest() { RUN_TEST(IgnoresBogusContentLength); RUN_TEST(SameOriginRestriction); RUN_TEST(StreamToFile); + RUN_TEST(AuditURLRedirect); } std::string TestURLLoader::ReadEntireFile(pp::FileIO_Dev* file_io, @@ -255,4 +256,35 @@ std::string TestURLLoader::TestSameOriginRestriction() { return ""; } +// This test should cause a redirect and ensure that the loader runs +// the callback, rather than following the redirect. +std::string TestURLLoader::TestAuditURLRedirect() { + pp::URLRequestInfo_Dev request; + // This path will cause the server to return a 301 redirect. + request.SetURL("/server-redirect?www.google.com"); + request.SetFollowRedirects(false); + + TestCompletionCallback callback; + + pp::URLLoader_Dev loader(*instance_); + int32_t rv = loader.Open(request, callback); + if (rv == PP_ERROR_WOULDBLOCK) + rv = callback.WaitForResult(); + if (rv != PP_OK) + return ReportError("URLLoader::Open", rv); + + // Checks that the response indicates a redirect, and that the URL + // is correct. + pp::URLResponseInfo_Dev response_info(loader.GetResponseInfo()); + if (response_info.is_null()) + return "URLLoader::GetResponseInfo returned null"; + int32_t status_code = response_info.GetStatusCode(); + if (status_code != 301) + return "Response status should be 301"; + if (response_info.GetRedirectURL().AsString() != "www.google.com") + return "Redirect URL should be www.google.com"; + + return ""; +} + // TODO(darin): Add a test for GrantUniversalAccess. diff --git a/ppapi/tests/test_url_loader.h b/ppapi/tests/test_url_loader.h index 9664508..681016d 100644 --- a/ppapi/tests/test_url_loader.h +++ b/ppapi/tests/test_url_loader.h @@ -39,6 +39,7 @@ class TestURLLoader : public TestCase { std::string TestIgnoresBogusContentLength(); std::string TestStreamToFile(); std::string TestSameOriginRestriction(); + std::string TestAuditURLRedirect(); }; #endif // PAPPI_TESTS_TEST_URL_LOADER_H_ diff --git a/webkit/glue/plugins/pepper_url_loader.cc b/webkit/glue/plugins/pepper_url_loader.cc index 9c3b03a..cb7cb5f 100644 --- a/webkit/glue/plugins/pepper_url_loader.cc +++ b/webkit/glue/plugins/pepper_url_loader.cc @@ -16,6 +16,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h" #include "webkit/appcache/web_application_cache_host_impl.h" @@ -175,6 +176,10 @@ const PPB_URLLoaderTrusted_Dev ppb_urlloadertrusted = { &SetStatusCallback }; +WebKit::WebFrame* GetFrame(PluginInstance* instance) { + return instance->container()->element().document().frame(); +} + } // namespace URLLoader::URLLoader(PluginInstance* instance, bool main_document_loader) @@ -217,15 +222,14 @@ int32_t URLLoader::Open(URLRequestInfo* request, if (!callback.func) return PP_ERROR_BADARGUMENT; - WebFrame* frame = instance_->container()->element().document().frame(); + WebFrame* frame = GetFrame(instance_); if (!frame) return PP_ERROR_FAILED; WebURLRequest web_request(request->ToWebURLRequest(frame)); - // Check if we are allowed to access this URL. - if (!has_universal_access_ && - !frame->securityOrigin().canRequest(web_request.url())) - return PP_ERROR_NOACCESS; + int32_t rv = CanRequest(frame, web_request.url()); + if (rv != PP_OK) + return rv; frame->dispatchWillSendRequest(web_request); @@ -238,8 +242,10 @@ int32_t URLLoader::Open(URLRequestInfo* request, loader_.reset(WebKit::webKitClient()->createURLLoader()); if (!loader_.get()) return PP_ERROR_FAILED; + loader_->loadAsynchronously(web_request, this); + request_info_ = scoped_refptr<URLRequestInfo>(request); pending_callback_ = callback; record_download_progress_ = request->record_download_progress(); record_upload_progress_ = request->record_upload_progress(); @@ -249,8 +255,22 @@ int32_t URLLoader::Open(URLRequestInfo* request, } int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) { - NOTIMPLEMENTED(); // TODO(darin): Implement me. - return PP_ERROR_FAILED; + if (pending_callback_.func) + return PP_ERROR_INPROGRESS; + + // We only support non-blocking calls. + if (!callback.func) + return PP_ERROR_BADARGUMENT; + + WebURL redirect_url = GURL(response_info_->redirect_url()); + + int32_t rv = CanRequest(GetFrame(instance_), redirect_url); + if (rv != PP_OK) + return rv; + + pending_callback_ = callback; + loader_->setDefersLoading(false); // Allow the redirect to continue. + return PP_ERROR_WOULDBLOCK; } bool URLLoader::GetUploadProgress(int64_t* bytes_sent, @@ -342,7 +362,17 @@ void URLLoader::SetStatusCallback(PP_URLLoaderTrusted_StatusCallback cb) { void URLLoader::willSendRequest(WebURLLoader* loader, WebURLRequest& new_request, const WebURLResponse& redirect_response) { - NOTIMPLEMENTED(); // TODO(darin): Allow the plugin to inspect redirects. + if (!request_info_->follow_redirects()) { + SaveResponse(redirect_response); + loader_->setDefersLoading(true); + RunCallback(PP_OK); + } else { + int32_t rv = CanRequest(GetFrame(instance_), new_request.url()); + if (rv != PP_OK) { + loader_->setDefersLoading(true); + RunCallback(rv); + } + } } void URLLoader::didSendData(WebURLLoader* loader, @@ -356,9 +386,7 @@ void URLLoader::didSendData(WebURLLoader* loader, void URLLoader::didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response) { - scoped_refptr<URLResponseInfo> response_info(new URLResponseInfo(module())); - if (response_info->Initialize(response)) - response_info_ = response_info; + SaveResponse(response); // Sets -1 if the content length is unknown. total_bytes_to_be_received_ = response.expectedContentLength(); @@ -420,6 +448,22 @@ size_t URLLoader::FillUserBuffer() { return bytes_to_copy; } +void URLLoader::SaveResponse(const WebKit::WebURLResponse& response) { + scoped_refptr<URLResponseInfo> response_info(new URLResponseInfo(module())); + if (response_info->Initialize(response)) + response_info_ = response_info; +} + +// Checks that the client can request the URL. Returns a PPAPI error code. +int32_t URLLoader::CanRequest(const WebKit::WebFrame* frame, + const WebKit::WebURL& url) { + if (!has_universal_access_ && + !frame->securityOrigin().canRequest(url)) + return PP_ERROR_NOACCESS; + + return PP_OK; +} + void URLLoader::UpdateStatus() { if (status_callback_ && (record_download_progress_ || record_upload_progress_)) { diff --git a/webkit/glue/plugins/pepper_url_loader.h b/webkit/glue/plugins/pepper_url_loader.h index e018555..fbeb163 100644 --- a/webkit/glue/plugins/pepper_url_loader.h +++ b/webkit/glue/plugins/pepper_url_loader.h @@ -10,13 +10,17 @@ #include "base/scoped_ptr.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/dev/ppb_url_loader_trusted_dev.h" -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h" #include "webkit/glue/plugins/pepper_resource.h" struct PPB_URLLoader_Dev; struct PPB_URLLoaderTrusted_Dev; +namespace WebKit { +class WebFrame; +class WebURL; +} + namespace pepper { class PluginInstance; @@ -80,6 +84,11 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { void RunCallback(int32_t result); size_t FillUserBuffer(); + // Converts a WebURLResponse to a URLResponseInfo and saves it. + void SaveResponse(const WebKit::WebURLResponse& response); + + int32_t CanRequest(const WebKit::WebFrame* frame, const WebKit::WebURL& url); + // 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. @@ -90,6 +99,7 @@ class URLLoader : public Resource, public WebKit::WebURLLoaderClient { // wrapping the main document's loader (i.e. loader_ is null). bool main_document_loader_; scoped_ptr<WebKit::WebURLLoader> loader_; + scoped_refptr<URLRequestInfo> request_info_; scoped_refptr<URLResponseInfo> response_info_; PP_CompletionCallback pending_callback_; std::deque<char> buffer_; diff --git a/webkit/glue/plugins/pepper_url_request_info.cc b/webkit/glue/plugins/pepper_url_request_info.cc index a7a6589..ae0c280 100644 --- a/webkit/glue/plugins/pepper_url_request_info.cc +++ b/webkit/glue/plugins/pepper_url_request_info.cc @@ -155,6 +155,7 @@ struct URLRequestInfo::BodyItem { URLRequestInfo::URLRequestInfo(PluginModule* module) : Resource(module), stream_to_file_(false), + follow_redirects_(true), record_download_progress_(false), record_upload_progress_(false) { } @@ -173,6 +174,9 @@ bool URLRequestInfo::SetBooleanProperty(PP_URLRequestProperty_Dev property, case PP_URLREQUESTPROPERTY_STREAMTOFILE: stream_to_file_ = value; return true; + case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS: + follow_redirects_ = value; + return true; case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS: record_download_progress_ = value; return true; diff --git a/webkit/glue/plugins/pepper_url_request_info.h b/webkit/glue/plugins/pepper_url_request_info.h index 067756f..4fd4e26 100644 --- a/webkit/glue/plugins/pepper_url_request_info.h +++ b/webkit/glue/plugins/pepper_url_request_info.h @@ -44,6 +44,8 @@ class URLRequestInfo : public Resource { WebKit::WebURLRequest ToWebURLRequest(WebKit::WebFrame* frame) const; + bool follow_redirects() { return follow_redirects_; } + bool record_download_progress() const { return record_download_progress_; } bool record_upload_progress() const { return record_upload_progress_; } @@ -57,6 +59,7 @@ class URLRequestInfo : public Resource { Body body_; bool stream_to_file_; + bool follow_redirects_; bool record_download_progress_; bool record_upload_progress_; }; diff --git a/webkit/glue/plugins/pepper_url_response_info.cc b/webkit/glue/plugins/pepper_url_response_info.cc index ee27003..2e7202f 100644 --- a/webkit/glue/plugins/pepper_url_response_info.cc +++ b/webkit/glue/plugins/pepper_url_response_info.cc @@ -73,6 +73,10 @@ const PPB_URLResponseInfo_Dev ppb_urlresponseinfo = { &GetBody }; +bool IsRedirect(int32_t status) { + return status >= 300 && status <= 399; +} + } // namespace URLResponseInfo::URLResponseInfo(PluginModule* module) @@ -92,19 +96,33 @@ PP_Var URLResponseInfo::GetProperty(PP_URLResponseProperty_Dev property) { switch (property) { case PP_URLRESPONSEPROPERTY_URL: return StringVar::StringToPPVar(module(), url_); + case PP_URLRESPONSEPROPERTY_REDIRECTURL: + if (IsRedirect(status_code_)) + return StringVar::StringToPPVar(module(), redirect_url_); + break; + case PP_URLRESPONSEPROPERTY_REDIRECTMETHOD: + if (IsRedirect(status_code_)) + return StringVar::StringToPPVar(module(), status_text_); + break; case PP_URLRESPONSEPROPERTY_STATUSCODE: return PP_MakeInt32(status_code_); + case PP_URLRESPONSEPROPERTY_STATUSLINE: + return StringVar::StringToPPVar(module(), status_text_); case PP_URLRESPONSEPROPERTY_HEADERS: return StringVar::StringToPPVar(module(), headers_); - default: - NOTIMPLEMENTED(); // TODO(darin): Implement me! - return PP_MakeUndefined(); } + // The default is to return an undefined PP_Var. + return PP_MakeUndefined(); } bool URLResponseInfo::Initialize(const WebURLResponse& response) { url_ = response.url().spec(); status_code_ = response.httpStatusCode(); + status_text_ = response.httpStatusText().utf8(); + if (IsRedirect(status_code_)) { + redirect_url_ = response.httpHeaderField( + WebString::fromUTF8("Location")).utf8(); + } HeaderFlattener flattener; response.visitHTTPHeaderFields(&flattener); diff --git a/webkit/glue/plugins/pepper_url_response_info.h b/webkit/glue/plugins/pepper_url_response_info.h index b73ec67..ff3a832 100644 --- a/webkit/glue/plugins/pepper_url_response_info.h +++ b/webkit/glue/plugins/pepper_url_response_info.h @@ -35,10 +35,14 @@ class URLResponseInfo : public Resource { FileRef* body() { return body_; } + std::string redirect_url() { return redirect_url_; } + private: std::string url_; std::string headers_; int32_t status_code_; + std::string status_text_; + std::string redirect_url_; scoped_refptr<FileRef> body_; }; |