|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * vim: sw=2 ts=2 et : |
|
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_PluginScriptableObjectUtils_h |
|
8 #define dom_plugins_PluginScriptableObjectUtils_h |
|
9 |
|
10 #include "PluginModuleParent.h" |
|
11 #include "PluginModuleChild.h" |
|
12 #include "PluginInstanceParent.h" |
|
13 #include "PluginInstanceChild.h" |
|
14 #include "PluginScriptableObjectParent.h" |
|
15 #include "PluginScriptableObjectChild.h" |
|
16 |
|
17 #include "npapi.h" |
|
18 #include "npfunctions.h" |
|
19 #include "npruntime.h" |
|
20 |
|
21 #include "nsDebug.h" |
|
22 |
|
23 namespace mozilla { |
|
24 namespace plugins { |
|
25 |
|
26 inline PluginInstanceParent* |
|
27 GetInstance(NPObject* aObject) |
|
28 { |
|
29 NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(), |
|
30 "Bad class!"); |
|
31 |
|
32 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject); |
|
33 if (object->invalidated) { |
|
34 NS_WARNING("Calling method on an invalidated object!"); |
|
35 return nullptr; |
|
36 } |
|
37 if (!object->parent) { |
|
38 return nullptr; |
|
39 } |
|
40 return object->parent->GetInstance(); |
|
41 } |
|
42 |
|
43 inline NPObject* |
|
44 NPObjectFromVariant(const Variant& aRemoteVariant) |
|
45 { |
|
46 switch (aRemoteVariant.type()) { |
|
47 case Variant::TPPluginScriptableObjectParent: { |
|
48 PluginScriptableObjectParent* actor = |
|
49 const_cast<PluginScriptableObjectParent*>( |
|
50 reinterpret_cast<const PluginScriptableObjectParent*>( |
|
51 aRemoteVariant.get_PPluginScriptableObjectParent())); |
|
52 return actor->GetObject(true); |
|
53 } |
|
54 |
|
55 case Variant::TPPluginScriptableObjectChild: { |
|
56 PluginScriptableObjectChild* actor = |
|
57 const_cast<PluginScriptableObjectChild*>( |
|
58 reinterpret_cast<const PluginScriptableObjectChild*>( |
|
59 aRemoteVariant.get_PPluginScriptableObjectChild())); |
|
60 return actor->GetObject(true); |
|
61 } |
|
62 |
|
63 default: |
|
64 NS_NOTREACHED("Shouldn't get here!"); |
|
65 return nullptr; |
|
66 } |
|
67 } |
|
68 |
|
69 inline NPObject* |
|
70 NPObjectFromVariant(const NPVariant& aVariant) |
|
71 { |
|
72 NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!"); |
|
73 return NPVARIANT_TO_OBJECT(aVariant); |
|
74 } |
|
75 |
|
76 inline const NPNetscapeFuncs* |
|
77 GetNetscapeFuncs(PluginInstanceParent* aInstance) |
|
78 { |
|
79 PluginModuleParent* module = aInstance->Module(); |
|
80 if (!module) { |
|
81 NS_WARNING("Null module?!"); |
|
82 return nullptr; |
|
83 } |
|
84 return module->GetNetscapeFuncs(); |
|
85 } |
|
86 |
|
87 inline const NPNetscapeFuncs* |
|
88 GetNetscapeFuncs(NPObject* aObject) |
|
89 { |
|
90 NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(), |
|
91 "Bad class!"); |
|
92 |
|
93 PluginInstanceParent* instance = GetInstance(aObject); |
|
94 if (!instance) { |
|
95 return nullptr; |
|
96 } |
|
97 |
|
98 return GetNetscapeFuncs(instance); |
|
99 } |
|
100 |
|
101 inline void |
|
102 ReleaseRemoteVariant(Variant& aVariant) |
|
103 { |
|
104 switch (aVariant.type()) { |
|
105 case Variant::TPPluginScriptableObjectParent: { |
|
106 PluginScriptableObjectParent* actor = |
|
107 const_cast<PluginScriptableObjectParent*>( |
|
108 reinterpret_cast<const PluginScriptableObjectParent*>( |
|
109 aVariant.get_PPluginScriptableObjectParent())); |
|
110 actor->Unprotect(); |
|
111 break; |
|
112 } |
|
113 |
|
114 case Variant::TPPluginScriptableObjectChild: { |
|
115 NS_ASSERTION(PluginModuleChild::current(), |
|
116 "Should only be running in the child!"); |
|
117 PluginScriptableObjectChild* actor = |
|
118 const_cast<PluginScriptableObjectChild*>( |
|
119 reinterpret_cast<const PluginScriptableObjectChild*>( |
|
120 aVariant.get_PPluginScriptableObjectChild())); |
|
121 actor->Unprotect(); |
|
122 break; |
|
123 } |
|
124 |
|
125 default: |
|
126 break; // Intentional fall-through for other variant types. |
|
127 } |
|
128 |
|
129 aVariant = mozilla::void_t(); |
|
130 } |
|
131 |
|
132 bool |
|
133 ConvertToVariant(const Variant& aRemoteVariant, |
|
134 NPVariant& aVariant, |
|
135 PluginInstanceParent* aInstance = nullptr); |
|
136 |
|
137 template <class InstanceType> |
|
138 bool |
|
139 ConvertToRemoteVariant(const NPVariant& aVariant, |
|
140 Variant& aRemoteVariant, |
|
141 InstanceType* aInstance, |
|
142 bool aProtectActors = false); |
|
143 |
|
144 class ProtectedVariant |
|
145 { |
|
146 public: |
|
147 ProtectedVariant(const NPVariant& aVariant, |
|
148 PluginInstanceParent* aInstance) |
|
149 { |
|
150 mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true); |
|
151 } |
|
152 |
|
153 ProtectedVariant(const NPVariant& aVariant, |
|
154 PluginInstanceChild* aInstance) |
|
155 { |
|
156 mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true); |
|
157 } |
|
158 |
|
159 ~ProtectedVariant() { |
|
160 ReleaseRemoteVariant(mVariant); |
|
161 } |
|
162 |
|
163 bool IsOk() { |
|
164 return mOk; |
|
165 } |
|
166 |
|
167 operator const Variant&() { |
|
168 return mVariant; |
|
169 } |
|
170 |
|
171 private: |
|
172 Variant mVariant; |
|
173 bool mOk; |
|
174 }; |
|
175 |
|
176 class ProtectedVariantArray |
|
177 { |
|
178 public: |
|
179 ProtectedVariantArray(const NPVariant* aArgs, |
|
180 uint32_t aCount, |
|
181 PluginInstanceParent* aInstance) |
|
182 : mUsingShadowArray(false) |
|
183 { |
|
184 for (uint32_t index = 0; index < aCount; index++) { |
|
185 Variant* remoteVariant = mArray.AppendElement(); |
|
186 if (!(remoteVariant && |
|
187 ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance, |
|
188 true))) { |
|
189 mOk = false; |
|
190 return; |
|
191 } |
|
192 } |
|
193 mOk = true; |
|
194 } |
|
195 |
|
196 ProtectedVariantArray(const NPVariant* aArgs, |
|
197 uint32_t aCount, |
|
198 PluginInstanceChild* aInstance) |
|
199 : mUsingShadowArray(false) |
|
200 { |
|
201 for (uint32_t index = 0; index < aCount; index++) { |
|
202 Variant* remoteVariant = mArray.AppendElement(); |
|
203 if (!(remoteVariant && |
|
204 ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance, |
|
205 true))) { |
|
206 mOk = false; |
|
207 return; |
|
208 } |
|
209 } |
|
210 mOk = true; |
|
211 } |
|
212 |
|
213 ~ProtectedVariantArray() |
|
214 { |
|
215 InfallibleTArray<Variant>& vars = EnsureAndGetShadowArray(); |
|
216 uint32_t count = vars.Length(); |
|
217 for (uint32_t index = 0; index < count; index++) { |
|
218 ReleaseRemoteVariant(vars[index]); |
|
219 } |
|
220 } |
|
221 |
|
222 operator const InfallibleTArray<Variant>&() |
|
223 { |
|
224 return EnsureAndGetShadowArray(); |
|
225 } |
|
226 |
|
227 bool IsOk() |
|
228 { |
|
229 return mOk; |
|
230 } |
|
231 |
|
232 private: |
|
233 InfallibleTArray<Variant>& |
|
234 EnsureAndGetShadowArray() |
|
235 { |
|
236 if (!mUsingShadowArray) { |
|
237 mShadowArray.SwapElements(mArray); |
|
238 mUsingShadowArray = true; |
|
239 } |
|
240 return mShadowArray; |
|
241 } |
|
242 |
|
243 // We convert the variants fallibly, but pass them to Call*() |
|
244 // methods as an infallible array |
|
245 nsTArray<Variant> mArray; |
|
246 InfallibleTArray<Variant> mShadowArray; |
|
247 bool mOk; |
|
248 bool mUsingShadowArray; |
|
249 }; |
|
250 |
|
251 template<class ActorType> |
|
252 struct ProtectedActorTraits |
|
253 { |
|
254 static bool Nullable(); |
|
255 }; |
|
256 |
|
257 template<class ActorType, class Traits=ProtectedActorTraits<ActorType> > |
|
258 class ProtectedActor |
|
259 { |
|
260 public: |
|
261 ProtectedActor(ActorType* aActor) : mActor(aActor) |
|
262 { |
|
263 if (!Traits::Nullable()) { |
|
264 NS_ASSERTION(mActor, "This should never be null!"); |
|
265 } |
|
266 } |
|
267 |
|
268 ~ProtectedActor() |
|
269 { |
|
270 if (Traits::Nullable() && !mActor) |
|
271 return; |
|
272 mActor->Unprotect(); |
|
273 } |
|
274 |
|
275 ActorType* operator->() |
|
276 { |
|
277 return mActor; |
|
278 } |
|
279 |
|
280 operator bool() |
|
281 { |
|
282 return !!mActor; |
|
283 } |
|
284 |
|
285 private: |
|
286 ActorType* mActor; |
|
287 }; |
|
288 |
|
289 template<> |
|
290 struct ProtectedActorTraits<PluginScriptableObjectParent> |
|
291 { |
|
292 static bool Nullable() { return true; } |
|
293 }; |
|
294 |
|
295 template<> |
|
296 struct ProtectedActorTraits<PluginScriptableObjectChild> |
|
297 { |
|
298 static bool Nullable() { return false; } |
|
299 }; |
|
300 |
|
301 } /* namespace plugins */ |
|
302 } /* namespace mozilla */ |
|
303 |
|
304 #include "PluginScriptableObjectUtils-inl.h" |
|
305 |
|
306 #endif /* dom_plugins_PluginScriptableObjectUtils_h */ |