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/. */
7 #ifndef __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__
8 #define __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__
14 #include <type_traits>
15 #include <unordered_map>
18 #include "chrome/common/ipc_message.h"
19 #include "chrome/common/ipc_message_utils.h"
20 #include "ipc/EnumSerializer.h"
21 #include "ipc/IPCMessageUtils.h"
22 #include "mozilla/Assertions.h"
23 #include "mozilla/BitSet.h"
24 #include "mozilla/EnumSet.h"
25 #include "mozilla/EnumTypeTraits.h"
26 #include "mozilla/IntegerRange.h"
27 #include "mozilla/Maybe.h"
28 #include "mozilla/TimeStamp.h"
30 # include "mozilla/TimeStamp_windows.h"
33 #include "mozilla/UniquePtr.h"
34 #include "mozilla/Unused.h"
35 #include "mozilla/Vector.h"
36 #include "mozilla/dom/ipc/StructuredCloneData.h"
37 #include "mozilla/dom/UserActivation.h"
38 #include "gfxPlatform.h"
39 #include "nsCSSPropertyID.h"
41 #include "nsIContentPolicy.h"
43 #include "nsILoadInfo.h"
44 #include "nsIThread.h"
45 #include "nsLiteralString.h"
46 #include "nsNetUtil.h"
49 #include "nsTHashSet.h"
51 // XXX Includes that are only required by implementations which could be moved
53 #include "base/string_util.h" // for StringPrintf
54 #include "mozilla/ArrayUtils.h" // for ArrayLength
55 #include "mozilla/CheckedInt.h"
58 # pragma warning(disable : 4800)
62 template <typename
... Ts
>
66 template <typename
... Ts
>
69 } // namespace mozilla
71 namespace mozilla::dom
{
81 struct ParamTraits
<nsTSubstring
<T
>> {
82 typedef nsTSubstring
<T
> paramType
;
84 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
85 bool isVoid
= aParam
.IsVoid();
86 aWriter
->WriteBool(isVoid
);
89 // represents a nullptr pointer
93 WriteSequenceParam
<const T
&>(aWriter
, aParam
.BeginReading(),
97 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
99 if (!aReader
->ReadBool(&isVoid
)) {
104 aResult
->SetIsVoid(true);
108 return ReadSequenceParam
<T
>(aReader
, [&](uint32_t aLength
) -> T
* {
110 aResult
->GetMutableData(&data
, aLength
);
117 struct ParamTraits
<nsTString
<T
>> : ParamTraits
<nsTSubstring
<T
>> {};
120 struct ParamTraits
<nsTLiteralString
<T
>> : ParamTraits
<nsTSubstring
<T
>> {};
122 template <class T
, size_t N
>
123 struct ParamTraits
<nsTAutoStringN
<T
, N
>> : ParamTraits
<nsTSubstring
<T
>> {};
126 struct ParamTraits
<nsTDependentString
<T
>> : ParamTraits
<nsTSubstring
<T
>> {};
128 // XXX While this has no special dependencies, it's currently only used in
129 // GfxMessageUtils and could be moved there, or generalized to potentially work
130 // with any nsTHashSet.
132 struct ParamTraits
<nsTHashSet
<uint64_t>> {
133 typedef nsTHashSet
<uint64_t> paramType
;
135 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
136 uint32_t count
= aParam
.Count();
137 WriteParam(aWriter
, count
);
138 for (const auto& key
: aParam
) {
139 WriteParam(aWriter
, key
);
143 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
145 if (!ReadParam(aReader
, &count
)) {
148 paramType
table(count
);
149 for (uint32_t i
= 0; i
< count
; ++i
) {
151 if (!ReadParam(aReader
, &key
)) {
156 *aResult
= std::move(table
);
161 template <typename E
>
162 struct ParamTraits
<nsTArray
<E
>> {
163 typedef nsTArray
<E
> paramType
;
165 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
166 WriteSequenceParam
<const E
&>(aWriter
, aParam
.Elements(), aParam
.Length());
169 static void Write(MessageWriter
* aWriter
, paramType
&& aParam
) {
170 WriteSequenceParam
<E
&&>(aWriter
, aParam
.Elements(), aParam
.Length());
173 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
174 return ReadSequenceParam
<E
>(aReader
, [&](uint32_t aLength
) {
175 if constexpr (std::is_trivially_default_constructible_v
<E
>) {
176 return aResult
->AppendElements(aLength
);
178 aResult
->SetCapacity(aLength
);
179 return mozilla::Some(MakeBackInserter(*aResult
));
185 template <typename E
>
186 struct ParamTraits
<CopyableTArray
<E
>> : ParamTraits
<nsTArray
<E
>> {};
188 template <typename E
>
189 struct ParamTraits
<FallibleTArray
<E
>> {
190 typedef FallibleTArray
<E
> paramType
;
192 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
193 WriteSequenceParam
<const E
&>(aWriter
, aParam
.Elements(), aParam
.Length());
196 static void Write(MessageWriter
* aWriter
, paramType
&& aParam
) {
197 WriteSequenceParam
<E
&&>(aWriter
, aParam
.Elements(), aParam
.Length());
200 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
201 return ReadSequenceParam
<E
>(aReader
, [&](uint32_t aLength
) {
202 if constexpr (std::is_trivially_default_constructible_v
<E
>) {
203 return aResult
->AppendElements(aLength
, mozilla::fallible
);
205 if (!aResult
->SetCapacity(aLength
, mozilla::fallible
)) {
206 return mozilla::Maybe
<BackInserter
>{};
208 return mozilla::Some(BackInserter
{.mArray
= aResult
});
214 struct BackInserter
{
215 using iterator_category
= std::output_iterator_tag
;
216 using value_type
= void;
217 using difference_type
= void;
218 using pointer
= void;
219 using reference
= void;
224 template <typename U
>
225 void operator=(U
&& aValue
) {
226 // This won't fail because we've reserved capacity earlier.
227 MOZ_ALWAYS_TRUE(mArray
.AppendElement(aValue
, mozilla::fallible
));
230 Proxy
operator*() { return Proxy
{.mArray
= *mArray
}; }
232 BackInserter
& operator++() { return *this; }
233 BackInserter
& operator++(int) { return *this; }
235 paramType
* mArray
= nullptr;
239 template <typename E
, size_t N
>
240 struct ParamTraits
<AutoTArray
<E
, N
>> : ParamTraits
<nsTArray
<E
>> {
241 typedef AutoTArray
<E
, N
> paramType
;
244 template <typename E
, size_t N
>
245 struct ParamTraits
<CopyableAutoTArray
<E
, N
>> : ParamTraits
<AutoTArray
<E
, N
>> {};
247 template <typename T
>
248 struct ParamTraits
<mozilla::dom::Sequence
<T
>> : ParamTraits
<FallibleTArray
<T
>> {
251 template <typename E
, size_t N
, typename AP
>
252 struct ParamTraits
<mozilla::Vector
<E
, N
, AP
>> {
253 typedef mozilla::Vector
<E
, N
, AP
> paramType
;
255 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
256 WriteSequenceParam
<const E
&>(aWriter
, aParam
.Elements(), aParam
.Length());
259 static void Write(MessageWriter
* aWriter
, paramType
&& aParam
) {
260 WriteSequenceParam
<E
&&>(aWriter
, aParam
.Elements(), aParam
.Length());
263 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
264 return ReadSequenceParam
<E
>(aReader
, [&](uint32_t aLength
) -> E
* {
265 if (!aResult
->resize(aLength
)) {
266 // So that OOM failure shows up as OOM crash instead of IPC FatalError.
267 NS_ABORT_OOM(aLength
* sizeof(E
));
269 return aResult
->begin();
274 template <typename E
>
275 struct ParamTraits
<std::vector
<E
>> {
276 typedef std::vector
<E
> paramType
;
278 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
279 WriteSequenceParam
<const E
&>(aWriter
, aParam
.data(), aParam
.size());
281 static void Write(MessageWriter
* aWriter
, paramType
&& aParam
) {
282 WriteSequenceParam
<E
&&>(aWriter
, aParam
.data(), aParam
.size());
285 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
286 return ReadSequenceParam
<E
>(aReader
, [&](uint32_t aLength
) {
287 if constexpr (std::is_trivially_default_constructible_v
<E
>) {
288 aResult
->resize(aLength
);
289 return aResult
->data();
291 aResult
->reserve(aLength
);
292 return mozilla::Some(std::back_inserter(*aResult
));
298 template <typename K
, typename V
>
299 struct ParamTraits
<std::unordered_map
<K
, V
>> final
{
300 using T
= std::unordered_map
<K
, V
>;
302 static void Write(MessageWriter
* const writer
, const T
& in
) {
303 WriteParam(writer
, in
.size());
304 for (const auto& pair
: in
) {
305 WriteParam(writer
, pair
.first
);
306 WriteParam(writer
, pair
.second
);
310 static bool Read(MessageReader
* const reader
, T
* const out
) {
312 if (!ReadParam(reader
, &size
)) return false;
315 for (const auto i
: mozilla::IntegerRange(size
)) {
316 std::pair
<K
, V
> pair
;
317 mozilla::Unused
<< i
;
318 if (!ReadParam(reader
, &(pair
.first
)) ||
319 !ReadParam(reader
, &(pair
.second
))) {
322 map
.insert(std::move(pair
));
324 *out
= std::move(map
);
330 struct ParamTraits
<float> {
331 typedef float paramType
;
333 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
334 aWriter
->WriteBytes(&aParam
, sizeof(paramType
));
337 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
338 return aReader
->ReadBytesInto(aResult
, sizeof(*aResult
));
343 struct ParamTraits
<nsCSSPropertyID
>
344 : public ContiguousEnumSerializer
<nsCSSPropertyID
, eCSSProperty_UNKNOWN
,
345 eCSSProperty_COUNT
> {};
348 struct ParamTraits
<nsID
> {
349 typedef nsID paramType
;
351 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
352 WriteParam(aWriter
, aParam
.m0
);
353 WriteParam(aWriter
, aParam
.m1
);
354 WriteParam(aWriter
, aParam
.m2
);
355 for (unsigned int i
= 0; i
< std::size(aParam
.m3
); i
++) {
356 WriteParam(aWriter
, aParam
.m3
[i
]);
360 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
361 if (!ReadParam(aReader
, &(aResult
->m0
)) ||
362 !ReadParam(aReader
, &(aResult
->m1
)) ||
363 !ReadParam(aReader
, &(aResult
->m2
)))
366 for (unsigned int i
= 0; i
< std::size(aResult
->m3
); i
++)
367 if (!ReadParam(aReader
, &(aResult
->m3
[i
]))) return false;
374 struct ParamTraits
<nsContentPolicyType
>
375 : public ContiguousEnumSerializer
<nsContentPolicyType
,
376 nsIContentPolicy::TYPE_INVALID
,
377 nsIContentPolicy::TYPE_END
> {};
380 struct ParamTraits
<mozilla::TimeDuration
> {
381 typedef mozilla::TimeDuration paramType
;
382 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
383 WriteParam(aWriter
, aParam
.mValue
);
385 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
386 return ReadParam(aReader
, &aResult
->mValue
);
391 struct ParamTraits
<mozilla::TimeStamp
> {
392 typedef mozilla::TimeStamp paramType
;
393 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
394 WriteParam(aWriter
, aParam
.mValue
);
396 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
397 return ReadParam(aReader
, &aResult
->mValue
);
404 struct ParamTraits
<mozilla::TimeStampValue
> {
405 typedef mozilla::TimeStampValue paramType
;
406 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
407 WriteParam(aWriter
, aParam
.mGTC
);
408 WriteParam(aWriter
, aParam
.mQPC
);
409 WriteParam(aWriter
, aParam
.mIsNull
);
410 WriteParam(aWriter
, aParam
.mHasQPC
);
412 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
413 return (ReadParam(aReader
, &aResult
->mGTC
) &&
414 ReadParam(aReader
, &aResult
->mQPC
) &&
415 ReadParam(aReader
, &aResult
->mIsNull
) &&
416 ReadParam(aReader
, &aResult
->mHasQPC
));
423 struct ParamTraits
<mozilla::dom::ipc::StructuredCloneData
> {
424 typedef mozilla::dom::ipc::StructuredCloneData paramType
;
426 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
427 aParam
.WriteIPCParams(aWriter
);
430 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
431 return aResult
->ReadIPCParams(aReader
);
436 struct ParamTraits
<mozilla::Maybe
<T
>> {
437 typedef mozilla::Maybe
<T
> paramType
;
439 static void Write(MessageWriter
* writer
, const paramType
& param
) {
440 if (param
.isSome()) {
441 WriteParam(writer
, true);
442 WriteParam(writer
, param
.ref());
444 WriteParam(writer
, false);
448 static void Write(MessageWriter
* writer
, paramType
&& param
) {
449 if (param
.isSome()) {
450 WriteParam(writer
, true);
451 WriteParam(writer
, std::move(param
.ref()));
453 WriteParam(writer
, false);
457 static bool Read(MessageReader
* reader
, paramType
* result
) {
459 if (!ReadParam(reader
, &isSome
)) {
463 mozilla::Maybe
<T
> tmp
= ReadParam
<T
>(reader
).TakeMaybe();
467 *result
= std::move(tmp
);
469 *result
= mozilla::Nothing();
475 template <typename T
, typename U
>
476 struct ParamTraits
<mozilla::EnumSet
<T
, U
>> {
477 typedef mozilla::EnumSet
<T
, U
> paramType
;
478 typedef U serializedType
;
480 static void Write(MessageWriter
* writer
, const paramType
& param
) {
481 MOZ_RELEASE_ASSERT(IsLegalValue(param
.serialize()));
482 WriteParam(writer
, param
.serialize());
485 static bool Read(MessageReader
* reader
, paramType
* result
) {
488 if (ReadParam(reader
, &tmp
)) {
489 if (IsLegalValue(tmp
)) {
490 result
->deserialize(tmp
);
498 static constexpr size_t kUnderlyingWidth
= [] {
499 if constexpr (std::numeric_limits
<serializedType
>::is_specialized
) {
500 return std::numeric_limits
<serializedType
>::digits
;
502 return serializedType().size(); // for std::bitset<N>
506 static constexpr serializedType
AllEnumBits() {
507 return ~serializedType(0) >>
508 (kUnderlyingWidth
- (mozilla::MaxEnumValue
<T
>::value
+ 1));
511 static constexpr bool IsLegalValue(const serializedType value
) {
512 static_assert(mozilla::MaxEnumValue
<T
>::value
< kUnderlyingWidth
,
513 "Enum max value is not in the range!");
515 std::is_unsigned
<decltype(mozilla::MaxEnumValue
<T
>::value
)>::value
,
516 "Type of MaxEnumValue<T>::value specialization should be unsigned!");
518 return (value
& AllEnumBits()) == value
;
522 template <class... Ts
>
523 struct ParamTraits
<mozilla::Variant
<Ts
...>> {
524 typedef mozilla::Variant
<Ts
...> paramType
;
525 using Tag
= typename
mozilla::detail::VariantTag
<Ts
...>::Type
;
527 static void Write(MessageWriter
* writer
, const paramType
& param
) {
528 WriteParam(writer
, param
.tag
);
529 param
.match([writer
](const auto& t
) { WriteParam(writer
, t
); });
532 // Because VariantReader is a nested struct, we need the dummy template
533 // parameter to avoid making VariantReader<0> an explicit specialization,
534 // which is not allowed for a nested class template
535 template <size_t N
, typename dummy
= void>
536 struct VariantReader
{
537 using Next
= VariantReader
<N
- 1>;
539 static bool Read(MessageReader
* reader
, Tag tag
, paramType
* result
) {
540 // Since the VariantReader specializations start at N , we need to
541 // subtract one to look at N - 1, the first valid tag. This means our
542 // comparisons are off by 1. If we get to N = 0 then we have failed to
543 // find a match to the tag.
545 // Recall, even though the template parameter is N, we are
546 // actually interested in the N - 1 tag.
547 // Default construct our field within the result outparameter and
548 // directly deserialize into the variant. Note that this means that
549 // every type in Ts needs to be default constructible
550 return ReadParam(reader
, &result
->template emplace
<N
- 1>());
552 return Next::Read(reader
, tag
, result
);
556 }; // VariantReader<N>
558 // Since we are conditioning on tag = N - 1 in the preceding specialization,
559 // if we get to `VariantReader<0, dummy>` we have failed to find
561 template <typename dummy
>
562 struct VariantReader
<0, dummy
> {
563 static bool Read(MessageReader
* reader
, Tag tag
, paramType
* result
) {
568 static bool Read(MessageReader
* reader
, paramType
* result
) {
570 if (ReadParam(reader
, &tag
)) {
571 return VariantReader
<sizeof...(Ts
)>::Read(reader
, tag
, result
);
577 template <typename T
>
578 struct ParamTraits
<mozilla::dom::Optional
<T
>> {
579 typedef mozilla::dom::Optional
<T
> paramType
;
581 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
582 if (aParam
.WasPassed()) {
583 WriteParam(aWriter
, true);
584 WriteParam(aWriter
, aParam
.Value());
588 WriteParam(aWriter
, false);
591 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
592 bool wasPassed
= false;
594 if (!ReadParam(aReader
, &wasPassed
)) {
601 if (!ReadParam(aReader
, &aResult
->Construct())) {
611 struct ParamTraits
<nsAtom
*> {
612 typedef nsAtom paramType
;
614 static void Write(MessageWriter
* aWriter
, const paramType
* aParam
);
615 static bool Read(MessageReader
* aReader
, RefPtr
<paramType
>* aResult
);
618 struct CrossOriginOpenerPolicyValidator
{
620 std::underlying_type_t
<nsILoadInfo::CrossOriginOpenerPolicy
>;
622 static bool IsLegalValue(const IntegralType e
) {
623 return AreIntegralValuesEqual(e
, nsILoadInfo::OPENER_POLICY_UNSAFE_NONE
) ||
624 AreIntegralValuesEqual(e
, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN
) ||
625 AreIntegralValuesEqual(
626 e
, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS
) ||
627 AreIntegralValuesEqual(
629 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP
);
633 static bool AreIntegralValuesEqual(
634 const IntegralType aLhs
,
635 const nsILoadInfo::CrossOriginOpenerPolicy aRhs
) {
636 return aLhs
== static_cast<IntegralType
>(aRhs
);
641 struct ParamTraits
<nsILoadInfo::CrossOriginOpenerPolicy
>
642 : EnumSerializer
<nsILoadInfo::CrossOriginOpenerPolicy
,
643 CrossOriginOpenerPolicyValidator
> {};
645 struct CrossOriginEmbedderPolicyValidator
{
647 std::underlying_type_t
<nsILoadInfo::CrossOriginEmbedderPolicy
>;
649 static bool IsLegalValue(const IntegralType e
) {
650 return AreIntegralValuesEqual(e
, nsILoadInfo::EMBEDDER_POLICY_NULL
) ||
651 AreIntegralValuesEqual(e
,
652 nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP
) ||
653 AreIntegralValuesEqual(e
,
654 nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS
);
658 static bool AreIntegralValuesEqual(
659 const IntegralType aLhs
,
660 const nsILoadInfo::CrossOriginEmbedderPolicy aRhs
) {
661 return aLhs
== static_cast<IntegralType
>(aRhs
);
666 struct ParamTraits
<nsILoadInfo::CrossOriginEmbedderPolicy
>
667 : EnumSerializer
<nsILoadInfo::CrossOriginEmbedderPolicy
,
668 CrossOriginEmbedderPolicyValidator
> {};
671 struct ParamTraits
<nsIThread::QoSPriority
>
672 : public ContiguousEnumSerializerInclusive
<nsIThread::QoSPriority
,
673 nsIThread::QOS_PRIORITY_NORMAL
,
674 nsIThread::QOS_PRIORITY_LOW
> {};
676 template <size_t N
, typename Word
>
677 struct ParamTraits
<mozilla::BitSet
<N
, Word
>> {
678 typedef mozilla::BitSet
<N
, Word
> paramType
;
680 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
681 for (Word word
: aParam
.Storage()) {
682 WriteParam(aWriter
, word
);
686 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
687 for (Word
& word
: aResult
->Storage()) {
688 if (!ReadParam(aReader
, &word
)) {
696 template <typename T
>
697 struct ParamTraits
<mozilla::UniquePtr
<T
>> {
698 typedef mozilla::UniquePtr
<T
> paramType
;
700 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
701 bool isNull
= aParam
== nullptr;
702 WriteParam(aWriter
, isNull
);
705 WriteParam(aWriter
, *aParam
.get());
709 static bool Read(IPC::MessageReader
* aReader
, paramType
* aResult
) {
711 if (!ReadParam(aReader
, &isNull
)) {
718 *aResult
= mozilla::MakeUnique
<T
>();
719 if (!ReadParam(aReader
, aResult
->get())) {
727 template <typename
... Ts
>
728 struct ParamTraits
<std::tuple
<Ts
...>> {
729 typedef std::tuple
<Ts
...> paramType
;
731 template <typename U
>
732 static void Write(IPC::MessageWriter
* aWriter
, U
&& aParam
) {
733 WriteInternal(aWriter
, std::forward
<U
>(aParam
),
734 std::index_sequence_for
<Ts
...>{});
737 static bool Read(IPC::MessageReader
* aReader
, std::tuple
<Ts
...>* aResult
) {
738 return ReadInternal(aReader
, *aResult
, std::index_sequence_for
<Ts
...>{});
742 template <size_t... Is
>
743 static void WriteInternal(IPC::MessageWriter
* aWriter
,
744 const std::tuple
<Ts
...>& aParam
,
745 std::index_sequence
<Is
...>) {
746 WriteParams(aWriter
, std::get
<Is
>(aParam
)...);
749 template <size_t... Is
>
750 static void WriteInternal(IPC::MessageWriter
* aWriter
,
751 std::tuple
<Ts
...>&& aParam
,
752 std::index_sequence
<Is
...>) {
753 WriteParams(aWriter
, std::move(std::get
<Is
>(aParam
))...);
756 template <size_t... Is
>
757 static bool ReadInternal(IPC::MessageReader
* aReader
,
758 std::tuple
<Ts
...>& aResult
,
759 std::index_sequence
<Is
...>) {
760 return ReadParams(aReader
, std::get
<Is
>(aResult
)...);
765 struct ParamTraits
<mozilla::net::LinkHeader
> {
766 typedef mozilla::net::LinkHeader paramType
;
767 constexpr static int kNumberOfMembers
= 14;
768 constexpr static int kSizeOfEachMember
= sizeof(nsString
);
769 constexpr static int kExpectedSizeOfParamType
=
770 kNumberOfMembers
* kSizeOfEachMember
;
772 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
773 static_assert(sizeof(paramType
) == kExpectedSizeOfParamType
,
774 "All members of should be written below.");
775 // Bug 1860565: `aParam.mAnchor` is not written.
777 WriteParam(aWriter
, aParam
.mHref
);
778 WriteParam(aWriter
, aParam
.mRel
);
779 WriteParam(aWriter
, aParam
.mTitle
);
780 WriteParam(aWriter
, aParam
.mNonce
);
781 WriteParam(aWriter
, aParam
.mIntegrity
);
782 WriteParam(aWriter
, aParam
.mSrcset
);
783 WriteParam(aWriter
, aParam
.mSizes
);
784 WriteParam(aWriter
, aParam
.mType
);
785 WriteParam(aWriter
, aParam
.mMedia
);
786 WriteParam(aWriter
, aParam
.mAnchor
);
787 WriteParam(aWriter
, aParam
.mCrossOrigin
);
788 WriteParam(aWriter
, aParam
.mReferrerPolicy
);
789 WriteParam(aWriter
, aParam
.mAs
);
790 WriteParam(aWriter
, aParam
.mFetchPriority
);
792 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
793 static_assert(sizeof(paramType
) == kExpectedSizeOfParamType
,
794 "All members of should be handled below.");
795 // Bug 1860565: `aParam.mAnchor` is not handled.
797 if (!ReadParam(aReader
, &aResult
->mHref
)) {
800 if (!ReadParam(aReader
, &aResult
->mRel
)) {
803 if (!ReadParam(aReader
, &aResult
->mTitle
)) {
806 if (!ReadParam(aReader
, &aResult
->mNonce
)) {
809 if (!ReadParam(aReader
, &aResult
->mIntegrity
)) {
812 if (!ReadParam(aReader
, &aResult
->mSrcset
)) {
815 if (!ReadParam(aReader
, &aResult
->mSizes
)) {
818 if (!ReadParam(aReader
, &aResult
->mType
)) {
821 if (!ReadParam(aReader
, &aResult
->mMedia
)) {
824 if (!ReadParam(aReader
, &aResult
->mAnchor
)) {
827 if (!ReadParam(aReader
, &aResult
->mCrossOrigin
)) {
830 if (!ReadParam(aReader
, &aResult
->mReferrerPolicy
)) {
833 if (!ReadParam(aReader
, &aResult
->mAs
)) {
836 return ReadParam(aReader
, &aResult
->mFetchPriority
);
841 struct ParamTraits
<mozilla::dom::UserActivation::Modifiers
> {
842 typedef mozilla::dom::UserActivation::Modifiers paramType
;
843 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
844 WriteParam(aWriter
, aParam
.mModifiers
);
846 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
847 return ReadParam(aReader
, &aResult
->mModifiers
);
852 struct ParamTraits
<gfxPlatform::GlobalReflowFlags
>
853 : public BitFlagsEnumSerializer
<gfxPlatform::GlobalReflowFlags
,
854 gfxPlatform::GlobalReflowFlags::ALL_BITS
> {
858 struct ParamTraits
<std::bitset
<N
>> {
859 typedef std::bitset
<N
> paramType
;
860 static void Write(MessageWriter
* aWriter
, const paramType
& aParam
) {
861 paramType
mask(UINT64_MAX
);
862 for (size_t i
= 0; i
< N
; i
+= 64) {
863 uint64_t value
= ((aParam
>> i
) & mask
).to_ullong();
864 WriteParam(aWriter
, value
);
868 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
869 for (size_t i
= 0; i
< N
; i
+= 64) {
871 if (!ReadParam(aReader
, &value
)) {
874 *aResult
|= std::bitset
<N
>(value
) << i
;
880 } /* namespace IPC */
882 #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */