2009-09-22 06:02:15 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2016-05-28 00:54:31 +03:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2009-06-29 22:38:29 +04:00
|
|
|
|
|
|
|
#ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
|
|
|
|
#define __IPC_GLUE_IPCMESSAGEUTILS_H__
|
|
|
|
|
2013-01-18 00:06:36 +04:00
|
|
|
#include "base/process_util.h"
|
2009-06-29 22:38:29 +04:00
|
|
|
#include "chrome/common/ipc_message_utils.h"
|
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2016-01-28 10:43:46 +03:00
|
|
|
#include "mozilla/Attributes.h"
|
2014-11-04 16:57:25 +03:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2015-09-10 23:50:58 +03:00
|
|
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
2017-12-27 23:46:03 +03:00
|
|
|
#include "mozilla/EnumSet.h"
|
2018-01-21 23:23:21 +03:00
|
|
|
#include "mozilla/EnumTypeTraits.h"
|
2015-05-26 22:40:24 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2015-10-26 18:31:00 +03:00
|
|
|
#include "mozilla/net/WebSocketFrame.h"
|
2012-07-31 21:28:20 +04:00
|
|
|
#include "mozilla/TimeStamp.h"
|
2013-02-12 01:56:58 +04:00
|
|
|
#ifdef XP_WIN
|
|
|
|
# include "mozilla/TimeStamp_windows.h"
|
|
|
|
#endif
|
2014-04-14 18:17:40 +04:00
|
|
|
#include "mozilla/IntegerTypeTraits.h"
|
2019-11-18 22:45:41 +03:00
|
|
|
#include "mozilla/Vector.h"
|
2013-07-30 18:25:31 +04:00
|
|
|
|
2018-01-21 23:23:21 +03:00
|
|
|
#include <limits>
|
2013-07-30 18:25:31 +04:00
|
|
|
#include <stdint.h>
|
2018-01-21 23:23:21 +03:00
|
|
|
#include <type_traits>
|
2019-11-18 22:45:41 +03:00
|
|
|
#include <vector>
|
2011-10-11 09:50:08 +04:00
|
|
|
|
2019-11-18 22:45:41 +03:00
|
|
|
#include "nsDebug.h"
|
2016-03-30 07:32:26 +03:00
|
|
|
#include "nsExceptionHandler.h"
|
2018-09-25 05:35:31 +03:00
|
|
|
#include "nsHashKeys.h"
|
2011-06-24 18:19:56 +04:00
|
|
|
#include "nsID.h"
|
2019-02-16 01:02:58 +03:00
|
|
|
#include "nsILoadInfo.h"
|
2015-04-14 18:36:36 +03:00
|
|
|
#include "nsIWidget.h"
|
2011-06-24 18:19:56 +04:00
|
|
|
#include "nsMemory.h"
|
2013-09-23 21:25:00 +04:00
|
|
|
#include "nsString.h"
|
2009-06-29 22:38:29 +04:00
|
|
|
#include "nsTArray.h"
|
2018-09-25 05:35:31 +03:00
|
|
|
#include "nsTHashtable.h"
|
2013-08-20 10:43:47 +04:00
|
|
|
#include "js/StructuredClone.h"
|
2016-08-10 02:28:19 +03:00
|
|
|
#include "nsCSSPropertyID.h"
|
2009-06-29 22:38:29 +04:00
|
|
|
|
2010-01-22 18:06:13 +03:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
# pragma warning(disable : 4800)
|
|
|
|
#endif
|
|
|
|
|
2010-11-09 05:48:59 +03:00
|
|
|
#if !defined(OS_POSIX)
|
|
|
|
// This condition must be kept in sync with the one in
|
|
|
|
// ipc_message_utils.h, but this dummy definition of
|
|
|
|
// base::FileDescriptor acts as a static assert that we only get one
|
|
|
|
// def or the other (or neither, in which case code using
|
|
|
|
// FileDescriptor fails to build)
|
2012-01-18 06:01:51 +04:00
|
|
|
namespace base {
|
|
|
|
struct FileDescriptor {};
|
|
|
|
} // namespace base
|
2010-11-09 05:48:59 +03:00
|
|
|
#endif
|
2010-05-22 23:35:40 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
2011-07-22 04:49:35 +04:00
|
|
|
// This is a cross-platform approximation to HANDLE, which we expect
|
|
|
|
// to be typedef'd to void* or thereabouts.
|
|
|
|
typedef uintptr_t WindowsHandle;
|
|
|
|
|
2010-05-22 23:35:40 +04:00
|
|
|
// XXX there are out of place and might be generally useful. Could
|
|
|
|
// move to nscore.h or something.
|
2010-05-22 23:35:42 +04:00
|
|
|
struct void_t {
|
|
|
|
bool operator==(const void_t&) const { return true; }
|
|
|
|
};
|
|
|
|
struct null_t {
|
|
|
|
bool operator==(const null_t&) const { return true; }
|
|
|
|
};
|
2010-05-22 23:35:40 +04:00
|
|
|
|
2016-04-22 13:04:20 +03:00
|
|
|
struct SerializedStructuredCloneBuffer final {
|
2020-02-14 03:57:39 +03:00
|
|
|
SerializedStructuredCloneBuffer() = default;
|
2018-04-03 21:17:33 +03:00
|
|
|
|
2020-02-01 18:26:37 +03:00
|
|
|
SerializedStructuredCloneBuffer(SerializedStructuredCloneBuffer&&) = default;
|
|
|
|
SerializedStructuredCloneBuffer& operator=(
|
|
|
|
SerializedStructuredCloneBuffer&&) = default;
|
|
|
|
|
2020-02-01 18:16:43 +03:00
|
|
|
SerializedStructuredCloneBuffer(const SerializedStructuredCloneBuffer&) =
|
|
|
|
delete;
|
2016-04-22 13:04:20 +03:00
|
|
|
SerializedStructuredCloneBuffer& operator=(
|
2020-02-01 18:16:43 +03:00
|
|
|
const SerializedStructuredCloneBuffer& aOther) = delete;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
bool operator==(const SerializedStructuredCloneBuffer& aOther) const {
|
2016-04-22 13:04:20 +03:00
|
|
|
// The copy assignment operator and the equality operator are
|
|
|
|
// needed by the IPDL generated code. We relied on the copy
|
|
|
|
// assignment operator at some places but we never use the
|
|
|
|
// equality operator.
|
|
|
|
return false;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2020-02-14 03:57:39 +03:00
|
|
|
JSStructuredCloneData data{JS::StructuredCloneScope::Unassigned};
|
2012-08-02 10:02:29 +04:00
|
|
|
};
|
|
|
|
|
2010-05-22 23:35:40 +04:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2009-06-29 22:38:29 +04:00
|
|
|
namespace IPC {
|
|
|
|
|
2011-11-24 15:45:55 +04:00
|
|
|
/**
|
|
|
|
* Generic enum serializer.
|
2012-02-05 23:51:06 +04:00
|
|
|
*
|
2014-04-14 18:17:40 +04:00
|
|
|
* Consider using the specializations below, such as ContiguousEnumSerializer.
|
|
|
|
*
|
2012-02-05 23:51:06 +04:00
|
|
|
* This is a generic serializer for any enum type used in IPDL.
|
|
|
|
* Programmers can define ParamTraits<E> for enum type E by deriving
|
2014-04-14 18:17:40 +04:00
|
|
|
* EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
|
|
|
|
* that has to define a static IsLegalValue function returning whether
|
|
|
|
* a given value is a legal value of the enum type at hand.
|
2012-02-05 23:51:06 +04:00
|
|
|
*
|
|
|
|
* \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
|
2011-11-24 15:45:55 +04:00
|
|
|
*/
|
2014-04-14 18:17:40 +04:00
|
|
|
template <typename E, typename EnumValidator>
|
2011-11-24 15:45:55 +04:00
|
|
|
struct EnumSerializer {
|
|
|
|
typedef E paramType;
|
2014-04-14 18:17:40 +04:00
|
|
|
typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type
|
|
|
|
uintParamType;
|
2011-11-24 15:45:55 +04:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aValue) {
|
2017-04-13 23:55:10 +03:00
|
|
|
MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(aValue));
|
2014-04-14 18:17:40 +04:00
|
|
|
WriteParam(aMsg, uintParamType(aValue));
|
2011-11-24 15:45:55 +04:00
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2014-04-14 18:17:40 +04:00
|
|
|
uintParamType value;
|
2016-03-30 07:32:26 +03:00
|
|
|
if (!ReadParam(aMsg, aIter, &value)) {
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
CrashReporter::Annotation::IPCReadErrorReason,
|
|
|
|
NS_LITERAL_CSTRING("Bad iter"));
|
2016-03-30 07:32:26 +03:00
|
|
|
return false;
|
|
|
|
} else if (!EnumValidator::IsLegalValue(paramType(value))) {
|
Bug 1348273 - Convert crash annotations into a machine-readable list of constants; r=ted.mielczarek,njn,dholbert,mak,cpearce,mcmanus,froydnj,Dexter,jrmuizel,jchen,jimm,bz,surkov
This introduces the machinery needed to generate crash annotations from a YAML
file. The relevant C++ functions are updated to take a typed enum. JavaScript
calls are unaffected but they will throw if the string argument does not
correspond to one of the known entries in the C++ enum. The existing whitelists
and blacklists of annotations are also generated from the YAML file and all
duplicate code related to them has been consolidated. Once written out to the
.extra file the annotations are converted in string form and are no different
than the existing ones.
All existing annotations have been included in the list (and some obsolete ones
have been removed) and all call sites have been updated including tests where
appropriate.
--HG--
extra : source : 4f6c43f2830701ec5552e08e3f1b06fe6d045860
2018-07-05 16:42:11 +03:00
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
CrashReporter::Annotation::IPCReadErrorReason,
|
|
|
|
NS_LITERAL_CSTRING("Illegal value"));
|
2011-11-24 15:45:55 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*aResult = paramType(value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-01-10 23:06:12 +04:00
|
|
|
template <typename E, E MinLegal, E HighBound>
|
2015-01-26 01:22:08 +03:00
|
|
|
class ContiguousEnumValidator {
|
2014-04-14 18:17:40 +04:00
|
|
|
// Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
|
|
|
|
// "comparison of unsigned expression >= 0 is always true"
|
|
|
|
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
|
|
|
|
template <typename T>
|
|
|
|
static bool IsLessThanOrEqual(T a, T b) {
|
|
|
|
return a <= b;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
static bool IsLegalValue(E e) {
|
2015-01-26 01:22:08 +03:00
|
|
|
return IsLessThanOrEqual(MinLegal, e) && e < HighBound;
|
2014-01-10 23:06:12 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-01 04:18:49 +03:00
|
|
|
template <typename E, E MinLegal, E MaxLegal>
|
|
|
|
class ContiguousEnumValidatorInclusive {
|
|
|
|
// Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
|
|
|
|
// "comparison of unsigned expression >= 0 is always true"
|
|
|
|
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
|
|
|
|
template <typename T>
|
|
|
|
static bool IsLessThanOrEqual(T a, T b) {
|
|
|
|
return a <= b;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
static bool IsLegalValue(E e) {
|
|
|
|
return IsLessThanOrEqual(MinLegal, e) && e <= MaxLegal;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-26 06:34:04 +04:00
|
|
|
template <typename E, E AllBits>
|
|
|
|
struct BitFlagsEnumValidator {
|
|
|
|
static bool IsLegalValue(E e) { return (e & AllBits) == e; }
|
|
|
|
};
|
|
|
|
|
2014-04-14 18:17:40 +04:00
|
|
|
/**
|
|
|
|
* Specialization of EnumSerializer for enums with contiguous enum values.
|
|
|
|
*
|
|
|
|
* Provide two values: MinLegal, HighBound. An enum value x will be
|
|
|
|
* considered legal if MinLegal <= x < HighBound.
|
|
|
|
*
|
|
|
|
* For example, following is definition of serializer for enum type FOO.
|
|
|
|
* \code
|
|
|
|
* enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
|
|
|
|
*
|
|
|
|
* template <>
|
|
|
|
* struct ParamTraits<FOO>:
|
|
|
|
* public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
|
|
|
|
* \endcode
|
|
|
|
* FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
|
|
|
|
*/
|
|
|
|
template <typename E, E MinLegal, E HighBound>
|
|
|
|
struct ContiguousEnumSerializer
|
|
|
|
: EnumSerializer<E, ContiguousEnumValidator<E, MinLegal, HighBound>> {};
|
2017-07-01 04:18:49 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This is similar to ContiguousEnumSerializer, but the last template
|
|
|
|
* parameter is expected to be the highest legal value, rather than a
|
|
|
|
* sentinel value. This is intended to support enumerations that don't
|
|
|
|
* have sentinel values.
|
|
|
|
*/
|
|
|
|
template <typename E, E MinLegal, E MaxLegal>
|
|
|
|
struct ContiguousEnumSerializerInclusive
|
|
|
|
: EnumSerializer<E,
|
|
|
|
ContiguousEnumValidatorInclusive<E, MinLegal, MaxLegal>> {
|
|
|
|
};
|
2014-04-14 18:17:40 +04:00
|
|
|
|
2014-04-26 06:34:04 +04:00
|
|
|
/**
|
|
|
|
* Specialization of EnumSerializer for enums representing bit flags.
|
|
|
|
*
|
|
|
|
* Provide one value: AllBits. An enum value x will be
|
|
|
|
* considered legal if (x & AllBits) == x;
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* \code
|
|
|
|
* enum FOO {
|
|
|
|
* FOO_FIRST = 1 << 0,
|
|
|
|
* FOO_SECOND = 1 << 1,
|
|
|
|
* FOO_LAST = 1 << 2,
|
|
|
|
* ALL_BITS = (1 << 3) - 1
|
|
|
|
* };
|
|
|
|
*
|
|
|
|
* template <>
|
|
|
|
* struct ParamTraits<FOO>:
|
|
|
|
* public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
|
|
|
|
* \endcode
|
|
|
|
*/
|
|
|
|
template <typename E, E AllBits>
|
|
|
|
struct BitFlagsEnumSerializer
|
|
|
|
: EnumSerializer<E, BitFlagsEnumValidator<E, AllBits>> {};
|
|
|
|
|
2017-05-04 03:21:11 +03:00
|
|
|
/**
|
|
|
|
* A helper class for serializing plain-old data (POD) structures.
|
|
|
|
* The memory representation of the structure is written to and read from
|
|
|
|
* the serialized stream directly, without individual processing of the
|
|
|
|
* structure's members.
|
|
|
|
*
|
|
|
|
* Derive ParamTraits<T> from PlainOldDataSerializer<T> if T is POD.
|
2017-10-19 03:13:19 +03:00
|
|
|
*
|
|
|
|
* Note: For POD structures with enumeration fields, this will not do
|
|
|
|
* validation of the enum values the way serializing the fields
|
|
|
|
* individually would. Prefer serializing the fields individually
|
|
|
|
* in such cases.
|
2017-05-04 03:21:11 +03:00
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
struct PlainOldDataSerializer {
|
2020-03-14 07:12:50 +03:00
|
|
|
static_assert(
|
|
|
|
std::is_trivially_copyable<T>::value,
|
|
|
|
"PlainOldDataSerializer can only be used with trivially copyable types!");
|
|
|
|
|
2017-05-04 03:21:11 +03:00
|
|
|
typedef T paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aMsg->WriteBytes(&aParam, sizeof(aParam));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
return aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-02 22:10:40 +03:00
|
|
|
/**
|
|
|
|
* A helper class for serializing empty structs. Since the struct is empty there
|
|
|
|
* is nothing to write, and a priori we know the result of the read.
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
struct EmptyStructSerializer {
|
|
|
|
typedef T paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
*aResult = {};
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-26 01:47:39 +03:00
|
|
|
template <>
|
2012-08-22 19:56:38 +04:00
|
|
|
struct ParamTraits<int8_t> {
|
|
|
|
typedef int8_t paramType;
|
2010-01-26 01:47:39 +03:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aMsg->WriteBytes(&aParam, sizeof(aParam));
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-05-17 00:32:37 +03:00
|
|
|
return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
|
2010-01-26 01:47:39 +03:00
|
|
|
}
|
2017-11-06 21:34:47 +03:00
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
// Use 0xff to avoid sign extension.
|
|
|
|
aLog->append(StringPrintf(L"0x%02x", aParam & 0xff));
|
|
|
|
}
|
2010-01-26 01:47:39 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
2012-08-22 19:56:38 +04:00
|
|
|
struct ParamTraits<uint8_t> {
|
|
|
|
typedef uint8_t paramType;
|
2010-01-26 01:47:39 +03:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aMsg->WriteBytes(&aParam, sizeof(aParam));
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-05-17 00:32:37 +03:00
|
|
|
return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
|
2010-01-26 01:47:39 +03:00
|
|
|
}
|
2017-11-06 21:34:47 +03:00
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
aLog->append(StringPrintf(L"0x%02x", aParam));
|
|
|
|
}
|
2010-01-26 01:47:39 +03:00
|
|
|
};
|
|
|
|
|
2010-11-09 05:48:59 +03:00
|
|
|
#if !defined(OS_POSIX)
|
|
|
|
// See above re: keeping definitions in sync
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<base::FileDescriptor> {
|
|
|
|
typedef base::FileDescriptor paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
|
2010-11-09 05:48:59 +03:00
|
|
|
}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("FileDescriptor isn't meaningful on this platform");
|
2010-11-09 05:48:59 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // !defined(OS_POSIX)
|
|
|
|
|
2009-06-29 22:38:29 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsACString> {
|
|
|
|
typedef nsACString paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2009-09-22 06:02:15 +04:00
|
|
|
bool isVoid = aParam.IsVoid();
|
|
|
|
aMsg->WriteBool(isVoid);
|
|
|
|
|
|
|
|
if (isVoid)
|
2013-08-23 23:51:58 +04:00
|
|
|
// represents a nullptr pointer
|
2009-09-22 06:02:15 +04:00
|
|
|
return;
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length = aParam.Length();
|
2009-06-29 22:38:29 +04:00
|
|
|
WriteParam(aMsg, length);
|
|
|
|
aMsg->WriteBytes(aParam.BeginReading(), length);
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2009-09-22 06:02:15 +04:00
|
|
|
bool isVoid;
|
|
|
|
if (!aMsg->ReadBool(aIter, &isVoid)) return false;
|
|
|
|
|
|
|
|
if (isVoid) {
|
2011-10-17 18:59:28 +04:00
|
|
|
aResult->SetIsVoid(true);
|
2009-09-22 06:02:15 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length;
|
2016-05-17 00:32:37 +03:00
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
|
|
|
return false;
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
2018-04-19 23:53:29 +03:00
|
|
|
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-17 00:32:37 +03:00
|
|
|
aResult->SetLength(length);
|
|
|
|
|
|
|
|
return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(), length);
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
2009-09-22 06:02:15 +04:00
|
|
|
if (aParam.IsVoid())
|
|
|
|
aLog->append(L"(NULL)");
|
|
|
|
else
|
|
|
|
aLog->append(UTF8ToWide(aParam.BeginReading()));
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsAString> {
|
|
|
|
typedef nsAString paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2009-09-22 06:02:15 +04:00
|
|
|
bool isVoid = aParam.IsVoid();
|
|
|
|
aMsg->WriteBool(isVoid);
|
|
|
|
|
|
|
|
if (isVoid)
|
2013-08-23 23:51:58 +04:00
|
|
|
// represents a nullptr pointer
|
2009-09-22 06:02:15 +04:00
|
|
|
return;
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length = aParam.Length();
|
2009-06-29 22:38:29 +04:00
|
|
|
WriteParam(aMsg, length);
|
2014-01-04 19:02:17 +04:00
|
|
|
aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(char16_t));
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2009-09-22 06:02:15 +04:00
|
|
|
bool isVoid;
|
|
|
|
if (!aMsg->ReadBool(aIter, &isVoid)) return false;
|
|
|
|
|
|
|
|
if (isVoid) {
|
2011-10-17 18:59:28 +04:00
|
|
|
aResult->SetIsVoid(true);
|
2009-09-22 06:02:15 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length;
|
2016-05-17 00:32:37 +03:00
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
|
|
|
return false;
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
2017-10-27 23:13:46 +03:00
|
|
|
|
|
|
|
mozilla::CheckedInt<uint32_t> byteLength =
|
|
|
|
mozilla::CheckedInt<uint32_t>(length) * sizeof(char16_t);
|
2018-04-19 23:53:29 +03:00
|
|
|
if (!byteLength.isValid() ||
|
|
|
|
!aMsg->HasBytesAvailable(aIter, byteLength.value())) {
|
2017-10-27 23:13:46 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-04-19 23:53:29 +03:00
|
|
|
aResult->SetLength(length);
|
|
|
|
|
2017-10-27 23:13:46 +03:00
|
|
|
return aMsg->ReadBytesInto(aIter, aResult->BeginWriting(),
|
|
|
|
byteLength.value());
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
2009-09-22 06:02:15 +04:00
|
|
|
if (aParam.IsVoid())
|
|
|
|
aLog->append(L"(NULL)");
|
|
|
|
else {
|
2009-06-29 22:38:29 +04:00
|
|
|
#ifdef WCHAR_T_IS_UTF16
|
2009-09-22 06:02:15 +04:00
|
|
|
aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading()));
|
2009-06-29 22:38:29 +04:00
|
|
|
#else
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length = aParam.Length();
|
|
|
|
for (uint32_t index = 0; index < length; index++) {
|
2009-09-22 06:02:15 +04:00
|
|
|
aLog->push_back(std::wstring::value_type(aParam[index]));
|
|
|
|
}
|
2009-06-29 22:38:29 +04:00
|
|
|
#endif
|
2009-09-22 06:02:15 +04:00
|
|
|
}
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-07-30 01:12:15 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsCString> : ParamTraits<nsACString> {
|
|
|
|
typedef nsCString paramType;
|
|
|
|
};
|
|
|
|
|
2014-01-09 00:51:38 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsLiteralCString> : ParamTraits<nsACString> {
|
|
|
|
typedef nsLiteralCString paramType;
|
|
|
|
};
|
|
|
|
|
2010-03-23 18:14:36 +03:00
|
|
|
#ifdef MOZILLA_INTERNAL_API
|
|
|
|
|
|
|
|
template <>
|
2012-09-02 06:35:17 +04:00
|
|
|
struct ParamTraits<nsAutoCString> : ParamTraits<nsCString> {
|
|
|
|
typedef nsAutoCString paramType;
|
2010-03-23 18:14:36 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // MOZILLA_INTERNAL_API
|
|
|
|
|
2009-07-30 01:12:15 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsString> : ParamTraits<nsAString> {
|
|
|
|
typedef nsString paramType;
|
|
|
|
};
|
|
|
|
|
2014-01-09 00:51:38 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsLiteralString> : ParamTraits<nsAString> {
|
|
|
|
typedef nsLiteralString paramType;
|
|
|
|
};
|
|
|
|
|
2017-02-16 03:26:04 +03:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsDependentSubstring> : ParamTraits<nsAString> {
|
|
|
|
typedef nsDependentSubstring paramType;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsDependentCSubstring> : ParamTraits<nsACString> {
|
|
|
|
typedef nsDependentCSubstring paramType;
|
|
|
|
};
|
|
|
|
|
2017-01-17 15:06:00 +03:00
|
|
|
#ifdef MOZILLA_INTERNAL_API
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsAutoString> : ParamTraits<nsString> {
|
|
|
|
typedef nsAutoString paramType;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // MOZILLA_INTERNAL_API
|
|
|
|
|
2018-09-25 05:35:31 +03:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsTHashtable<nsUint64HashKey>> {
|
|
|
|
typedef nsTHashtable<nsUint64HashKey> paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
uint32_t count = aParam.Count();
|
|
|
|
WriteParam(aMsg, count);
|
|
|
|
for (auto iter = aParam.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
WriteParam(aMsg, iter.Get()->GetKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
uint32_t count;
|
|
|
|
if (!ReadParam(aMsg, aIter, &count)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
paramType table(count);
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
uint64_t key;
|
|
|
|
if (!ReadParam(aMsg, aIter, &key)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
table.PutEntry(key);
|
|
|
|
}
|
|
|
|
*aResult = std::move(table);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-04-28 20:00:46 +03:00
|
|
|
// 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|.
|
|
|
|
bool ByteLengthIsValid(uint32_t aNumElements, size_t aElementSize,
|
|
|
|
int* aByteLength);
|
|
|
|
|
2016-05-03 19:29:39 +03:00
|
|
|
// Note: IPDL will sometimes codegen specialized implementations of
|
|
|
|
// nsTArray serialization and deserialization code in
|
|
|
|
// implementSpecialArrayPickling(). This is needed when ParamTraits<E>
|
|
|
|
// is not defined.
|
2012-12-19 05:16:06 +04:00
|
|
|
template <typename E>
|
2016-05-03 19:29:39 +03:00
|
|
|
struct ParamTraits<nsTArray<E>> {
|
|
|
|
typedef nsTArray<E> paramType;
|
2009-06-29 22:38:29 +04:00
|
|
|
|
2014-11-04 16:57:25 +03:00
|
|
|
// 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.
|
|
|
|
static const bool sUseWriteBytes =
|
2020-03-28 16:57:15 +03:00
|
|
|
(std::is_integral_v<E> || std::is_floating_point_v<E>);
|
2014-11-04 16:57:25 +03:00
|
|
|
|
2009-06-29 22:38:29 +04:00
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length = aParam.Length();
|
2009-06-29 22:38:29 +04:00
|
|
|
WriteParam(aMsg, length);
|
2014-11-04 16:57:25 +03:00
|
|
|
|
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
2016-04-28 20:00:46 +03:00
|
|
|
MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
|
2014-11-04 16:57:25 +03:00
|
|
|
aMsg->WriteBytes(aParam.Elements(), pickledLength);
|
|
|
|
} else {
|
2016-09-02 23:14:28 +03:00
|
|
|
const E* elems = aParam.Elements();
|
2014-11-04 16:57:25 +03:00
|
|
|
for (uint32_t index = 0; index < length; index++) {
|
2016-09-02 23:14:28 +03:00
|
|
|
WriteParam(aMsg, elems[index]);
|
2014-11-04 16:57:25 +03:00
|
|
|
}
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 19:29:39 +03:00
|
|
|
// This method uses infallible allocation so that an OOM failure will
|
|
|
|
// show up as an OOM crash rather than an IPC FatalError.
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t length;
|
2009-06-29 22:38:29 +04:00
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-11-04 16:57:25 +03:00
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
2016-04-28 20:00:46 +03:00
|
|
|
if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
|
2009-08-06 02:36:33 +04:00
|
|
|
return false;
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
2014-11-04 16:57:25 +03:00
|
|
|
|
2016-05-03 19:29:39 +03:00
|
|
|
E* elements = aResult->AppendElements(length);
|
2016-05-17 00:32:37 +03:00
|
|
|
return aMsg->ReadBytesInto(aIter, elements, pickledLength);
|
2014-11-04 16:57:25 +03:00
|
|
|
} else {
|
2018-04-19 23:53:29 +03:00
|
|
|
// 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 aMsg.
|
|
|
|
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-03 19:29:39 +03:00
|
|
|
aResult->SetCapacity(length);
|
2014-11-04 16:57:25 +03:00
|
|
|
|
|
|
|
for (uint32_t index = 0; index < length; index++) {
|
2016-05-03 19:29:39 +03:00
|
|
|
E* element = aResult->AppendElement();
|
2014-11-04 16:57:25 +03:00
|
|
|
if (!ReadParam(aMsg, aIter, element)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-05-17 00:32:37 +03:00
|
|
|
return true;
|
2009-06-29 22:38:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t index = 0; index < aParam.Length(); index++) {
|
2009-06-29 22:38:29 +04:00
|
|
|
if (index) {
|
|
|
|
aLog->append(L" ");
|
|
|
|
}
|
|
|
|
LogParam(aParam[index], aLog);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-30 12:36:04 +03:00
|
|
|
template <typename E>
|
|
|
|
struct ParamTraits<CopyableTArray<E>> : ParamTraits<nsTArray<E>> {};
|
|
|
|
|
2010-11-09 05:49:00 +03:00
|
|
|
template <typename E>
|
2016-05-03 19:29:39 +03:00
|
|
|
struct ParamTraits<FallibleTArray<E>> {
|
|
|
|
typedef FallibleTArray<E> paramType;
|
2010-11-09 05:49:00 +03:00
|
|
|
|
2012-12-19 05:16:06 +04:00
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2016-05-03 19:29:39 +03:00
|
|
|
WriteParam(aMsg, static_cast<const nsTArray<E>&>(aParam));
|
2012-12-19 05:16:06 +04:00
|
|
|
}
|
2010-11-09 05:49:00 +03:00
|
|
|
|
2016-05-03 19:29:39 +03:00
|
|
|
// Deserialize the array infallibly, but return a FallibleTArray.
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-05-03 19:29:39 +03:00
|
|
|
nsTArray<E> temp;
|
2010-11-09 05:49:00 +03:00
|
|
|
if (!ReadParam(aMsg, aIter, &temp)) return false;
|
|
|
|
|
|
|
|
aResult->SwapElements(temp);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-12-19 05:16:06 +04:00
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
2016-05-03 19:29:39 +03:00
|
|
|
LogParam(static_cast<const nsTArray<E>&>(aParam), aLog);
|
2012-12-19 05:16:06 +04:00
|
|
|
}
|
2010-11-09 05:49:00 +03:00
|
|
|
};
|
|
|
|
|
2015-01-31 10:17:12 +03:00
|
|
|
template <typename E, size_t N>
|
2016-02-02 18:36:30 +03:00
|
|
|
struct ParamTraits<AutoTArray<E, N>> : ParamTraits<nsTArray<E>> {
|
|
|
|
typedef AutoTArray<E, N> paramType;
|
2015-01-31 10:17:12 +03:00
|
|
|
};
|
|
|
|
|
2020-05-05 13:56:14 +03:00
|
|
|
template <typename E, size_t N>
|
|
|
|
struct ParamTraits<CopyableAutoTArray<E, N>> : ParamTraits<AutoTArray<E, N>> {};
|
|
|
|
|
2019-11-18 22:45:41 +03:00
|
|
|
template <typename E, size_t N, typename AP>
|
|
|
|
struct ParamTraits<mozilla::Vector<E, N, AP>> {
|
|
|
|
typedef mozilla::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.
|
|
|
|
static const bool sUseWriteBytes =
|
2020-03-28 16:57:15 +03:00
|
|
|
(std::is_integral_v<E> || std::is_floating_point_v<E>);
|
2019-11-18 22:45:41 +03:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
uint32_t length = aParam.length();
|
|
|
|
WriteParam(aMsg, length);
|
|
|
|
|
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
|
|
|
MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
|
|
|
|
aMsg->WriteBytes(aParam.begin(), pickledLength);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const E& elem : aParam) {
|
|
|
|
WriteParam(aMsg, elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
uint32_t length;
|
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
|
|
|
if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
return aMsg->ReadBytesInto(aIter, 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 aMsg.
|
|
|
|
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
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_t index = 0; index < length; ++index) {
|
|
|
|
if (!ReadParam(aMsg, aIter, &((*aResult)[index]))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
for (uint32_t index = 0, len = aParam.length(); index < len; ++index) {
|
|
|
|
if (index) {
|
|
|
|
aLog->append(L" ");
|
|
|
|
}
|
|
|
|
LogParam(aParam[index], aLog);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename E>
|
|
|
|
struct ParamTraits<std::vector<E>> {
|
|
|
|
typedef std::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.
|
|
|
|
static const bool sUseWriteBytes =
|
2020-03-28 16:57:15 +03:00
|
|
|
(std::is_integral_v<E> || std::is_floating_point_v<E>);
|
2019-11-18 22:45:41 +03:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
uint32_t length = aParam.size();
|
|
|
|
WriteParam(aMsg, length);
|
|
|
|
|
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
|
|
|
MOZ_RELEASE_ASSERT(ByteLengthIsValid(length, sizeof(E), &pickledLength));
|
|
|
|
aMsg->WriteBytes(aParam.data(), pickledLength);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const E& elem : aParam) {
|
|
|
|
WriteParam(aMsg, elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
uint32_t length;
|
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sUseWriteBytes) {
|
|
|
|
int pickledLength = 0;
|
|
|
|
if (!ByteLengthIsValid(length, sizeof(E), &pickledLength)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResult->resize(length);
|
|
|
|
|
|
|
|
E* elements = aResult->data();
|
|
|
|
return aMsg->ReadBytesInto(aIter, 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 aMsg.
|
|
|
|
if (!aMsg->HasBytesAvailable(aIter, length)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResult->resize(length);
|
|
|
|
|
|
|
|
for (uint32_t index = 0; index < length; ++index) {
|
|
|
|
if (!ReadParam(aMsg, aIter, &((*aResult)[index]))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
for (uint32_t index = 0, len = aParam.size(); index < len; ++index) {
|
|
|
|
if (index) {
|
|
|
|
aLog->append(L" ");
|
|
|
|
}
|
|
|
|
LogParam(aParam[index], aLog);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-11-06 23:24:35 +03:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<float> {
|
|
|
|
typedef float paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aMsg->WriteBytes(&aParam, sizeof(paramType));
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-05-17 00:32:37 +03:00
|
|
|
return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
|
2009-11-06 23:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
aLog->append(StringPrintf(L"%g", aParam));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-20 17:35:41 +04:00
|
|
|
template <>
|
2016-08-10 02:28:19 +03:00
|
|
|
struct ParamTraits<nsCSSPropertyID>
|
|
|
|
: public ContiguousEnumSerializer<nsCSSPropertyID, eCSSProperty_UNKNOWN,
|
2014-04-14 18:17:40 +04:00
|
|
|
eCSSProperty_COUNT> {};
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2010-05-22 23:35:40 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::void_t> {
|
|
|
|
typedef mozilla::void_t paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2010-05-22 23:35:40 +04:00
|
|
|
*aResult = paramType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::null_t> {
|
|
|
|
typedef mozilla::null_t paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2010-05-22 23:35:40 +04:00
|
|
|
*aResult = paramType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-06-24 18:19:56 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsID> {
|
|
|
|
typedef nsID paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.m0);
|
|
|
|
WriteParam(aMsg, aParam.m1);
|
|
|
|
WriteParam(aMsg, aParam.m2);
|
2011-10-11 09:50:08 +04:00
|
|
|
for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++) {
|
2011-06-24 18:19:56 +04:00
|
|
|
WriteParam(aMsg, aParam.m3[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2011-06-24 18:19:56 +04:00
|
|
|
if (!ReadParam(aMsg, aIter, &(aResult->m0)) ||
|
|
|
|
!ReadParam(aMsg, aIter, &(aResult->m1)) ||
|
|
|
|
!ReadParam(aMsg, aIter, &(aResult->m2)))
|
|
|
|
return false;
|
|
|
|
|
2011-10-11 09:50:08 +04:00
|
|
|
for (unsigned int i = 0; i < mozilla::ArrayLength(aResult->m3); i++)
|
2011-06-24 18:19:56 +04:00
|
|
|
if (!ReadParam(aMsg, aIter, &(aResult->m3[i]))) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
aLog->append(L"{");
|
|
|
|
aLog->append(
|
|
|
|
StringPrintf(L"%8.8X-%4.4X-%4.4X-", aParam.m0, aParam.m1, aParam.m2));
|
2011-10-11 09:50:08 +04:00
|
|
|
for (unsigned int i = 0; i < mozilla::ArrayLength(aParam.m3); i++)
|
2011-06-24 18:19:56 +04:00
|
|
|
aLog->append(StringPrintf(L"%2.2X", aParam.m3[i]));
|
|
|
|
aLog->append(L"}");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-07-31 21:28:20 +04:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::TimeDuration> {
|
|
|
|
typedef mozilla::TimeDuration paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.mValue);
|
|
|
|
}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2012-07-31 21:28:20 +04:00
|
|
|
return ReadParam(aMsg, aIter, &aResult->mValue);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::TimeStamp> {
|
|
|
|
typedef mozilla::TimeStamp paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.mValue);
|
|
|
|
}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2012-07-31 21:28:20 +04:00
|
|
|
return ReadParam(aMsg, aIter, &aResult->mValue);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2013-02-12 01:56:58 +04:00
|
|
|
#ifdef XP_WIN
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::TimeStampValue> {
|
|
|
|
typedef mozilla::TimeStampValue paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.mGTC);
|
|
|
|
WriteParam(aMsg, aParam.mQPC);
|
2018-10-09 20:05:25 +03:00
|
|
|
WriteParam(aMsg, aParam.mUsedCanonicalNow);
|
2013-02-12 01:56:58 +04:00
|
|
|
WriteParam(aMsg, aParam.mIsNull);
|
2018-10-09 20:05:25 +03:00
|
|
|
WriteParam(aMsg, aParam.mHasQPC);
|
2013-02-12 01:56:58 +04:00
|
|
|
}
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2013-02-12 01:56:58 +04:00
|
|
|
return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
|
|
|
|
ReadParam(aMsg, aIter, &aResult->mQPC) &&
|
2018-10-09 20:05:25 +03:00
|
|
|
ReadParam(aMsg, aIter, &aResult->mUsedCanonicalNow) &&
|
|
|
|
ReadParam(aMsg, aIter, &aResult->mIsNull) &&
|
|
|
|
ReadParam(aMsg, aIter, &aResult->mHasQPC));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::TimeStamp63Bit> {
|
|
|
|
typedef mozilla::TimeStamp63Bit paramType;
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.mUsedCanonicalNow);
|
|
|
|
WriteParam(aMsg, aParam.mTimeStamp);
|
|
|
|
}
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
bool success = true;
|
|
|
|
uint64_t result;
|
|
|
|
|
|
|
|
success &= ReadParam(aMsg, aIter, &result);
|
|
|
|
aResult->mUsedCanonicalNow = result & 0x01;
|
|
|
|
|
|
|
|
success &= ReadParam(aMsg, aIter, &result);
|
|
|
|
aResult->mTimeStamp = result & 0x7FFFFFFFFFFFFFFF;
|
|
|
|
|
|
|
|
return success;
|
2013-02-12 01:56:58 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2015-09-09 10:10:32 +03:00
|
|
|
template <>
|
2015-09-10 23:50:58 +03:00
|
|
|
struct ParamTraits<mozilla::dom::ipc::StructuredCloneData> {
|
|
|
|
typedef mozilla::dom::ipc::StructuredCloneData paramType;
|
2015-09-09 10:10:32 +03:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aParam.WriteIPCParams(aMsg);
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2015-09-09 10:10:32 +03:00
|
|
|
return aResult->ReadIPCParams(aMsg, aIter);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
|
|
|
LogParam(aParam.DataLength(), aLog);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-10-26 18:31:00 +03:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::net::WebSocketFrameData> {
|
|
|
|
typedef mozilla::net::WebSocketFrameData paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
aParam.WriteIPCParams(aMsg);
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2015-10-26 18:31:00 +03:00
|
|
|
return aResult->ReadIPCParams(aMsg, aIter);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
template <>
|
2016-04-22 13:04:20 +03:00
|
|
|
struct ParamTraits<JSStructuredCloneData> {
|
|
|
|
typedef JSStructuredCloneData paramType;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
2016-04-22 13:04:20 +03:00
|
|
|
MOZ_ASSERT(!(aParam.Size() % sizeof(uint64_t)));
|
|
|
|
WriteParam(aMsg, aParam.Size());
|
2018-03-16 02:56:09 +03:00
|
|
|
aParam.ForEachDataChunk([&](const char* aData, size_t aSize) {
|
|
|
|
return aMsg->WriteBytes(aData, aSize, sizeof(uint64_t));
|
|
|
|
});
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
2016-04-22 13:04:20 +03:00
|
|
|
size_t length = 0;
|
|
|
|
if (!ReadParam(aMsg, aIter, &length)) {
|
2012-08-02 10:02:29 +04:00
|
|
|
return false;
|
|
|
|
}
|
2016-04-22 13:04:20 +03:00
|
|
|
MOZ_ASSERT(!(length % sizeof(uint64_t)));
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2016-04-22 13:04:20 +03:00
|
|
|
mozilla::BufferList<InfallibleAllocPolicy> buffers(0, 0, 4096);
|
|
|
|
|
|
|
|
// Borrowing is not suitable to use for IPC to hand out data
|
|
|
|
// because we often want to store the data somewhere for
|
|
|
|
// processing after IPC has released the underlying buffers. One
|
|
|
|
// case is PContentChild::SendGetXPCOMProcessAttributes. We can't
|
|
|
|
// return a borrowed buffer because the out param outlives the
|
|
|
|
// IPDL callback.
|
|
|
|
if (length &&
|
|
|
|
!aMsg->ExtractBuffers(aIter, length, &buffers, sizeof(uint64_t))) {
|
|
|
|
return false;
|
2016-05-17 00:32:37 +03:00
|
|
|
}
|
|
|
|
|
2016-04-22 13:04:20 +03:00
|
|
|
bool success;
|
|
|
|
mozilla::BufferList<js::SystemAllocPolicy> out =
|
|
|
|
buffers.MoveFallible<js::SystemAllocPolicy>(&success);
|
|
|
|
if (!success) {
|
2016-05-17 00:32:37 +03:00
|
|
|
return false;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2018-05-30 22:15:35 +03:00
|
|
|
*aResult = JSStructuredCloneData(
|
|
|
|
std::move(out), JS::StructuredCloneScope::DifferentProcess);
|
2016-04-22 13:04:20 +03:00
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
return true;
|
|
|
|
}
|
2016-04-22 13:04:20 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<mozilla::SerializedStructuredCloneBuffer> {
|
|
|
|
typedef mozilla::SerializedStructuredCloneBuffer paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
WriteParam(aMsg, aParam.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
return ReadParam(aMsg, aIter, &aResult->data);
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
static void Log(const paramType& aParam, std::wstring* aLog) {
|
2016-04-22 13:04:20 +03:00
|
|
|
LogParam(aParam.data.Size(), aLog);
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-14 18:36:36 +03:00
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsIWidget::TouchPointerState>
|
|
|
|
: public BitFlagsEnumSerializer<nsIWidget::TouchPointerState,
|
|
|
|
nsIWidget::TouchPointerState::ALL_BITS> {};
|
|
|
|
|
2015-05-26 22:40:24 +03:00
|
|
|
template <class T>
|
2016-05-03 19:29:39 +03:00
|
|
|
struct ParamTraits<mozilla::Maybe<T>> {
|
2015-05-26 22:40:24 +03:00
|
|
|
typedef mozilla::Maybe<T> paramType;
|
|
|
|
|
|
|
|
static void Write(Message* msg, const paramType& param) {
|
|
|
|
if (param.isSome()) {
|
|
|
|
WriteParam(msg, true);
|
|
|
|
WriteParam(msg, param.value());
|
|
|
|
} else {
|
|
|
|
WriteParam(msg, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-21 07:09:15 +03:00
|
|
|
static bool Read(const Message* msg, PickleIterator* iter,
|
|
|
|
paramType* result) {
|
2015-05-26 22:40:24 +03:00
|
|
|
bool isSome;
|
|
|
|
if (!ReadParam(msg, iter, &isSome)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (isSome) {
|
|
|
|
T tmp;
|
|
|
|
if (!ReadParam(msg, iter, &tmp)) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-30 22:15:35 +03:00
|
|
|
*result = mozilla::Some(std::move(tmp));
|
2015-05-26 22:40:24 +03:00
|
|
|
} else {
|
|
|
|
*result = mozilla::Nothing();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-09-07 17:40:02 +03:00
|
|
|
template <typename T, typename U>
|
|
|
|
struct ParamTraits<mozilla::EnumSet<T, U>> {
|
|
|
|
typedef mozilla::EnumSet<T, U> paramType;
|
|
|
|
typedef U serializedType;
|
2017-12-27 23:46:03 +03:00
|
|
|
|
|
|
|
static void Write(Message* msg, const paramType& param) {
|
2018-01-21 23:23:21 +03:00
|
|
|
MOZ_RELEASE_ASSERT(IsLegalValue(param.serialize()));
|
2017-12-27 23:46:03 +03:00
|
|
|
WriteParam(msg, param.serialize());
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* msg, PickleIterator* iter,
|
|
|
|
paramType* result) {
|
2018-01-21 23:23:21 +03:00
|
|
|
serializedType tmp;
|
|
|
|
|
2017-12-27 23:46:03 +03:00
|
|
|
if (ReadParam(msg, iter, &tmp)) {
|
2018-01-21 23:23:21 +03:00
|
|
|
if (IsLegalValue(tmp)) {
|
|
|
|
result->deserialize(tmp);
|
|
|
|
return true;
|
|
|
|
}
|
2017-12-27 23:46:03 +03:00
|
|
|
}
|
2018-01-21 23:23:21 +03:00
|
|
|
|
2017-12-27 23:46:03 +03:00
|
|
|
return false;
|
|
|
|
}
|
2018-01-21 23:23:21 +03:00
|
|
|
|
|
|
|
static constexpr serializedType AllEnumBits() {
|
|
|
|
return ~serializedType(0) >> (std::numeric_limits<serializedType>::digits -
|
|
|
|
(mozilla::MaxEnumValue<T>::value + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr bool IsLegalValue(const serializedType value) {
|
|
|
|
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;
|
|
|
|
}
|
2017-12-27 23:46:03 +03:00
|
|
|
};
|
|
|
|
|
2017-07-21 15:18:02 +03:00
|
|
|
template <class... Ts>
|
|
|
|
struct ParamTraits<mozilla::Variant<Ts...>> {
|
|
|
|
typedef mozilla::Variant<Ts...> paramType;
|
|
|
|
using Tag = typename mozilla::detail::VariantTag<Ts...>::Type;
|
|
|
|
|
|
|
|
static void Write(Message* msg, const paramType& param) {
|
|
|
|
WriteParam(msg, param.tag);
|
2019-04-02 14:53:55 +03:00
|
|
|
param.match([msg](const auto& t) { WriteParam(msg, t); });
|
2017-07-21 15:18:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 template
|
|
|
|
template <size_t N, typename dummy = void>
|
|
|
|
struct VariantReader {
|
|
|
|
using Next = VariantReader<N - 1>;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-07-21 15:18:02 +03:00
|
|
|
static bool Read(const Message* msg, PickleIterator* iter, Tag tag,
|
|
|
|
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.
|
2019-10-08 19:03:11 +03:00
|
|
|
// 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 constructible
|
|
|
|
return ReadParam(msg, iter, &result->template emplace<N - 1>());
|
2017-07-21 15:18:02 +03:00
|
|
|
} else {
|
2017-09-03 14:30:42 +03:00
|
|
|
return Next::Read(msg, iter, tag, result);
|
2017-07-21 15:18:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}; // 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 <typename dummy>
|
|
|
|
struct VariantReader<0, dummy> {
|
|
|
|
static bool Read(const Message* msg, PickleIterator* iter, Tag tag,
|
|
|
|
paramType* result) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool Read(const Message* msg, PickleIterator* iter,
|
|
|
|
paramType* result) {
|
|
|
|
Tag tag;
|
|
|
|
if (ReadParam(msg, iter, &tag)) {
|
|
|
|
return VariantReader<sizeof...(Ts)>::Read(msg, iter, tag, result);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-08-09 00:01:03 +03:00
|
|
|
template <typename T>
|
|
|
|
struct ParamTraits<mozilla::dom::Optional<T>> {
|
|
|
|
typedef mozilla::dom::Optional<T> paramType;
|
|
|
|
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) {
|
|
|
|
if (aParam.WasPassed()) {
|
|
|
|
WriteParam(aMsg, true);
|
|
|
|
WriteParam(aMsg, aParam.Value());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteParam(aMsg, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
paramType* aResult) {
|
|
|
|
bool wasPassed = false;
|
|
|
|
|
|
|
|
if (!ReadParam(aMsg, aIter, &wasPassed)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResult->Reset();
|
|
|
|
|
|
|
|
if (wasPassed) {
|
|
|
|
if (!ReadParam(aMsg, aIter, &aResult->Construct())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-16 01:02:58 +03:00
|
|
|
struct CrossOriginOpenerPolicyValidator {
|
|
|
|
static bool IsLegalValue(nsILoadInfo::CrossOriginOpenerPolicy e) {
|
2020-02-18 19:39:08 +03:00
|
|
|
return e == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE ||
|
2019-02-16 01:02:58 +03:00
|
|
|
e == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
|
2020-02-18 19:39:08 +03:00
|
|
|
e == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS ||
|
2019-08-08 22:00:00 +03:00
|
|
|
e == nsILoadInfo::
|
2020-02-18 19:39:08 +03:00
|
|
|
OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP;
|
2019-02-16 01:02:58 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ParamTraits<nsILoadInfo::CrossOriginOpenerPolicy>
|
|
|
|
: EnumSerializer<nsILoadInfo::CrossOriginOpenerPolicy,
|
|
|
|
CrossOriginOpenerPolicyValidator> {};
|
|
|
|
|
2019-08-08 21:38:03 +03:00
|
|
|
struct CrossOriginEmbedderPolicyValidator {
|
|
|
|
static bool IsLegalValue(nsILoadInfo::CrossOriginEmbedderPolicy e) {
|
|
|
|
return e == nsILoadInfo::EMBEDDER_POLICY_NULL ||
|
|
|
|
e == nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP;
|
2019-03-12 11:04:01 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
2019-08-08 21:38:03 +03:00
|
|
|
struct ParamTraits<nsILoadInfo::CrossOriginEmbedderPolicy>
|
|
|
|
: EnumSerializer<nsILoadInfo::CrossOriginEmbedderPolicy,
|
|
|
|
CrossOriginEmbedderPolicyValidator> {};
|
2019-03-12 11:04:01 +03:00
|
|
|
|
2019-06-20 23:18:45 +03:00
|
|
|
// Helper class for reading bitfields.
|
|
|
|
// If T has bitfields members, derive ParamTraits<T> from BitfieldHelper<T>.
|
|
|
|
template <typename ParamType>
|
|
|
|
struct BitfieldHelper {
|
|
|
|
// We need this helper because we can't get the address of a bitfield to
|
|
|
|
// pass directly to ReadParam. So instead we read it into a temporary bool
|
|
|
|
// and set the bitfield using a setter function
|
|
|
|
static bool ReadBoolForBitfield(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
ParamType* aResult,
|
|
|
|
void (ParamType::*aSetter)(bool)) {
|
|
|
|
bool value;
|
|
|
|
if (ReadParam(aMsg, aIter, &value)) {
|
|
|
|
(aResult->*aSetter)(value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-11-04 18:00:04 +03:00
|
|
|
// A couple of recursive helper functions, allows syntax like:
|
|
|
|
// WriteParams(aMsg, aParam.foo, aParam.bar, aParam.baz)
|
|
|
|
// ReadParams(aMsg, aIter, aParam.foo, aParam.bar, aParam.baz)
|
|
|
|
|
2020-05-14 19:31:17 +03:00
|
|
|
template <typename... Ts>
|
|
|
|
static void WriteParams(Message* aMsg, const Ts&... aArgs) {
|
|
|
|
(WriteParam(aMsg, aArgs), ...);
|
2019-11-04 18:00:04 +03:00
|
|
|
}
|
|
|
|
|
2020-05-14 19:31:17 +03:00
|
|
|
template <typename... Ts>
|
|
|
|
static bool ReadParams(const Message* aMsg, PickleIterator* aIter,
|
|
|
|
Ts&... aArgs) {
|
|
|
|
return (ReadParam(aMsg, aIter, &aArgs) && ...);
|
2019-11-04 18:00:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Macros that allow syntax like:
|
|
|
|
// DEFINE_IPC_SERIALIZER_WITH_FIELDS(SomeType, member1, member2, member3)
|
|
|
|
// Makes sure that serialize/deserialize code do the same members in the same
|
|
|
|
// order.
|
|
|
|
#define ACCESS_PARAM_FIELD(Field) aParam.Field
|
|
|
|
|
|
|
|
#define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \
|
|
|
|
template <> \
|
|
|
|
struct ParamTraits<Type> { \
|
|
|
|
typedef Type paramType; \
|
|
|
|
static void Write(Message* aMsg, const paramType& aParam) { \
|
|
|
|
WriteParams(aMsg, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
|
|
|
|
(__VA_ARGS__))); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static bool Read(const Message* aMsg, PickleIterator* aIter, \
|
|
|
|
paramType* aResult) { \
|
|
|
|
paramType& aParam = *aResult; \
|
|
|
|
return ReadParams(aMsg, aIter, \
|
|
|
|
MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
|
|
|
|
(__VA_ARGS__))); \
|
|
|
|
} \
|
|
|
|
};
|
|
|
|
|
2020-01-22 10:31:51 +03:00
|
|
|
#define DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(Type) \
|
|
|
|
template <> \
|
|
|
|
struct ParamTraits<Type> : public EmptyStructSerializer<Type> {};
|
|
|
|
|
2009-06-29 22:38:29 +04:00
|
|
|
} /* namespace IPC */
|
|
|
|
|
|
|
|
#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
|