IPCMessageUtils.h (8397B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__ 8 #define __IPC_GLUE_IPCMESSAGEUTILS_H__ 9 10 #include <cstdint> 11 #include "chrome/common/ipc_message.h" 12 #include "chrome/common/ipc_message_utils.h" 13 #include "mozilla/ipc/IPCCore.h" 14 #include "mozilla/MacroForEach.h" 15 16 class PickleIterator; 17 18 // XXX Things that are not necessary if moving implementations to the cpp file 19 #include "base/string_util.h" 20 21 #ifdef _MSC_VER 22 # pragma warning(disable : 4800) 23 #endif 24 25 #if !defined(XP_UNIX) 26 // This condition must be kept in sync with the one in 27 // ipc_message_utils.h, but this dummy definition of 28 // base::FileDescriptor acts as a static assert that we only get one 29 // def or the other (or neither, in which case code using 30 // FileDescriptor fails to build) 31 namespace base { 32 struct FileDescriptor {}; 33 } // namespace base 34 #endif 35 36 namespace mozilla { 37 template <typename...> 38 class Variant; 39 40 namespace detail { 41 template <typename...> 42 struct VariantTag; 43 } 44 } // namespace mozilla 45 46 namespace IPC { 47 48 /** 49 * A helper class for serializing empty structs. Since the struct is empty there 50 * is nothing to write, and a priori we know the result of the read. 51 */ 52 template <typename T> 53 struct EmptyStructSerializer { 54 typedef T paramType; 55 56 static void Write(MessageWriter* aWriter, const paramType& aParam) {} 57 58 static bool Read(MessageReader* aReader, paramType* aResult) { 59 *aResult = {}; 60 return true; 61 } 62 }; 63 64 template <> 65 struct ParamTraits<int8_t> { 66 typedef int8_t paramType; 67 68 static void Write(MessageWriter* aWriter, const paramType& aParam) { 69 aWriter->WriteBytes(&aParam, sizeof(aParam)); 70 } 71 72 static bool Read(MessageReader* aReader, paramType* aResult) { 73 return aReader->ReadBytesInto(aResult, sizeof(*aResult)); 74 } 75 }; 76 77 template <> 78 struct ParamTraits<uint8_t> { 79 typedef uint8_t paramType; 80 81 static void Write(MessageWriter* aWriter, const paramType& aParam) { 82 aWriter->WriteBytes(&aParam, sizeof(aParam)); 83 } 84 85 static bool Read(MessageReader* aReader, paramType* aResult) { 86 return aReader->ReadBytesInto(aResult, sizeof(*aResult)); 87 } 88 }; 89 90 #if !defined(XP_UNIX) 91 // See above re: keeping definitions in sync 92 template <> 93 struct ParamTraits<base::FileDescriptor> { 94 typedef base::FileDescriptor paramType; 95 static void Write(MessageWriter* aWriter, const paramType& aParam) { 96 MOZ_CRASH("FileDescriptor isn't meaningful on this platform"); 97 } 98 static bool Read(MessageReader* aReader, paramType* aResult) { 99 MOZ_CRASH("FileDescriptor isn't meaningful on this platform"); 100 return false; 101 } 102 }; 103 #endif // !defined(XP_UNIX) 104 105 template <> 106 struct ParamTraits<mozilla::void_t> { 107 typedef mozilla::void_t paramType; 108 static void Write(MessageWriter* aWriter, const paramType& aParam) {} 109 static bool Read(MessageReader* aReader, paramType* aResult) { 110 *aResult = paramType(); 111 return true; 112 } 113 }; 114 115 template <> 116 struct ParamTraits<mozilla::null_t> { 117 typedef mozilla::null_t paramType; 118 static void Write(MessageWriter* aWriter, const paramType& aParam) {} 119 static bool Read(MessageReader* aReader, paramType* aResult) { 120 *aResult = paramType(); 121 return true; 122 } 123 }; 124 125 // Helper class for reading bitfields. 126 // If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>. 127 template <typename ParamType> 128 struct BitfieldHelper { 129 // We need this helper because we can't get the address of a bitfield to 130 // pass directly to ReadParam. So instead we read it into a temporary bool 131 // and set the bitfield using a setter function 132 static bool ReadBoolForBitfield(MessageReader* aReader, ParamType* aResult, 133 void (ParamType::*aSetter)(bool)) { 134 bool value; 135 if (ReadParam(aReader, &value)) { 136 (aResult->*aSetter)(value); 137 return true; 138 } 139 return false; 140 } 141 }; 142 143 // A couple of recursive helper functions, allows syntax like: 144 // WriteParams(aMsg, aParam.foo, aParam.bar, aParam.baz) 145 // ReadParams(aMsg, aIter, aParam.foo, aParam.bar, aParam.baz) 146 147 template <typename... Ts> 148 static void WriteParams(MessageWriter* aWriter, const Ts&... aArgs) { 149 (WriteParam(aWriter, aArgs), ...); 150 } 151 152 template <typename... Ts> 153 static bool ReadParams(MessageReader* aReader, Ts&... aArgs) { 154 return (ReadParam(aReader, &aArgs) && ...); 155 } 156 157 // Macros that allow syntax like: 158 // DEFINE_IPC_SERIALIZER_WITH_FIELDS(SomeType, member1, member2, member3) 159 // Makes sure that serialize/deserialize code do the same members in the same 160 // order. 161 #define ACCESS_PARAM_FIELD(Field) aParam.Field 162 163 #define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \ 164 template <> \ 165 struct ParamTraits<Type> { \ 166 typedef Type paramType; \ 167 static void Write(MessageWriter* aWriter, const paramType& aParam) { \ 168 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \ 169 (), (__VA_ARGS__))); \ 170 } \ 171 \ 172 static bool Read(MessageReader* aReader, paramType* aResult) { \ 173 paramType& aParam = *aResult; \ 174 return ReadParams(aReader, \ 175 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \ 176 (__VA_ARGS__))); \ 177 } \ 178 }; 179 180 #define DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(Type) \ 181 template <> \ 182 struct ParamTraits<Type> : public EmptyStructSerializer<Type> {}; 183 184 } /* namespace IPC */ 185 186 #define DEFINE_IPC_SERIALIZER_WITH_SUPER_CLASS(Type, Super) \ 187 template <> \ 188 struct ParamTraits<Type> { \ 189 typedef Type paramType; \ 190 static void Write(MessageWriter* aWriter, const paramType& aParam) { \ 191 WriteParam(aWriter, static_cast<const Super&>(aParam)); \ 192 } \ 193 \ 194 static bool Read(MessageReader* aReader, paramType* aResult) { \ 195 return ReadParam(aReader, static_cast<Super*>(aResult)); \ 196 } \ 197 }; 198 199 #define DEFINE_IPC_SERIALIZER_WITH_SUPER_CLASS_AND_FIELDS(Type, Super, ...) \ 200 template <> \ 201 struct ParamTraits<Type> { \ 202 typedef Type paramType; \ 203 static void Write(MessageWriter* aWriter, const paramType& aParam) { \ 204 WriteParam(aWriter, static_cast<const Super&>(aParam)); \ 205 WriteParams(aWriter, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), \ 206 (), (__VA_ARGS__))); \ 207 } \ 208 \ 209 static bool Read(MessageReader* aReader, paramType* aResult) { \ 210 paramType& aParam = *aResult; \ 211 return ReadParam(aReader, static_cast<Super*>(aResult)) && \ 212 ReadParams(aReader, \ 213 MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \ 214 (__VA_ARGS__))); \ 215 } \ 216 }; 217 218 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */