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__ */