tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

IPCMessageUtilsSpecializations.h (26950B)


      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/. */
      6 
      7 #ifndef __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__
      8 #define __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__
      9 
     10 #include <cstdint>
     11 #include <limits>
     12 #include <set>
     13 #include <type_traits>
     14 #include <unordered_map>
     15 #include <utility>
     16 #include <vector>
     17 #include "chrome/common/ipc_message.h"
     18 #include "chrome/common/ipc_message_utils.h"
     19 #include "ipc/EnumSerializer.h"
     20 #include "ipc/IPCMessageUtils.h"
     21 #include "mozilla/Assertions.h"
     22 #include "mozilla/BitSet.h"
     23 #include "mozilla/EnumSet.h"
     24 #include "mozilla/EnumTypeTraits.h"
     25 #include "mozilla/IntegerRange.h"
     26 #include "mozilla/Maybe.h"
     27 #include "mozilla/TimeStamp.h"
     28 
     29 #include "mozilla/UniquePtr.h"
     30 #include "mozilla/Vector.h"
     31 #include "mozilla/dom/ipc/StructuredCloneData.h"
     32 #include "mozilla/dom/UserActivation.h"
     33 #include "gfxPlatform.h"
     34 #include "NonCustomCSSPropertyId.h"
     35 #include "nsContentPermissionHelper.h"
     36 #include "nsDebug.h"
     37 #include "nsIContentPolicy.h"
     38 #include "nsID.h"
     39 #include "nsILoadInfo.h"
     40 #include "nsIThread.h"
     41 #include "nsLiteralString.h"
     42 #include "nsNetUtil.h"
     43 #include "nsString.h"
     44 #include "nsTArray.h"
     45 #include "nsTHashSet.h"
     46 
     47 // XXX Includes that are only required by implementations which could be moved
     48 // to the cpp file.
     49 #include "base/string_util.h"  // for StringPrintf
     50 
     51 #ifdef _MSC_VER
     52 #  pragma warning(disable : 4800)
     53 #endif
     54 
     55 namespace mozilla {
     56 template <typename... Ts>
     57 class Variant;
     58 
     59 namespace detail {
     60 template <typename... Ts>
     61 struct VariantTag;
     62 }
     63 }  // namespace mozilla
     64 
     65 namespace mozilla::dom {
     66 template <typename T>
     67 class Optional;
     68 }
     69 
     70 class nsAtom;
     71 
     72 namespace IPC {
     73 
     74 template <class T>
     75 struct ParamTraits<nsTSubstring<T>> {
     76  typedef nsTSubstring<T> paramType;
     77 
     78  static void Write(MessageWriter* aWriter, const paramType& aParam) {
     79    bool isVoid = aParam.IsVoid();
     80    aWriter->WriteBool(isVoid);
     81 
     82    if (isVoid) {
     83      // represents a nullptr pointer
     84      return;
     85    }
     86 
     87    WriteSequenceParam<const T&>(aWriter, aParam.BeginReading(),
     88                                 aParam.Length());
     89  }
     90 
     91  static bool Read(MessageReader* aReader, paramType* aResult) {
     92    bool isVoid;
     93    if (!aReader->ReadBool(&isVoid)) {
     94      return false;
     95    }
     96 
     97    if (isVoid) {
     98      aResult->SetIsVoid(true);
     99      return true;
    100    }
    101 
    102    return ReadSequenceParam<T>(aReader, [&](uint32_t aLength) -> T* {
    103      T* data = nullptr;
    104      aResult->GetMutableData(&data, aLength);
    105      return data;
    106    });
    107  }
    108 };
    109 
    110 template <class T>
    111 struct ParamTraits<nsTString<T>> : ParamTraits<nsTSubstring<T>> {};
    112 
    113 template <class T>
    114 struct ParamTraits<nsTLiteralString<T>> : ParamTraits<nsTSubstring<T>> {};
    115 
    116 template <class T, size_t N>
    117 struct ParamTraits<nsTAutoStringN<T, N>> : ParamTraits<nsTSubstring<T>> {};
    118 
    119 template <class T>
    120 struct ParamTraits<nsTDependentString<T>> : ParamTraits<nsTSubstring<T>> {};
    121 
    122 // Key type must be a type with ParamTraits, a default constructor and a move
    123 // constructor.
    124 template <
    125    typename KeyClass,
    126    typename ConstructableKeyType = typename std::remove_const<
    127        typename std::remove_reference<typename KeyClass::KeyType>::type>::type>
    128 struct ParamTraitsforHashSet {
    129  typedef nsTBaseHashSet<KeyClass> paramType;
    130  using KeyType = typename KeyClass::KeyType;
    131 
    132  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    133    uint32_t count = aParam.Count();
    134    WriteParam(aWriter, count);
    135    for (const auto& key : aParam) {
    136      WriteParam(aWriter, key);
    137    }
    138  }
    139 
    140  static bool Read(MessageReader* aReader, paramType* aResult) {
    141    uint32_t count;
    142    if (!ReadParam(aReader, &count)) {
    143      return false;
    144    }
    145    paramType table(count);
    146    for (uint32_t i = 0; i < count; ++i) {
    147      ConstructableKeyType key;
    148      if (!ReadParam(aReader, &key)) {
    149        return false;
    150      }
    151      table.Insert(std::move(key));
    152    }
    153    *aResult = std::move(table);
    154    return true;
    155  }
    156 };
    157 
    158 template <typename KeyClass>
    159 struct ParamTraits<nsTBaseHashSet<KeyClass>> : ParamTraitsforHashSet<KeyClass> {
    160 };
    161 template <>
    162 struct ParamTraits<nsTBaseHashSet<nsStringHashKey>>
    163    : ParamTraitsforHashSet<nsStringHashKey, nsString> {};
    164 
    165 template <typename E>
    166 struct ParamTraits<nsTArray<E>> {
    167  typedef nsTArray<E> paramType;
    168 
    169  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    170    WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
    171  }
    172 
    173  static void Write(MessageWriter* aWriter, paramType&& aParam) {
    174    WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
    175  }
    176 
    177  static bool Read(MessageReader* aReader, paramType* aResult) {
    178    return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
    179      if constexpr (std::is_trivially_default_constructible_v<E>) {
    180        return aResult->AppendElements(aLength);
    181      } else {
    182        aResult->SetCapacity(aLength);
    183        return mozilla::Some(MakeBackInserter(*aResult));
    184      }
    185    });
    186  }
    187 };
    188 
    189 template <typename E>
    190 struct ParamTraits<CopyableTArray<E>> : ParamTraits<nsTArray<E>> {};
    191 
    192 template <typename E>
    193 struct ParamTraits<FallibleTArray<E>> {
    194  typedef FallibleTArray<E> paramType;
    195 
    196  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    197    WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
    198  }
    199 
    200  static void Write(MessageWriter* aWriter, paramType&& aParam) {
    201    WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
    202  }
    203 
    204  static bool Read(MessageReader* aReader, paramType* aResult) {
    205    return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
    206      if constexpr (std::is_trivially_default_constructible_v<E>) {
    207        return aResult->AppendElements(aLength, mozilla::fallible);
    208      } else {
    209        if (!aResult->SetCapacity(aLength, mozilla::fallible)) {
    210          return mozilla::Maybe<BackInserter>{};
    211        }
    212        return mozilla::Some(BackInserter{.mArray = aResult});
    213      }
    214    });
    215  }
    216 
    217 private:
    218  struct BackInserter {
    219    using iterator_category = std::output_iterator_tag;
    220    using value_type = void;
    221    using difference_type = void;
    222    using pointer = void;
    223    using reference = void;
    224 
    225    struct Proxy {
    226      paramType& mArray;
    227 
    228      template <typename U>
    229      void operator=(U&& aValue) {
    230        // This won't fail because we've reserved capacity earlier.
    231        MOZ_ALWAYS_TRUE(mArray.AppendElement(aValue, mozilla::fallible));
    232      }
    233    };
    234    Proxy operator*() { return Proxy{.mArray = *mArray}; }
    235 
    236    BackInserter& operator++() { return *this; }
    237    BackInserter& operator++(int) { return *this; }
    238 
    239    paramType* mArray = nullptr;
    240  };
    241 };
    242 
    243 template <typename E, size_t N>
    244 struct ParamTraits<AutoTArray<E, N>> : ParamTraits<nsTArray<E>> {
    245  typedef AutoTArray<E, N> paramType;
    246 };
    247 
    248 template <typename E, size_t N>
    249 struct ParamTraits<CopyableAutoTArray<E, N>> : ParamTraits<AutoTArray<E, N>> {};
    250 
    251 template <typename T>
    252 struct ParamTraits<mozilla::dom::Sequence<T>> : ParamTraits<FallibleTArray<T>> {
    253 };
    254 
    255 template <typename E, size_t N, typename AP>
    256 struct ParamTraits<mozilla::Vector<E, N, AP>> {
    257  typedef mozilla::Vector<E, N, AP> paramType;
    258 
    259  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    260    WriteSequenceParam<const E&>(aWriter, aParam.Elements(), aParam.Length());
    261  }
    262 
    263  static void Write(MessageWriter* aWriter, paramType&& aParam) {
    264    WriteSequenceParam<E&&>(aWriter, aParam.Elements(), aParam.Length());
    265  }
    266 
    267  static bool Read(MessageReader* aReader, paramType* aResult) {
    268    return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) -> E* {
    269      if (!aResult->resize(aLength)) {
    270        // So that OOM failure shows up as OOM crash instead of IPC FatalError.
    271        NS_ABORT_OOM(aLength * sizeof(E));
    272      }
    273      return aResult->begin();
    274    });
    275  }
    276 };
    277 
    278 template <typename E>
    279 struct ParamTraits<std::vector<E>> {
    280  typedef std::vector<E> paramType;
    281 
    282  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    283    WriteSequenceParam<const E&>(aWriter, aParam.data(), aParam.size());
    284  }
    285  static void Write(MessageWriter* aWriter, paramType&& aParam) {
    286    WriteSequenceParam<E&&>(aWriter, aParam.data(), aParam.size());
    287  }
    288 
    289  static bool Read(MessageReader* aReader, paramType* aResult) {
    290    return ReadSequenceParam<E>(aReader, [&](uint32_t aLength) {
    291      if constexpr (std::is_trivially_default_constructible_v<E>) {
    292        aResult->resize(aLength);
    293        return aResult->data();
    294      } else {
    295        aResult->reserve(aLength);
    296        return mozilla::Some(std::back_inserter(*aResult));
    297      }
    298    });
    299  }
    300 };
    301 
    302 template <typename V, typename Compare, typename Allocator>
    303 struct ParamTraits<std::set<V, Compare, Allocator>> final {
    304  using T = std::set<V, Compare, Allocator>;
    305 
    306  static void Write(MessageWriter* const writer, const T& in) {
    307    WriteParam(writer, in.size());
    308    for (const auto& value : in) {
    309      WriteParam(writer, value);
    310    }
    311  }
    312 
    313  static bool Read(MessageReader* const reader, T* const out) {
    314    size_t size = 0;
    315    if (!ReadParam(reader, &size)) return false;
    316    T set;
    317    for (const auto i : mozilla::IntegerRange(size)) {
    318      V value;
    319      (void)i;
    320      if (!ReadParam(reader, &(value))) {
    321        return false;
    322      }
    323      set.insert(std::move(value));
    324    }
    325    *out = std::move(set);
    326    return true;
    327  }
    328 };
    329 
    330 template <typename K, typename V>
    331 struct ParamTraits<std::unordered_map<K, V>> final {
    332  using T = std::unordered_map<K, V>;
    333 
    334  static void Write(MessageWriter* const writer, const T& in) {
    335    WriteParam(writer, in.size());
    336    for (const auto& pair : in) {
    337      WriteParam(writer, pair.first);
    338      WriteParam(writer, pair.second);
    339    }
    340  }
    341 
    342  static bool Read(MessageReader* const reader, T* const out) {
    343    size_t size = 0;
    344    if (!ReadParam(reader, &size)) return false;
    345    T map;
    346    map.reserve(size);
    347    for (const auto i : mozilla::IntegerRange(size)) {
    348      std::pair<K, V> pair;
    349      (void)i;
    350      if (!ReadParam(reader, &(pair.first)) ||
    351          !ReadParam(reader, &(pair.second))) {
    352        return false;
    353      }
    354      map.insert(std::move(pair));
    355    }
    356    *out = std::move(map);
    357    return true;
    358  }
    359 };
    360 
    361 template <>
    362 struct ParamTraits<float> {
    363  typedef float paramType;
    364 
    365  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    366    aWriter->WriteBytes(&aParam, sizeof(paramType));
    367  }
    368 
    369  static bool Read(MessageReader* aReader, paramType* aResult) {
    370    return aReader->ReadBytesInto(aResult, sizeof(*aResult));
    371  }
    372 };
    373 
    374 template <>
    375 struct ParamTraits<NonCustomCSSPropertyId>
    376    : public ContiguousEnumSerializer<
    377          NonCustomCSSPropertyId, eCSSProperty_FIRST, eCSSProperty_INVALID> {};
    378 
    379 template <>
    380 struct ParamTraits<nsID> {
    381  typedef nsID paramType;
    382 
    383  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    384    WriteParam(aWriter, aParam.m0);
    385    WriteParam(aWriter, aParam.m1);
    386    WriteParam(aWriter, aParam.m2);
    387    for (unsigned int i = 0; i < std::size(aParam.m3); i++) {
    388      WriteParam(aWriter, aParam.m3[i]);
    389    }
    390  }
    391 
    392  static bool Read(MessageReader* aReader, paramType* aResult) {
    393    if (!ReadParam(aReader, &(aResult->m0)) ||
    394        !ReadParam(aReader, &(aResult->m1)) ||
    395        !ReadParam(aReader, &(aResult->m2)))
    396      return false;
    397 
    398    for (unsigned int i = 0; i < std::size(aResult->m3); i++)
    399      if (!ReadParam(aReader, &(aResult->m3[i]))) return false;
    400 
    401    return true;
    402  }
    403 };
    404 
    405 template <>
    406 struct ParamTraits<nsContentPolicyType>
    407    : public ContiguousEnumSerializer<nsContentPolicyType,
    408                                      nsIContentPolicy::TYPE_INVALID,
    409                                      nsIContentPolicy::TYPE_END> {};
    410 
    411 template <>
    412 struct ParamTraits<mozilla::TimeDuration> {
    413  typedef mozilla::TimeDuration paramType;
    414  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    415    WriteParam(aWriter, aParam.mValue);
    416  }
    417  static bool Read(MessageReader* aReader, paramType* aResult) {
    418    return ReadParam(aReader, &aResult->mValue);
    419  };
    420 };
    421 
    422 template <>
    423 struct ParamTraits<mozilla::TimeStamp> {
    424  typedef mozilla::TimeStamp paramType;
    425  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    426    WriteParam(aWriter, aParam.mValue);
    427  }
    428  static bool Read(MessageReader* aReader, paramType* aResult) {
    429    return ReadParam(aReader, &aResult->mValue);
    430  };
    431 };
    432 
    433 template <>
    434 struct ParamTraits<mozilla::dom::ipc::StructuredCloneData> {
    435  typedef mozilla::dom::ipc::StructuredCloneData paramType;
    436 
    437  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    438    aParam.WriteIPCParams(aWriter);
    439  }
    440 
    441  static bool Read(MessageReader* aReader, paramType* aResult) {
    442    return aResult->ReadIPCParams(aReader);
    443  }
    444 };
    445 
    446 template <class T>
    447 struct ParamTraits<mozilla::Maybe<T>> {
    448  typedef mozilla::Maybe<T> paramType;
    449 
    450  static void Write(MessageWriter* writer, const paramType& param) {
    451    if (param.isSome()) {
    452      WriteParam(writer, true);
    453      WriteParam(writer, param.ref());
    454    } else {
    455      WriteParam(writer, false);
    456    }
    457  }
    458 
    459  static void Write(MessageWriter* writer, paramType&& param) {
    460    if (param.isSome()) {
    461      WriteParam(writer, true);
    462      WriteParam(writer, std::move(param.ref()));
    463    } else {
    464      WriteParam(writer, false);
    465    }
    466  }
    467 
    468  static bool Read(MessageReader* reader, paramType* result) {
    469    bool isSome;
    470    if (!ReadParam(reader, &isSome)) {
    471      return false;
    472    }
    473    if (isSome) {
    474      mozilla::Maybe<T> tmp = ReadParam<T>(reader).TakeMaybe();
    475      if (!tmp) {
    476        return false;
    477      }
    478      *result = std::move(tmp);
    479    } else {
    480      *result = mozilla::Nothing();
    481    }
    482    return true;
    483  }
    484 };
    485 
    486 template <typename T, typename U>
    487 struct ParamTraits<mozilla::EnumSet<T, U>> {
    488  typedef mozilla::EnumSet<T, U> paramType;
    489  typedef U serializedType;
    490 
    491  static void Write(MessageWriter* writer, const paramType& param) {
    492    MOZ_RELEASE_ASSERT(IsLegalValue(param.serialize()));
    493    WriteParam(writer, param.serialize());
    494  }
    495 
    496  static bool Read(MessageReader* reader, paramType* result) {
    497    serializedType tmp;
    498 
    499    if (ReadParam(reader, &tmp)) {
    500      if (IsLegalValue(tmp)) {
    501        result->deserialize(tmp);
    502        return true;
    503      }
    504    }
    505 
    506    return false;
    507  }
    508 
    509  static constexpr size_t kUnderlyingWidth = [] {
    510    if constexpr (std::numeric_limits<serializedType>::is_specialized) {
    511      return std::numeric_limits<serializedType>::digits;
    512    } else {
    513      return serializedType().size();  // for std::bitset<N>
    514    }
    515  }();
    516 
    517  static constexpr serializedType AllEnumBits() {
    518    return ~serializedType(0) >>
    519           (kUnderlyingWidth - (mozilla::MaxEnumValue<T>::value + 1));
    520  }
    521 
    522  static constexpr bool IsLegalValue(const serializedType value) {
    523    static_assert(mozilla::MaxEnumValue<T>::value < kUnderlyingWidth,
    524                  "Enum max value is not in the range!");
    525    static_assert(
    526        std::is_unsigned<decltype(mozilla::MaxEnumValue<T>::value)>::value,
    527        "Type of MaxEnumValue<T>::value specialization should be unsigned!");
    528 
    529    return (value & AllEnumBits()) == value;
    530  }
    531 };
    532 
    533 template <class... Ts>
    534 struct ParamTraits<mozilla::Variant<Ts...>> {
    535  typedef mozilla::Variant<Ts...> paramType;
    536  using Tag = typename mozilla::detail::VariantTag<Ts...>::Type;
    537 
    538  static void Write(MessageWriter* writer, const paramType& param) {
    539    WriteParam(writer, param.tag);
    540    param.match([writer](const auto& t) { WriteParam(writer, t); });
    541  }
    542 
    543  // Because VariantReader is a nested struct, we need the dummy template
    544  // parameter to avoid making VariantReader<0> an explicit specialization,
    545  // which is not allowed for a nested class template
    546  template <size_t N, typename dummy = void>
    547  struct VariantReader {
    548    using Next = VariantReader<N - 1>;
    549 
    550    // Since the VariantReader specializations start at N , we need to
    551    // subtract one to look at N - 1, the first valid tag.  This means our
    552    // comparisons are off by 1.  If we get to N = 0 then we have failed to
    553    // find a match to the tag.
    554    static constexpr size_t Idx = N - 1;
    555    using T = typename mozilla::detail::Nth<Idx, Ts...>::Type;
    556 
    557    static ReadResult<paramType> Read(MessageReader* reader, Tag tag) {
    558      if (tag == Idx) {
    559        auto p = ReadParam<T>(reader);
    560        if (p) {
    561          return ReadResult<paramType>(
    562              std::in_place, mozilla::VariantIndex<Idx>{}, std::move(*p));
    563        }
    564        return {};
    565      } else {
    566        return Next::Read(reader, tag);
    567      }
    568    }
    569 
    570  };  // VariantReader<N>
    571 
    572  // Since we are conditioning on tag = N - 1 in the preceding specialization,
    573  // if we get to `VariantReader<0, dummy>` we have failed to find
    574  // a matching tag.
    575  template <typename dummy>
    576  struct VariantReader<0, dummy> {
    577    static ReadResult<paramType> Read(MessageReader* reader, Tag tag) {
    578      return {};
    579    }
    580  };
    581 
    582  static ReadResult<paramType> Read(MessageReader* reader) {
    583    Tag tag;
    584    if (ReadParam(reader, &tag)) {
    585      return VariantReader<sizeof...(Ts)>::Read(reader, tag);
    586    }
    587    return {};
    588  }
    589 };
    590 
    591 template <typename T>
    592 struct ParamTraits<mozilla::dom::Optional<T>> {
    593  typedef mozilla::dom::Optional<T> paramType;
    594 
    595  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    596    if (aParam.WasPassed()) {
    597      WriteParam(aWriter, true);
    598      WriteParam(aWriter, aParam.Value());
    599      return;
    600    }
    601 
    602    WriteParam(aWriter, false);
    603  }
    604 
    605  static bool Read(MessageReader* aReader, paramType* aResult) {
    606    bool wasPassed = false;
    607 
    608    if (!ReadParam(aReader, &wasPassed)) {
    609      return false;
    610    }
    611 
    612    aResult->Reset();
    613 
    614    if (wasPassed) {
    615      if (!ReadParam(aReader, &aResult->Construct())) {
    616        return false;
    617      }
    618    }
    619 
    620    return true;
    621  }
    622 };
    623 
    624 template <>
    625 struct ParamTraits<nsAtom*> {
    626  typedef nsAtom paramType;
    627 
    628  static void Write(MessageWriter* aWriter, const paramType* aParam);
    629  static bool Read(MessageReader* aReader, RefPtr<paramType>* aResult);
    630 };
    631 
    632 struct CrossOriginOpenerPolicyValidator {
    633  using IntegralType =
    634      std::underlying_type_t<nsILoadInfo::CrossOriginOpenerPolicy>;
    635 
    636  static bool IsLegalValue(const IntegralType e) {
    637    return AreIntegralValuesEqual(e, nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) ||
    638           AreIntegralValuesEqual(e, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN) ||
    639           AreIntegralValuesEqual(
    640               e, nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS) ||
    641           AreIntegralValuesEqual(
    642               e, nsILoadInfo::
    643                      OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP);
    644  }
    645 
    646 private:
    647  static bool AreIntegralValuesEqual(
    648      const IntegralType aLhs,
    649      const nsILoadInfo::CrossOriginOpenerPolicy aRhs) {
    650    return aLhs == static_cast<IntegralType>(aRhs);
    651  }
    652 };
    653 
    654 template <>
    655 struct ParamTraits<nsILoadInfo::CrossOriginOpenerPolicy>
    656    : EnumSerializer<nsILoadInfo::CrossOriginOpenerPolicy,
    657                     CrossOriginOpenerPolicyValidator> {};
    658 
    659 struct CrossOriginEmbedderPolicyValidator {
    660  using IntegralType =
    661      std::underlying_type_t<nsILoadInfo::CrossOriginEmbedderPolicy>;
    662 
    663  static bool IsLegalValue(const IntegralType e) {
    664    return AreIntegralValuesEqual(e, nsILoadInfo::EMBEDDER_POLICY_NULL) ||
    665           AreIntegralValuesEqual(e,
    666                                  nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) ||
    667           AreIntegralValuesEqual(e,
    668                                  nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS);
    669  }
    670 
    671 private:
    672  static bool AreIntegralValuesEqual(
    673      const IntegralType aLhs,
    674      const nsILoadInfo::CrossOriginEmbedderPolicy aRhs) {
    675    return aLhs == static_cast<IntegralType>(aRhs);
    676  }
    677 };
    678 
    679 template <>
    680 struct ParamTraits<nsILoadInfo::CrossOriginEmbedderPolicy>
    681    : EnumSerializer<nsILoadInfo::CrossOriginEmbedderPolicy,
    682                     CrossOriginEmbedderPolicyValidator> {};
    683 
    684 template <>
    685 struct ParamTraits<nsIThread::QoSPriority>
    686    : public ContiguousEnumSerializerInclusive<nsIThread::QoSPriority,
    687                                               nsIThread::QOS_PRIORITY_NORMAL,
    688                                               nsIThread::QOS_PRIORITY_LOW> {};
    689 
    690 template <size_t N, typename Word>
    691 struct ParamTraits<mozilla::BitSet<N, Word>> {
    692  typedef mozilla::BitSet<N, Word> paramType;
    693 
    694  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    695    for (Word word : aParam.Storage()) {
    696      WriteParam(aWriter, word);
    697    }
    698  }
    699 
    700  static bool Read(MessageReader* aReader, paramType* aResult) {
    701    for (Word& word : aResult->Storage()) {
    702      if (!ReadParam(aReader, &word)) {
    703        return false;
    704      }
    705    }
    706    return true;
    707  }
    708 };
    709 
    710 template <typename T>
    711 struct ParamTraits<mozilla::UniquePtr<T>> {
    712  typedef mozilla::UniquePtr<T> paramType;
    713 
    714  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    715    bool isNull = aParam == nullptr;
    716    WriteParam(aWriter, isNull);
    717 
    718    if (!isNull) {
    719      WriteParam(aWriter, *aParam.get());
    720    }
    721  }
    722 
    723  static bool Read(IPC::MessageReader* aReader, paramType* aResult) {
    724    bool isNull = true;
    725    if (!ReadParam(aReader, &isNull)) {
    726      return false;
    727    }
    728 
    729    if (isNull) {
    730      aResult->reset();
    731    } else {
    732      *aResult = mozilla::MakeUnique<T>();
    733      if (!ReadParam(aReader, aResult->get())) {
    734        return false;
    735      }
    736    }
    737    return true;
    738  }
    739 };
    740 
    741 template <typename... Ts>
    742 struct ParamTraits<std::tuple<Ts...>> {
    743  typedef std::tuple<Ts...> paramType;
    744 
    745  template <typename U>
    746  static void Write(IPC::MessageWriter* aWriter, U&& aParam) {
    747    WriteInternal(aWriter, std::forward<U>(aParam),
    748                  std::index_sequence_for<Ts...>{});
    749  }
    750 
    751  static bool Read(IPC::MessageReader* aReader, std::tuple<Ts...>* aResult) {
    752    return ReadInternal(aReader, *aResult, std::index_sequence_for<Ts...>{});
    753  }
    754 
    755 private:
    756  template <size_t... Is>
    757  static void WriteInternal(IPC::MessageWriter* aWriter,
    758                            const std::tuple<Ts...>& aParam,
    759                            std::index_sequence<Is...>) {
    760    WriteParams(aWriter, std::get<Is>(aParam)...);
    761  }
    762 
    763  template <size_t... Is>
    764  static void WriteInternal(IPC::MessageWriter* aWriter,
    765                            std::tuple<Ts...>&& aParam,
    766                            std::index_sequence<Is...>) {
    767    WriteParams(aWriter, std::move(std::get<Is>(aParam))...);
    768  }
    769 
    770  template <size_t... Is>
    771  static bool ReadInternal(IPC::MessageReader* aReader,
    772                           std::tuple<Ts...>& aResult,
    773                           std::index_sequence<Is...>) {
    774    return ReadParams(aReader, std::get<Is>(aResult)...);
    775  }
    776 };
    777 
    778 template <>
    779 struct ParamTraits<mozilla::net::LinkHeader> {
    780  typedef mozilla::net::LinkHeader paramType;
    781  constexpr static int kNumberOfMembers = 14;
    782  constexpr static int kSizeOfEachMember = sizeof(nsString);
    783  constexpr static int kExpectedSizeOfParamType =
    784      kNumberOfMembers * kSizeOfEachMember;
    785 
    786  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    787    static_assert(sizeof(paramType) == kExpectedSizeOfParamType,
    788                  "All members of should be written below.");
    789    // Bug 1860565: `aParam.mAnchor` is not written.
    790 
    791    WriteParam(aWriter, aParam.mHref);
    792    WriteParam(aWriter, aParam.mRel);
    793    WriteParam(aWriter, aParam.mTitle);
    794    WriteParam(aWriter, aParam.mNonce);
    795    WriteParam(aWriter, aParam.mIntegrity);
    796    WriteParam(aWriter, aParam.mSrcset);
    797    WriteParam(aWriter, aParam.mSizes);
    798    WriteParam(aWriter, aParam.mType);
    799    WriteParam(aWriter, aParam.mMedia);
    800    WriteParam(aWriter, aParam.mAnchor);
    801    WriteParam(aWriter, aParam.mCrossOrigin);
    802    WriteParam(aWriter, aParam.mReferrerPolicy);
    803    WriteParam(aWriter, aParam.mAs);
    804    WriteParam(aWriter, aParam.mFetchPriority);
    805  }
    806  static bool Read(MessageReader* aReader, paramType* aResult) {
    807    static_assert(sizeof(paramType) == kExpectedSizeOfParamType,
    808                  "All members of should be handled below.");
    809    // Bug 1860565: `aParam.mAnchor` is not handled.
    810 
    811    if (!ReadParam(aReader, &aResult->mHref)) {
    812      return false;
    813    }
    814    if (!ReadParam(aReader, &aResult->mRel)) {
    815      return false;
    816    }
    817    if (!ReadParam(aReader, &aResult->mTitle)) {
    818      return false;
    819    }
    820    if (!ReadParam(aReader, &aResult->mNonce)) {
    821      return false;
    822    }
    823    if (!ReadParam(aReader, &aResult->mIntegrity)) {
    824      return false;
    825    }
    826    if (!ReadParam(aReader, &aResult->mSrcset)) {
    827      return false;
    828    }
    829    if (!ReadParam(aReader, &aResult->mSizes)) {
    830      return false;
    831    }
    832    if (!ReadParam(aReader, &aResult->mType)) {
    833      return false;
    834    }
    835    if (!ReadParam(aReader, &aResult->mMedia)) {
    836      return false;
    837    }
    838    if (!ReadParam(aReader, &aResult->mAnchor)) {
    839      return false;
    840    }
    841    if (!ReadParam(aReader, &aResult->mCrossOrigin)) {
    842      return false;
    843    }
    844    if (!ReadParam(aReader, &aResult->mReferrerPolicy)) {
    845      return false;
    846    }
    847    if (!ReadParam(aReader, &aResult->mAs)) {
    848      return false;
    849    }
    850    return ReadParam(aReader, &aResult->mFetchPriority);
    851  };
    852 };
    853 
    854 template <>
    855 struct ParamTraits<mozilla::dom::UserActivation::Modifiers> {
    856  typedef mozilla::dom::UserActivation::Modifiers paramType;
    857  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    858    WriteParam(aWriter, aParam.mModifiers);
    859  }
    860  static bool Read(MessageReader* aReader, paramType* aResult) {
    861    return ReadParam(aReader, &aResult->mModifiers);
    862  };
    863 };
    864 
    865 template <>
    866 struct ParamTraits<gfxPlatform::GlobalReflowFlags>
    867    : public BitFlagsEnumSerializer<gfxPlatform::GlobalReflowFlags,
    868                                    gfxPlatform::GlobalReflowFlags::ALL_BITS> {
    869 };
    870 
    871 template <size_t N>
    872 struct ParamTraits<std::bitset<N>> {
    873  typedef std::bitset<N> paramType;
    874  static void Write(MessageWriter* aWriter, const paramType& aParam) {
    875    paramType mask(UINT64_MAX);
    876    for (size_t i = 0; i < N; i += 64) {
    877      uint64_t value = ((aParam >> i) & mask).to_ullong();
    878      WriteParam(aWriter, value);
    879    }
    880  }
    881 
    882  static bool Read(MessageReader* aReader, paramType* aResult) {
    883    for (size_t i = 0; i < N; i += 64) {
    884      uint64_t value = 0;
    885      if (!ReadParam(aReader, &value)) {
    886        return false;
    887      }
    888      *aResult |= std::bitset<N>(value) << i;
    889    }
    890    return true;
    891  }
    892 };
    893 
    894 template <>
    895 struct ParamTraits<nsILoadInfo::IPAddressSpace>
    896    : public ContiguousEnumSerializer<nsILoadInfo::IPAddressSpace,
    897                                      nsILoadInfo::IPAddressSpace::Unknown,
    898                                      nsILoadInfo::IPAddressSpace::Invalid> {};
    899 
    900 using PromptResult = mozilla::dom::ContentPermissionRequestBase::PromptResult;
    901 template <>
    902 struct ParamTraits<PromptResult>
    903    : public ContiguousEnumSerializerInclusive<
    904          PromptResult, PromptResult::Granted, PromptResult::Pending> {};
    905 
    906 } /* namespace IPC */
    907 
    908 #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */