diff options
Diffstat (limited to 'ppapi/shared_impl')
-rw-r--r-- | ppapi/shared_impl/file_ref_impl.cc | 65 | ||||
-rw-r--r-- | ppapi/shared_impl/file_ref_impl.h | 63 | ||||
-rw-r--r-- | ppapi/shared_impl/scoped_pp_resource.cc | 4 | ||||
-rw-r--r-- | ppapi/shared_impl/scoped_pp_resource.h | 5 | ||||
-rw-r--r-- | ppapi/shared_impl/url_request_info_impl.cc | 337 | ||||
-rw-r--r-- | ppapi/shared_impl/url_request_info_impl.h | 143 | ||||
-rw-r--r-- | ppapi/shared_impl/var.cc | 5 | ||||
-rw-r--r-- | ppapi/shared_impl/var.h | 1 |
8 files changed, 623 insertions, 0 deletions
diff --git a/ppapi/shared_impl/file_ref_impl.cc b/ppapi/shared_impl/file_ref_impl.cc new file mode 100644 index 0000000..1eae27b --- /dev/null +++ b/ppapi/shared_impl/file_ref_impl.cc @@ -0,0 +1,65 @@ +// 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/file_ref_impl.h" + +#include "base/logging.h" +#include "ppapi/shared_impl/tracker_base.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { + +FileRefImpl::FileRefImpl(const InitAsImpl&, const PPB_FileRef_CreateInfo& info) + : Resource(info.resource.instance()), + create_info_(info) { + // Should not have been passed a host resource for the trusted constructor. + DCHECK(info.resource.is_null()); + + // Resource's constructor assigned a PP_Resource, so we can fill out our + // host resource now. + create_info_.resource = host_resource(); + DCHECK(!create_info_.resource.is_null()); +} + +FileRefImpl::FileRefImpl(const InitAsProxy&, const PPB_FileRef_CreateInfo& info) + : Resource(info.resource), + create_info_(info) { +} + +FileRefImpl::~FileRefImpl() { +} + +thunk::PPB_FileRef_API* FileRefImpl::AsPPB_FileRef_API() { + return this; +} + +PP_FileSystemType FileRefImpl::GetFileSystemType() const { + return static_cast<PP_FileSystemType>(create_info_.file_system_type); +} + +PP_Var FileRefImpl::GetName() const { + if (!name_var_.get()) { + name_var_ = new StringVar( + TrackerBase::Get()->GetModuleForInstance(pp_instance()), + create_info_.name); + } + return name_var_->GetPPVar(); +} + +PP_Var FileRefImpl::GetPath() const { + if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL) + return PP_MakeUndefined(); + if (!path_var_.get()) { + path_var_ = new StringVar( + TrackerBase::Get()->GetModuleForInstance(pp_instance()), + create_info_.path); + } + return path_var_->GetPPVar(); +} + +const PPB_FileRef_CreateInfo& FileRefImpl::GetCreateInfo() const { + return create_info_; +} + +} // namespace ppapi diff --git a/ppapi/shared_impl/file_ref_impl.h b/ppapi/shared_impl/file_ref_impl.h new file mode 100644 index 0000000..515912b --- /dev/null +++ b/ppapi/shared_impl/file_ref_impl.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef PPAPI_SHARED_IMPL_FILE_REF_IMPL_H_ +#define PPAPI_SHARED_IMPL_FILE_REF_IMPL_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_file_ref_api.h" + +namespace ppapi { + +class StringVar; + +// FileRefs are created in a number of places and they include a number of +// return values. This struct encapsulates everything in one place. +struct PPB_FileRef_CreateInfo { + PPB_FileRef_CreateInfo() : file_system_type(PP_FILESYSTEMTYPE_EXTERNAL) {} + + ppapi::HostResource resource; + int file_system_type; // One of PP_FileSystemType values. + std::string path; + std::string name; +}; + +// This class provides the shared implementation of a FileRef. The functions +// that actually "do stuff" like Touch and MakeDirectory are implemented +// differently for the proxied and non-proxied derived classes. +class FileRefImpl : public Resource, public thunk::PPB_FileRef_API { + public: + struct InitAsImpl {}; + struct InitAsProxy {}; + + FileRefImpl(const InitAsImpl&, const PPB_FileRef_CreateInfo& info); + FileRefImpl(const InitAsProxy&, const PPB_FileRef_CreateInfo& info); + virtual ~FileRefImpl(); + + // Resource overrides. + virtual thunk::PPB_FileRef_API* AsPPB_FileRef_API() OVERRIDE; + + // PPB_FileRef_API implementation (partial). + virtual PP_FileSystemType GetFileSystemType() const OVERRIDE; + virtual PP_Var GetName() const OVERRIDE; + virtual PP_Var GetPath() const OVERRIDE; + virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE; + + private: + PPB_FileRef_CreateInfo create_info_; + + // Lazily initialized vars created from the create_info_. This is so we can + // return the identical string object every time they're requested. + mutable scoped_refptr<StringVar> name_var_; + mutable scoped_refptr<StringVar> path_var_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(FileRefImpl); +}; + +} // namespace ppapi + +#endif // PPAPI_SHARED_IMPL_FILE_REF_IMPL_H_ diff --git a/ppapi/shared_impl/scoped_pp_resource.cc b/ppapi/shared_impl/scoped_pp_resource.cc index 1b8f705..d5a9748 100644 --- a/ppapi/shared_impl/scoped_pp_resource.cc +++ b/ppapi/shared_impl/scoped_pp_resource.cc @@ -17,6 +17,10 @@ ScopedPPResource::ScopedPPResource(PP_Resource resource) : id_(resource) { CallAddRef(); } +ScopedPPResource::ScopedPPResource(const PassRef&, PP_Resource resource) + : id_(resource) { +} + ScopedPPResource::ScopedPPResource(Resource* resource) : id_(resource ? resource->GetReference() : 0) { // GetReference AddRef's for us. diff --git a/ppapi/shared_impl/scoped_pp_resource.h b/ppapi/shared_impl/scoped_pp_resource.h index 74cb9eb..96db4ee 100644 --- a/ppapi/shared_impl/scoped_pp_resource.h +++ b/ppapi/shared_impl/scoped_pp_resource.h @@ -14,11 +14,16 @@ class Resource; // This is a version of scoped_refptr but for PP_Resources. class ScopedPPResource { public: + struct PassRef {}; + ScopedPPResource(); // Takes one reference to the given resource. explicit ScopedPPResource(PP_Resource resource); + // Assumes responsibility for one ref that the resource already has. + explicit ScopedPPResource(const PassRef&, PP_Resource resource); + // Helper to get the PP_Resource out of the given object and take a reference // to it. explicit ScopedPPResource(Resource* resource); 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 diff --git a/ppapi/shared_impl/url_request_info_impl.h b/ppapi/shared_impl/url_request_info_impl.h new file mode 100644 index 0000000..622f8c5 --- /dev/null +++ b/ppapi/shared_impl/url_request_info_impl.h @@ -0,0 +1,143 @@ +// 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. + +#ifndef PPAPI_SHARED_IMPL_URL_REQUEST_INFO_IMPL_H_ +#define PPAPI_SHARED_IMPL_URL_REQUEST_INFO_IMPL_H_ + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_url_request_info_api.h" + +namespace ppapi { + +namespace thunk { +class PPB_FileRef_API; +} + +struct PPB_URLRequestInfo_Data { + struct BodyItem { + BodyItem(); + explicit BodyItem(const std::string& data); + BodyItem(Resource* file_ref, + int64_t start_offset, + int64_t number_of_bytes, + PP_Time expected_last_modified_time); + + // Set if the input is a file, false means the |data| is valid. + bool is_file; + + std::string data; + + // Is is_file is set, these variables are set. Note that the resource + // may still be NULL in some cases, such as deserialization errors. + // + // This is a bit tricky. In the plugin side of the proxy, both the file ref + // and the file_ref_host_resource will be set and valid. The scoped_ptr + // ensures that the resource is alive for as long as the BodyItem is. + // + // When we deserialize this in the renderer, only the + // file_ref_host_resource's are serialized over IPC. The file_refs won't be + // valid until the host resources are converted to Resource pointers in the + // PPB_URLRequestInfo_Impl. + scoped_refptr<Resource> file_ref; + HostResource file_ref_host_resource; + + int64_t start_offset; + int64_t number_of_bytes; + PP_Time expected_last_modified_time; + + // If you add more stuff here, be sure to modify the serialization rules in + // ppapi_messages.h + }; + + PPB_URLRequestInfo_Data(); + ~PPB_URLRequestInfo_Data(); + + std::string url; + std::string method; + std::string headers; + + bool stream_to_file; + bool follow_redirects; + bool record_download_progress; + bool record_upload_progress; + + // |has_custom_referrer_url| is set to false if a custom referrer hasn't been + // set (or has been set to an Undefined Var) and the default referrer should + // be used. (Setting the custom referrer to an empty string indicates that no + // referrer header should be generated.) + bool has_custom_referrer_url; + std::string custom_referrer_url; + + bool allow_cross_origin_requests; + bool allow_credentials; + + // Similar to the custom referrer (above), but for custom content transfer + // encoding. + bool has_custom_content_transfer_encoding; + std::string custom_content_transfer_encoding; + + int32_t prefetch_buffer_upper_threshold; + int32_t prefetch_buffer_lower_threshold; + + std::vector<BodyItem> body; + + // If you add more stuff here, be sure to modify the serialization rules in + // ppapi_messages.h +}; + +class URLRequestInfoImpl : public ::ppapi::Resource, + public ::ppapi::thunk::PPB_URLRequestInfo_API { + public: + // This constructor initializes the object as a proxy object with the given + // host resource. + URLRequestInfoImpl(const HostResource& host_resource, + const PPB_URLRequestInfo_Data& data); + + ~URLRequestInfoImpl(); + + // Resource overrides. + virtual thunk::PPB_URLRequestInfo_API* AsPPB_URLRequestInfo_API() OVERRIDE; + + // PPB_URLRequestInfo_API implementation. + virtual PP_Bool SetProperty(PP_URLRequestProperty property, + PP_Var var) OVERRIDE; + virtual PP_Bool AppendDataToBody(const void* data, uint32_t len) OVERRIDE; + virtual PP_Bool AppendFileToBody( + PP_Resource file_ref, + int64_t start_offset, + int64_t number_of_bytes, + PP_Time expected_last_modified_time) OVERRIDE; + virtual const PPB_URLRequestInfo_Data& GetData() const OVERRIDE; + + protected: + // Constructor used by the webkit implementation. + URLRequestInfoImpl(PP_Instance instance, + const PPB_URLRequestInfo_Data& data); + + // Checks that the HTTP method is valid, returning the canonicalized version + // if so. Returns empty string if it's invalid. + static std::string ValidateMethod(const std::string& method); + + bool SetUndefinedProperty(PP_URLRequestProperty property); + bool SetBooleanProperty(PP_URLRequestProperty property, bool value); + bool SetIntegerProperty(PP_URLRequestProperty property, int32_t value); + bool SetStringProperty(PP_URLRequestProperty property, + const std::string& value); + + const PPB_URLRequestInfo_Data& data() const { return data_; } + PPB_URLRequestInfo_Data& data() { return data_; } + + private: + PPB_URLRequestInfo_Data data_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(URLRequestInfoImpl); +}; + +} // namespace ppapi + +#endif // PPAPI_SHARED_IMPL_URL_REQUEST_INFO_IMPL_H_ diff --git a/ppapi/shared_impl/var.cc b/ppapi/shared_impl/var.cc index 0542e50..165b8ff 100644 --- a/ppapi/shared_impl/var.cc +++ b/ppapi/shared_impl/var.cc @@ -97,6 +97,11 @@ void Var::AssignVarID(int32 id) { // StringVar ------------------------------------------------------------------- +StringVar::StringVar(PP_Module module, const std::string& str) + : Var(module), + value_(str) { +} + StringVar::StringVar(PP_Module module, const char* str, uint32 len) : Var(module), value_(str, len) { diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h index 02553bb..ce5aa2b 100644 --- a/ppapi/shared_impl/var.h +++ b/ppapi/shared_impl/var.h @@ -90,6 +90,7 @@ class Var : public base::RefCounted<Var> { // DoSomethingWithTheString(string->value()); class StringVar : public Var { public: + StringVar(PP_Module module, const std::string& str); StringVar(PP_Module module, const char* str, uint32 len); virtual ~StringVar(); |