Index: webkit/plugins/ppapi/ppb_url_request_info_impl.cc |
diff --git a/webkit/plugins/ppapi/ppb_url_request_info_impl.cc b/webkit/plugins/ppapi/ppb_url_request_info_impl.cc |
index 985a795514315ad103230d8ce556f7cfa5b9db20..6f937ebdfde0db99af02498e1d769e9e55f51b1f 100644 |
--- a/webkit/plugins/ppapi/ppb_url_request_info_impl.cc |
+++ b/webkit/plugins/ppapi/ppb_url_request_info_impl.cc |
@@ -9,10 +9,8 @@ |
#include "googleurl/src/gurl.h" |
#include "googleurl/src/url_util.h" |
#include "net/http/http_util.h" |
-#include "ppapi/c/pp_var.h" |
#include "ppapi/shared_impl/var.h" |
#include "ppapi/thunk/enter.h" |
-#include "ppapi/thunk/ppb_file_ref_api.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
@@ -22,16 +20,14 @@ |
#include "webkit/glue/webkit_glue.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/ppb_file_ref_impl.h" |
#include "webkit/plugins/ppapi/ppb_file_system_impl.h" |
#include "webkit/plugins/ppapi/resource_helper.h" |
-#include "webkit/plugins/ppapi/string.h" |
-using ppapi::StringVar; |
+using ppapi::PPB_URLRequestInfo_Data; |
+using ppapi::Resource; |
using ppapi::thunk::EnterResourceNoLock; |
using ppapi::thunk::PPB_FileRef_API; |
-using ppapi::thunk::PPB_URLRequestInfo_API; |
using WebKit::WebData; |
using WebKit::WebHTTPBody; |
using WebKit::WebString; |
@@ -65,51 +61,6 @@ bool IsValidToken(const std::string& token) { |
return true; |
} |
-// These methods are not allowed by the XMLHttpRequest standard. |
-// http://www.w3.org/TR/XMLHttpRequest/#the-open-method |
-const char* const kForbiddenHttpMethods[] = { |
- "connect", |
- "trace", |
- "track", |
-}; |
- |
-// These are the "known" methods in the Webkit XHR implementation. Also see |
-// the XMLHttpRequest standard. |
-// http://www.w3.org/TR/XMLHttpRequest/#the-open-method |
-const char* const kKnownHttpMethods[] = { |
- "get", |
- "post", |
- "put", |
- "head", |
- "copy", |
- "delete", |
- "index", |
- "lock", |
- "m-post", |
- "mkcol", |
- "move", |
- "options", |
- "propfind", |
- "proppatch", |
- "unlock", |
-}; |
- |
-std::string ValidateMethod(const std::string& method) { |
- for (size_t i = 0; i < arraysize(kForbiddenHttpMethods); ++i) { |
- if (LowerCaseEqualsASCII(method, kForbiddenHttpMethods[i])) |
- return std::string(); |
- } |
- for (size_t i = 0; i < arraysize(kKnownHttpMethods); ++i) { |
- if (LowerCaseEqualsASCII(method, kKnownHttpMethods[i])) { |
- // Convert the method name to upper case to match Webkit and Firefox's |
- // XHR implementation. |
- return StringToUpperASCII(std::string(kKnownHttpMethods[i])); |
- } |
- } |
- // Pass through unknown methods that are not forbidden. |
- return method; |
-} |
- |
// A header string containing any of the following fields will cause |
// an error. The list comes from the XMLHttpRequest standard. |
// http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method |
@@ -159,282 +110,163 @@ bool AreValidHeaders(const std::string& headers) { |
} // namespace |
-struct PPB_URLRequestInfo_Impl::BodyItem { |
- explicit BodyItem(const std::string& data) |
- : data(data), |
- start_offset(0), |
- number_of_bytes(-1), |
- expected_last_modified_time(0.0) { |
- } |
- |
- BodyItem(PPB_FileRef_Impl* file_ref, |
- int64_t start_offset, |
- int64_t number_of_bytes, |
- PP_Time expected_last_modified_time) |
- : file_ref(file_ref), |
- start_offset(start_offset), |
- number_of_bytes(number_of_bytes), |
- expected_last_modified_time(expected_last_modified_time) { |
- } |
- std::string data; |
- scoped_refptr<PPB_FileRef_Impl> file_ref; |
- int64_t start_offset; |
- int64_t number_of_bytes; |
- PP_Time expected_last_modified_time; |
-}; |
- |
-PPB_URLRequestInfo_Impl::PPB_URLRequestInfo_Impl(PP_Instance instance) |
- : Resource(instance), |
- stream_to_file_(false), |
- follow_redirects_(true), |
- record_download_progress_(false), |
- record_upload_progress_(false), |
- has_custom_referrer_url_(false), |
- allow_cross_origin_requests_(false), |
- allow_credentials_(false), |
- has_custom_content_transfer_encoding_(false), |
- prefetch_buffer_upper_threshold_(kDefaultPrefetchBufferUpperThreshold), |
- prefetch_buffer_lower_threshold_(kDefaultPrefetchBufferLowerThreshold) { |
+PPB_URLRequestInfo_Impl::PPB_URLRequestInfo_Impl( |
+ PP_Instance instance, |
+ const PPB_URLRequestInfo_Data& data) |
+ : URLRequestInfoImpl(instance, data) { |
} |
PPB_URLRequestInfo_Impl::~PPB_URLRequestInfo_Impl() { |
} |
-PPB_URLRequestInfo_API* PPB_URLRequestInfo_Impl::AsPPB_URLRequestInfo_API() { |
- return this; |
-} |
- |
-PP_Bool PPB_URLRequestInfo_Impl::SetProperty(PP_URLRequestProperty property, |
- PP_Var var) { |
- PP_Bool result = PP_FALSE; |
- switch (var.type) { |
- case PP_VARTYPE_UNDEFINED: |
- result = PP_FromBool(SetUndefinedProperty(property)); |
- break; |
- case PP_VARTYPE_BOOL: |
- result = PP_FromBool( |
- SetBooleanProperty(property, PP_ToBool(var.value.as_bool))); |
- break; |
- case PP_VARTYPE_INT32: |
- result = PP_FromBool( |
- SetIntegerProperty(property, var.value.as_int)); |
- break; |
- case PP_VARTYPE_STRING: { |
- StringVar* string = StringVar::FromPPVar(var); |
- if (string) |
- result = PP_FromBool(SetStringProperty(property, string->value())); |
- break; |
- } |
- default: |
- break; |
- } |
- return result; |
-} |
- |
-PP_Bool PPB_URLRequestInfo_Impl::AppendDataToBody(const void* data, |
- uint32_t len) { |
- if (len > 0) |
- body_.push_back(BodyItem(std::string(static_cast<const char*>(data), len))); |
- return PP_TRUE; |
-} |
- |
-PP_Bool PPB_URLRequestInfo_Impl::AppendFileToBody( |
- PP_Resource file_ref, |
- int64_t start_offset, |
- int64_t number_of_bytes, |
- PP_Time expected_last_modified_time) { |
- // Ignore a call to append nothing. |
- if (number_of_bytes == 0) |
- return PP_TRUE; |
- |
- // Check for bad values. (-1 means read until end of file.) |
- if (start_offset < 0 || number_of_bytes < -1) |
- return PP_FALSE; |
- |
- EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true); |
- if (enter.failed()) |
- return PP_FALSE; |
- |
- body_.push_back(BodyItem(static_cast<PPB_FileRef_Impl*>(enter.object()), |
- start_offset, |
- number_of_bytes, |
- expected_last_modified_time)); |
- return PP_TRUE; |
-} |
+bool PPB_URLRequestInfo_Impl::ToWebURLRequest(WebFrame* frame, |
+ WebURLRequest* dest) { |
+ // In the out-of-process case, we've received the PPB_URLRequestInfo_Data |
+ // from the untrusted plugin and done no validation on it. We need to be |
+ // sure it's not being malicious by checking everything for consistency. |
+ if (!ValidateData()) |
+ return false; |
-WebURLRequest PPB_URLRequestInfo_Impl::ToWebURLRequest(WebFrame* frame) const { |
- WebURLRequest web_request; |
- web_request.initialize(); |
- web_request.setURL(frame->document().completeURL(WebString::fromUTF8(url_))); |
- web_request.setDownloadToFile(stream_to_file_); |
- web_request.setReportUploadProgress(record_upload_progress()); |
+ dest->initialize(); |
+ dest->setURL(frame->document().completeURL(WebString::fromUTF8( |
+ data().url))); |
bbudge
2011/08/25 19:50:37
Single line?
|
+ dest->setDownloadToFile(data().stream_to_file); |
+ dest->setReportUploadProgress(data().record_upload_progress); |
- if (!method_.empty()) |
- web_request.setHTTPMethod(WebString::fromUTF8(method_)); |
+ if (!data().method.empty()) |
+ dest->setHTTPMethod(WebString::fromUTF8(data().method)); |
- web_request.setFirstPartyForCookies( |
+ dest->setFirstPartyForCookies( |
frame->document().firstPartyForCookies()); |
bbudge
2011/08/25 19:50:37
Single line?
|
- if (!headers_.empty()) { |
- net::HttpUtil::HeadersIterator it(headers_.begin(), headers_.end(), "\n"); |
+ const std::string& headers = data().headers; |
+ if (!headers.empty()) { |
+ net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n"); |
while (it.GetNext()) { |
- web_request.addHTTPHeaderField( |
+ dest->addHTTPHeaderField( |
WebString::fromUTF8(it.name()), |
WebString::fromUTF8(it.values())); |
} |
} |
- if (!body_.empty()) { |
+ // Append the upload data. |
+ if (!data().body.empty()) { |
WebHTTPBody http_body; |
http_body.initialize(); |
- for (size_t i = 0; i < body_.size(); ++i) { |
- if (body_[i].file_ref) { |
- FilePath platform_path; |
- switch (body_[i].file_ref->file_system()->type()) { |
- case PP_FILESYSTEMTYPE_LOCALTEMPORARY: |
- case PP_FILESYSTEMTYPE_LOCALPERSISTENT: { |
- // TODO(kinuko): remove this sync IPC when we add more generic |
- // AppendURLRange solution that works for both Blob/FileSystem URL. |
- PluginDelegate* plugin_delegate = |
- ResourceHelper::GetPluginDelegate(this); |
- if (plugin_delegate) { |
- plugin_delegate->SyncGetFileSystemPlatformPath( |
- body_[i].file_ref->GetFileSystemURL(), &platform_path); |
- } |
- break; |
- } |
- case PP_FILESYSTEMTYPE_EXTERNAL: |
- platform_path = body_[i].file_ref->GetSystemPath(); |
- break; |
- default: |
- NOTREACHED(); |
- } |
- http_body.appendFileRange( |
- webkit_glue::FilePathToWebString(platform_path), |
- body_[i].start_offset, |
- body_[i].number_of_bytes, |
- body_[i].expected_last_modified_time); |
+ for (size_t i = 0; i < data().body.size(); ++i) { |
+ const PPB_URLRequestInfo_Data::BodyItem& item = data().body[i]; |
+ if (item.is_file) { |
+ if (!AppendFileRefToBody(item.file_ref, |
+ item.start_offset, |
+ item.number_of_bytes, |
+ item.expected_last_modified_time, |
+ &http_body)) |
+ return false; |
} else { |
- DCHECK(!body_[i].data.empty()); |
- http_body.appendData(WebData(body_[i].data)); |
+ DCHECK(!item.data.empty()); |
+ http_body.appendData(WebData(item.data)); |
} |
} |
- web_request.setHTTPBody(http_body); |
+ dest->setHTTPBody(http_body); |
} |
- if (has_custom_referrer_url_) { |
- if (!custom_referrer_url_.empty()) |
- frame->setReferrerForRequest(web_request, GURL(custom_referrer_url_)); |
- } else if (!allow_cross_origin_requests_) { |
+ if (data().has_custom_referrer_url) { |
+ if (!data().custom_referrer_url.empty()) |
+ frame->setReferrerForRequest(*dest, GURL(data().custom_referrer_url)); |
+ } else if (!data().allow_cross_origin_requests) { |
// Use default, except for cross-origin requests, since 'referer' is not |
// whitelisted and will cause the request to fail. |
- frame->setReferrerForRequest(web_request, WebURL()); |
+ frame->setReferrerForRequest(*dest, WebURL()); |
} |
- if (has_custom_content_transfer_encoding_) { |
- if (!custom_content_transfer_encoding_.empty()) { |
- web_request.addHTTPHeaderField( |
+ if (data().has_custom_content_transfer_encoding) { |
+ if (!data().custom_content_transfer_encoding.empty()) { |
+ dest->addHTTPHeaderField( |
WebString::fromUTF8("Content-Transfer-Encoding"), |
- WebString::fromUTF8(custom_content_transfer_encoding_)); |
+ WebString::fromUTF8(data().custom_content_transfer_encoding)); |
} |
} |
- return web_request; |
+ return true; |
} |
bool PPB_URLRequestInfo_Impl::RequiresUniversalAccess() const { |
return |
- has_custom_referrer_url_ || |
- has_custom_content_transfer_encoding_ || |
- url_util::FindAndCompareScheme(url_, "javascript", NULL); |
+ data().has_custom_referrer_url || |
+ data().has_custom_content_transfer_encoding || |
+ url_util::FindAndCompareScheme(data().url, "javascript", NULL); |
} |
-bool PPB_URLRequestInfo_Impl::SetUndefinedProperty( |
- PP_URLRequestProperty property) { |
- switch (property) { |
- case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL: |
- has_custom_referrer_url_ = false; |
- custom_referrer_url_ = std::string(); |
- return true; |
- case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING: |
- has_custom_content_transfer_encoding_ = false; |
- custom_content_transfer_encoding_ = std::string(); |
- return true; |
- default: |
+bool PPB_URLRequestInfo_Impl::ValidateData() { |
+ // Method should either be empty or a valid one. |
+ if (!data().method.empty()) { |
+ std::string canonicalized = ValidateMethod(data().method); |
+ if (canonicalized.empty()) |
return false; |
+ data().method = canonicalized; |
} |
-} |
-bool PPB_URLRequestInfo_Impl::SetBooleanProperty(PP_URLRequestProperty property, |
- bool value) { |
- switch (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; |
- case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS: |
- record_upload_progress_ = value; |
- return true; |
- case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS: |
- allow_cross_origin_requests_ = value; |
- return true; |
- case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS: |
- allow_credentials_ = value; |
- return true; |
- default: |
- return false; |
- } |
-} |
+ if (!AreValidHeaders(data().headers)) |
+ return false; |
-bool PPB_URLRequestInfo_Impl::SetIntegerProperty(PP_URLRequestProperty property, |
- int32_t value) { |
- switch (property) { |
- case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD: |
- prefetch_buffer_upper_threshold_ = value; |
- return true; |
- case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD: |
- prefetch_buffer_lower_threshold_ = value; |
- return true; |
- default: |
- return false; |
+ // Get the Resource objects for any file refs with only host resource (this |
+ // is the state of the request as it comes off IPC). |
+ for (size_t i = 0; i < data().body.size(); ++i) { |
+ PPB_URLRequestInfo_Data::BodyItem& item = data().body[i]; |
+ if (item.is_file && !item.file_ref) { |
+ EnterResourceNoLock<PPB_FileRef_API> enter( |
+ item.file_ref_host_resource.host_resource(), false); |
+ if (!enter.succeeded()) |
+ return false; |
+ item.file_ref = enter.resource(); |
+ } |
} |
+ return true; |
} |
-bool PPB_URLRequestInfo_Impl::SetStringProperty(PP_URLRequestProperty property, |
- const std::string& value) { |
- // TODO(darin): Validate input. Perhaps at a different layer? |
- switch (property) { |
- case PP_URLREQUESTPROPERTY_URL: |
- url_ = value; // NOTE: This may be a relative URL. |
- return true; |
- case PP_URLREQUESTPROPERTY_METHOD: |
- if (!IsValidToken(value)) |
- return false; |
- method_ = ValidateMethod(value); |
- return !method_.empty(); |
- case PP_URLREQUESTPROPERTY_HEADERS: |
- if (!AreValidHeaders(value)) |
- return false; |
- headers_ = value; |
- return true; |
- case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL: |
- has_custom_referrer_url_ = true; |
- custom_referrer_url_ = value; |
- return true; |
- case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING: |
- has_custom_content_transfer_encoding_ = true; |
- custom_content_transfer_encoding_ = value; |
- return true; |
+bool PPB_URLRequestInfo_Impl::AppendFileRefToBody( |
+ Resource* file_ref_resource, |
+ int64_t start_offset, |
+ int64_t number_of_bytes, |
+ PP_Time expected_last_modified_time, |
+ WebHTTPBody *http_body) { |
+ // Get the underlying file ref impl. |
+ if (!file_ref_resource) |
+ return false; |
+ PPB_FileRef_API* file_ref_api = file_ref_resource->AsPPB_FileRef_API(); |
+ if (!file_ref_api) |
+ return false; |
+ const PPB_FileRef_Impl* file_ref = |
+ static_cast<PPB_FileRef_Impl*>(file_ref_api); |
+ |
+ PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this); |
+ if (!plugin_delegate) |
+ return false; |
+ |
+ FilePath platform_path; |
+ switch (file_ref->file_system()->type()) { |
+ case PP_FILESYSTEMTYPE_LOCALTEMPORARY: |
+ case PP_FILESYSTEMTYPE_LOCALPERSISTENT: |
+ // TODO(kinuko): remove this sync IPC when we add more generic |
+ // AppendURLRange solution that works for both Blob/FileSystem URL. |
+ plugin_delegate->SyncGetFileSystemPlatformPath( |
+ file_ref->GetFileSystemURL(), &platform_path); |
+ break; |
+ case PP_FILESYSTEMTYPE_EXTERNAL: |
+ platform_path = file_ref->GetSystemPath(); |
+ break; |
default: |
- return false; |
+ NOTREACHED(); |
} |
+ http_body->appendFileRange( |
+ webkit_glue::FilePathToWebString(platform_path), |
+ start_offset, |
+ number_of_bytes, |
+ expected_last_modified_time); |
+ return true; |
} |
+ |
} // namespace ppapi |
} // namespace webkit |