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