• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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