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
GetInstance(NPObject * aObject)26 inline PluginInstanceParent* GetInstance(NPObject* aObject) {
27 NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
28 "Bad class!");
29
30 ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
31 if (object->invalidated) {
32 NS_WARNING("Calling method on an invalidated object!");
33 return nullptr;
34 }
35 if (!object->parent) {
36 return nullptr;
37 }
38 return object->parent->GetInstance();
39 }
40
NPObjectFromVariant(const Variant & aRemoteVariant)41 inline NPObject* NPObjectFromVariant(const Variant& aRemoteVariant) {
42 switch (aRemoteVariant.type()) {
43 case Variant::TPPluginScriptableObjectParent: {
44 PluginScriptableObjectParent* actor =
45 const_cast<PluginScriptableObjectParent*>(
46 reinterpret_cast<const PluginScriptableObjectParent*>(
47 aRemoteVariant.get_PPluginScriptableObjectParent()));
48 return actor->GetObject(true);
49 }
50
51 case Variant::TPPluginScriptableObjectChild: {
52 PluginScriptableObjectChild* actor =
53 const_cast<PluginScriptableObjectChild*>(
54 reinterpret_cast<const PluginScriptableObjectChild*>(
55 aRemoteVariant.get_PPluginScriptableObjectChild()));
56 return actor->GetObject(true);
57 }
58
59 default:
60 MOZ_ASSERT_UNREACHABLE("Shouldn't get here!");
61 return nullptr;
62 }
63 }
64
NPObjectFromVariant(const NPVariant & aVariant)65 inline NPObject* NPObjectFromVariant(const NPVariant& aVariant) {
66 NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!");
67 return NPVARIANT_TO_OBJECT(aVariant);
68 }
69
GetNetscapeFuncs(PluginInstanceParent * aInstance)70 inline const NPNetscapeFuncs* GetNetscapeFuncs(
71 PluginInstanceParent* aInstance) {
72 PluginModuleParent* module = aInstance->Module();
73 if (!module) {
74 NS_WARNING("Null module?!");
75 return nullptr;
76 }
77 return module->GetNetscapeFuncs();
78 }
79
GetNetscapeFuncs(NPObject * aObject)80 inline const NPNetscapeFuncs* GetNetscapeFuncs(NPObject* aObject) {
81 NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
82 "Bad class!");
83
84 PluginInstanceParent* instance = GetInstance(aObject);
85 if (!instance) {
86 return nullptr;
87 }
88
89 return GetNetscapeFuncs(instance);
90 }
91
ReleaseRemoteVariant(Variant & aVariant)92 inline void ReleaseRemoteVariant(Variant& aVariant) {
93 switch (aVariant.type()) {
94 case Variant::TPPluginScriptableObjectParent: {
95 PluginScriptableObjectParent* actor =
96 const_cast<PluginScriptableObjectParent*>(
97 reinterpret_cast<const PluginScriptableObjectParent*>(
98 aVariant.get_PPluginScriptableObjectParent()));
99 actor->Unprotect();
100 break;
101 }
102
103 case Variant::TPPluginScriptableObjectChild: {
104 NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Plugin,
105 "Should only be running in the child!");
106 PluginScriptableObjectChild* actor =
107 const_cast<PluginScriptableObjectChild*>(
108 reinterpret_cast<const PluginScriptableObjectChild*>(
109 aVariant.get_PPluginScriptableObjectChild()));
110 actor->Unprotect();
111 break;
112 }
113
114 default:
115 break; // Intentional fall-through for other variant types.
116 }
117
118 aVariant = mozilla::void_t();
119 }
120
121 bool ConvertToVariant(const Variant& aRemoteVariant, NPVariant& aVariant,
122 PluginInstanceParent* aInstance = nullptr);
123
124 template <class InstanceType>
125 bool ConvertToRemoteVariant(const NPVariant& aVariant, Variant& aRemoteVariant,
126 InstanceType* aInstance,
127 bool aProtectActors = false);
128
129 class ProtectedVariant {
130 public:
ProtectedVariant(const NPVariant & aVariant,PluginInstanceParent * aInstance)131 ProtectedVariant(const NPVariant& aVariant, PluginInstanceParent* aInstance) {
132 mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true);
133 }
134
ProtectedVariant(const NPVariant & aVariant,PluginInstanceChild * aInstance)135 ProtectedVariant(const NPVariant& aVariant, PluginInstanceChild* aInstance) {
136 mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true);
137 }
138
~ProtectedVariant()139 ~ProtectedVariant() { ReleaseRemoteVariant(mVariant); }
140
IsOk()141 bool IsOk() { return mOk; }
142
143 operator const Variant&() { return mVariant; }
144
145 private:
146 Variant mVariant;
147 bool mOk;
148 };
149
150 class ProtectedVariantArray {
151 public:
ProtectedVariantArray(const NPVariant * aArgs,uint32_t aCount,PluginInstanceParent * aInstance)152 ProtectedVariantArray(const NPVariant* aArgs, uint32_t aCount,
153 PluginInstanceParent* aInstance)
154 : mUsingShadowArray(false) {
155 for (uint32_t index = 0; index < aCount; index++) {
156 Variant* remoteVariant = mArray.AppendElement();
157 if (!(remoteVariant &&
158 ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance,
159 true))) {
160 mOk = false;
161 return;
162 }
163 }
164 mOk = true;
165 }
166
ProtectedVariantArray(const NPVariant * aArgs,uint32_t aCount,PluginInstanceChild * aInstance)167 ProtectedVariantArray(const NPVariant* aArgs, uint32_t aCount,
168 PluginInstanceChild* aInstance)
169 : mUsingShadowArray(false) {
170 for (uint32_t index = 0; index < aCount; index++) {
171 Variant* remoteVariant = mArray.AppendElement();
172 if (!(remoteVariant &&
173 ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance,
174 true))) {
175 mOk = false;
176 return;
177 }
178 }
179 mOk = true;
180 }
181
~ProtectedVariantArray()182 ~ProtectedVariantArray() {
183 nsTArray<Variant>& vars = EnsureAndGetShadowArray();
184 uint32_t count = vars.Length();
185 for (uint32_t index = 0; index < count; index++) {
186 ReleaseRemoteVariant(vars[index]);
187 }
188 }
189
190 operator const nsTArray<Variant>&() { return EnsureAndGetShadowArray(); }
191
IsOk()192 bool IsOk() { return mOk; }
193
194 private:
EnsureAndGetShadowArray()195 nsTArray<Variant>& EnsureAndGetShadowArray() {
196 if (!mUsingShadowArray) {
197 mShadowArray.SwapElements(mArray);
198 mUsingShadowArray = true;
199 }
200 return mShadowArray;
201 }
202
203 // We convert the variants fallibly, but pass them to Call*()
204 // methods as an infallible array
205 nsTArray<Variant> mArray;
206 nsTArray<Variant> mShadowArray;
207 bool mOk;
208 bool mUsingShadowArray;
209 };
210
211 template <class ActorType>
212 struct ProtectedActorTraits {
213 static bool Nullable();
214 };
215
216 template <class ActorType, class Traits = ProtectedActorTraits<ActorType> >
217 class ProtectedActor {
218 public:
ProtectedActor(ActorType * aActor)219 explicit ProtectedActor(ActorType* aActor) : mActor(aActor) {
220 if (!Traits::Nullable()) {
221 NS_ASSERTION(mActor, "This should never be null!");
222 }
223 }
224
~ProtectedActor()225 ~ProtectedActor() {
226 if (Traits::Nullable() && !mActor) return;
227 mActor->Unprotect();
228 }
229
230 ActorType* operator->() { return mActor; }
231
232 explicit operator bool() { return !!mActor; }
233
234 private:
235 ActorType* mActor;
236 };
237
238 template <>
239 struct ProtectedActorTraits<PluginScriptableObjectParent> {
240 static bool Nullable() { return true; }
241 };
242
243 template <>
244 struct ProtectedActorTraits<PluginScriptableObjectChild> {
245 static bool Nullable() { return false; }
246 };
247
248 } /* namespace plugins */
249 } /* namespace mozilla */
250
251 #include "PluginScriptableObjectUtils-inl.h"
252
253 #endif /* dom_plugins_PluginScriptableObjectUtils_h */
254