// 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 // For memcpy #include "ppapi/c/pp_resource.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/proxy/serialized_flash_menu.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 bool ReadVectorWithoutCopy(const Message* m, PickleIterator* iter, std::vector* output) { // This part is just a copy of the the default ParamTraits vector Read(). int size; // ReadLength() checks for < 0 itself. if (!m->ReadLength(iter, &size)) return false; // Resizing beforehand is not safe, see BUG 1006367 for details. if (INT_MAX / sizeof(T) <= static_cast(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 void WriteVectorWithoutCopy(Message* m, const std::vector& p) { WriteParam(m, static_cast(p.size())); for (size_t i = 0; i < p.size(); i++) WriteParam(m, p[i]); } } // namespace // PP_Bool --------------------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, PP_ToBool(p)); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { // We specifically want to be strict here about what types of input we accept, // which ParamTraits does for us. We don't want to deserialize "2" into // a PP_Bool, for example. bool result = false; if (!ParamTraits::Read(m, iter, &result)) return false; *r = PP_FromBool(result); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // PP_NetAddress_Private ------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { WriteParam(m, p.size); m->WriteBytes(p.data, static_cast(p.size)); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* p) { uint16 size; if (!ReadParam(m, iter, &size)) return false; if (size > sizeof(p->data)) return false; p->size = size; const char* data; if (!m->ReadBytes(iter, &data, size)) return false; memcpy(p->data, data, size); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { l->append("append(" bytes)>"); } // HostResource ---------------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, p.instance()); ParamTraits::Write(m, p.host_resource()); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { PP_Instance instance; PP_Resource resource; if (!ParamTraits::Read(m, iter, &instance) || !ParamTraits::Read(m, iter, &resource)) return false; r->SetHostResource(instance, resource); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // SerializedVar --------------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { p.WriteToMessage(m); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { return r->ReadFromMessage(m, iter); } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // std::vector -------------------------------------------------- void ParamTraits< std::vector >::Write( Message* m, const param_type& p) { WriteVectorWithoutCopy(m, p); } // static bool ParamTraits< std::vector >::Read( const Message* m, PickleIterator* iter, param_type* r) { return ReadVectorWithoutCopy(m, iter, r); } // static void ParamTraits< std::vector >::Log( const param_type& p, std::string* l) { } // ppapi::PpapiPermissions ----------------------------------------------------- void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, p.GetBits()); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { uint32_t bits; if (!ParamTraits::Read(m, iter, &bits)) return false; *r = ppapi::PpapiPermissions(bits); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // SerializedHandle ------------------------------------------------------------ // static void ParamTraits::Write(Message* m, const param_type& p) { ppapi::proxy::SerializedHandle::WriteHeader(p.header(), m); switch (p.type()) { case ppapi::proxy::SerializedHandle::SHARED_MEMORY: ParamTraits::Write(m, p.shmem()); break; case ppapi::proxy::SerializedHandle::SOCKET: case ppapi::proxy::SerializedHandle::FILE: ParamTraits::Write(m, p.descriptor()); break; case ppapi::proxy::SerializedHandle::INVALID: break; // No default so the compiler will warn on new types. } } // static bool ParamTraits::Read(const Message* m, 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 (ParamTraits::Read(m, iter, &handle)) { r->set_shmem(handle, header.size); return true; } break; } case ppapi::proxy::SerializedHandle::SOCKET: { IPC::PlatformFileForTransit socket; if (ParamTraits::Read(m, iter, &socket)) { r->set_socket(socket); return true; } break; } case ppapi::proxy::SerializedHandle::FILE: { IPC::PlatformFileForTransit desc; if (ParamTraits::Read(m, iter, &desc)) { r->set_file_handle(desc, header.open_flags, header.file_io); return true; } break; } case ppapi::proxy::SerializedHandle::INVALID: return true; // No default so the compiler will warn us if a new type is added. } return false; } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // PPBURLLoader_UpdateProgress_Params ------------------------------------------ // static void ParamTraits::Write( Message* m, const param_type& p) { ParamTraits::Write(m, p.instance); ParamTraits::Write(m, p.resource); ParamTraits::Write(m, p.bytes_sent); ParamTraits::Write(m, p.total_bytes_to_be_sent); ParamTraits::Write(m, p.bytes_received); ParamTraits::Write(m, p.total_bytes_to_be_received); } // static bool ParamTraits::Read( const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &r->instance) && ParamTraits::Read(m, iter, &r->resource) && ParamTraits::Read(m, iter, &r->bytes_sent) && ParamTraits::Read(m, iter, &r->total_bytes_to_be_sent) && ParamTraits::Read(m, iter, &r->bytes_received) && ParamTraits::Read(m, iter, &r->total_bytes_to_be_received); } // static void ParamTraits::Log( const param_type& p, std::string* l) { } #if !defined(OS_NACL) && !defined(NACL_WIN64) // PPBFlash_DrawGlyphs_Params -------------------------------------------------- // static void ParamTraits::Write( Message* m, const param_type& p) { ParamTraits::Write(m, p.instance); ParamTraits::Write(m, p.image_data); ParamTraits::Write(m, p.font_desc); ParamTraits::Write(m, p.color); ParamTraits::Write(m, p.position); ParamTraits::Write(m, p.clip); ParamTraits::Write(m, p.transformation[0][0]); ParamTraits::Write(m, p.transformation[0][1]); ParamTraits::Write(m, p.transformation[0][2]); ParamTraits::Write(m, p.transformation[1][0]); ParamTraits::Write(m, p.transformation[1][1]); ParamTraits::Write(m, p.transformation[1][2]); ParamTraits::Write(m, p.transformation[2][0]); ParamTraits::Write(m, p.transformation[2][1]); ParamTraits::Write(m, p.transformation[2][2]); ParamTraits::Write(m, p.allow_subpixel_aa); ParamTraits >::Write(m, p.glyph_indices); ParamTraits >::Write(m, p.glyph_advances); } // static bool ParamTraits::Read( const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &r->instance) && ParamTraits::Read(m, iter, &r->image_data) && ParamTraits::Read(m, iter, &r->font_desc) && ParamTraits::Read(m, iter, &r->color) && ParamTraits::Read(m, iter, &r->position) && ParamTraits::Read(m, iter, &r->clip) && ParamTraits::Read(m, iter, &r->transformation[0][0]) && ParamTraits::Read(m, iter, &r->transformation[0][1]) && ParamTraits::Read(m, iter, &r->transformation[0][2]) && ParamTraits::Read(m, iter, &r->transformation[1][0]) && ParamTraits::Read(m, iter, &r->transformation[1][1]) && ParamTraits::Read(m, iter, &r->transformation[1][2]) && ParamTraits::Read(m, iter, &r->transformation[2][0]) && ParamTraits::Read(m, iter, &r->transformation[2][1]) && ParamTraits::Read(m, iter, &r->transformation[2][2]) && ParamTraits::Read(m, iter, &r->allow_subpixel_aa) && ParamTraits >::Read(m, iter, &r->glyph_indices) && ParamTraits >::Read(m, iter, &r->glyph_advances) && r->glyph_indices.size() == r->glyph_advances.size(); } // static void ParamTraits::Log( const param_type& p, std::string* l) { } // SerializedDirEntry ---------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, p.name); ParamTraits::Write(m, p.is_dir); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &r->name) && ParamTraits::Read(m, iter, &r->is_dir); } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // ppapi::proxy::SerializedFontDescription ------------------------------------- // static void ParamTraits::Write( Message* m, const param_type& p) { ParamTraits::Write(m, p.face); ParamTraits::Write(m, p.family); ParamTraits::Write(m, p.size); ParamTraits::Write(m, p.weight); ParamTraits::Write(m, p.italic); ParamTraits::Write(m, p.small_caps); ParamTraits::Write(m, p.letter_spacing); ParamTraits::Write(m, p.word_spacing); } // static bool ParamTraits::Read( const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &r->face) && ParamTraits::Read(m, iter, &r->family) && ParamTraits::Read(m, iter, &r->size) && ParamTraits::Read(m, iter, &r->weight) && ParamTraits::Read(m, iter, &r->italic) && ParamTraits::Read(m, iter, &r->small_caps) && ParamTraits::Read(m, iter, &r->letter_spacing) && ParamTraits::Read(m, iter, &r->word_spacing); } // static void ParamTraits::Log( const param_type& p, std::string* l) { } #endif // !defined(OS_NACL) && !defined(NACL_WIN64) // ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------ // static void ParamTraits::Write( Message* m, const param_type& p) { ParamTraits::Write(m, p.family); ParamTraits::Write(m, p.generic_family); ParamTraits::Write(m, p.style); ParamTraits::Write(m, p.weight); ParamTraits::Write(m, p.width); ParamTraits::Write(m, p.charset); } // static bool ParamTraits::Read( const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &r->family) && ParamTraits::Read(m, iter, &r->generic_family) && ParamTraits::Read(m, iter, &r->style) && ParamTraits::Read(m, iter, &r->weight) && ParamTraits::Read(m, iter, &r->width) && ParamTraits::Read(m, iter, &r->charset); } // static void ParamTraits::Log( const param_type& p, std::string* l) { } #if !defined(OS_NACL) && !defined(NACL_WIN64) // ppapi::PepperFilePath ------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { WriteParam(m, static_cast(p.domain())); WriteParam(m, p.path()); } // static bool ParamTraits::Read(const Message* m, 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(domain), path); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); LogParam(static_cast(p.domain()), l); l->append(", "); LogParam(p.path(), l); l->append(")"); } // SerializedFlashMenu --------------------------------------------------------- // static void ParamTraits::Write( Message* m, const param_type& p) { p.WriteToMessage(m); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { return r->ReadFromMessage(m, iter); } // static void ParamTraits::Log(const param_type& p, std::string* l) { } #endif // !defined(OS_NACL) && !defined(NACL_WIN64) // PPB_X509Certificate_Fields -------------------------------------------------- // static void ParamTraits::Write( Message* m, const param_type& p) { ParamTraits::Write(m, p.values_); } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { return ParamTraits::Read(m, iter, &(r->values_)); } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // ppapi::SocketOptionData ----------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { ppapi::SocketOptionData::Type type = p.GetType(); ParamTraits::Write(m, static_cast(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(result); DCHECK(result); ParamTraits::Write(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(result); DCHECK(result); ParamTraits::Write(m, out_value); break; } // No default so the compiler will warn on new types. } } // static bool ParamTraits::Read(const Message* m, PickleIterator* iter, param_type* r) { *r = ppapi::SocketOptionData(); int32_t type = 0; if (!ParamTraits::Read(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(type)) { case ppapi::SocketOptionData::TYPE_INVALID: { return true; } case ppapi::SocketOptionData::TYPE_BOOL: { bool value = false; if (!ParamTraits::Read(m, iter, &value)) return false; r->SetBool(value); return true; } case ppapi::SocketOptionData::TYPE_INT32: { int32_t value = 0; if (!ParamTraits::Read(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::Log(const param_type& p, std::string* l) { } } // namespace IPC