Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set sw=2 ts=8 et tw=80 : */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__ |
michael@0 | 8 | #define __IPC_GLUE_IPCMESSAGEUTILS_H__ |
michael@0 | 9 | |
michael@0 | 10 | #include "base/process_util.h" |
michael@0 | 11 | #include "chrome/common/ipc_message_utils.h" |
michael@0 | 12 | |
michael@0 | 13 | #include "mozilla/ArrayUtils.h" |
michael@0 | 14 | #include "mozilla/TimeStamp.h" |
michael@0 | 15 | #ifdef XP_WIN |
michael@0 | 16 | #include "mozilla/TimeStamp_windows.h" |
michael@0 | 17 | #endif |
michael@0 | 18 | #include "mozilla/TypedEnum.h" |
michael@0 | 19 | #include "mozilla/IntegerTypeTraits.h" |
michael@0 | 20 | |
michael@0 | 21 | #include <stdint.h> |
michael@0 | 22 | |
michael@0 | 23 | #include "nsID.h" |
michael@0 | 24 | #include "nsMemory.h" |
michael@0 | 25 | #include "nsString.h" |
michael@0 | 26 | #include "nsTArray.h" |
michael@0 | 27 | #include "js/StructuredClone.h" |
michael@0 | 28 | #include "nsCSSProperty.h" |
michael@0 | 29 | |
michael@0 | 30 | #ifdef _MSC_VER |
michael@0 | 31 | #pragma warning( disable : 4800 ) |
michael@0 | 32 | #endif |
michael@0 | 33 | |
michael@0 | 34 | #if !defined(OS_POSIX) |
michael@0 | 35 | // This condition must be kept in sync with the one in |
michael@0 | 36 | // ipc_message_utils.h, but this dummy definition of |
michael@0 | 37 | // base::FileDescriptor acts as a static assert that we only get one |
michael@0 | 38 | // def or the other (or neither, in which case code using |
michael@0 | 39 | // FileDescriptor fails to build) |
michael@0 | 40 | namespace base { struct FileDescriptor { }; } |
michael@0 | 41 | #endif |
michael@0 | 42 | |
michael@0 | 43 | namespace mozilla { |
michael@0 | 44 | |
michael@0 | 45 | // This is a cross-platform approximation to HANDLE, which we expect |
michael@0 | 46 | // to be typedef'd to void* or thereabouts. |
michael@0 | 47 | typedef uintptr_t WindowsHandle; |
michael@0 | 48 | |
michael@0 | 49 | // XXX there are out of place and might be generally useful. Could |
michael@0 | 50 | // move to nscore.h or something. |
michael@0 | 51 | struct void_t { |
michael@0 | 52 | bool operator==(const void_t&) const { return true; } |
michael@0 | 53 | }; |
michael@0 | 54 | struct null_t { |
michael@0 | 55 | bool operator==(const null_t&) const { return true; } |
michael@0 | 56 | }; |
michael@0 | 57 | |
michael@0 | 58 | struct SerializedStructuredCloneBuffer |
michael@0 | 59 | { |
michael@0 | 60 | SerializedStructuredCloneBuffer() |
michael@0 | 61 | : data(nullptr), dataLength(0) |
michael@0 | 62 | { } |
michael@0 | 63 | |
michael@0 | 64 | SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther) |
michael@0 | 65 | { |
michael@0 | 66 | *this = aOther; |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | bool |
michael@0 | 70 | operator==(const SerializedStructuredCloneBuffer& aOther) const |
michael@0 | 71 | { |
michael@0 | 72 | return this->data == aOther.data && |
michael@0 | 73 | this->dataLength == aOther.dataLength; |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | SerializedStructuredCloneBuffer& |
michael@0 | 77 | operator=(const JSAutoStructuredCloneBuffer& aOther) |
michael@0 | 78 | { |
michael@0 | 79 | data = aOther.data(); |
michael@0 | 80 | dataLength = aOther.nbytes(); |
michael@0 | 81 | return *this; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | uint64_t* data; |
michael@0 | 85 | size_t dataLength; |
michael@0 | 86 | }; |
michael@0 | 87 | |
michael@0 | 88 | } // namespace mozilla |
michael@0 | 89 | |
michael@0 | 90 | namespace IPC { |
michael@0 | 91 | |
michael@0 | 92 | /** |
michael@0 | 93 | * Generic enum serializer. |
michael@0 | 94 | * |
michael@0 | 95 | * Consider using the specializations below, such as ContiguousEnumSerializer. |
michael@0 | 96 | * |
michael@0 | 97 | * This is a generic serializer for any enum type used in IPDL. |
michael@0 | 98 | * Programmers can define ParamTraits<E> for enum type E by deriving |
michael@0 | 99 | * EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct |
michael@0 | 100 | * that has to define a static IsLegalValue function returning whether |
michael@0 | 101 | * a given value is a legal value of the enum type at hand. |
michael@0 | 102 | * |
michael@0 | 103 | * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization |
michael@0 | 104 | */ |
michael@0 | 105 | template <typename E, typename EnumValidator> |
michael@0 | 106 | struct EnumSerializer { |
michael@0 | 107 | typedef E paramType; |
michael@0 | 108 | typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type |
michael@0 | 109 | uintParamType; |
michael@0 | 110 | |
michael@0 | 111 | static void Write(Message* aMsg, const paramType& aValue) { |
michael@0 | 112 | MOZ_ASSERT(EnumValidator::IsLegalValue(aValue)); |
michael@0 | 113 | WriteParam(aMsg, uintParamType(aValue)); |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { |
michael@0 | 117 | uintParamType value; |
michael@0 | 118 | if(!ReadParam(aMsg, aIter, &value) || |
michael@0 | 119 | !EnumValidator::IsLegalValue(paramType(value))) { |
michael@0 | 120 | return false; |
michael@0 | 121 | } |
michael@0 | 122 | *aResult = paramType(value); |
michael@0 | 123 | return true; |
michael@0 | 124 | } |
michael@0 | 125 | }; |
michael@0 | 126 | |
michael@0 | 127 | template <typename E, |
michael@0 | 128 | E MinLegal, |
michael@0 | 129 | E HighBound> |
michael@0 | 130 | struct ContiguousEnumValidator |
michael@0 | 131 | { |
michael@0 | 132 | static bool IsLegalValue(E e) |
michael@0 | 133 | { |
michael@0 | 134 | return MinLegal <= e && e < HighBound; |
michael@0 | 135 | } |
michael@0 | 136 | }; |
michael@0 | 137 | |
michael@0 | 138 | template <typename E, |
michael@0 | 139 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal, |
michael@0 | 140 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound> |
michael@0 | 141 | class ContiguousTypedEnumValidator |
michael@0 | 142 | { |
michael@0 | 143 | // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8: |
michael@0 | 144 | // "comparison of unsigned expression >= 0 is always true" |
michael@0 | 145 | // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856 |
michael@0 | 146 | template <typename T> |
michael@0 | 147 | static bool IsLessThanOrEqual(T a, T b) { return a <= b; } |
michael@0 | 148 | |
michael@0 | 149 | public: |
michael@0 | 150 | static bool IsLegalValue(E e) |
michael@0 | 151 | { |
michael@0 | 152 | typedef MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) ActualEnumType; |
michael@0 | 153 | return IsLessThanOrEqual(MinLegal, ActualEnumType(e)) && |
michael@0 | 154 | ActualEnumType(e) < HighBound; |
michael@0 | 155 | } |
michael@0 | 156 | }; |
michael@0 | 157 | |
michael@0 | 158 | template <typename E, |
michael@0 | 159 | E AllBits> |
michael@0 | 160 | struct BitFlagsEnumValidator |
michael@0 | 161 | { |
michael@0 | 162 | static bool IsLegalValue(E e) |
michael@0 | 163 | { |
michael@0 | 164 | return (e & AllBits) == e; |
michael@0 | 165 | } |
michael@0 | 166 | }; |
michael@0 | 167 | |
michael@0 | 168 | template <typename E, |
michael@0 | 169 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits> |
michael@0 | 170 | struct BitFlagsTypedEnumValidator |
michael@0 | 171 | { |
michael@0 | 172 | static bool IsLegalValue(E e) |
michael@0 | 173 | { |
michael@0 | 174 | return (e & AllBits) == e; |
michael@0 | 175 | } |
michael@0 | 176 | }; |
michael@0 | 177 | |
michael@0 | 178 | /** |
michael@0 | 179 | * Specialization of EnumSerializer for enums with contiguous enum values. |
michael@0 | 180 | * |
michael@0 | 181 | * Provide two values: MinLegal, HighBound. An enum value x will be |
michael@0 | 182 | * considered legal if MinLegal <= x < HighBound. |
michael@0 | 183 | * |
michael@0 | 184 | * For example, following is definition of serializer for enum type FOO. |
michael@0 | 185 | * \code |
michael@0 | 186 | * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO }; |
michael@0 | 187 | * |
michael@0 | 188 | * template <> |
michael@0 | 189 | * struct ParamTraits<FOO>: |
michael@0 | 190 | * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {}; |
michael@0 | 191 | * \endcode |
michael@0 | 192 | * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value. |
michael@0 | 193 | */ |
michael@0 | 194 | template <typename E, |
michael@0 | 195 | E MinLegal, |
michael@0 | 196 | E HighBound> |
michael@0 | 197 | struct ContiguousEnumSerializer |
michael@0 | 198 | : EnumSerializer<E, |
michael@0 | 199 | ContiguousEnumValidator<E, MinLegal, HighBound>> |
michael@0 | 200 | {}; |
michael@0 | 201 | |
michael@0 | 202 | /** |
michael@0 | 203 | * Similar to ContiguousEnumSerializer, but for MFBT typed enums |
michael@0 | 204 | * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when |
michael@0 | 205 | * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly. |
michael@0 | 206 | */ |
michael@0 | 207 | template <typename E, |
michael@0 | 208 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal, |
michael@0 | 209 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound> |
michael@0 | 210 | struct ContiguousTypedEnumSerializer |
michael@0 | 211 | : EnumSerializer<E, |
michael@0 | 212 | ContiguousTypedEnumValidator<E, MinLegal, HighBound>> |
michael@0 | 213 | {}; |
michael@0 | 214 | |
michael@0 | 215 | /** |
michael@0 | 216 | * Specialization of EnumSerializer for enums representing bit flags. |
michael@0 | 217 | * |
michael@0 | 218 | * Provide one value: AllBits. An enum value x will be |
michael@0 | 219 | * considered legal if (x & AllBits) == x; |
michael@0 | 220 | * |
michael@0 | 221 | * Example: |
michael@0 | 222 | * \code |
michael@0 | 223 | * enum FOO { |
michael@0 | 224 | * FOO_FIRST = 1 << 0, |
michael@0 | 225 | * FOO_SECOND = 1 << 1, |
michael@0 | 226 | * FOO_LAST = 1 << 2, |
michael@0 | 227 | * ALL_BITS = (1 << 3) - 1 |
michael@0 | 228 | * }; |
michael@0 | 229 | * |
michael@0 | 230 | * template <> |
michael@0 | 231 | * struct ParamTraits<FOO>: |
michael@0 | 232 | * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {}; |
michael@0 | 233 | * \endcode |
michael@0 | 234 | */ |
michael@0 | 235 | template <typename E, |
michael@0 | 236 | E AllBits> |
michael@0 | 237 | struct BitFlagsEnumSerializer |
michael@0 | 238 | : EnumSerializer<E, |
michael@0 | 239 | BitFlagsEnumValidator<E, AllBits>> |
michael@0 | 240 | {}; |
michael@0 | 241 | |
michael@0 | 242 | /** |
michael@0 | 243 | * Similar to BitFlagsEnumSerializer, but for MFBT typed enums |
michael@0 | 244 | * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when |
michael@0 | 245 | * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly. |
michael@0 | 246 | */ |
michael@0 | 247 | template <typename E, |
michael@0 | 248 | MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits> |
michael@0 | 249 | struct BitFlagsTypedEnumSerializer |
michael@0 | 250 | : EnumSerializer<E, |
michael@0 | 251 | BitFlagsTypedEnumValidator<E, AllBits>> |
michael@0 | 252 | {}; |
michael@0 | 253 | |
michael@0 | 254 | template <> |
michael@0 | 255 | struct ParamTraits<base::ChildPrivileges> |
michael@0 | 256 | : public ContiguousEnumSerializer<base::ChildPrivileges, |
michael@0 | 257 | base::PRIVILEGES_DEFAULT, |
michael@0 | 258 | base::PRIVILEGES_LAST> |
michael@0 | 259 | { }; |
michael@0 | 260 | |
michael@0 | 261 | template<> |
michael@0 | 262 | struct ParamTraits<int8_t> |
michael@0 | 263 | { |
michael@0 | 264 | typedef int8_t paramType; |
michael@0 | 265 | |
michael@0 | 266 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 267 | { |
michael@0 | 268 | aMsg->WriteBytes(&aParam, sizeof(aParam)); |
michael@0 | 269 | } |
michael@0 | 270 | |
michael@0 | 271 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 272 | { |
michael@0 | 273 | const char* outp; |
michael@0 | 274 | if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult))) |
michael@0 | 275 | return false; |
michael@0 | 276 | |
michael@0 | 277 | *aResult = *reinterpret_cast<const paramType*>(outp); |
michael@0 | 278 | return true; |
michael@0 | 279 | } |
michael@0 | 280 | }; |
michael@0 | 281 | |
michael@0 | 282 | template<> |
michael@0 | 283 | struct ParamTraits<uint8_t> |
michael@0 | 284 | { |
michael@0 | 285 | typedef uint8_t paramType; |
michael@0 | 286 | |
michael@0 | 287 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 288 | { |
michael@0 | 289 | aMsg->WriteBytes(&aParam, sizeof(aParam)); |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 293 | { |
michael@0 | 294 | const char* outp; |
michael@0 | 295 | if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult))) |
michael@0 | 296 | return false; |
michael@0 | 297 | |
michael@0 | 298 | *aResult = *reinterpret_cast<const paramType*>(outp); |
michael@0 | 299 | return true; |
michael@0 | 300 | } |
michael@0 | 301 | }; |
michael@0 | 302 | |
michael@0 | 303 | #if !defined(OS_POSIX) |
michael@0 | 304 | // See above re: keeping definitions in sync |
michael@0 | 305 | template<> |
michael@0 | 306 | struct ParamTraits<base::FileDescriptor> |
michael@0 | 307 | { |
michael@0 | 308 | typedef base::FileDescriptor paramType; |
michael@0 | 309 | static void Write(Message* aMsg, const paramType& aParam) { |
michael@0 | 310 | NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform"); |
michael@0 | 311 | } |
michael@0 | 312 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { |
michael@0 | 313 | NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform"); |
michael@0 | 314 | return false; |
michael@0 | 315 | } |
michael@0 | 316 | }; |
michael@0 | 317 | #endif // !defined(OS_POSIX) |
michael@0 | 318 | |
michael@0 | 319 | template <> |
michael@0 | 320 | struct ParamTraits<nsACString> |
michael@0 | 321 | { |
michael@0 | 322 | typedef nsACString paramType; |
michael@0 | 323 | |
michael@0 | 324 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 325 | { |
michael@0 | 326 | bool isVoid = aParam.IsVoid(); |
michael@0 | 327 | aMsg->WriteBool(isVoid); |
michael@0 | 328 | |
michael@0 | 329 | if (isVoid) |
michael@0 | 330 | // represents a nullptr pointer |
michael@0 | 331 | return; |
michael@0 | 332 | |
michael@0 | 333 | uint32_t length = aParam.Length(); |
michael@0 | 334 | WriteParam(aMsg, length); |
michael@0 | 335 | aMsg->WriteBytes(aParam.BeginReading(), length); |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 339 | { |
michael@0 | 340 | bool isVoid; |
michael@0 | 341 | if (!aMsg->ReadBool(aIter, &isVoid)) |
michael@0 | 342 | return false; |
michael@0 | 343 | |
michael@0 | 344 | if (isVoid) { |
michael@0 | 345 | aResult->SetIsVoid(true); |
michael@0 | 346 | return true; |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | uint32_t length; |
michael@0 | 350 | if (ReadParam(aMsg, aIter, &length)) { |
michael@0 | 351 | const char* buf; |
michael@0 | 352 | if (aMsg->ReadBytes(aIter, &buf, length)) { |
michael@0 | 353 | aResult->Assign(buf, length); |
michael@0 | 354 | return true; |
michael@0 | 355 | } |
michael@0 | 356 | } |
michael@0 | 357 | return false; |
michael@0 | 358 | } |
michael@0 | 359 | |
michael@0 | 360 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 361 | { |
michael@0 | 362 | if (aParam.IsVoid()) |
michael@0 | 363 | aLog->append(L"(NULL)"); |
michael@0 | 364 | else |
michael@0 | 365 | aLog->append(UTF8ToWide(aParam.BeginReading())); |
michael@0 | 366 | } |
michael@0 | 367 | }; |
michael@0 | 368 | |
michael@0 | 369 | template <> |
michael@0 | 370 | struct ParamTraits<nsAString> |
michael@0 | 371 | { |
michael@0 | 372 | typedef nsAString paramType; |
michael@0 | 373 | |
michael@0 | 374 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 375 | { |
michael@0 | 376 | bool isVoid = aParam.IsVoid(); |
michael@0 | 377 | aMsg->WriteBool(isVoid); |
michael@0 | 378 | |
michael@0 | 379 | if (isVoid) |
michael@0 | 380 | // represents a nullptr pointer |
michael@0 | 381 | return; |
michael@0 | 382 | |
michael@0 | 383 | uint32_t length = aParam.Length(); |
michael@0 | 384 | WriteParam(aMsg, length); |
michael@0 | 385 | aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t)); |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 389 | { |
michael@0 | 390 | bool isVoid; |
michael@0 | 391 | if (!aMsg->ReadBool(aIter, &isVoid)) |
michael@0 | 392 | return false; |
michael@0 | 393 | |
michael@0 | 394 | if (isVoid) { |
michael@0 | 395 | aResult->SetIsVoid(true); |
michael@0 | 396 | return true; |
michael@0 | 397 | } |
michael@0 | 398 | |
michael@0 | 399 | uint32_t length; |
michael@0 | 400 | if (ReadParam(aMsg, aIter, &length)) { |
michael@0 | 401 | const char16_t* buf; |
michael@0 | 402 | if (aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(&buf), |
michael@0 | 403 | length * sizeof(char16_t))) { |
michael@0 | 404 | aResult->Assign(buf, length); |
michael@0 | 405 | return true; |
michael@0 | 406 | } |
michael@0 | 407 | } |
michael@0 | 408 | return false; |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 412 | { |
michael@0 | 413 | if (aParam.IsVoid()) |
michael@0 | 414 | aLog->append(L"(NULL)"); |
michael@0 | 415 | else { |
michael@0 | 416 | #ifdef WCHAR_T_IS_UTF16 |
michael@0 | 417 | aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading())); |
michael@0 | 418 | #else |
michael@0 | 419 | uint32_t length = aParam.Length(); |
michael@0 | 420 | for (uint32_t index = 0; index < length; index++) { |
michael@0 | 421 | aLog->push_back(std::wstring::value_type(aParam[index])); |
michael@0 | 422 | } |
michael@0 | 423 | #endif |
michael@0 | 424 | } |
michael@0 | 425 | } |
michael@0 | 426 | }; |
michael@0 | 427 | |
michael@0 | 428 | template <> |
michael@0 | 429 | struct ParamTraits<nsCString> : ParamTraits<nsACString> |
michael@0 | 430 | { |
michael@0 | 431 | typedef nsCString paramType; |
michael@0 | 432 | }; |
michael@0 | 433 | |
michael@0 | 434 | template <> |
michael@0 | 435 | struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString> |
michael@0 | 436 | { |
michael@0 | 437 | typedef nsLiteralCString paramType; |
michael@0 | 438 | }; |
michael@0 | 439 | |
michael@0 | 440 | #ifdef MOZILLA_INTERNAL_API |
michael@0 | 441 | |
michael@0 | 442 | template<> |
michael@0 | 443 | struct ParamTraits<nsAutoCString> : ParamTraits<nsCString> |
michael@0 | 444 | { |
michael@0 | 445 | typedef nsAutoCString paramType; |
michael@0 | 446 | }; |
michael@0 | 447 | |
michael@0 | 448 | #endif // MOZILLA_INTERNAL_API |
michael@0 | 449 | |
michael@0 | 450 | template <> |
michael@0 | 451 | struct ParamTraits<nsString> : ParamTraits<nsAString> |
michael@0 | 452 | { |
michael@0 | 453 | typedef nsString paramType; |
michael@0 | 454 | }; |
michael@0 | 455 | |
michael@0 | 456 | template <> |
michael@0 | 457 | struct ParamTraits<nsLiteralString> : ParamTraits<nsAString> |
michael@0 | 458 | { |
michael@0 | 459 | typedef nsLiteralString paramType; |
michael@0 | 460 | }; |
michael@0 | 461 | |
michael@0 | 462 | template <typename E> |
michael@0 | 463 | struct ParamTraits<FallibleTArray<E> > |
michael@0 | 464 | { |
michael@0 | 465 | typedef FallibleTArray<E> paramType; |
michael@0 | 466 | |
michael@0 | 467 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 468 | { |
michael@0 | 469 | uint32_t length = aParam.Length(); |
michael@0 | 470 | WriteParam(aMsg, length); |
michael@0 | 471 | for (uint32_t index = 0; index < length; index++) { |
michael@0 | 472 | WriteParam(aMsg, aParam[index]); |
michael@0 | 473 | } |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 477 | { |
michael@0 | 478 | uint32_t length; |
michael@0 | 479 | if (!ReadParam(aMsg, aIter, &length)) { |
michael@0 | 480 | return false; |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | aResult->SetCapacity(length); |
michael@0 | 484 | for (uint32_t index = 0; index < length; index++) { |
michael@0 | 485 | E* element = aResult->AppendElement(); |
michael@0 | 486 | if (!(element && ReadParam(aMsg, aIter, element))) { |
michael@0 | 487 | return false; |
michael@0 | 488 | } |
michael@0 | 489 | } |
michael@0 | 490 | |
michael@0 | 491 | return true; |
michael@0 | 492 | } |
michael@0 | 493 | |
michael@0 | 494 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 495 | { |
michael@0 | 496 | for (uint32_t index = 0; index < aParam.Length(); index++) { |
michael@0 | 497 | if (index) { |
michael@0 | 498 | aLog->append(L" "); |
michael@0 | 499 | } |
michael@0 | 500 | LogParam(aParam[index], aLog); |
michael@0 | 501 | } |
michael@0 | 502 | } |
michael@0 | 503 | }; |
michael@0 | 504 | |
michael@0 | 505 | template<typename E> |
michael@0 | 506 | struct ParamTraits<InfallibleTArray<E> > |
michael@0 | 507 | { |
michael@0 | 508 | typedef InfallibleTArray<E> paramType; |
michael@0 | 509 | |
michael@0 | 510 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 511 | { |
michael@0 | 512 | WriteParam(aMsg, static_cast<const FallibleTArray<E>&>(aParam)); |
michael@0 | 513 | } |
michael@0 | 514 | |
michael@0 | 515 | // deserialize the array fallibly, but return an InfallibleTArray |
michael@0 | 516 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 517 | { |
michael@0 | 518 | FallibleTArray<E> temp; |
michael@0 | 519 | if (!ReadParam(aMsg, aIter, &temp)) |
michael@0 | 520 | return false; |
michael@0 | 521 | |
michael@0 | 522 | aResult->SwapElements(temp); |
michael@0 | 523 | return true; |
michael@0 | 524 | } |
michael@0 | 525 | |
michael@0 | 526 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 527 | { |
michael@0 | 528 | LogParam(static_cast<const FallibleTArray<E>&>(aParam), aLog); |
michael@0 | 529 | } |
michael@0 | 530 | }; |
michael@0 | 531 | |
michael@0 | 532 | template<> |
michael@0 | 533 | struct ParamTraits<float> |
michael@0 | 534 | { |
michael@0 | 535 | typedef float paramType; |
michael@0 | 536 | |
michael@0 | 537 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 538 | { |
michael@0 | 539 | aMsg->WriteBytes(&aParam, sizeof(paramType)); |
michael@0 | 540 | } |
michael@0 | 541 | |
michael@0 | 542 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 543 | { |
michael@0 | 544 | const char* outFloat; |
michael@0 | 545 | if (!aMsg->ReadBytes(aIter, &outFloat, sizeof(float))) |
michael@0 | 546 | return false; |
michael@0 | 547 | *aResult = *reinterpret_cast<const float*>(outFloat); |
michael@0 | 548 | return true; |
michael@0 | 549 | } |
michael@0 | 550 | |
michael@0 | 551 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 552 | { |
michael@0 | 553 | aLog->append(StringPrintf(L"%g", aParam)); |
michael@0 | 554 | } |
michael@0 | 555 | }; |
michael@0 | 556 | |
michael@0 | 557 | template <> |
michael@0 | 558 | struct ParamTraits<nsCSSProperty> |
michael@0 | 559 | : public ContiguousEnumSerializer<nsCSSProperty, |
michael@0 | 560 | eCSSProperty_UNKNOWN, |
michael@0 | 561 | eCSSProperty_COUNT> |
michael@0 | 562 | {}; |
michael@0 | 563 | |
michael@0 | 564 | template<> |
michael@0 | 565 | struct ParamTraits<mozilla::void_t> |
michael@0 | 566 | { |
michael@0 | 567 | typedef mozilla::void_t paramType; |
michael@0 | 568 | static void Write(Message* aMsg, const paramType& aParam) { } |
michael@0 | 569 | static bool |
michael@0 | 570 | Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 571 | { |
michael@0 | 572 | *aResult = paramType(); |
michael@0 | 573 | return true; |
michael@0 | 574 | } |
michael@0 | 575 | }; |
michael@0 | 576 | |
michael@0 | 577 | template<> |
michael@0 | 578 | struct ParamTraits<mozilla::null_t> |
michael@0 | 579 | { |
michael@0 | 580 | typedef mozilla::null_t paramType; |
michael@0 | 581 | static void Write(Message* aMsg, const paramType& aParam) { } |
michael@0 | 582 | static bool |
michael@0 | 583 | Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 584 | { |
michael@0 | 585 | *aResult = paramType(); |
michael@0 | 586 | return true; |
michael@0 | 587 | } |
michael@0 | 588 | }; |
michael@0 | 589 | |
michael@0 | 590 | template<> |
michael@0 | 591 | struct ParamTraits<nsID> |
michael@0 | 592 | { |
michael@0 | 593 | typedef nsID paramType; |
michael@0 | 594 | |
michael@0 | 595 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 596 | { |
michael@0 | 597 | WriteParam(aMsg, aParam.m0); |
michael@0 | 598 | WriteParam(aMsg, aParam.m1); |
michael@0 | 599 | WriteParam(aMsg, aParam.m2); |
michael@0 | 600 | for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) { |
michael@0 | 601 | WriteParam(aMsg, aParam.m3[i]); |
michael@0 | 602 | } |
michael@0 | 603 | } |
michael@0 | 604 | |
michael@0 | 605 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 606 | { |
michael@0 | 607 | if(!ReadParam(aMsg, aIter, &(aResult->m0)) || |
michael@0 | 608 | !ReadParam(aMsg, aIter, &(aResult->m1)) || |
michael@0 | 609 | !ReadParam(aMsg, aIter, &(aResult->m2))) |
michael@0 | 610 | return false; |
michael@0 | 611 | |
michael@0 | 612 | for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++) |
michael@0 | 613 | if (!ReadParam(aMsg, aIter, &(aResult->m3[i]))) |
michael@0 | 614 | return false; |
michael@0 | 615 | |
michael@0 | 616 | return true; |
michael@0 | 617 | } |
michael@0 | 618 | |
michael@0 | 619 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 620 | { |
michael@0 | 621 | aLog->append(L"{"); |
michael@0 | 622 | aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-", |
michael@0 | 623 | aParam.m0, |
michael@0 | 624 | aParam.m1, |
michael@0 | 625 | aParam.m2)); |
michael@0 | 626 | for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) |
michael@0 | 627 | aLog->append(StringPrintf(L"%2.2X", aParam.m3[i])); |
michael@0 | 628 | aLog->append(L"}"); |
michael@0 | 629 | } |
michael@0 | 630 | }; |
michael@0 | 631 | |
michael@0 | 632 | template<> |
michael@0 | 633 | struct ParamTraits<mozilla::TimeDuration> |
michael@0 | 634 | { |
michael@0 | 635 | typedef mozilla::TimeDuration paramType; |
michael@0 | 636 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 637 | { |
michael@0 | 638 | WriteParam(aMsg, aParam.mValue); |
michael@0 | 639 | } |
michael@0 | 640 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 641 | { |
michael@0 | 642 | return ReadParam(aMsg, aIter, &aResult->mValue); |
michael@0 | 643 | }; |
michael@0 | 644 | }; |
michael@0 | 645 | |
michael@0 | 646 | template<> |
michael@0 | 647 | struct ParamTraits<mozilla::TimeStamp> |
michael@0 | 648 | { |
michael@0 | 649 | typedef mozilla::TimeStamp paramType; |
michael@0 | 650 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 651 | { |
michael@0 | 652 | WriteParam(aMsg, aParam.mValue); |
michael@0 | 653 | } |
michael@0 | 654 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 655 | { |
michael@0 | 656 | return ReadParam(aMsg, aIter, &aResult->mValue); |
michael@0 | 657 | }; |
michael@0 | 658 | }; |
michael@0 | 659 | |
michael@0 | 660 | #ifdef XP_WIN |
michael@0 | 661 | |
michael@0 | 662 | template<> |
michael@0 | 663 | struct ParamTraits<mozilla::TimeStampValue> |
michael@0 | 664 | { |
michael@0 | 665 | typedef mozilla::TimeStampValue paramType; |
michael@0 | 666 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 667 | { |
michael@0 | 668 | WriteParam(aMsg, aParam.mGTC); |
michael@0 | 669 | WriteParam(aMsg, aParam.mQPC); |
michael@0 | 670 | WriteParam(aMsg, aParam.mHasQPC); |
michael@0 | 671 | WriteParam(aMsg, aParam.mIsNull); |
michael@0 | 672 | } |
michael@0 | 673 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 674 | { |
michael@0 | 675 | return (ReadParam(aMsg, aIter, &aResult->mGTC) && |
michael@0 | 676 | ReadParam(aMsg, aIter, &aResult->mQPC) && |
michael@0 | 677 | ReadParam(aMsg, aIter, &aResult->mHasQPC) && |
michael@0 | 678 | ReadParam(aMsg, aIter, &aResult->mIsNull)); |
michael@0 | 679 | } |
michael@0 | 680 | }; |
michael@0 | 681 | |
michael@0 | 682 | #endif |
michael@0 | 683 | |
michael@0 | 684 | template <> |
michael@0 | 685 | struct ParamTraits<mozilla::SerializedStructuredCloneBuffer> |
michael@0 | 686 | { |
michael@0 | 687 | typedef mozilla::SerializedStructuredCloneBuffer paramType; |
michael@0 | 688 | |
michael@0 | 689 | static void Write(Message* aMsg, const paramType& aParam) |
michael@0 | 690 | { |
michael@0 | 691 | WriteParam(aMsg, aParam.dataLength); |
michael@0 | 692 | if (aParam.dataLength) { |
michael@0 | 693 | // Structured clone data must be 64-bit aligned. |
michael@0 | 694 | aMsg->WriteBytes(aParam.data, aParam.dataLength, sizeof(uint64_t)); |
michael@0 | 695 | } |
michael@0 | 696 | } |
michael@0 | 697 | |
michael@0 | 698 | static bool Read(const Message* aMsg, void** aIter, paramType* aResult) |
michael@0 | 699 | { |
michael@0 | 700 | if (!ReadParam(aMsg, aIter, &aResult->dataLength)) { |
michael@0 | 701 | return false; |
michael@0 | 702 | } |
michael@0 | 703 | |
michael@0 | 704 | if (aResult->dataLength) { |
michael@0 | 705 | const char** buffer = |
michael@0 | 706 | const_cast<const char**>(reinterpret_cast<char**>(&aResult->data)); |
michael@0 | 707 | // Structured clone data must be 64-bit aligned. |
michael@0 | 708 | if (!aMsg->ReadBytes(aIter, buffer, aResult->dataLength, |
michael@0 | 709 | sizeof(uint64_t))) { |
michael@0 | 710 | return false; |
michael@0 | 711 | } |
michael@0 | 712 | } else { |
michael@0 | 713 | aResult->data = nullptr; |
michael@0 | 714 | } |
michael@0 | 715 | |
michael@0 | 716 | return true; |
michael@0 | 717 | } |
michael@0 | 718 | |
michael@0 | 719 | static void Log(const paramType& aParam, std::wstring* aLog) |
michael@0 | 720 | { |
michael@0 | 721 | LogParam(aParam.dataLength, aLog); |
michael@0 | 722 | } |
michael@0 | 723 | }; |
michael@0 | 724 | |
michael@0 | 725 | } /* namespace IPC */ |
michael@0 | 726 | |
michael@0 | 727 | #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */ |