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 dom_plugins_ipc_ipdltuple_h
8 #define dom_plugins_ipc_ipdltuple_h
9
10 #include "mozilla/plugins/FunctionBrokerIPCUtils.h"
11 #include "mozilla/Variant.h"
12
13 namespace mozilla {
14 namespace plugins {
15
16 // The stuff in this "internal" namespace used to be inside the IpdlTuple
17 // class, but that prevented the MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR
18 // that is needed on the IpdlTupleElement struct. Without this, nsTArray can end
19 // up using a move constructor on this struct, which is not memmovable on
20 // Windows.
21 namespace internal {
22
23 struct InvalidType {};
24
25 // Like Variant but with a default constructor.
26 template <typename... Types>
27 struct MaybeVariant {
28 public:
MaybeVariantMaybeVariant29 MaybeVariant() : mValue(InvalidType()) {}
MaybeVariantMaybeVariant30 MaybeVariant(MaybeVariant&& o) : mValue(std::move(o.mValue)) {}
31
32 template <typename Param>
SetMaybeVariant33 void Set(const Param& aParam) {
34 mValue = mozilla::AsVariant(aParam);
35 }
36
37 typedef mozilla::Variant<InvalidType, Types...> MaybeVariantType;
GetVariantMaybeVariant38 MaybeVariantType& GetVariant() { return mValue; }
GetVariantMaybeVariant39 const MaybeVariantType& GetVariant() const { return mValue; }
40
41 private:
42 MaybeVariantType mValue;
43 };
44
45 #if defined(XP_WIN)
46 typedef MaybeVariant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
47 int64_t, uint64_t, nsCString, nsString, bool,
48 OpenFileNameIPC, OpenFileNameRetIPC, NativeWindowHandle,
49 IPCSchannelCred, IPCInternetBuffers, StringArray,
50 IPCPrintDlg>
51 IpdlTupleElement;
52 #else
53 typedef MaybeVariant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
54 int64_t, uint64_t, nsCString, nsString, bool>
55 IpdlTupleElement;
56 #endif // defined(XP_WIN)
57
58 } // namespace internal
59 } // namespace plugins
60 } // namespace mozilla
61
MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::plugins::internal::IpdlTupleElement)62 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
63 mozilla::plugins::internal::IpdlTupleElement)
64
65 namespace mozilla {
66 namespace plugins {
67
68 /**
69 * IpdlTuple is used by automatic function brokering to pass parameter
70 * lists for brokered functions. It supports a limited set of types
71 * (see IpdlTuple::IpdlTupleElement).
72 */
73 class IpdlTuple {
74 public:
75 uint32_t NumElements() const { return mTupleElements.Length(); }
76
77 template <typename EltType>
78 EltType* Element(uint32_t index) {
79 if ((index >= mTupleElements.Length()) ||
80 !mTupleElements[index].GetVariant().is<EltType>()) {
81 return nullptr;
82 }
83 return &mTupleElements[index].GetVariant().as<EltType>();
84 }
85
86 template <typename EltType>
87 const EltType* Element(uint32_t index) const {
88 return const_cast<IpdlTuple*>(this)->Element<EltType>(index);
89 }
90
91 template <typename EltType>
92 void AddElement(const EltType& aElt) {
93 IpdlTupleElement* newEntry = mTupleElements.AppendElement();
94 newEntry->Set(aElt);
95 }
96
97 private:
98 typedef mozilla::plugins::internal::InvalidType InvalidType;
99 typedef mozilla::plugins::internal::IpdlTupleElement IpdlTupleElement;
100
101 friend struct IPC::ParamTraits<IpdlTuple>;
102 friend struct IPC::ParamTraits<IpdlTuple::IpdlTupleElement>;
103 friend struct IPC::ParamTraits<IpdlTuple::InvalidType>;
104
105 nsTArray<IpdlTupleElement> mTupleElements;
106 };
107
108 namespace internal {
109 template <>
110 template <>
111 inline void IpdlTupleElement::Set<nsDependentCSubstring>(
112 const nsDependentCSubstring& aParam) {
113 mValue = MaybeVariantType(mozilla::VariantType<nsCString>(), aParam);
114 }
115 } // namespace internal
116
117 } // namespace plugins
118 } // namespace mozilla
119
120 namespace IPC {
121
122 using namespace mozilla::plugins;
123
124 template <>
125 struct ParamTraits<IpdlTuple> {
126 typedef IpdlTuple paramType;
127
128 static void Write(Message* aMsg, const paramType& aParam) {
129 WriteParam(aMsg, aParam.mTupleElements);
130 }
131
132 static bool Read(const Message* aMsg, PickleIterator* aIter,
133 paramType* aParam) {
134 return ReadParam(aMsg, aIter, &aParam->mTupleElements);
135 }
136
137 static void Log(const paramType& aParam, std::wstring* aLog) {
138 LogParam(aParam.mTupleElements, aLog);
139 }
140 };
141
142 template <>
143 struct ParamTraits<IpdlTuple::IpdlTupleElement> {
144 typedef IpdlTuple::IpdlTupleElement paramType;
145
146 static void Write(Message* aMsg, const paramType& aParam) {
147 MOZ_RELEASE_ASSERT(!aParam.GetVariant().is<IpdlTuple::InvalidType>());
148 WriteParam(aMsg, aParam.GetVariant());
149 }
150
151 static bool Read(const Message* aMsg, PickleIterator* aIter,
152 paramType* aParam) {
153 bool ret = ReadParam(aMsg, aIter, &aParam->GetVariant());
154 MOZ_RELEASE_ASSERT(!aParam->GetVariant().is<IpdlTuple::InvalidType>());
155 return ret;
156 }
157
158 static void Log(const paramType& aParam, std::wstring* aLog) {
159 aParam.GetVariant().match(
160 [aLog](const auto& aParam) { LogParam(aParam, aLog); });
161 }
162 };
163
164 template <>
165 struct ParamTraits<IpdlTuple::InvalidType> {
166 typedef IpdlTuple::InvalidType paramType;
167
168 static void Write(Message* aMsg, const paramType& aParam) {
169 MOZ_ASSERT_UNREACHABLE("Attempt to serialize an invalid tuple element");
170 }
171
172 static bool Read(const Message* aMsg, PickleIterator* aIter,
173 paramType* aParam) {
174 MOZ_ASSERT_UNREACHABLE("Attempt to deserialize an invalid tuple element");
175 return false;
176 }
177
178 static void Log(const paramType& aParam, std::wstring* aLog) {
179 aLog->append(L"<Invalid Tuple Entry>");
180 }
181 };
182
183 } // namespace IPC
184
185 #endif /* dom_plugins_ipc_ipdltuple_h */
186