no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / ipc / glue / IPCMessageUtilsSpecializations.h
blobec0620d0572d16a0572ae3cff831169c213f688a
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 "nsCSSPropertyID.h"
39 #include "nsDebug.h"
40 #include "nsIContentPolicy.h"
41 #include "nsID.h"
42 #include "nsILoadInfo.h"
43 #include "nsIThread.h"
44 #include "nsLiteralString.h"
45 #include "nsNetUtil.h"
46 #include "nsString.h"
47 #include "nsTArray.h"
48 #include "nsTHashSet.h"
50 // XXX Includes that are only required by implementations which could be moved
51 // to the cpp file.
52 #include "base/string_util.h" // for StringPrintf
53 #include "mozilla/ArrayUtils.h" // for ArrayLength
54 #include "mozilla/CheckedInt.h"
56 #ifdef _MSC_VER
57 # pragma warning(disable : 4800)
58 #endif
60 namespace mozilla {
61 template <typename... Ts>
62 class Variant;
64 namespace detail {
65 template <typename... Ts>
66 struct VariantTag;
68 } // namespace mozilla
70 namespace mozilla::dom {
71 template <typename T>
72 class Optional;
75 class nsAtom;
77 namespace IPC {
79 template <class T>
80 struct ParamTraits<nsTSubstring<T>> {
81 typedef nsTSubstring<T> paramType;
83 static void Write(MessageWriter* aWriter, const paramType& aParam) {
84 bool isVoid = aParam.IsVoid();
85 aWriter->WriteBool(isVoid);
87 if (isVoid) {
88 // represents a nullptr pointer
89 return;
92 WriteSequenceParam<const T&>(aWriter, aParam.BeginReading(),
93 aParam.Length());
96 static bool Read(MessageReader* aReader, paramType* aResult) {
97 bool isVoid;
98 if (!aReader->ReadBool(&isVoid)) {
99 return false;
102 if (isVoid) {
103 aResult->SetIsVoid(true);
104 return true;
107 return ReadSequenceParam<T>(aReader, [&](uint32_t aLength) -> T* {
108 T* data = nullptr;
109 aResult->GetMutableData(&data, aLength);
110 return data;
115 template <class T>
116 struct ParamTraits<nsTString<T>> : ParamTraits<nsTSubstring<T>> {};
118 template <class T>
119 struct ParamTraits<nsTLiteralString<T>> : ParamTraits<nsTSubstring<T>> {};
121 template <class T, size_t N>
122 struct ParamTraits<nsTAutoStringN<T, N>> : ParamTraits<nsTSubstring<T>> {};
124 template <class T>
125 struct ParamTraits<nsTDependentString<T>> : ParamTraits<nsTSubstring<T>> {};
127 // XXX While this has no special dependencies, it's currently only used in
128 // GfxMessageUtils and could be moved there, or generalized to potentially work
129 // with any nsTHashSet.
130 template <>
131 struct ParamTraits<nsTHashSet<uint64_t>> {
132 typedef nsTHashSet<uint64_t> paramType;
134 static void Write(MessageWriter* aWriter, const paramType& aParam) {
135 uint32_t count = aParam.Count();
136 WriteParam(aWriter, count);
137 for (const auto& key : aParam) {
138 WriteParam(aWriter, key);
142 static bool Read(MessageReader* aReader, paramType* aResult) {
143 uint32_t count;
144 if (!ReadParam(aReader, &count)) {
145 return false;
147 paramType table(count);
148 for (uint32_t i = 0; i < count; ++i) {
149 uint64_t key;
150 if (!ReadParam(aReader, &key)) {
151 return false;
153 table.Insert(key);
155 *aResult = std::move(table);
156 return true;
160 template <typename E>
161 struct ParamTraits<nsTArray<E>> {
162 typedef nsTArray<E> paramType;
164 static void Write(MessageWriter* aWriter, const paramType& aParam) {
165 WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
168 static void Write(MessageWriter* aWriter, paramType&& aParam) {
169 WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
172 static bool Read(MessageReader* aReader, paramType* aResult) {
173 return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
174 if constexpr (std::is_trivially_default_constructible_v<E>) {
175 return aResult->AppendElements(aLength);
176 } else {
177 aResult->SetCapacity(aLength);
178 return mozilla::Some(MakeBackInserter(*aResult));
184 template <typename E>
185 struct ParamTraits<CopyableTArray<E>> : ParamTraits<nsTArray<E>> {};
187 template <typename E>
188 struct ParamTraits<FallibleTArray<E>> {
189 typedef FallibleTArray<E> paramType;
191 static void Write(MessageWriter* aWriter, const paramType& aParam) {
192 WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
195 static void Write(MessageWriter* aWriter, paramType&& aParam) {
196 WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
199 static bool Read(MessageReader* aReader, paramType* aResult) {
200 return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
201 if constexpr (std::is_trivially_default_constructible_v<E>) {
202 return aResult->AppendElements(aLength, mozilla::fallible);
203 } else {
204 if (!aResult->SetCapacity(aLength, mozilla::fallible)) {
205 return mozilla::Maybe<BackInserter>{};
207 return mozilla::Some(BackInserter{.mArray = aResult});
212 private:
213 struct BackInserter {
214 using iterator_category = std::output_iterator_tag;
215 using value_type = void;
216 using difference_type = void;
217 using pointer = void;
218 using reference = void;
220 struct Proxy {
221 paramType& mArray;
223 template <typename U>
224 void operator=(U&& aValue) {
225 // This won't fail because we've reserved capacity earlier.
226 MOZ_ALWAYS_TRUE(mArray.AppendElement(aValue, mozilla::fallible));
229 Proxy operator*() { return Proxy{.mArray = *mArray}; }
231 BackInserter& operator++() { return *this; }
232 BackInserter& operator++(int) { return *this; }
234 paramType* mArray = nullptr;
238 template <typename E, size_t N>
239 struct ParamTraits<AutoTArray<E, N>> : ParamTraits<nsTArray<E>> {
240 typedef AutoTArray<E, N> paramType;
243 template <typename E, size_t N>
244 struct ParamTraits<CopyableAutoTArray<E, N>> : ParamTraits<AutoTArray<E, N>> {};
246 template <typename T>
247 struct ParamTraits<mozilla::dom::Sequence<T>> : ParamTraits<FallibleTArray<T>> {
250 template <typename E, size_t N, typename AP>
251 struct ParamTraits<mozilla::Vector<E, N, AP>> {
252 typedef mozilla::Vector<E, N, AP> paramType;
254 static void Write(MessageWriter* aWriter, const paramType& aParam) {
255 WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
258 static void Write(MessageWriter* aWriter, paramType&& aParam) {
259 WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
262 static bool Read(MessageReader* aReader, paramType* aResult) {
263 return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) -> E* {
264 if (!aResult->resize(aLength)) {
265 // So that OOM failure shows up as OOM crash instead of IPC FatalError.
266 NS_ABORT_OOM(aLength * sizeof(E));
268 return aResult->begin();
273 template <typename E>
274 struct ParamTraits<std::vector<E>> {
275 typedef std::vector<E> paramType;
277 static void Write(MessageWriter* aWriter, const paramType& aParam) {
278 WriteSequenceParam<const E&>(aWriter, aParam.data(), aParam.size());
280 static void Write(MessageWriter* aWriter, paramType&& aParam) {
281 WriteSequenceParam<E&&>(aWriter, aParam.data(), aParam.size());
284 static bool Read(MessageReader* aReader, paramType* aResult) {
285 return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
286 if constexpr (std::is_trivially_default_constructible_v<E>) {
287 aResult->resize(aLength);
288 return aResult->data();
289 } else {
290 aResult->reserve(aLength);
291 return mozilla::Some(std::back_inserter(*aResult));
297 template <typename K, typename V>
298 struct ParamTraits<std::unordered_map<K, V>> final {
299 using T = std::unordered_map<K, V>;
301 static void Write(MessageWriter* const writer, const T& in) {
302 WriteParam(writer, in.size());
303 for (const auto& pair : in) {
304 WriteParam(writer, pair.first);
305 WriteParam(writer, pair.second);
309 static bool Read(MessageReader* const reader, T* const out) {
310 size_t size = 0;
311 if (!ReadParam(reader, &size)) return false;
312 T map;
313 map.reserve(size);
314 for (const auto i : mozilla::IntegerRange(size)) {
315 std::pair<K, V> pair;
316 mozilla::Unused << i;
317 if (!ReadParam(reader, &(pair.first)) ||
318 !ReadParam(reader, &(pair.second))) {
319 return false;
321 map.insert(std::move(pair));
323 *out = std::move(map);
324 return true;
328 template <>
329 struct ParamTraits<float> {
330 typedef float paramType;
332 static void Write(MessageWriter* aWriter, const paramType& aParam) {
333 aWriter->WriteBytes(&aParam, sizeof(paramType));
336 static bool Read(MessageReader* aReader, paramType* aResult) {
337 return aReader->ReadBytesInto(aResult, sizeof(*aResult));
341 template <>
342 struct ParamTraits<nsCSSPropertyID>
343 : public ContiguousEnumSerializer<nsCSSPropertyID, eCSSProperty_UNKNOWN,
344 eCSSProperty_COUNT> {};
346 template <>
347 struct ParamTraits<nsID> {
348 typedef nsID paramType;
350 static void Write(MessageWriter* aWriter, const paramType& aParam) {
351 WriteParam(aWriter, aParam.m0);
352 WriteParam(aWriter, aParam.m1);
353 WriteParam(aWriter, aParam.m2);
354 for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) {
355 WriteParam(aWriter, aParam.m3[i]);
359 static bool Read(MessageReader* aReader, paramType* aResult) {
360 if (!ReadParam(aReader, &(aResult->m0)) ||
361 !ReadParam(aReader, &(aResult->m1)) ||
362 !ReadParam(aReader, &(aResult->m2)))
363 return false;
365 for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++)
366 if (!ReadParam(aReader, &(aResult->m3[i]))) return false;
368 return true;
372 template <>
373 struct ParamTraits<nsContentPolicyType>
374 : public ContiguousEnumSerializer<nsContentPolicyType,
375 nsIContentPolicy::TYPE_INVALID,
376 nsIContentPolicy::TYPE_END> {};
378 template <>
379 struct ParamTraits<mozilla::TimeDuration> {
380 typedef mozilla::TimeDuration paramType;
381 static void Write(MessageWriter* aWriter, const paramType& aParam) {
382 WriteParam(aWriter, aParam.mValue);
384 static bool Read(MessageReader* aReader, paramType* aResult) {
385 return ReadParam(aReader, &aResult->mValue);
389 template <>
390 struct ParamTraits<mozilla::TimeStamp> {
391 typedef mozilla::TimeStamp paramType;
392 static void Write(MessageWriter* aWriter, const paramType& aParam) {
393 WriteParam(aWriter, aParam.mValue);
395 static bool Read(MessageReader* aReader, paramType* aResult) {
396 return ReadParam(aReader, &aResult->mValue);
400 #ifdef XP_WIN
402 template <>
403 struct ParamTraits<mozilla::TimeStampValue> {
404 typedef mozilla::TimeStampValue paramType;
405 static void Write(MessageWriter* aWriter, const paramType& aParam) {
406 WriteParam(aWriter, aParam.mGTC);
407 WriteParam(aWriter, aParam.mQPC);
408 WriteParam(aWriter, aParam.mIsNull);
409 WriteParam(aWriter, aParam.mHasQPC);
411 static bool Read(MessageReader* aReader, paramType* aResult) {
412 return (ReadParam(aReader, &aResult->mGTC) &&
413 ReadParam(aReader, &aResult->mQPC) &&
414 ReadParam(aReader, &aResult->mIsNull) &&
415 ReadParam(aReader, &aResult->mHasQPC));
419 #endif
421 template <>
422 struct ParamTraits<mozilla::dom::ipc::StructuredCloneData> {
423 typedef mozilla::dom::ipc::StructuredCloneData paramType;
425 static void Write(MessageWriter* aWriter, const paramType& aParam) {
426 aParam.WriteIPCParams(aWriter);
429 static bool Read(MessageReader* aReader, paramType* aResult) {
430 return aResult->ReadIPCParams(aReader);
434 template <class T>
435 struct ParamTraits<mozilla::Maybe<T>> {
436 typedef mozilla::Maybe<T> paramType;
438 static void Write(MessageWriter* writer, const paramType& param) {
439 if (param.isSome()) {
440 WriteParam(writer, true);
441 WriteParam(writer, param.ref());
442 } else {
443 WriteParam(writer, false);
447 static void Write(MessageWriter* writer, paramType&& param) {
448 if (param.isSome()) {
449 WriteParam(writer, true);
450 WriteParam(writer, std::move(param.ref()));
451 } else {
452 WriteParam(writer, false);
456 static bool Read(MessageReader* reader, paramType* result) {
457 bool isSome;
458 if (!ReadParam(reader, &isSome)) {
459 return false;
461 if (isSome) {
462 mozilla::Maybe<T> tmp = ReadParam<T>(reader).TakeMaybe();
463 if (!tmp) {
464 return false;
466 *result = std::move(tmp);
467 } else {
468 *result = mozilla::Nothing();
470 return true;
474 template <typename T, typename U>
475 struct ParamTraits<mozilla::EnumSet<T, U>> {
476 typedef mozilla::EnumSet<T, U> paramType;
477 typedef U serializedType;
479 static void Write(MessageWriter* writer, const paramType& param) {
480 MOZ_RELEASE_ASSERT(IsLegalValue(param.serialize()));
481 WriteParam(writer, param.serialize());
484 static bool Read(MessageReader* reader, paramType* result) {
485 serializedType tmp;
487 if (ReadParam(reader, &tmp)) {
488 if (IsLegalValue(tmp)) {
489 result->deserialize(tmp);
490 return true;
494 return false;
497 static constexpr serializedType AllEnumBits() {
498 return ~serializedType(0) >> (std::numeric_limits<serializedType>::digits -
499 (mozilla::MaxEnumValue<T>::value + 1));
502 static constexpr bool IsLegalValue(const serializedType value) {
503 static_assert(mozilla::MaxEnumValue<T>::value <
504 std::numeric_limits<serializedType>::digits,
505 "Enum max value is not in the range!");
506 static_assert(
507 std::is_unsigned<decltype(mozilla::MaxEnumValue<T>::value)>::value,
508 "Type of MaxEnumValue<T>::value specialization should be unsigned!");
510 return (value & AllEnumBits()) == value;
514 template <class... Ts>
515 struct ParamTraits<mozilla::Variant<Ts...>> {
516 typedef mozilla::Variant<Ts...> paramType;
517 using Tag = typename mozilla::detail::VariantTag<Ts...>::Type;
519 static void Write(MessageWriter* writer, const paramType& param) {
520 WriteParam(writer, param.tag);
521 param.match([writer](const auto& t) { WriteParam(writer, t); });
524 // Because VariantReader is a nested struct, we need the dummy template
525 // parameter to avoid making VariantReader<0> an explicit specialization,
526 // which is not allowed for a nested class template
527 template <size_t N, typename dummy = void>
528 struct VariantReader {
529 using Next = VariantReader<N - 1>;
531 static bool Read(MessageReader* reader, Tag tag, paramType* result) {
532 // Since the VariantReader specializations start at N , we need to
533 // subtract one to look at N - 1, the first valid tag. This means our
534 // comparisons are off by 1. If we get to N = 0 then we have failed to
535 // find a match to the tag.
536 if (tag == N - 1) {
537 // Recall, even though the template parameter is N, we are
538 // actually interested in the N - 1 tag.
539 // Default construct our field within the result outparameter and
540 // directly deserialize into the variant. Note that this means that
541 // every type in Ts needs to be default constructible
542 return ReadParam(reader, &result->template emplace<N - 1>());
543 } else {
544 return Next::Read(reader, tag, result);
548 }; // VariantReader<N>
550 // Since we are conditioning on tag = N - 1 in the preceding specialization,
551 // if we get to `VariantReader<0, dummy>` we have failed to find
552 // a matching tag.
553 template <typename dummy>
554 struct VariantReader<0, dummy> {
555 static bool Read(MessageReader* reader, Tag tag, paramType* result) {
556 return false;
560 static bool Read(MessageReader* reader, paramType* result) {
561 Tag tag;
562 if (ReadParam(reader, &tag)) {
563 return VariantReader<sizeof...(Ts)>::Read(reader, tag, result);
565 return false;
569 template <typename T>
570 struct ParamTraits<mozilla::dom::Optional<T>> {
571 typedef mozilla::dom::Optional<T> paramType;
573 static void Write(MessageWriter* aWriter, const paramType& aParam) {
574 if (aParam.WasPassed()) {
575 WriteParam(aWriter, true);
576 WriteParam(aWriter, aParam.Value());
577 return;
580 WriteParam(aWriter, false);
583 static bool Read(MessageReader* aReader, paramType* aResult) {
584 bool wasPassed = false;
586 if (!ReadParam(aReader, &wasPassed)) {
587 return false;
590 aResult->Reset();
592 if (wasPassed) {
593 if (!ReadParam(aReader, &aResult->Construct())) {
594 return false;
598 return true;
602 template <>
603 struct ParamTraits<nsAtom*> {
604 typedef nsAtom paramType;
606 static void Write(MessageWriter* aWriter, const paramType* aParam);
607 static bool Read(MessageReader* aReader, RefPtr<paramType>* aResult);
610 struct CrossOriginOpenerPolicyValidator {
611 using IntegralType =
612 std::underlying_type_t<nsILoadInfo::CrossOriginOpenerPolicy>;
614 static bool IsLegalValue(const IntegralType e) {
615 return AreIntegralValuesEqual(e, nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) ||
616 AreIntegralValuesEqual(e, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN) ||
617 AreIntegralValuesEqual(
618 e, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS) ||
619 AreIntegralValuesEqual(
620 e, nsILoadInfo::
621 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP);
624 private:
625 static bool AreIntegralValuesEqual(
626 const IntegralType aLhs,
627 const nsILoadInfo::CrossOriginOpenerPolicy aRhs) {
628 return aLhs == static_cast<IntegralType>(aRhs);
632 template <>
633 struct ParamTraits<nsILoadInfo::CrossOriginOpenerPolicy>
634 : EnumSerializer<nsILoadInfo::CrossOriginOpenerPolicy,
635 CrossOriginOpenerPolicyValidator> {};
637 struct CrossOriginEmbedderPolicyValidator {
638 using IntegralType =
639 std::underlying_type_t<nsILoadInfo::CrossOriginEmbedderPolicy>;
641 static bool IsLegalValue(const IntegralType e) {
642 return AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_NULL) ||
643 AreIntegralValuesEqual(e,
644 nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) ||
645 AreIntegralValuesEqual(e,
646 nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS);
649 private:
650 static bool AreIntegralValuesEqual(
651 const IntegralType aLhs,
652 const nsILoadInfo::CrossOriginEmbedderPolicy aRhs) {
653 return aLhs == static_cast<IntegralType>(aRhs);
657 template <>
658 struct ParamTraits<nsILoadInfo::CrossOriginEmbedderPolicy>
659 : EnumSerializer<nsILoadInfo::CrossOriginEmbedderPolicy,
660 CrossOriginEmbedderPolicyValidator> {};
662 template <>
663 struct ParamTraits<nsIThread::QoSPriority>
664 : public ContiguousEnumSerializerInclusive<nsIThread::QoSPriority,
665 nsIThread::QOS_PRIORITY_NORMAL,
666 nsIThread::QOS_PRIORITY_LOW> {};
668 template <size_t N, typename Word>
669 struct ParamTraits<mozilla::BitSet<N, Word>> {
670 typedef mozilla::BitSet<N, Word> paramType;
672 static void Write(MessageWriter* aWriter, const paramType& aParam) {
673 for (Word word : aParam.Storage()) {
674 WriteParam(aWriter, word);
678 static bool Read(MessageReader* aReader, paramType* aResult) {
679 for (Word& word : aResult->Storage()) {
680 if (!ReadParam(aReader, &word)) {
681 return false;
684 return true;
688 template <typename T>
689 struct ParamTraits<mozilla::UniquePtr<T>> {
690 typedef mozilla::UniquePtr<T> paramType;
692 static void Write(MessageWriter* aWriter, const paramType& aParam) {
693 bool isNull = aParam == nullptr;
694 WriteParam(aWriter, isNull);
696 if (!isNull) {
697 WriteParam(aWriter, *aParam.get());
701 static bool Read(IPC::MessageReader* aReader, paramType* aResult) {
702 bool isNull = true;
703 if (!ReadParam(aReader, &isNull)) {
704 return false;
707 if (isNull) {
708 aResult->reset();
709 } else {
710 *aResult = mozilla::MakeUnique<T>();
711 if (!ReadParam(aReader, aResult->get())) {
712 return false;
715 return true;
719 template <typename... Ts>
720 struct ParamTraits<std::tuple<Ts...>> {
721 typedef std::tuple<Ts...> paramType;
723 template <typename U>
724 static void Write(IPC::MessageWriter* aWriter, U&& aParam) {
725 WriteInternal(aWriter, std::forward<U>(aParam),
726 std::index_sequence_for<Ts...>{});
729 static bool Read(IPC::MessageReader* aReader, std::tuple<Ts...>* aResult) {
730 return ReadInternal(aReader, *aResult, std::index_sequence_for<Ts...>{});
733 private:
734 template <size_t... Is>
735 static void WriteInternal(IPC::MessageWriter* aWriter,
736 const std::tuple<Ts...>& aParam,
737 std::index_sequence<Is...>) {
738 WriteParams(aWriter, std::get<Is>(aParam)...);
741 template <size_t... Is>
742 static void WriteInternal(IPC::MessageWriter* aWriter,
743 std::tuple<Ts...>&& aParam,
744 std::index_sequence<Is...>) {
745 WriteParams(aWriter, std::move(std::get<Is>(aParam))...);
748 template <size_t... Is>
749 static bool ReadInternal(IPC::MessageReader* aReader,
750 std::tuple<Ts...>& aResult,
751 std::index_sequence<Is...>) {
752 return ReadParams(aReader, std::get<Is>(aResult)...);
756 template <>
757 struct ParamTraits<mozilla::net::LinkHeader> {
758 typedef mozilla::net::LinkHeader paramType;
759 constexpr static int kNumberOfMembers = 14;
760 constexpr static int kSizeOfEachMember = sizeof(nsString);
761 constexpr static int kExpectedSizeOfParamType =
762 kNumberOfMembers * kSizeOfEachMember;
764 static void Write(MessageWriter* aWriter, const paramType& aParam) {
765 static_assert(sizeof(paramType) == kExpectedSizeOfParamType,
766 "All members of should be written below.");
767 // Bug 1860565: `aParam.mAnchor` is not written.
769 WriteParam(aWriter, aParam.mHref);
770 WriteParam(aWriter, aParam.mRel);
771 WriteParam(aWriter, aParam.mTitle);
772 WriteParam(aWriter, aParam.mNonce);
773 WriteParam(aWriter, aParam.mIntegrity);
774 WriteParam(aWriter, aParam.mSrcset);
775 WriteParam(aWriter, aParam.mSizes);
776 WriteParam(aWriter, aParam.mType);
777 WriteParam(aWriter, aParam.mMedia);
778 WriteParam(aWriter, aParam.mAnchor);
779 WriteParam(aWriter, aParam.mCrossOrigin);
780 WriteParam(aWriter, aParam.mReferrerPolicy);
781 WriteParam(aWriter, aParam.mAs);
782 WriteParam(aWriter, aParam.mFetchPriority);
784 static bool Read(MessageReader* aReader, paramType* aResult) {
785 static_assert(sizeof(paramType) == kExpectedSizeOfParamType,
786 "All members of should be handled below.");
787 // Bug 1860565: `aParam.mAnchor` is not handled.
789 if (!ReadParam(aReader, &aResult->mHref)) {
790 return false;
792 if (!ReadParam(aReader, &aResult->mRel)) {
793 return false;
795 if (!ReadParam(aReader, &aResult->mTitle)) {
796 return false;
798 if (!ReadParam(aReader, &aResult->mNonce)) {
799 return false;
801 if (!ReadParam(aReader, &aResult->mIntegrity)) {
802 return false;
804 if (!ReadParam(aReader, &aResult->mSrcset)) {
805 return false;
807 if (!ReadParam(aReader, &aResult->mSizes)) {
808 return false;
810 if (!ReadParam(aReader, &aResult->mType)) {
811 return false;
813 if (!ReadParam(aReader, &aResult->mMedia)) {
814 return false;
816 if (!ReadParam(aReader, &aResult->mAnchor)) {
817 return false;
819 if (!ReadParam(aReader, &aResult->mCrossOrigin)) {
820 return false;
822 if (!ReadParam(aReader, &aResult->mReferrerPolicy)) {
823 return false;
825 if (!ReadParam(aReader, &aResult->mAs)) {
826 return false;
828 return ReadParam(aReader, &aResult->mFetchPriority);
832 template <>
833 struct ParamTraits<mozilla::dom::UserActivation::Modifiers> {
834 typedef mozilla::dom::UserActivation::Modifiers paramType;
835 static void Write(MessageWriter* aWriter, const paramType& aParam) {
836 WriteParam(aWriter, aParam.mModifiers);
838 static bool Read(MessageReader* aReader, paramType* aResult) {
839 return ReadParam(aReader, &aResult->mModifiers);
843 } /* namespace IPC */
845 #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */