1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <limits> 12 13 #include "base/logging.h" 14 #include "base/pickle.h" 15 #include "ipc/ipc_message.h" 16 #include "ipc/ipc_param_traits.h" 17 #include "mojo/public/cpp/bindings/bindings_export.h" 18 #include "mojo/public/cpp/bindings/lib/array_internal.h" 19 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 20 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" 21 #include "mojo/public/cpp/bindings/lib/serialization_util.h" 22 #include "mojo/public/interfaces/bindings/native_struct.mojom.h" 23 24 namespace mojo { 25 namespace internal { 26 27 // Base class for the templated native struct serialization interface below, 28 // used to consolidated some shared logic and provide a basic 29 // Serialize/Deserialize for [Native] mojom structs which do not have a 30 // registered typemap in the current configuration (i.e. structs that are 31 // represented by a raw native::NativeStruct mojom struct in C++ bindings.) 32 struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { 33 static void Serialize( 34 const native::NativeStructPtr& input, 35 Buffer* buffer, 36 native::internal::NativeStruct_Data::BufferWriter* writer, 37 SerializationContext* context); 38 39 static bool Deserialize(native::internal::NativeStruct_Data* input, 40 native::NativeStructPtr* output, 41 SerializationContext* context); 42 43 static void SerializeMessageContents( 44 IPC::Message* message, 45 Buffer* buffer, 46 native::internal::NativeStruct_Data::BufferWriter* writer, 47 SerializationContext* context); 48 49 static bool DeserializeMessageAttachments( 50 native::internal::NativeStruct_Data* data, 51 SerializationContext* context, 52 IPC::Message* message); 53 }; 54 55 template <typename MaybeConstUserType> 56 struct NativeStructSerializerImpl { 57 using UserType = typename std::remove_const<MaybeConstUserType>::type; 58 using Traits = IPC::ParamTraits<UserType>; 59 SerializeNativeStructSerializerImpl60 static void Serialize( 61 MaybeConstUserType& value, 62 Buffer* buffer, 63 native::internal::NativeStruct_Data::BufferWriter* writer, 64 SerializationContext* context) { 65 IPC::Message message; 66 Traits::Write(&message, value); 67 UnmappedNativeStructSerializerImpl::SerializeMessageContents( 68 &message, buffer, writer, context); 69 } 70 DeserializeNativeStructSerializerImpl71 static bool Deserialize(native::internal::NativeStruct_Data* data, 72 UserType* out, 73 SerializationContext* context) { 74 if (!data) 75 return false; 76 77 // Construct a temporary base::Pickle view over the array data. Note that 78 // the Array_Data is laid out like this: 79 // 80 // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] 81 // 82 // and base::Pickle expects to view data like this: 83 // 84 // [payload_size (4 bytes)] [header bytes ...] [payload...] 85 // 86 // Because ArrayHeader's num_bytes includes the length of the header and 87 // Pickle's payload_size does not, we need to adjust the stored value 88 // momentarily so Pickle can view the data. 89 ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data->data.Get()); 90 DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); 91 header->num_bytes -= sizeof(ArrayHeader); 92 93 { 94 // Construct a view over the full Array_Data, including our hacked up 95 // header. Pickle will infer from this that the header is 8 bytes long, 96 // and the payload will contain all of the pickled bytes. 97 IPC::Message message_view(reinterpret_cast<const char*>(header), 98 header->num_bytes + sizeof(ArrayHeader)); 99 base::PickleIterator iter(message_view); 100 if (!UnmappedNativeStructSerializerImpl::DeserializeMessageAttachments( 101 data, context, &message_view)) { 102 return false; 103 } 104 105 if (!Traits::Read(&message_view, &iter, out)) 106 return false; 107 } 108 109 // Return the header to its original state. 110 header->num_bytes += sizeof(ArrayHeader); 111 112 return true; 113 } 114 }; 115 116 template <> 117 struct NativeStructSerializerImpl<native::NativeStructPtr> 118 : public UnmappedNativeStructSerializerImpl {}; 119 120 template <> 121 struct NativeStructSerializerImpl<const native::NativeStructPtr> 122 : public UnmappedNativeStructSerializerImpl {}; 123 124 template <typename MaybeConstUserType> 125 struct Serializer<native::NativeStructDataView, MaybeConstUserType> 126 : public NativeStructSerializerImpl<MaybeConstUserType> {}; 127 128 } // namespace internal 129 } // namespace mojo 130 131 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ 132