| // Copyright (c) 2012 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/proxy/ppapi_param_traits.h" | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <string.h> // For memcpy | |
| #include "base/macros.h" | |
| #include "build/build_config.h" | |
| #include "ppapi/c/pp_resource.h" | |
| #include "ppapi/proxy/ppapi_messages.h" | |
| #include "ppapi/proxy/serialized_flash_menu.h" | |
| #include "ppapi/proxy/serialized_var.h" | |
| #include "ppapi/shared_impl/host_resource.h" | |
| #include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h" | |
| namespace IPC { | |
| namespace { | |
| // Deserializes a vector from IPC. This special version must be used instead | |
| // of the default IPC version when the vector contains a SerializedVar, either | |
| // directly or indirectly (i.e. a vector of objects that have a SerializedVar | |
| // inside them). | |
| // | |
| // The default vector deserializer does resize and then we deserialize into | |
| // those allocated slots. However, the implementation of vector (at least in | |
| // GCC's implementation), creates a new empty object using the default | |
| // constructor, and then sets the rest of the items to that empty one using the | |
| // copy constructor. | |
| // | |
| // Since we allocate the inner class when you call the default constructor and | |
| // transfer the inner class when you do operator=, the entire vector will end | |
| // up referring to the same inner class. Deserializing into this will just end | |
| // up overwriting the same item over and over, since all the SerializedVars | |
| // will refer to the same thing. | |
| // | |
| // The solution is to make a new object for each deserialized item, and then | |
| // add it to the vector one at a time. | |
| template <typename T> | |
| bool ReadVectorWithoutCopy(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| std::vector<T>* output) { | |
| // This part is just a copy of the the default ParamTraits vector Read(). | |
| int size; | |
| // ReadLength() checks for < 0 itself. | |
| if (!iter->ReadLength(&size)) | |
| return false; | |
| // Resizing beforehand is not safe, see BUG 1006367 for details. | |
| if (INT_MAX / sizeof(T) <= static_cast<size_t>(size)) | |
| return false; | |
| output->reserve(size); | |
| for (int i = 0; i < size; i++) { | |
| T cur; | |
| if (!ReadParam(m, iter, &cur)) | |
| return false; | |
| output->push_back(cur); | |
| } | |
| return true; | |
| } | |
| // This serializes the vector of items to the IPC message in exactly the same | |
| // way as the "regular" IPC vector serializer does. But having the code here | |
| // saves us from having to copy this code into all ParamTraits that use the | |
| // ReadVectorWithoutCopy function for deserializing. | |
| template <typename T> | |
| void WriteVectorWithoutCopy(base::Pickle* m, const std::vector<T>& p) { | |
| WriteParam(m, static_cast<int>(p.size())); | |
| for (size_t i = 0; i < p.size(); i++) | |
| WriteParam(m, p[i]); | |
| } | |
| } // namespace | |
| // PP_Bool --------------------------------------------------------------------- | |
| // static | |
| void ParamTraits<PP_Bool>::Write(base::Pickle* m, const param_type& p) { | |
| WriteParam(m, PP_ToBool(p)); | |
| } | |
| // static | |
| bool ParamTraits<PP_Bool>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| // We specifically want to be strict here about what types of input we accept, | |
| // which ParamTraits<bool> does for us. We don't want to deserialize "2" into | |
| // a PP_Bool, for example. | |
| bool result = false; | |
| if (!ReadParam(m, iter, &result)) | |
| return false; | |
| *r = PP_FromBool(result); | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<PP_Bool>::Log(const param_type& p, std::string* l) { | |
| } | |
| // PP_NetAddress_Private ------------------------------------------------------- | |
| // static | |
| void ParamTraits<PP_NetAddress_Private>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.size); | |
| m->WriteBytes(p.data, static_cast<int>(p.size)); | |
| } | |
| // static | |
| bool ParamTraits<PP_NetAddress_Private>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* p) { | |
| uint16_t size; | |
| if (!ReadParam(m, iter, &size)) | |
| return false; | |
| if (size > sizeof(p->data)) | |
| return false; | |
| p->size = size; | |
| const char* data; | |
| if (!iter->ReadBytes(&data, size)) | |
| return false; | |
| memcpy(p->data, data, size); | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<PP_NetAddress_Private>::Log(const param_type& p, | |
| std::string* l) { | |
| l->append("<PP_NetAddress_Private ("); | |
| LogParam(p.size, l); | |
| l->append(" bytes)>"); | |
| } | |
| // HostResource ---------------------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::HostResource>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.instance()); | |
| WriteParam(m, p.host_resource()); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::HostResource>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| PP_Instance instance; | |
| PP_Resource resource; | |
| if (!ReadParam(m, iter, &instance) || !ReadParam(m, iter, &resource)) | |
| return false; | |
| r->SetHostResource(instance, resource); | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<ppapi::HostResource>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // SerializedVar --------------------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedVar>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| p.WriteToMessage(m); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedVar>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return r->ReadFromMessage(m, iter); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedVar>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // std::vector<SerializedVar> -------------------------------------------------- | |
| void ParamTraits<std::vector<ppapi::proxy::SerializedVar>>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteVectorWithoutCopy(m, p); | |
| } | |
| // static | |
| bool ParamTraits<std::vector<ppapi::proxy::SerializedVar>>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadVectorWithoutCopy(m, iter, r); | |
| } | |
| // static | |
| void ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Log( | |
| const param_type& p, | |
| std::string* l) { | |
| } | |
| // ppapi::PpapiPermissions ----------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::PpapiPermissions>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.GetBits()); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::PpapiPermissions>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| uint32_t bits; | |
| if (!ReadParam(m, iter, &bits)) | |
| return false; | |
| *r = ppapi::PpapiPermissions(bits); | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<ppapi::PpapiPermissions>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // SerializedHandle ------------------------------------------------------------ | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedHandle>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| ppapi::proxy::SerializedHandle::WriteHeader(p.header(), m); | |
| switch (p.type()) { | |
| case ppapi::proxy::SerializedHandle::SHARED_MEMORY: | |
| WriteParam(m, p.shmem()); | |
| break; | |
| case ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION: | |
| WriteParam(m, const_cast<param_type&>(p).TakeSharedMemoryRegion()); | |
| break; | |
| case ppapi::proxy::SerializedHandle::SOCKET: | |
| case ppapi::proxy::SerializedHandle::FILE: | |
| WriteParam(m, p.descriptor()); | |
| break; | |
| case ppapi::proxy::SerializedHandle::INVALID: | |
| break; | |
| // No default so the compiler will warn on new types. | |
| } | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedHandle>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| ppapi::proxy::SerializedHandle::Header header; | |
| if (!ppapi::proxy::SerializedHandle::ReadHeader(iter, &header)) | |
| return false; | |
| switch (header.type) { | |
| case ppapi::proxy::SerializedHandle::SHARED_MEMORY: { | |
| base::SharedMemoryHandle handle; | |
| if (!ReadParam(m, iter, &handle)) | |
| return false; | |
| r->set_shmem(handle, header.size); | |
| break; | |
| } | |
| case ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION: { | |
| base::subtle::PlatformSharedMemoryRegion region; | |
| if (!ReadParam(m, iter, ®ion)) | |
| return false; | |
| r->set_shmem_region(std::move(region)); | |
| break; | |
| } | |
| case ppapi::proxy::SerializedHandle::SOCKET: { | |
| IPC::PlatformFileForTransit socket; | |
| if (!ReadParam(m, iter, &socket)) | |
| return false; | |
| r->set_socket(socket); | |
| break; | |
| } | |
| case ppapi::proxy::SerializedHandle::FILE: { | |
| IPC::PlatformFileForTransit desc; | |
| if (!ReadParam(m, iter, &desc)) | |
| return false; | |
| r->set_file_handle(desc, header.open_flags, header.file_io); | |
| break; | |
| } | |
| case ppapi::proxy::SerializedHandle::INVALID: | |
| break; | |
| // No default so the compiler will warn us if a new type is added. | |
| } | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedHandle>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // PPBURLLoader_UpdateProgress_Params ------------------------------------------ | |
| // static | |
| void ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.instance); | |
| WriteParam(m, p.resource); | |
| WriteParam(m, p.bytes_sent); | |
| WriteParam(m, p.total_bytes_to_be_sent); | |
| WriteParam(m, p.bytes_received); | |
| WriteParam(m, p.total_bytes_to_be_received); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &r->instance) && ReadParam(m, iter, &r->resource) && | |
| ReadParam(m, iter, &r->bytes_sent) && | |
| ReadParam(m, iter, &r->total_bytes_to_be_sent) && | |
| ReadParam(m, iter, &r->bytes_received) && | |
| ReadParam(m, iter, &r->total_bytes_to_be_received); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Log( | |
| const param_type& p, | |
| std::string* l) { | |
| } | |
| #if !defined(OS_NACL) && !defined(NACL_WIN64) | |
| // PPBFlash_DrawGlyphs_Params -------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.instance); | |
| WriteParam(m, p.image_data); | |
| WriteParam(m, p.font_desc); | |
| WriteParam(m, p.color); | |
| WriteParam(m, p.position); | |
| WriteParam(m, p.clip); | |
| WriteParam(m, p.transformation[0][0]); | |
| WriteParam(m, p.transformation[0][1]); | |
| WriteParam(m, p.transformation[0][2]); | |
| WriteParam(m, p.transformation[1][0]); | |
| WriteParam(m, p.transformation[1][1]); | |
| WriteParam(m, p.transformation[1][2]); | |
| WriteParam(m, p.transformation[2][0]); | |
| WriteParam(m, p.transformation[2][1]); | |
| WriteParam(m, p.transformation[2][2]); | |
| WriteParam(m, p.allow_subpixel_aa); | |
| WriteParam(m, p.glyph_indices); | |
| WriteParam(m, p.glyph_advances); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &r->instance) && | |
| ReadParam(m, iter, &r->image_data) && | |
| ReadParam(m, iter, &r->font_desc) && ReadParam(m, iter, &r->color) && | |
| ReadParam(m, iter, &r->position) && ReadParam(m, iter, &r->clip) && | |
| ReadParam(m, iter, &r->transformation[0][0]) && | |
| ReadParam(m, iter, &r->transformation[0][1]) && | |
| ReadParam(m, iter, &r->transformation[0][2]) && | |
| ReadParam(m, iter, &r->transformation[1][0]) && | |
| ReadParam(m, iter, &r->transformation[1][1]) && | |
| ReadParam(m, iter, &r->transformation[1][2]) && | |
| ReadParam(m, iter, &r->transformation[2][0]) && | |
| ReadParam(m, iter, &r->transformation[2][1]) && | |
| ReadParam(m, iter, &r->transformation[2][2]) && | |
| ReadParam(m, iter, &r->allow_subpixel_aa) && | |
| ReadParam(m, iter, &r->glyph_indices) && | |
| ReadParam(m, iter, &r->glyph_advances) && | |
| r->glyph_indices.size() == r->glyph_advances.size(); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Log( | |
| const param_type& p, | |
| std::string* l) { | |
| } | |
| // SerializedDirEntry ---------------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedDirEntry>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.name); | |
| WriteParam(m, p.is_dir); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedDirEntry>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &r->name) && ReadParam(m, iter, &r->is_dir); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedDirEntry>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // ppapi::proxy::SerializedFontDescription ------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedFontDescription>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.face); | |
| WriteParam(m, p.family); | |
| WriteParam(m, p.size); | |
| WriteParam(m, p.weight); | |
| WriteParam(m, p.italic); | |
| WriteParam(m, p.small_caps); | |
| WriteParam(m, p.letter_spacing); | |
| WriteParam(m, p.word_spacing); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedFontDescription>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &r->face) && ReadParam(m, iter, &r->family) && | |
| ReadParam(m, iter, &r->size) && ReadParam(m, iter, &r->weight) && | |
| ReadParam(m, iter, &r->italic) && ReadParam(m, iter, &r->small_caps) && | |
| ReadParam(m, iter, &r->letter_spacing) && | |
| ReadParam(m, iter, &r->word_spacing); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedFontDescription>::Log( | |
| const param_type& p, | |
| std::string* l) { | |
| } | |
| #endif // !defined(OS_NACL) && !defined(NACL_WIN64) | |
| // ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------ | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.family); | |
| WriteParam(m, p.generic_family); | |
| WriteParam(m, p.style); | |
| WriteParam(m, p.weight); | |
| WriteParam(m, p.width); | |
| WriteParam(m, p.charset); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &r->family) && | |
| ReadParam(m, iter, &r->generic_family) && | |
| ReadParam(m, iter, &r->style) && ReadParam(m, iter, &r->weight) && | |
| ReadParam(m, iter, &r->width) && ReadParam(m, iter, &r->charset); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Log( | |
| const param_type& p, | |
| std::string* l) { | |
| } | |
| #if !defined(OS_NACL) && !defined(NACL_WIN64) | |
| // ppapi::PepperFilePath ------------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::PepperFilePath>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, static_cast<unsigned>(p.domain())); | |
| WriteParam(m, p.path()); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::PepperFilePath>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* p) { | |
| unsigned domain; | |
| base::FilePath path; | |
| if (!ReadParam(m, iter, &domain) || !ReadParam(m, iter, &path)) | |
| return false; | |
| if (domain > ppapi::PepperFilePath::DOMAIN_MAX_VALID) | |
| return false; | |
| *p = ppapi::PepperFilePath( | |
| static_cast<ppapi::PepperFilePath::Domain>(domain), path); | |
| return true; | |
| } | |
| // static | |
| void ParamTraits<ppapi::PepperFilePath>::Log(const param_type& p, | |
| std::string* l) { | |
| l->append("("); | |
| LogParam(static_cast<unsigned>(p.domain()), l); | |
| l->append(", "); | |
| LogParam(p.path(), l); | |
| l->append(")"); | |
| } | |
| // SerializedFlashMenu --------------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| p.WriteToMessage(m); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::proxy::SerializedFlashMenu>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return r->ReadFromMessage(m, iter); | |
| } | |
| // static | |
| void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| #endif // !defined(OS_NACL) && !defined(NACL_WIN64) | |
| // PPB_X509Certificate_Fields -------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Write( | |
| base::Pickle* m, | |
| const param_type& p) { | |
| WriteParam(m, p.values_); | |
| } | |
| // static | |
| bool ParamTraits<ppapi::PPB_X509Certificate_Fields>::Read( | |
| const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| return ReadParam(m, iter, &(r->values_)); | |
| } | |
| // static | |
| void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| // ppapi::SocketOptionData ----------------------------------------------------- | |
| // static | |
| void ParamTraits<ppapi::SocketOptionData>::Write(base::Pickle* m, | |
| const param_type& p) { | |
| ppapi::SocketOptionData::Type type = p.GetType(); | |
| WriteParam(m, static_cast<int32_t>(type)); | |
| switch (type) { | |
| case ppapi::SocketOptionData::TYPE_INVALID: { | |
| break; | |
| } | |
| case ppapi::SocketOptionData::TYPE_BOOL: { | |
| bool out_value = false; | |
| bool result = p.GetBool(&out_value); | |
| // Suppress unused variable warnings. | |
| static_cast<void>(result); | |
| DCHECK(result); | |
| WriteParam(m, out_value); | |
| break; | |
| } | |
| case ppapi::SocketOptionData::TYPE_INT32: { | |
| int32_t out_value = 0; | |
| bool result = p.GetInt32(&out_value); | |
| // Suppress unused variable warnings. | |
| static_cast<void>(result); | |
| DCHECK(result); | |
| WriteParam(m, out_value); | |
| break; | |
| } | |
| // No default so the compiler will warn on new types. | |
| } | |
| } | |
| // static | |
| bool ParamTraits<ppapi::SocketOptionData>::Read(const base::Pickle* m, | |
| base::PickleIterator* iter, | |
| param_type* r) { | |
| *r = ppapi::SocketOptionData(); | |
| int32_t type = 0; | |
| if (!ReadParam(m, iter, &type)) | |
| return false; | |
| if (type != ppapi::SocketOptionData::TYPE_INVALID && | |
| type != ppapi::SocketOptionData::TYPE_BOOL && | |
| type != ppapi::SocketOptionData::TYPE_INT32) { | |
| return false; | |
| } | |
| switch (static_cast<ppapi::SocketOptionData::Type>(type)) { | |
| case ppapi::SocketOptionData::TYPE_INVALID: { | |
| return true; | |
| } | |
| case ppapi::SocketOptionData::TYPE_BOOL: { | |
| bool value = false; | |
| if (!ReadParam(m, iter, &value)) | |
| return false; | |
| r->SetBool(value); | |
| return true; | |
| } | |
| case ppapi::SocketOptionData::TYPE_INT32: { | |
| int32_t value = 0; | |
| if (!ReadParam(m, iter, &value)) | |
| return false; | |
| r->SetInt32(value); | |
| return true; | |
| } | |
| // No default so the compiler will warn on new types. | |
| } | |
| return false; | |
| } | |
| // static | |
| void ParamTraits<ppapi::SocketOptionData>::Log(const param_type& p, | |
| std::string* l) { | |
| } | |
| } // namespace IPC |