Bug 1791179 - Fix mistaken conditional in StaticPrefs. r=dragana, a=RyanVM
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__#define __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__#include<cstdint>#include<cstdlib>#include<limits>#include<string>#include<type_traits>#include<unordered_map>#include<utility>#include<vector>#include"chrome/common/ipc_message.h"#include"chrome/common/ipc_message_utils.h"#include"ipc/EnumSerializer.h"#include"ipc/IPCMessageUtils.h"#include"mozilla/Assertions.h"#include"mozilla/BitSet.h"#include"mozilla/EnumSet.h"#include"mozilla/EnumTypeTraits.h"#include"mozilla/IntegerRange.h"#include"mozilla/Maybe.h"#include"mozilla/TimeStamp.h"#ifdef XP_WIN# include "mozilla/TimeStamp_windows.h"#endif#include"mozilla/Tuple.h"#include"mozilla/UniquePtr.h"#include"mozilla/Unused.h"#include"mozilla/Vector.h"#include"mozilla/dom/ipc/StructuredCloneData.h"#include"nsCSSPropertyID.h"#include"nsDebug.h"#include"nsIContentPolicy.h"#include"nsID.h"#include"nsILoadInfo.h"#include"nsIThread.h"#include"nsLiteralString.h"#include"nsString.h"#include"nsTArray.h"#include"nsTHashSet.h"// XXX Includes that are only required by implementations which could be moved// to the cpp file.#include"base/string_util.h" // for StringPrintf#include"mozilla/ArrayUtils.h" // for ArrayLength#include"mozilla/CheckedInt.h"#ifdef _MSC_VER# pragma warning(disable : 4800)#endifnamespacemozilla{template<typename...Ts>classVariant;namespacedetail{template<typename...Ts>structVariantTag;}}// namespace mozillanamespacemozilla::dom{template<typenameT>classOptional;}classnsAtom;namespaceIPC{template<>structParamTraits<nsACString>{typedefnsACStringparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){boolisVoid=aParam.IsVoid();aWriter->WriteBool(isVoid);if(isVoid)// represents a nullptr pointerreturn;uint32_tlength=aParam.Length();WriteParam(aWriter,length);aWriter->WriteBytes(aParam.BeginReading(),length);}staticboolRead(MessageReader*aReader,paramType*aResult){boolisVoid;if(!aReader->ReadBool(&isVoid))returnfalse;if(isVoid){aResult->SetIsVoid(true);returntrue;}uint32_tlength;if(!ReadParam(aReader,&length)){returnfalse;}if(!aReader->HasBytesAvailable(length)){returnfalse;}aResult->SetLength(length);returnaReader->ReadBytesInto(aResult->BeginWriting(),length);}staticvoidLog(constparamType&aParam,std::wstring*aLog){if(aParam.IsVoid())aLog->append(L"(NULL)");elseaLog->append(UTF8ToWide(aParam.BeginReading()));}};template<>structParamTraits<nsAString>{typedefnsAStringparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){boolisVoid=aParam.IsVoid();aWriter->WriteBool(isVoid);if(isVoid)// represents a nullptr pointerreturn;uint32_tlength=aParam.Length();WriteParam(aWriter,length);aWriter->WriteBytes(aParam.BeginReading(),length*sizeof(char16_t));}staticboolRead(MessageReader*aReader,paramType*aResult){boolisVoid;if(!aReader->ReadBool(&isVoid))returnfalse;if(isVoid){aResult->SetIsVoid(true);returntrue;}uint32_tlength;if(!ReadParam(aReader,&length)){returnfalse;}mozilla::CheckedInt<uint32_t>byteLength=mozilla::CheckedInt<uint32_t>(length)*sizeof(char16_t);if(!byteLength.isValid()||!aReader->HasBytesAvailable(byteLength.value())){returnfalse;}aResult->SetLength(length);returnaReader->ReadBytesInto(aResult->BeginWriting(),byteLength.value());}staticvoidLog(constparamType&aParam,std::wstring*aLog){if(aParam.IsVoid())aLog->append(L"(NULL)");else{#ifdef WCHAR_T_IS_UTF16aLog->append(reinterpret_cast<constwchar_t*>(aParam.BeginReading()));#elseuint32_tlength=aParam.Length();for(uint32_tindex=0;index<length;index++){aLog->push_back(std::wstring::value_type(aParam[index]));}#endif}}};template<>structParamTraits<nsCString>:ParamTraits<nsACString>{typedefnsCStringparamType;};template<>structParamTraits<nsLiteralCString>:ParamTraits<nsACString>{typedefnsLiteralCStringparamType;};#ifdef MOZILLA_INTERNAL_APItemplate<>structParamTraits<nsAutoCString>:ParamTraits<nsCString>{typedefnsAutoCStringparamType;};#endif // MOZILLA_INTERNAL_APItemplate<>structParamTraits<nsString>:ParamTraits<nsAString>{typedefnsStringparamType;};template<>structParamTraits<nsLiteralString>:ParamTraits<nsAString>{typedefnsLiteralStringparamType;};template<>structParamTraits<nsDependentSubstring>:ParamTraits<nsAString>{typedefnsDependentSubstringparamType;};template<>structParamTraits<nsDependentCSubstring>:ParamTraits<nsACString>{typedefnsDependentCSubstringparamType;};#ifdef MOZILLA_INTERNAL_APItemplate<>structParamTraits<nsAutoString>:ParamTraits<nsString>{typedefnsAutoStringparamType;};#endif // MOZILLA_INTERNAL_API// XXX While this has no special dependencies, it's currently only used in// GfxMessageUtils and could be moved there, or generalized to potentially work// with any nsTHashSet.template<>structParamTraits<nsTHashSet<uint64_t>>{typedefnsTHashSet<uint64_t>paramType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){uint32_tcount=aParam.Count();WriteParam(aWriter,count);for(constauto&key:aParam){WriteParam(aWriter,key);}}staticboolRead(MessageReader*aReader,paramType*aResult){uint32_tcount;if(!ReadParam(aReader,&count)){returnfalse;}paramTypetable(count);for(uint32_ti=0;i<count;++i){uint64_tkey;if(!ReadParam(aReader,&key)){returnfalse;}table.Insert(key);}*aResult=std::move(table);returntrue;}};// Pickle::ReadBytes and ::WriteBytes take the length in ints, so we must// ensure there is no overflow. This returns |false| if it would overflow.// Otherwise, it returns |true| and places the byte length in |aByteLength|.boolByteLengthIsValid(uint32_taNumElements,size_taElementSize,int*aByteLength);template<typenameE>structParamTraits<nsTArray<E>>{typedefnsTArray<E>paramType;// We write arrays of integer or floating-point data using a single pickling// call, rather than writing each element individually. We deliberately do// not use mozilla::IsPod here because it is perfectly reasonable to have// a data structure T for which IsPod<T>::value is true, yet also have a// ParamTraits<T> specialization.staticconstexprboolsUseWriteBytes=(std::is_integral_v<E>||std::is_floating_point_v<E>);// Some serializers need to take a mutable reference to their backing object,// such as Shmem segments and Byte Buffers. These serializers take the// backing data and move it into the IPC layer for efficiency. `Write` uses a// forwarding reference as occasionally these types appear inside of IPDL// arrays.template<typenameU>staticvoidWrite(MessageWriter*aWriter,U&&aParam){uint32_tlength=aParam.Length();WriteParam(aWriter,length);if(sUseWriteBytes){intpickledLength=0;MOZ_RELEASE_ASSERT(ByteLengthIsValid(length,sizeof(E),&pickledLength));aWriter->WriteBytes(aParam.Elements(),pickledLength);}else{WriteValues(aWriter,std::forward<U>(aParam));}}// This method uses infallible allocation so that an OOM failure will// show up as an OOM crash rather than an IPC FatalError.staticboolRead(MessageReader*aReader,paramType*aResult){uint32_tlength;if(!ReadParam(aReader,&length)){returnfalse;}if(sUseWriteBytes){intpickledLength=0;if(!ByteLengthIsValid(length,sizeof(E),&pickledLength)){returnfalse;}E*elements=aResult->AppendElements(length);returnaReader->ReadBytesInto(elements,pickledLength);}else{// Each ReadParam<E> may read more than 1 byte each; this is an attempt// to minimally validate that the length isn't much larger than what's// actually available in aReader.if(!aReader->HasBytesAvailable(length)){returnfalse;}aResult->SetCapacity(length);for(uint32_tindex=0;index<length;index++){E*element=aResult->AppendElement();if(!ReadParam(aReader,element)){returnfalse;}}returntrue;}}staticvoidLog(constparamType&aParam,std::wstring*aLog){for(uint32_tindex=0;index<aParam.Length();index++){if(index){aLog->append(L" ");}LogParam(aParam[index],aLog);}}private:// Length has already been written. Const overload.staticvoidWriteValues(MessageWriter*aWriter,constparamType&aParam){for(auto&elt:aParam){WriteParam(aWriter,elt);}}// Length has already been written. Rvalue overload.staticvoidWriteValues(MessageWriter*aWriter,paramType&&aParam){for(auto&elt:aParam){WriteParam(aWriter,std::move(elt));}// As we just moved all of our values out, let's clean up after ourselves &// clear the input array. This means our move write method will act more// like a traditional move constructor.aParam.Clear();}};template<typenameE>structParamTraits<CopyableTArray<E>>:ParamTraits<nsTArray<E>>{};template<typenameE>structParamTraits<FallibleTArray<E>>{typedefFallibleTArray<E>paramType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){WriteParam(aWriter,static_cast<constnsTArray<E>&>(aParam));}// Deserialize the array infallibly, but return a FallibleTArray.staticboolRead(MessageReader*aReader,paramType*aResult){nsTArray<E>temp;if(!ReadParam(aReader,&temp))returnfalse;*aResult=std::move(temp);returntrue;}staticvoidLog(constparamType&aParam,std::wstring*aLog){LogParam(static_cast<constnsTArray<E>&>(aParam),aLog);}};template<typenameE,size_tN>structParamTraits<AutoTArray<E,N>>:ParamTraits<nsTArray<E>>{typedefAutoTArray<E,N>paramType;};template<typenameE,size_tN>structParamTraits<CopyableAutoTArray<E,N>>:ParamTraits<AutoTArray<E,N>>{};template<typenameT>structParamTraits<mozilla::dom::Sequence<T>>:ParamTraits<FallibleTArray<T>>{};template<typenameE,size_tN,typenameAP>structParamTraits<mozilla::Vector<E,N,AP>>{typedefmozilla::Vector<E,N,AP>paramType;// We write arrays of integer or floating-point data using a single pickling// call, rather than writing each element individually. We deliberately do// not use mozilla::IsPod here because it is perfectly reasonable to have// a data structure T for which IsPod<T>::value is true, yet also have a// ParamTraits<T> specialization.staticconstboolsUseWriteBytes=(std::is_integral_v<E>||std::is_floating_point_v<E>);staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){uint32_tlength=aParam.length();WriteParam(aWriter,length);if(sUseWriteBytes){intpickledLength=0;MOZ_RELEASE_ASSERT(ByteLengthIsValid(length,sizeof(E),&pickledLength));aWriter->WriteBytes(aParam.begin(),pickledLength);return;}for(constE&elem:aParam){WriteParam(aWriter,elem);}}staticboolRead(MessageReader*aReader,paramType*aResult){uint32_tlength;if(!ReadParam(aReader,&length)){returnfalse;}if(sUseWriteBytes){intpickledLength=0;if(!ByteLengthIsValid(length,sizeof(E),&pickledLength)){returnfalse;}if(!aResult->resizeUninitialized(length)){// So that OOM failure shows up as OOM crash instead of IPC FatalError.NS_ABORT_OOM(length*sizeof(E));}E*elements=aResult->begin();returnaReader->ReadBytesInto(elements,pickledLength);}// Each ReadParam<E> may read more than 1 byte each; this is an attempt// to minimally validate that the length isn't much larger than what's// actually available in aReader.if(!aReader->HasBytesAvailable(length)){returnfalse;}if(!aResult->resize(length)){// So that OOM failure shows up as OOM crash instead of IPC FatalError.NS_ABORT_OOM(length*sizeof(E));}for(uint32_tindex=0;index<length;++index){if(!ReadParam(aReader,&((*aResult)[index]))){returnfalse;}}returntrue;}staticvoidLog(constparamType&aParam,std::wstring*aLog){for(uint32_tindex=0,len=aParam.length();index<len;++index){if(index){aLog->append(L" ");}LogParam(aParam[index],aLog);}}};template<typenameE>structParamTraits<std::vector<E>>{typedefstd::vector<E>paramType;// We write arrays of integer or floating-point data using a single pickling// call, rather than writing each element individually. We deliberately do// not use mozilla::IsPod here because it is perfectly reasonable to have// a data structure T for which IsPod<T>::value is true, yet also have a// ParamTraits<T> specialization.staticconstboolsUseWriteBytes=(std::is_integral_v<E>||std::is_floating_point_v<E>);staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){uint32_tlength=aParam.size();WriteParam(aWriter,length);if(sUseWriteBytes){intpickledLength=0;MOZ_RELEASE_ASSERT(ByteLengthIsValid(length,sizeof(E),&pickledLength));aWriter->WriteBytes(aParam.data(),pickledLength);return;}for(constE&elem:aParam){WriteParam(aWriter,elem);}}staticboolRead(MessageReader*aReader,paramType*aResult){uint32_tlength;if(!ReadParam(aReader,&length)){returnfalse;}if(sUseWriteBytes){intpickledLength=0;if(!ByteLengthIsValid(length,sizeof(E),&pickledLength)){returnfalse;}aResult->resize(length);E*elements=aResult->data();returnaReader->ReadBytesInto(elements,pickledLength);}// Each ReadParam<E> may read more than 1 byte each; this is an attempt// to minimally validate that the length isn't much larger than what's// actually available in aReader.if(!aReader->HasBytesAvailable(length)){returnfalse;}aResult->resize(length);for(uint32_tindex=0;index<length;++index){if(!ReadParam(aReader,&((*aResult)[index]))){returnfalse;}}returntrue;}staticvoidLog(constparamType&aParam,std::wstring*aLog){for(uint32_tindex=0,len=aParam.size();index<len;++index){if(index){aLog->append(L" ");}LogParam(aParam[index],aLog);}}};template<typenameK,typenameV>structParamTraits<std::unordered_map<K,V>>final{usingT=std::unordered_map<K,V>;staticvoidWrite(MessageWriter*constwriter,constT&in){WriteParam(writer,in.size());for(constauto&pair:in){WriteParam(writer,pair.first);WriteParam(writer,pair.second);}}staticboolRead(MessageReader*constreader,T*constout){size_tsize=0;if(!ReadParam(reader,&size))returnfalse;Tmap;map.reserve(size);for(constautoi:mozilla::IntegerRange(size)){std::pair<K,V>pair;mozilla::Unused<<i;if(!ReadParam(reader,&(pair.first))||!ReadParam(reader,&(pair.second))){returnfalse;}map.insert(std::move(pair));}*out=std::move(map);returntrue;}};template<>structParamTraits<float>{typedeffloatparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){aWriter->WriteBytes(&aParam,sizeof(paramType));}staticboolRead(MessageReader*aReader,paramType*aResult){returnaReader->ReadBytesInto(aResult,sizeof(*aResult));}staticvoidLog(constparamType&aParam,std::wstring*aLog){aLog->append(StringPrintf(L"%g",aParam));}};template<>structParamTraits<nsCSSPropertyID>:publicContiguousEnumSerializer<nsCSSPropertyID,eCSSProperty_UNKNOWN,eCSSProperty_COUNT>{};template<>structParamTraits<nsID>{typedefnsIDparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){WriteParam(aWriter,aParam.m0);WriteParam(aWriter,aParam.m1);WriteParam(aWriter,aParam.m2);for(unsignedinti=0;i<mozilla::ArrayLength(aParam.m3);i++){WriteParam(aWriter,aParam.m3[i]);}}staticboolRead(MessageReader*aReader,paramType*aResult){if(!ReadParam(aReader,&(aResult->m0))||!ReadParam(aReader,&(aResult->m1))||!ReadParam(aReader,&(aResult->m2)))returnfalse;for(unsignedinti=0;i<mozilla::ArrayLength(aResult->m3);i++)if(!ReadParam(aReader,&(aResult->m3[i])))returnfalse;returntrue;}staticvoidLog(constparamType&aParam,std::wstring*aLog){aLog->append(L"{");aLog->append(StringPrintf(L"%8.8X-%4.4X-%4.4X-",aParam.m0,aParam.m1,aParam.m2));for(unsignedinti=0;i<mozilla::ArrayLength(aParam.m3);i++)aLog->append(StringPrintf(L"%2.2X",aParam.m3[i]));aLog->append(L"}");}};template<>structParamTraits<nsContentPolicyType>:publicContiguousEnumSerializerInclusive<nsContentPolicyType,nsIContentPolicy::TYPE_INVALID,nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD>{};template<>structParamTraits<mozilla::TimeDuration>{typedefmozilla::TimeDurationparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){WriteParam(aWriter,aParam.mValue);}staticboolRead(MessageReader*aReader,paramType*aResult){returnReadParam(aReader,&aResult->mValue);};};template<>structParamTraits<mozilla::TimeStamp>{typedefmozilla::TimeStampparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){WriteParam(aWriter,aParam.mValue);}staticboolRead(MessageReader*aReader,paramType*aResult){returnReadParam(aReader,&aResult->mValue);};};#ifdef XP_WINtemplate<>structParamTraits<mozilla::TimeStampValue>{typedefmozilla::TimeStampValueparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){WriteParam(aWriter,aParam.mGTC);WriteParam(aWriter,aParam.mQPC);WriteParam(aWriter,aParam.mIsNull);WriteParam(aWriter,aParam.mHasQPC);}staticboolRead(MessageReader*aReader,paramType*aResult){return(ReadParam(aReader,&aResult->mGTC)&&ReadParam(aReader,&aResult->mQPC)&&ReadParam(aReader,&aResult->mIsNull)&&ReadParam(aReader,&aResult->mHasQPC));}};#endiftemplate<>structParamTraits<mozilla::dom::ipc::StructuredCloneData>{typedefmozilla::dom::ipc::StructuredCloneDataparamType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){aParam.WriteIPCParams(aWriter);}staticboolRead(MessageReader*aReader,paramType*aResult){returnaResult->ReadIPCParams(aReader);}staticvoidLog(constparamType&aParam,std::wstring*aLog){LogParam(aParam.DataLength(),aLog);}};template<classT>structParamTraits<mozilla::Maybe<T>>{typedefmozilla::Maybe<T>paramType;staticvoidWrite(MessageWriter*writer,constparamType¶m){if(param.isSome()){WriteParam(writer,true);WriteParam(writer,param.ref());}else{WriteParam(writer,false);}}staticvoidWrite(MessageWriter*writer,paramType&¶m){if(param.isSome()){WriteParam(writer,true);WriteParam(writer,std::move(param.ref()));}else{WriteParam(writer,false);}}staticboolRead(MessageReader*reader,paramType*result){boolisSome;if(!ReadParam(reader,&isSome)){returnfalse;}if(isSome){Ttmp;if(!ReadParam(reader,&tmp)){returnfalse;}*result=mozilla::Some(std::move(tmp));}else{*result=mozilla::Nothing();}returntrue;}};template<typenameT,typenameU>structParamTraits<mozilla::EnumSet<T,U>>{typedefmozilla::EnumSet<T,U>paramType;typedefUserializedType;staticvoidWrite(MessageWriter*writer,constparamType¶m){MOZ_RELEASE_ASSERT(IsLegalValue(param.serialize()));WriteParam(writer,param.serialize());}staticboolRead(MessageReader*reader,paramType*result){serializedTypetmp;if(ReadParam(reader,&tmp)){if(IsLegalValue(tmp)){result->deserialize(tmp);returntrue;}}returnfalse;}staticconstexprserializedTypeAllEnumBits(){return~serializedType(0)>>(std::numeric_limits<serializedType>::digits-(mozilla::MaxEnumValue<T>::value+1));}staticconstexprboolIsLegalValue(constserializedTypevalue){static_assert(mozilla::MaxEnumValue<T>::value<std::numeric_limits<serializedType>::digits,"Enum max value is not in the range!");static_assert(std::is_unsigned<decltype(mozilla::MaxEnumValue<T>::value)>::value,"Type of MaxEnumValue<T>::value specialization should be unsigned!");return(value&AllEnumBits())==value;}};template<class...Ts>structParamTraits<mozilla::Variant<Ts...>>{typedefmozilla::Variant<Ts...>paramType;usingTag=typenamemozilla::detail::VariantTag<Ts...>::Type;staticvoidWrite(MessageWriter*writer,constparamType¶m){WriteParam(writer,param.tag);param.match([writer](constauto&t){WriteParam(writer,t);});}// Because VariantReader is a nested struct, we need the dummy template// parameter to avoid making VariantReader<0> an explicit specialization,// which is not allowed for a nested class templatetemplate<size_tN,typenamedummy=void>structVariantReader{usingNext=VariantReader<N-1>;staticboolRead(MessageReader*reader,Tagtag,paramType*result){// Since the VariantReader specializations start at N , we need to// subtract one to look at N - 1, the first valid tag. This means our// comparisons are off by 1. If we get to N = 0 then we have failed to// find a match to the tag.if(tag==N-1){// Recall, even though the template parameter is N, we are// actually interested in the N - 1 tag.// Default construct our field within the result outparameter and// directly deserialize into the variant. Note that this means that// every type in Ts needs to be default constructiblereturnReadParam(reader,&result->templateemplace<N-1>());}else{returnNext::Read(reader,tag,result);}}};// VariantReader<N>// Since we are conditioning on tag = N - 1 in the preceding specialization,// if we get to `VariantReader<0, dummy>` we have failed to find// a matching tag.template<typenamedummy>structVariantReader<0,dummy>{staticboolRead(MessageReader*reader,Tagtag,paramType*result){returnfalse;}};staticboolRead(MessageReader*reader,paramType*result){Tagtag;if(ReadParam(reader,&tag)){returnVariantReader<sizeof...(Ts)>::Read(reader,tag,result);}returnfalse;}};template<typenameT>structParamTraits<mozilla::dom::Optional<T>>{typedefmozilla::dom::Optional<T>paramType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){if(aParam.WasPassed()){WriteParam(aWriter,true);WriteParam(aWriter,aParam.Value());return;}WriteParam(aWriter,false);}staticboolRead(MessageReader*aReader,paramType*aResult){boolwasPassed=false;if(!ReadParam(aReader,&wasPassed)){returnfalse;}aResult->Reset();if(wasPassed){if(!ReadParam(aReader,&aResult->Construct())){returnfalse;}}returntrue;}};template<>structParamTraits<nsAtom*>{typedefnsAtomparamType;staticvoidWrite(MessageWriter*aWriter,constparamType*aParam);staticboolRead(MessageReader*aReader,RefPtr<paramType>*aResult);};structCrossOriginOpenerPolicyValidator{usingIntegralType=std::underlying_type_t<nsILoadInfo::CrossOriginOpenerPolicy>;staticboolIsLegalValue(constIntegralTypee){returnAreIntegralValuesEqual(e,nsILoadInfo::OPENER_POLICY_UNSAFE_NONE)||AreIntegralValuesEqual(e,nsILoadInfo::OPENER_POLICY_SAME_ORIGIN)||AreIntegralValuesEqual(e,nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS)||AreIntegralValuesEqual(e,nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP);}private:staticboolAreIntegralValuesEqual(constIntegralTypeaLhs,constnsILoadInfo::CrossOriginOpenerPolicyaRhs){returnaLhs==static_cast<IntegralType>(aRhs);}};template<>structParamTraits<nsILoadInfo::CrossOriginOpenerPolicy>:EnumSerializer<nsILoadInfo::CrossOriginOpenerPolicy,CrossOriginOpenerPolicyValidator>{};structCrossOriginEmbedderPolicyValidator{usingIntegralType=std::underlying_type_t<nsILoadInfo::CrossOriginEmbedderPolicy>;staticboolIsLegalValue(constIntegralTypee){returnAreIntegralValuesEqual(e,nsILoadInfo::EMBEDDER_POLICY_NULL)||AreIntegralValuesEqual(e,nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP)||AreIntegralValuesEqual(e,nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS);}private:staticboolAreIntegralValuesEqual(constIntegralTypeaLhs,constnsILoadInfo::CrossOriginEmbedderPolicyaRhs){returnaLhs==static_cast<IntegralType>(aRhs);}};template<>structParamTraits<nsILoadInfo::CrossOriginEmbedderPolicy>:EnumSerializer<nsILoadInfo::CrossOriginEmbedderPolicy,CrossOriginEmbedderPolicyValidator>{};template<size_tN,typenameWord>structParamTraits<mozilla::BitSet<N,Word>>{typedefmozilla::BitSet<N,Word>paramType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){for(Wordword:aParam.Storage()){WriteParam(aWriter,word);}}staticboolRead(MessageReader*aReader,paramType*aResult){for(Word&word:aResult->Storage()){if(!ReadParam(aReader,&word)){returnfalse;}}returntrue;}};template<typenameT>structParamTraits<mozilla::UniquePtr<T>>{typedefmozilla::UniquePtr<T>paramType;staticvoidWrite(MessageWriter*aWriter,constparamType&aParam){boolisNull=aParam==nullptr;WriteParam(aWriter,isNull);if(!isNull){WriteParam(aWriter,*aParam.get());}}staticboolRead(IPC::MessageReader*aReader,paramType*aResult){boolisNull=true;if(!ReadParam(aReader,&isNull)){returnfalse;}if(isNull){aResult->reset();}else{*aResult=mozilla::MakeUnique<T>();if(!ReadParam(aReader,aResult->get())){returnfalse;}}returntrue;}};template<typename...Ts>structParamTraits<mozilla::Tuple<Ts...>>{typedefmozilla::Tuple<Ts...>paramType;template<typenameU>staticvoidWrite(IPC::MessageWriter*aWriter,U&&aParam){WriteInternal(aWriter,std::forward<U>(aParam),std::index_sequence_for<Ts...>{});}staticboolRead(IPC::MessageReader*aReader,mozilla::Tuple<Ts...>*aResult){returnReadInternal(aReader,*aResult,std::index_sequence_for<Ts...>{});}private:template<size_t...Is>staticvoidWriteInternal(IPC::MessageWriter*aWriter,constmozilla::Tuple<Ts...>&aParam,std::index_sequence<Is...>){WriteParams(aWriter,mozilla::Get<Is>(aParam)...);}template<size_t...Is>staticvoidWriteInternal(IPC::MessageWriter*aWriter,mozilla::Tuple<Ts...>&&aParam,std::index_sequence<Is...>){WriteParams(aWriter,std::move(mozilla::Get<Is>(aParam))...);}template<size_t...Is>staticboolReadInternal(IPC::MessageReader*aReader,mozilla::Tuple<Ts...>&aResult,std::index_sequence<Is...>){returnReadParams(aReader,mozilla::Get<Is>(aResult)...);}};}/* namespace IPC */#endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */