// 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/proxy/ppapi_param_traits.h" #include // For memcpy #include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/private/ppb_flash_tcp_socket.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" 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, void** 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, void** 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_FileInfo ------------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, p.size); ParamTraits::Write(m, static_cast(p.type)); ParamTraits::Write(m, static_cast(p.system_type)); ParamTraits::Write(m, p.creation_time); ParamTraits::Write(m, p.last_access_time); ParamTraits::Write(m, p.last_modified_time); } // static bool ParamTraits::Read(const Message* m, void** iter, param_type* r) { int type, system_type; if (!ParamTraits::Read(m, iter, &r->size) || !ParamTraits::Read(m, iter, &type) || !ParamTraits::Read(m, iter, &system_type) || !ParamTraits::Read(m, iter, &r->creation_time) || !ParamTraits::Read(m, iter, &r->last_access_time) || !ParamTraits::Read(m, iter, &r->last_modified_time)) return false; if (type != PP_FILETYPE_REGULAR && type != PP_FILETYPE_DIRECTORY && type != PP_FILETYPE_OTHER) return false; r->type = static_cast(type); if (system_type != PP_FILESYSTEMTYPE_INVALID && system_type != PP_FILESYSTEMTYPE_EXTERNAL && system_type != PP_FILESYSTEMTYPE_LOCALPERSISTENT && system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY) return false; r->system_type = static_cast(system_type); 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, void** 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)>"); } // PP_ObjectProperty ----------------------------------------------------------- // static void ParamTraits::Write(Message* m, const param_type& p) { // FIXME(brettw); } // static bool ParamTraits::Read(const Message* m, void** iter, param_type* r) { // FIXME(brettw); return true; } // static void ParamTraits::Log(const param_type& p, std::string* l) { } // 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, void** 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) { } // PPB_FileRef_CreateInfo ------------------------------------------------------ // static void ParamTraits::Write(Message* m, const param_type& p) { ParamTraits::Write(m, p.resource); ParamTraits::Write(m, p.file_system_type); ParamTraits::Write(m, p.path); ParamTraits::Write(m, p.name); } // static bool ParamTraits::Read(const Message* m, void** iter, param_type* r) { return ParamTraits::Read(m, iter, &r->resource) && ParamTraits::Read(m, iter, &r->file_system_type) && ParamTraits::Read(m, iter, &r->path) && ParamTraits::Read(m, iter, &r->name); } // 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, void** 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) { } // 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, void** 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, void** 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) { } // 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, void** 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, void** 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, void** iter, param_type* r) { return ReadVectorWithoutCopy(m, iter, r); } // static void ParamTraits< std::vector >::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, void** iter, param_type* r) { return ReadVectorWithoutCopy(m, iter, r); } // static void ParamTraits< std::vector >::Log( const param_type& p, std::string* l) { } // SerializedFlashMenu --------------------------------------------------------- // static void ParamTraits::Write( Message* m, const param_type& p) { p.WriteToMessage(m); } // static bool ParamTraits::Read(const Message* m, void** iter, param_type* r) { return r->ReadFromMessage(m, iter); } // static void ParamTraits::Log(const param_type& p, std::string* l) { } } // namespace IPC