Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / ipc / glue / IPCMessageUtilsSpecializations.h
blob0a80bc8cb86376f1ddfc28f5d5365104ca133c2b
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__
10 #include <cstdint>
11 #include <cstdlib>
12 #include <limits>
13 #include <string>
14 #include <type_traits>
15 #include <unordered_map>
16 #include <utility>
17 #include <vector>
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"
29 #ifdef XP_WIN
30 # include "mozilla/TimeStamp_windows.h"
31 #endif
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"
40 #include "nsDebug.h"
41 #include "nsIContentPolicy.h"
42 #include "nsID.h"
43 #include "nsILoadInfo.h"
44 #include "nsIThread.h"
45 #include "nsLiteralString.h"
46 #include "nsNetUtil.h"
47 #include "nsString.h"
48 #include "nsTArray.h"
49 #include "nsTHashSet.h"
51 // XXX Includes that are only required by implementations which could be moved
52 // to the cpp file.
53 #include "base/string_util.h" // for StringPrintf
54 #include "mozilla/ArrayUtils.h" // for ArrayLength
55 #include "mozilla/CheckedInt.h"
57 #ifdef _MSC_VER
58 # pragma warning(disable : 4800)
59 #endif
61 namespace mozilla {
62 template <typename... Ts>
63 class Variant;
65 namespace detail {
66 template <typename... Ts>
67 struct VariantTag;
69 } // namespace mozilla
71 namespace mozilla::dom {
72 template <typename T>
73 class Optional;
76 class nsAtom;
78 namespace IPC {
80 template <class T>
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);
88 if (isVoid) {
89 // represents a nullptr pointer
90 return;
93 WriteSequenceParam<const T&>(aWriter, aParam.BeginReading(),
94 aParam.Length());
97 static bool Read(MessageReader* aReader, paramType* aResult) {
98 bool isVoid;
99 if (!aReader->ReadBool(&isVoid)) {
100 return false;
103 if (isVoid) {
104 aResult->SetIsVoid(true);
105 return true;
108 return ReadSequenceParam<T>(aReader, [&](uint32_t aLength) -> T* {
109 T* data = nullptr;
110 aResult->GetMutableData(&data, aLength);
111 return data;
116 template <class T>
117 struct ParamTraits<nsTString<T>> : ParamTraits<nsTSubstring<T>> {};
119 template <class 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>> {};
125 template <class 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.
131 template <>
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) {
144 uint32_t count;
145 if (!ReadParam(aReader, &count)) {
146 return false;
148 paramType table(count);
149 for (uint32_t i = 0; i < count; ++i) {
150 uint64_t key;
151 if (!ReadParam(aReader, &key)) {
152 return false;
154 table.Insert(key);
156 *aResult = std::move(table);
157 return true;
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);
177 } else {
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);
204 } else {
205 if (!aResult->SetCapacity(aLength, mozilla::fallible)) {
206 return mozilla::Maybe<BackInserter>{};
208 return mozilla::Some(BackInserter{.mArray = aResult});
213 private:
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;
221 struct Proxy {
222 paramType& mArray;
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();
290 } else {
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) {
311 size_t size = 0;
312 if (!ReadParam(reader, &size)) return false;
313 T map;
314 map.reserve(size);
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))) {
320 return false;
322 map.insert(std::move(pair));
324 *out = std::move(map);
325 return true;
329 template <>
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));
342 template <>
343 struct ParamTraits<nsCSSPropertyID>
344 : public ContiguousEnumSerializer<nsCSSPropertyID, eCSSProperty_UNKNOWN,
345 eCSSProperty_COUNT> {};
347 template <>
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)))
364 return false;
366 for (unsigned int i = 0; i < std::size(aResult->m3); i++)
367 if (!ReadParam(aReader, &(aResult->m3[i]))) return false;
369 return true;
373 template <>
374 struct ParamTraits<nsContentPolicyType>
375 : public ContiguousEnumSerializer<nsContentPolicyType,
376 nsIContentPolicy::TYPE_INVALID,
377 nsIContentPolicy::TYPE_END> {};
379 template <>
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);
390 template <>
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);
401 #ifdef XP_WIN
403 template <>
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));
420 #endif
422 template <>
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);
435 template <class T>
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());
443 } else {
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()));
452 } else {
453 WriteParam(writer, false);
457 static bool Read(MessageReader* reader, paramType* result) {
458 bool isSome;
459 if (!ReadParam(reader, &isSome)) {
460 return false;
462 if (isSome) {
463 mozilla::Maybe<T> tmp = ReadParam<T>(reader).TakeMaybe();
464 if (!tmp) {
465 return false;
467 *result = std::move(tmp);
468 } else {
469 *result = mozilla::Nothing();
471 return true;
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) {
486 serializedType tmp;
488 if (ReadParam(reader, &tmp)) {
489 if (IsLegalValue(tmp)) {
490 result->deserialize(tmp);
491 return true;
495 return false;
498 static constexpr size_t kUnderlyingWidth = [] {
499 if constexpr (std::numeric_limits<serializedType>::is_specialized) {
500 return std::numeric_limits<serializedType>::digits;
501 } else {
502 return serializedType().size(); // for std::bitset<N>
504 }();
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!");
514 static_assert(
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.
544 if (tag == N - 1) {
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>());
551 } else {
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
560 // a matching tag.
561 template <typename dummy>
562 struct VariantReader<0, dummy> {
563 static bool Read(MessageReader* reader, Tag tag, paramType* result) {
564 return false;
568 static bool Read(MessageReader* reader, paramType* result) {
569 Tag tag;
570 if (ReadParam(reader, &tag)) {
571 return VariantReader<sizeof...(Ts)>::Read(reader, tag, result);
573 return false;
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());
585 return;
588 WriteParam(aWriter, false);
591 static bool Read(MessageReader* aReader, paramType* aResult) {
592 bool wasPassed = false;
594 if (!ReadParam(aReader, &wasPassed)) {
595 return false;
598 aResult->Reset();
600 if (wasPassed) {
601 if (!ReadParam(aReader, &aResult->Construct())) {
602 return false;
606 return true;
610 template <>
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 {
619 using IntegralType =
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(
628 e, nsILoadInfo::
629 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP);
632 private:
633 static bool AreIntegralValuesEqual(
634 const IntegralType aLhs,
635 const nsILoadInfo::CrossOriginOpenerPolicy aRhs) {
636 return aLhs == static_cast<IntegralType>(aRhs);
640 template <>
641 struct ParamTraits<nsILoadInfo::CrossOriginOpenerPolicy>
642 : EnumSerializer<nsILoadInfo::CrossOriginOpenerPolicy,
643 CrossOriginOpenerPolicyValidator> {};
645 struct CrossOriginEmbedderPolicyValidator {
646 using IntegralType =
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);
657 private:
658 static bool AreIntegralValuesEqual(
659 const IntegralType aLhs,
660 const nsILoadInfo::CrossOriginEmbedderPolicy aRhs) {
661 return aLhs == static_cast<IntegralType>(aRhs);
665 template <>
666 struct ParamTraits<nsILoadInfo::CrossOriginEmbedderPolicy>
667 : EnumSerializer<nsILoadInfo::CrossOriginEmbedderPolicy,
668 CrossOriginEmbedderPolicyValidator> {};
670 template <>
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)) {
689 return false;
692 return true;
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);
704 if (!isNull) {
705 WriteParam(aWriter, *aParam.get());
709 static bool Read(IPC::MessageReader* aReader, paramType* aResult) {
710 bool isNull = true;
711 if (!ReadParam(aReader, &isNull)) {
712 return false;
715 if (isNull) {
716 aResult->reset();
717 } else {
718 *aResult = mozilla::MakeUnique<T>();
719 if (!ReadParam(aReader, aResult->get())) {
720 return false;
723 return true;
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...>{});
741 private:
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)...);
764 template <>
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)) {
798 return false;
800 if (!ReadParam(aReader, &aResult->mRel)) {
801 return false;
803 if (!ReadParam(aReader, &aResult->mTitle)) {
804 return false;
806 if (!ReadParam(aReader, &aResult->mNonce)) {
807 return false;
809 if (!ReadParam(aReader, &aResult->mIntegrity)) {
810 return false;
812 if (!ReadParam(aReader, &aResult->mSrcset)) {
813 return false;
815 if (!ReadParam(aReader, &aResult->mSizes)) {
816 return false;
818 if (!ReadParam(aReader, &aResult->mType)) {
819 return false;
821 if (!ReadParam(aReader, &aResult->mMedia)) {
822 return false;
824 if (!ReadParam(aReader, &aResult->mAnchor)) {
825 return false;
827 if (!ReadParam(aReader, &aResult->mCrossOrigin)) {
828 return false;
830 if (!ReadParam(aReader, &aResult->mReferrerPolicy)) {
831 return false;
833 if (!ReadParam(aReader, &aResult->mAs)) {
834 return false;
836 return ReadParam(aReader, &aResult->mFetchPriority);
840 template <>
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);
851 template <>
852 struct ParamTraits<gfxPlatform::GlobalReflowFlags>
853 : public BitFlagsEnumSerializer<gfxPlatform::GlobalReflowFlags,
854 gfxPlatform::GlobalReflowFlags::ALL_BITS> {
857 template <size_t N>
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) {
870 uint64_t value = 0;
871 if (!ReadParam(aReader, &value)) {
872 return false;
874 *aResult |= std::bitset<N>(value) << i;
876 return true;
880 } /* namespace IPC */
882 #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */