Bumping manifests a=b2g-bump
[gecko.git] / ipc / glue / IPCMessageUtils.h
blobbd3c69e45ba9dde66ec30162a75ccb00f68c3869
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et 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/. */
7 #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
8 #define __IPC_GLUE_IPCMESSAGEUTILS_H__
10 #include "base/process_util.h"
11 #include "chrome/common/ipc_message_utils.h"
13 #include "mozilla/ArrayUtils.h"
14 #include "mozilla/TimeStamp.h"
15 #ifdef XP_WIN
16 #include "mozilla/TimeStamp_windows.h"
17 #endif
18 #include "mozilla/TypedEnum.h"
19 #include "mozilla/IntegerTypeTraits.h"
21 #include <stdint.h>
23 #include "nsID.h"
24 #include "nsMemory.h"
25 #include "nsString.h"
26 #include "nsTArray.h"
27 #include "js/StructuredClone.h"
28 #include "nsCSSProperty.h"
30 #ifdef _MSC_VER
31 #pragma warning( disable : 4800 )
32 #endif
34 #if !defined(OS_POSIX)
35 // This condition must be kept in sync with the one in
36 // ipc_message_utils.h, but this dummy definition of
37 // base::FileDescriptor acts as a static assert that we only get one
38 // def or the other (or neither, in which case code using
39 // FileDescriptor fails to build)
40 namespace base { struct FileDescriptor { }; }
41 #endif
43 namespace mozilla {
45 // This is a cross-platform approximation to HANDLE, which we expect
46 // to be typedef'd to void* or thereabouts.
47 typedef uintptr_t WindowsHandle;
49 // XXX there are out of place and might be generally useful. Could
50 // move to nscore.h or something.
51 struct void_t {
52 bool operator==(const void_t&) const { return true; }
54 struct null_t {
55 bool operator==(const null_t&) const { return true; }
58 struct SerializedStructuredCloneBuffer
60 SerializedStructuredCloneBuffer()
61 : data(nullptr), dataLength(0)
62 { }
64 explicit SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther)
66 *this = aOther;
69 bool
70 operator==(const SerializedStructuredCloneBuffer& aOther) const
72 return this->data == aOther.data &&
73 this->dataLength == aOther.dataLength;
76 SerializedStructuredCloneBuffer&
77 operator=(const JSAutoStructuredCloneBuffer& aOther)
79 data = aOther.data();
80 dataLength = aOther.nbytes();
81 return *this;
84 uint64_t* data;
85 size_t dataLength;
88 } // namespace mozilla
90 namespace IPC {
92 /**
93 * Generic enum serializer.
95 * Consider using the specializations below, such as ContiguousEnumSerializer.
97 * This is a generic serializer for any enum type used in IPDL.
98 * Programmers can define ParamTraits<E> for enum type E by deriving
99 * EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
100 * that has to define a static IsLegalValue function returning whether
101 * a given value is a legal value of the enum type at hand.
103 * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
105 template <typename E, typename EnumValidator>
106 struct EnumSerializer {
107 typedef E paramType;
108 typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type
109 uintParamType;
111 static void Write(Message* aMsg, const paramType& aValue) {
112 MOZ_ASSERT(EnumValidator::IsLegalValue(aValue));
113 WriteParam(aMsg, uintParamType(aValue));
116 static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
117 uintParamType value;
118 if(!ReadParam(aMsg, aIter, &value) ||
119 !EnumValidator::IsLegalValue(paramType(value))) {
120 return false;
122 *aResult = paramType(value);
123 return true;
127 template <typename E,
128 E MinLegal,
129 E HighBound>
130 struct ContiguousEnumValidator
132 static bool IsLegalValue(E e)
134 return MinLegal <= e && e < HighBound;
138 template <typename E,
139 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal,
140 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound>
141 class ContiguousTypedEnumValidator
143 // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
144 // "comparison of unsigned expression >= 0 is always true"
145 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
146 template <typename T>
147 static bool IsLessThanOrEqual(T a, T b) { return a <= b; }
149 public:
150 static bool IsLegalValue(E e)
152 typedef MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) ActualEnumType;
153 return IsLessThanOrEqual(MinLegal, ActualEnumType(e)) &&
154 ActualEnumType(e) < HighBound;
158 template <typename E,
159 E AllBits>
160 struct BitFlagsEnumValidator
162 static bool IsLegalValue(E e)
164 return (e & AllBits) == e;
168 template <typename E,
169 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits>
170 struct BitFlagsTypedEnumValidator
172 static bool IsLegalValue(E e)
174 return (e & AllBits) == e;
179 * Specialization of EnumSerializer for enums with contiguous enum values.
181 * Provide two values: MinLegal, HighBound. An enum value x will be
182 * considered legal if MinLegal <= x < HighBound.
184 * For example, following is definition of serializer for enum type FOO.
185 * \code
186 * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
188 * template <>
189 * struct ParamTraits<FOO>:
190 * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
191 * \endcode
192 * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
194 template <typename E,
195 E MinLegal,
196 E HighBound>
197 struct ContiguousEnumSerializer
198 : EnumSerializer<E,
199 ContiguousEnumValidator<E, MinLegal, HighBound>>
203 * Similar to ContiguousEnumSerializer, but for MFBT typed enums
204 * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when
205 * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly.
207 template <typename E,
208 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) MinLegal,
209 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) HighBound>
210 struct ContiguousTypedEnumSerializer
211 : EnumSerializer<E,
212 ContiguousTypedEnumValidator<E, MinLegal, HighBound>>
216 * Specialization of EnumSerializer for enums representing bit flags.
218 * Provide one value: AllBits. An enum value x will be
219 * considered legal if (x & AllBits) == x;
221 * Example:
222 * \code
223 * enum FOO {
224 * FOO_FIRST = 1 << 0,
225 * FOO_SECOND = 1 << 1,
226 * FOO_LAST = 1 << 2,
227 * ALL_BITS = (1 << 3) - 1
228 * };
230 * template <>
231 * struct ParamTraits<FOO>:
232 * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
233 * \endcode
235 template <typename E,
236 E AllBits>
237 struct BitFlagsEnumSerializer
238 : EnumSerializer<E,
239 BitFlagsEnumValidator<E, AllBits>>
243 * Similar to BitFlagsEnumSerializer, but for MFBT typed enums
244 * as constructed by MOZ_BEGIN_ENUM_CLASS. This can go away when
245 * we drop MOZ_BEGIN_ENUM_CLASS and use C++11 enum classes directly.
247 template <typename E,
248 MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(E) AllBits>
249 struct BitFlagsTypedEnumSerializer
250 : EnumSerializer<E,
251 BitFlagsTypedEnumValidator<E, AllBits>>
254 template <>
255 struct ParamTraits<base::ChildPrivileges>
256 : public ContiguousEnumSerializer<base::ChildPrivileges,
257 base::PRIVILEGES_DEFAULT,
258 base::PRIVILEGES_LAST>
259 { };
261 template<>
262 struct ParamTraits<int8_t>
264 typedef int8_t paramType;
266 static void Write(Message* aMsg, const paramType& aParam)
268 aMsg->WriteBytes(&aParam, sizeof(aParam));
271 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
273 const char* outp;
274 if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult)))
275 return false;
277 *aResult = *reinterpret_cast<const paramType*>(outp);
278 return true;
282 template<>
283 struct ParamTraits<uint8_t>
285 typedef uint8_t paramType;
287 static void Write(Message* aMsg, const paramType& aParam)
289 aMsg->WriteBytes(&aParam, sizeof(aParam));
292 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
294 const char* outp;
295 if (!aMsg->ReadBytes(aIter, &outp, sizeof(*aResult)))
296 return false;
298 *aResult = *reinterpret_cast<const paramType*>(outp);
299 return true;
303 #if !defined(OS_POSIX)
304 // See above re: keeping definitions in sync
305 template<>
306 struct ParamTraits<base::FileDescriptor>
308 typedef base::FileDescriptor paramType;
309 static void Write(Message* aMsg, const paramType& aParam) {
310 NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform");
312 static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
313 NS_RUNTIMEABORT("FileDescriptor isn't meaningful on this platform");
314 return false;
317 #endif // !defined(OS_POSIX)
319 template <>
320 struct ParamTraits<nsACString>
322 typedef nsACString paramType;
324 static void Write(Message* aMsg, const paramType& aParam)
326 bool isVoid = aParam.IsVoid();
327 aMsg->WriteBool(isVoid);
329 if (isVoid)
330 // represents a nullptr pointer
331 return;
333 uint32_t length = aParam.Length();
334 WriteParam(aMsg, length);
335 aMsg->WriteBytes(aParam.BeginReading(), length);
338 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
340 bool isVoid;
341 if (!aMsg->ReadBool(aIter, &isVoid))
342 return false;
344 if (isVoid) {
345 aResult->SetIsVoid(true);
346 return true;
349 uint32_t length;
350 if (ReadParam(aMsg, aIter, &length)) {
351 const char* buf;
352 if (aMsg->ReadBytes(aIter, &buf, length)) {
353 aResult->Assign(buf, length);
354 return true;
357 return false;
360 static void Log(const paramType& aParam, std::wstring* aLog)
362 if (aParam.IsVoid())
363 aLog->append(L"(NULL)");
364 else
365 aLog->append(UTF8ToWide(aParam.BeginReading()));
369 template <>
370 struct ParamTraits<nsAString>
372 typedef nsAString paramType;
374 static void Write(Message* aMsg, const paramType& aParam)
376 bool isVoid = aParam.IsVoid();
377 aMsg->WriteBool(isVoid);
379 if (isVoid)
380 // represents a nullptr pointer
381 return;
383 uint32_t length = aParam.Length();
384 WriteParam(aMsg, length);
385 aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t));
388 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
390 bool isVoid;
391 if (!aMsg->ReadBool(aIter, &isVoid))
392 return false;
394 if (isVoid) {
395 aResult->SetIsVoid(true);
396 return true;
399 uint32_t length;
400 if (ReadParam(aMsg, aIter, &length)) {
401 const char16_t* buf;
402 if (aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(&buf),
403 length * sizeof(char16_t))) {
404 aResult->Assign(buf, length);
405 return true;
408 return false;
411 static void Log(const paramType& aParam, std::wstring* aLog)
413 if (aParam.IsVoid())
414 aLog->append(L"(NULL)");
415 else {
416 #ifdef WCHAR_T_IS_UTF16
417 aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading()));
418 #else
419 uint32_t length = aParam.Length();
420 for (uint32_t index = 0; index < length; index++) {
421 aLog->push_back(std::wstring::value_type(aParam[index]));
423 #endif
428 template <>
429 struct ParamTraits<nsCString> : ParamTraits<nsACString>
431 typedef nsCString paramType;
434 template <>
435 struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString>
437 typedef nsLiteralCString paramType;
440 #ifdef MOZILLA_INTERNAL_API
442 template<>
443 struct ParamTraits<nsAutoCString> : ParamTraits<nsCString>
445 typedef nsAutoCString paramType;
448 #endif // MOZILLA_INTERNAL_API
450 template <>
451 struct ParamTraits<nsString> : ParamTraits<nsAString>
453 typedef nsString paramType;
456 template <>
457 struct ParamTraits<nsLiteralString> : ParamTraits<nsAString>
459 typedef nsLiteralString paramType;
462 template <typename E>
463 struct ParamTraits<FallibleTArray<E> >
465 typedef FallibleTArray<E> paramType;
467 static void Write(Message* aMsg, const paramType& aParam)
469 uint32_t length = aParam.Length();
470 WriteParam(aMsg, length);
471 for (uint32_t index = 0; index < length; index++) {
472 WriteParam(aMsg, aParam[index]);
476 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
478 uint32_t length;
479 if (!ReadParam(aMsg, aIter, &length)) {
480 return false;
483 aResult->SetCapacity(length);
484 for (uint32_t index = 0; index < length; index++) {
485 E* element = aResult->AppendElement();
486 if (!(element && ReadParam(aMsg, aIter, element))) {
487 return false;
491 return true;
494 static void Log(const paramType& aParam, std::wstring* aLog)
496 for (uint32_t index = 0; index < aParam.Length(); index++) {
497 if (index) {
498 aLog->append(L" ");
500 LogParam(aParam[index], aLog);
505 template<typename E>
506 struct ParamTraits<InfallibleTArray<E> >
508 typedef InfallibleTArray<E> paramType;
510 static void Write(Message* aMsg, const paramType& aParam)
512 WriteParam(aMsg, static_cast<const FallibleTArray<E>&>(aParam));
515 // deserialize the array fallibly, but return an InfallibleTArray
516 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
518 FallibleTArray<E> temp;
519 if (!ReadParam(aMsg, aIter, &temp))
520 return false;
522 aResult->SwapElements(temp);
523 return true;
526 static void Log(const paramType& aParam, std::wstring* aLog)
528 LogParam(static_cast<const FallibleTArray<E>&>(aParam), aLog);
532 template<>
533 struct ParamTraits<float>
535 typedef float paramType;
537 static void Write(Message* aMsg, const paramType& aParam)
539 aMsg->WriteBytes(&aParam, sizeof(paramType));
542 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
544 const char* outFloat;
545 if (!aMsg->ReadBytes(aIter, &outFloat, sizeof(float)))
546 return false;
547 *aResult = *reinterpret_cast<const float*>(outFloat);
548 return true;
551 static void Log(const paramType& aParam, std::wstring* aLog)
553 aLog->append(StringPrintf(L"%g", aParam));
557 template <>
558 struct ParamTraits<nsCSSProperty>
559 : public ContiguousEnumSerializer<nsCSSProperty,
560 eCSSProperty_UNKNOWN,
561 eCSSProperty_COUNT>
564 template<>
565 struct ParamTraits<mozilla::void_t>
567 typedef mozilla::void_t paramType;
568 static void Write(Message* aMsg, const paramType& aParam) { }
569 static bool
570 Read(const Message* aMsg, void** aIter, paramType* aResult)
572 *aResult = paramType();
573 return true;
577 template<>
578 struct ParamTraits<mozilla::null_t>
580 typedef mozilla::null_t paramType;
581 static void Write(Message* aMsg, const paramType& aParam) { }
582 static bool
583 Read(const Message* aMsg, void** aIter, paramType* aResult)
585 *aResult = paramType();
586 return true;
590 template<>
591 struct ParamTraits<nsID>
593 typedef nsID paramType;
595 static void Write(Message* aMsg, const paramType& aParam)
597 WriteParam(aMsg, aParam.m0);
598 WriteParam(aMsg, aParam.m1);
599 WriteParam(aMsg, aParam.m2);
600 for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) {
601 WriteParam(aMsg, aParam.m3[i]);
605 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
607 if(!ReadParam(aMsg, aIter, &(aResult->m0)) ||
608 !ReadParam(aMsg, aIter, &(aResult->m1)) ||
609 !ReadParam(aMsg, aIter, &(aResult->m2)))
610 return false;
612 for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++)
613 if (!ReadParam(aMsg, aIter, &(aResult->m3[i])))
614 return false;
616 return true;
619 static void Log(const paramType& aParam, std::wstring* aLog)
621 aLog->append(L"{");
622 aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-",
623 aParam.m0,
624 aParam.m1,
625 aParam.m2));
626 for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++)
627 aLog->append(StringPrintf(L"%2.2X", aParam.m3[i]));
628 aLog->append(L"}");
632 template<>
633 struct ParamTraits<mozilla::TimeDuration>
635 typedef mozilla::TimeDuration paramType;
636 static void Write(Message* aMsg, const paramType& aParam)
638 WriteParam(aMsg, aParam.mValue);
640 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
642 return ReadParam(aMsg, aIter, &aResult->mValue);
646 template<>
647 struct ParamTraits<mozilla::TimeStamp>
649 typedef mozilla::TimeStamp paramType;
650 static void Write(Message* aMsg, const paramType& aParam)
652 WriteParam(aMsg, aParam.mValue);
654 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
656 return ReadParam(aMsg, aIter, &aResult->mValue);
660 #ifdef XP_WIN
662 template<>
663 struct ParamTraits<mozilla::TimeStampValue>
665 typedef mozilla::TimeStampValue paramType;
666 static void Write(Message* aMsg, const paramType& aParam)
668 WriteParam(aMsg, aParam.mGTC);
669 WriteParam(aMsg, aParam.mQPC);
670 WriteParam(aMsg, aParam.mHasQPC);
671 WriteParam(aMsg, aParam.mIsNull);
673 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
675 return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
676 ReadParam(aMsg, aIter, &aResult->mQPC) &&
677 ReadParam(aMsg, aIter, &aResult->mHasQPC) &&
678 ReadParam(aMsg, aIter, &aResult->mIsNull));
682 #endif
684 template <>
685 struct ParamTraits<mozilla::SerializedStructuredCloneBuffer>
687 typedef mozilla::SerializedStructuredCloneBuffer paramType;
689 static void Write(Message* aMsg, const paramType& aParam)
691 WriteParam(aMsg, aParam.dataLength);
692 if (aParam.dataLength) {
693 // Structured clone data must be 64-bit aligned.
694 aMsg->WriteBytes(aParam.data, aParam.dataLength, sizeof(uint64_t));
698 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
700 if (!ReadParam(aMsg, aIter, &aResult->dataLength)) {
701 return false;
704 if (aResult->dataLength) {
705 const char** buffer =
706 const_cast<const char**>(reinterpret_cast<char**>(&aResult->data));
707 // Structured clone data must be 64-bit aligned.
708 if (!aMsg->ReadBytes(aIter, buffer, aResult->dataLength,
709 sizeof(uint64_t))) {
710 return false;
712 } else {
713 aResult->data = nullptr;
716 return true;
719 static void Log(const paramType& aParam, std::wstring* aLog)
721 LogParam(aParam.dataLength, aLog);
725 } /* namespace IPC */
727 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */