summaryrefslogtreecommitdiffstats
path: root/ppapi/shared_impl/url_request_info_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/shared_impl/url_request_info_impl.cc')
-rw-r--r--ppapi/shared_impl/url_request_info_impl.cc337
1 files changed, 337 insertions, 0 deletions
diff --git a/ppapi/shared_impl/url_request_info_impl.cc b/ppapi/shared_impl/url_request_info_impl.cc
new file mode 100644
index 0000000..75fcb27
--- /dev/null
+++ b/ppapi/shared_impl/url_request_info_impl.cc
@@ -0,0 +1,337 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/url_request_info_impl.h"
+
+#include "base/string_util.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+
+namespace ppapi {
+
+namespace {
+
+const int32_t kDefaultPrefetchBufferUpperThreshold = 100 * 1000 * 1000;
+const int32_t kDefaultPrefetchBufferLowerThreshold = 50 * 1000 * 1000;
+
+// 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",
+};
+
+bool IsValidToken(const std::string& token) {
+ size_t length = token.size();
+ if (length == 0)
+ return false;
+
+ for (size_t i = 0; i < length; i++) {
+ char c = token[i];
+ if (c >= 127 || c <= 32)
+ return false;
+ if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
+ c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
+ c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
+ c == '{' || c == '}')
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+PPB_URLRequestInfo_Data::BodyItem::BodyItem()
+ : is_file(false),
+ start_offset(0),
+ number_of_bytes(-1),
+ expected_last_modified_time(0.0) {
+}
+
+PPB_URLRequestInfo_Data::BodyItem::BodyItem(const std::string& data)
+ : is_file(false),
+ data(data),
+ start_offset(0),
+ number_of_bytes(-1),
+ expected_last_modified_time(0.0) {
+}
+
+PPB_URLRequestInfo_Data::BodyItem::BodyItem(
+ Resource* file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time)
+ : is_file(true),
+ file_ref(file_ref),
+ file_ref_host_resource(file_ref->host_resource()),
+ start_offset(start_offset),
+ number_of_bytes(number_of_bytes),
+ expected_last_modified_time(expected_last_modified_time) {
+}
+
+PPB_URLRequestInfo_Data::PPB_URLRequestInfo_Data()
+ : url(),
+ method(),
+ headers(),
+ stream_to_file(false),
+ follow_redirects(true),
+ record_download_progress(false),
+ record_upload_progress(false),
+ has_custom_referrer_url(false),
+ custom_referrer_url(),
+ allow_cross_origin_requests(false),
+ allow_credentials(false),
+ has_custom_content_transfer_encoding(false),
+ custom_content_transfer_encoding(),
+ prefetch_buffer_upper_threshold(kDefaultPrefetchBufferUpperThreshold),
+ prefetch_buffer_lower_threshold(kDefaultPrefetchBufferLowerThreshold),
+ body() {
+}
+
+PPB_URLRequestInfo_Data::~PPB_URLRequestInfo_Data() {
+}
+
+URLRequestInfoImpl::URLRequestInfoImpl(PP_Instance instance,
+ const PPB_URLRequestInfo_Data& data)
+ : Resource(instance),
+ data_(data) {
+}
+
+URLRequestInfoImpl::URLRequestInfoImpl(const HostResource& host_resource,
+ const PPB_URLRequestInfo_Data& data)
+ : Resource(host_resource),
+ data_(data) {
+}
+
+URLRequestInfoImpl::~URLRequestInfoImpl() {
+}
+
+thunk::PPB_URLRequestInfo_API* URLRequestInfoImpl::AsPPB_URLRequestInfo_API() {
+ return this;
+}
+
+PP_Bool URLRequestInfoImpl::SetProperty(PP_URLRequestProperty property,
+ PP_Var var) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. This
+ // code is used both in the plugin (which we don't trust) and in the renderer
+ // (which we trust more). When running out-of-process, the plugin calls this
+ // function to configure the PPB_URLRequestInfo_Data, which is then sent to
+ // the renderer and *not* run through SetProperty again.
+ //
+ // This means that anything in the PPB_URLRequestInfo_Data needs to be
+ // validated at the time the URL is requested (which is what ValidateData
+ // does). If your feature requires security checks, it should be in the
+ // implementation in the renderer when the WebKit request is actually
+ // constructed.
+ //
+ // It is legal to do some validation here if you want to report failure to
+ // the plugin as a convenience, as long as you also do it in the renderer
+ // later.
+ 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 URLRequestInfoImpl::AppendDataToBody(const void* data, uint32_t len) {
+ if (len > 0) {
+ data_.body.push_back(PPB_URLRequestInfo_Data::BodyItem(
+ std::string(static_cast<const char*>(data), len)));
+ }
+ return PP_TRUE;
+}
+
+PP_Bool URLRequestInfoImpl::AppendFileToBody(
+ PP_Resource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) {
+ EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
+ if (enter.failed())
+ return PP_FALSE;
+
+ // 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;
+
+ data_.body.push_back(PPB_URLRequestInfo_Data::BodyItem(
+ enter.resource(),
+ start_offset,
+ number_of_bytes,
+ expected_last_modified_time));
+ return PP_TRUE;
+}
+
+const PPB_URLRequestInfo_Data& URLRequestInfoImpl::GetData() const {
+ return data_;
+}
+
+// static
+std::string URLRequestInfoImpl::ValidateMethod(const std::string& method) {
+ if (!IsValidToken(method))
+ return std::string();
+
+ 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;
+}
+
+bool URLRequestInfoImpl::SetUndefinedProperty(PP_URLRequestProperty property) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
+ data_.has_custom_referrer_url = false;
+ data_.custom_referrer_url = std::string();
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
+ data_.has_custom_content_transfer_encoding = false;
+ data_.custom_content_transfer_encoding = std::string();
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoImpl::SetBooleanProperty(PP_URLRequestProperty property,
+ bool value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_STREAMTOFILE:
+ data_.stream_to_file = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
+ data_.follow_redirects = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
+ data_.record_download_progress = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
+ data_.record_upload_progress = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS:
+ data_.allow_cross_origin_requests = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS:
+ data_.allow_credentials = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoImpl::SetIntegerProperty(PP_URLRequestProperty property,
+ int32_t value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
+ data_.prefetch_buffer_upper_threshold = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
+ data_.prefetch_buffer_lower_threshold = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoImpl::SetStringProperty(PP_URLRequestProperty property,
+ const std::string& value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_URL:
+ data_.url = value; // NOTE: This may be a relative URL.
+ return true;
+ case PP_URLREQUESTPROPERTY_METHOD: {
+ // Convenience check for synchronously returning errors to the plugin.
+ // This is re-checked in ValidateData.
+ std::string canonicalized = ValidateMethod(value);
+ if (canonicalized.empty())
+ return false;
+ data_.method = canonicalized;
+ return true;
+ }
+ case PP_URLREQUESTPROPERTY_HEADERS:
+ data_.headers = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
+ data_.has_custom_referrer_url = true;
+ data_.custom_referrer_url = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
+ data_.has_custom_content_transfer_encoding = true;
+ data_.custom_content_transfer_encoding = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace ppapi