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"
16 #include "mozilla/TimeStamp_windows.h"
18 #include "mozilla/TypedEnum.h"
19 #include "mozilla/IntegerTypeTraits.h"
27 #include "js/StructuredClone.h"
28 #include "nsCSSProperty.h"
31 #pragma warning( disable : 4800 )
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
{ }; }
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.
52 bool operator==(const void_t
&) const { return true; }
55 bool operator==(const null_t
&) const { return true; }
58 struct SerializedStructuredCloneBuffer
60 SerializedStructuredCloneBuffer()
61 : data(nullptr), dataLength(0)
64 explicit SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer
& aOther
)
70 operator==(const SerializedStructuredCloneBuffer
& aOther
) const
72 return this->data
== aOther
.data
&&
73 this->dataLength
== aOther
.dataLength
;
76 SerializedStructuredCloneBuffer
&
77 operator=(const JSAutoStructuredCloneBuffer
& aOther
)
80 dataLength
= aOther
.nbytes();
88 } // namespace mozilla
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
{
108 typedef typename
mozilla::UnsignedStdintTypeForSize
<sizeof(paramType
)>::Type
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
) {
118 if(!ReadParam(aMsg
, aIter
, &value
) ||
119 !EnumValidator::IsLegalValue(paramType(value
))) {
122 *aResult
= paramType(value
);
127 template <typename E
,
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
; }
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
,
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.
186 * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
189 * struct ParamTraits<FOO>:
190 * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
192 * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
194 template <typename E
,
197 struct ContiguousEnumSerializer
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
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;
224 * FOO_FIRST = 1 << 0,
225 * FOO_SECOND = 1 << 1,
227 * ALL_BITS = (1 << 3) - 1
231 * struct ParamTraits<FOO>:
232 * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
235 template <typename E
,
237 struct BitFlagsEnumSerializer
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
251 BitFlagsTypedEnumValidator
<E
, AllBits
>>
255 struct ParamTraits
<base::ChildPrivileges
>
256 : public ContiguousEnumSerializer
<base::ChildPrivileges
,
257 base::PRIVILEGES_DEFAULT
,
258 base::PRIVILEGES_LAST
>
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
)
274 if (!aMsg
->ReadBytes(aIter
, &outp
, sizeof(*aResult
)))
277 *aResult
= *reinterpret_cast<const paramType
*>(outp
);
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
)
295 if (!aMsg
->ReadBytes(aIter
, &outp
, sizeof(*aResult
)))
298 *aResult
= *reinterpret_cast<const paramType
*>(outp
);
303 #if !defined(OS_POSIX)
304 // See above re: keeping definitions in sync
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");
317 #endif // !defined(OS_POSIX)
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
);
330 // represents a nullptr pointer
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
)
341 if (!aMsg
->ReadBool(aIter
, &isVoid
))
345 aResult
->SetIsVoid(true);
350 if (ReadParam(aMsg
, aIter
, &length
)) {
352 if (aMsg
->ReadBytes(aIter
, &buf
, length
)) {
353 aResult
->Assign(buf
, length
);
360 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
363 aLog
->append(L
"(NULL)");
365 aLog
->append(UTF8ToWide(aParam
.BeginReading()));
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
);
380 // represents a nullptr pointer
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
)
391 if (!aMsg
->ReadBool(aIter
, &isVoid
))
395 aResult
->SetIsVoid(true);
400 if (ReadParam(aMsg
, aIter
, &length
)) {
402 if (aMsg
->ReadBytes(aIter
, reinterpret_cast<const char**>(&buf
),
403 length
* sizeof(char16_t
))) {
404 aResult
->Assign(buf
, length
);
411 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
414 aLog
->append(L
"(NULL)");
416 #ifdef WCHAR_T_IS_UTF16
417 aLog
->append(reinterpret_cast<const wchar_t*>(aParam
.BeginReading()));
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
]));
429 struct ParamTraits
<nsCString
> : ParamTraits
<nsACString
>
431 typedef nsCString paramType
;
435 struct ParamTraits
<nsLiteralCString
> : ParamTraits
<nsACString
>
437 typedef nsLiteralCString paramType
;
440 #ifdef MOZILLA_INTERNAL_API
443 struct ParamTraits
<nsAutoCString
> : ParamTraits
<nsCString
>
445 typedef nsAutoCString paramType
;
448 #endif // MOZILLA_INTERNAL_API
451 struct ParamTraits
<nsString
> : ParamTraits
<nsAString
>
453 typedef nsString paramType
;
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
)
479 if (!ReadParam(aMsg
, aIter
, &length
)) {
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
))) {
494 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
496 for (uint32_t index
= 0; index
< aParam
.Length(); index
++) {
500 LogParam(aParam
[index
], aLog
);
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
))
522 aResult
->SwapElements(temp
);
526 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
528 LogParam(static_cast<const FallibleTArray
<E
>&>(aParam
), aLog
);
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)))
547 *aResult
= *reinterpret_cast<const float*>(outFloat
);
551 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
553 aLog
->append(StringPrintf(L
"%g", aParam
));
558 struct ParamTraits
<nsCSSProperty
>
559 : public ContiguousEnumSerializer
<nsCSSProperty
,
560 eCSSProperty_UNKNOWN
,
565 struct ParamTraits
<mozilla::void_t
>
567 typedef mozilla::void_t paramType
;
568 static void Write(Message
* aMsg
, const paramType
& aParam
) { }
570 Read(const Message
* aMsg
, void** aIter
, paramType
* aResult
)
572 *aResult
= paramType();
578 struct ParamTraits
<mozilla::null_t
>
580 typedef mozilla::null_t paramType
;
581 static void Write(Message
* aMsg
, const paramType
& aParam
) { }
583 Read(const Message
* aMsg
, void** aIter
, paramType
* aResult
)
585 *aResult
= paramType();
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
)))
612 for (unsigned int i
= 0; i
< mozilla::ArrayLength(aResult
->m3
); i
++)
613 if (!ReadParam(aMsg
, aIter
, &(aResult
->m3
[i
])))
619 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
622 aLog
->append(StringPrintf(L
"%8.8X-%4.4X-%4.4X-",
626 for (unsigned int i
= 0; i
< mozilla::ArrayLength(aParam
.m3
); i
++)
627 aLog
->append(StringPrintf(L
"%2.2X", aParam
.m3
[i
]));
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
);
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
);
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
));
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
)) {
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
,
713 aResult
->data
= nullptr;
719 static void Log(const paramType
& aParam
, std::wstring
* aLog
)
721 LogParam(aParam
.dataLength
, aLog
);
725 } /* namespace IPC */
727 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */