1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: sw=2 ts=8 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 #include "mozilla/PluginPRLibrary.h"
8 #include "nsNPAPIPluginInstance.h"
9 
10 // Some plugins on Windows, notably Quake Live, implement NP_Initialize using
11 // cdecl instead of the documented stdcall. In order to work around this,
12 // we force the caller to use a frame pointer.
13 #if defined(XP_WIN) && defined(_M_IX86)
14 #include <malloc.h>
15 
16 // gNotOptimized exists so that the compiler will not optimize the alloca
17 // below.
18 static int gNotOptimized;
19 #define CALLING_CONVENTION_HACK void* foo = _alloca(gNotOptimized);
20 #else
21 #define CALLING_CONVENTION_HACK
22 #endif
23 
24 #ifdef MOZ_WIDGET_ANDROID
25 #include "AndroidBridge.h"
26 #include "android_npapi.h"
27 #include <android/log.h>
28 #undef ALOG
29 #define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoJavaEnv", ## args)
30 #endif
31 
32 using namespace mozilla::layers;
33 
34 namespace mozilla {
35 #ifdef MOZ_WIDGET_ANDROID
36 nsresult
NP_Initialize(NPNetscapeFuncs * bFuncs,NPPluginFuncs * pFuncs,NPError * error)37 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
38 			       NPPluginFuncs* pFuncs, NPError* error)
39 {
40   JNIEnv* env = jni::GetEnvForThread();
41 
42   mozilla::AutoLocalJNIFrame jniFrame(env);
43 
44   if (mNP_Initialize) {
45     *error = mNP_Initialize(bFuncs, pFuncs, env);
46   } else {
47     NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
48       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
49     if (!pfNP_Initialize)
50       return NS_ERROR_FAILURE;
51     *error = pfNP_Initialize(bFuncs, pFuncs, env);
52   }
53 
54   // Save pointers to functions that get called through PluginLibrary itself.
55   mNPP_New = pFuncs->newp;
56   mNPP_ClearSiteData = pFuncs->clearsitedata;
57   mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
58   return NS_OK;
59 }
60 #elif defined(MOZ_WIDGET_GONK)
61 nsresult
62 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
63 {
64   return NS_OK;
65 }
66 #elif defined(XP_UNIX) && !defined(XP_MACOSX)
67 nsresult
68 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
69                                NPPluginFuncs* pFuncs, NPError* error)
70 {
71   if (mNP_Initialize) {
72     *error = mNP_Initialize(bFuncs, pFuncs);
73   } else {
74     NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
75       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
76     if (!pfNP_Initialize)
77       return NS_ERROR_FAILURE;
78     *error = pfNP_Initialize(bFuncs, pFuncs);
79   }
80 
81 
82   // Save pointers to functions that get called through PluginLibrary itself.
83   mNPP_New = pFuncs->newp;
84   mNPP_ClearSiteData = pFuncs->clearsitedata;
85   mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
86   return NS_OK;
87 }
88 #else
89 nsresult
90 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
91 {
92   CALLING_CONVENTION_HACK
93 
94   if (mNP_Initialize) {
95     *error = mNP_Initialize(bFuncs);
96   } else {
97     NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
98       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
99     if (!pfNP_Initialize)
100       return NS_ERROR_FAILURE;
101     *error = pfNP_Initialize(bFuncs);
102   }
103 
104   return NS_OK;
105 }
106 #endif
107 
108 nsresult
NP_Shutdown(NPError * error)109 PluginPRLibrary::NP_Shutdown(NPError* error)
110 {
111   CALLING_CONVENTION_HACK
112 
113   if (mNP_Shutdown) {
114     *error = mNP_Shutdown();
115   } else {
116     NP_ShutdownFunc pfNP_Shutdown = (NP_ShutdownFunc)
117       PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
118     if (!pfNP_Shutdown)
119       return NS_ERROR_FAILURE;
120     *error = pfNP_Shutdown();
121   }
122 
123   return NS_OK;
124 }
125 
126 nsresult
NP_GetMIMEDescription(const char ** mimeDesc)127 PluginPRLibrary::NP_GetMIMEDescription(const char** mimeDesc)
128 {
129   CALLING_CONVENTION_HACK
130 
131   if (mNP_GetMIMEDescription) {
132     *mimeDesc = mNP_GetMIMEDescription();
133   }
134   else {
135     NP_GetMIMEDescriptionFunc pfNP_GetMIMEDescription =
136       (NP_GetMIMEDescriptionFunc)
137       PR_FindFunctionSymbol(mLibrary, "NP_GetMIMEDescription");
138     if (!pfNP_GetMIMEDescription) {
139       *mimeDesc = "";
140       return NS_ERROR_FAILURE;
141     }
142     *mimeDesc = pfNP_GetMIMEDescription();
143   }
144 
145   return NS_OK;
146 }
147 
148 nsresult
NP_GetValue(void * future,NPPVariable aVariable,void * aValue,NPError * error)149 PluginPRLibrary::NP_GetValue(void *future, NPPVariable aVariable,
150 			     void *aValue, NPError* error)
151 {
152 #if defined(XP_UNIX) && !defined(XP_MACOSX)
153   if (mNP_GetValue) {
154     *error = mNP_GetValue(future, aVariable, aValue);
155   } else {
156     NP_GetValueFunc pfNP_GetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(mLibrary, "NP_GetValue");
157     if (!pfNP_GetValue)
158       return NS_ERROR_FAILURE;
159     *error = pfNP_GetValue(future, aVariable, aValue);
160   }
161   return NS_OK;
162 #else
163   return NS_ERROR_NOT_IMPLEMENTED;
164 #endif
165 }
166 
167 #if defined(XP_WIN) || defined(XP_MACOSX)
168 nsresult
NP_GetEntryPoints(NPPluginFuncs * pFuncs,NPError * error)169 PluginPRLibrary::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
170 {
171   CALLING_CONVENTION_HACK
172 
173   if (mNP_GetEntryPoints) {
174     *error = mNP_GetEntryPoints(pFuncs);
175   } else {
176     NP_GetEntryPointsFunc pfNP_GetEntryPoints = (NP_GetEntryPointsFunc)
177       PR_FindFunctionSymbol(mLibrary, "NP_GetEntryPoints");
178     if (!pfNP_GetEntryPoints)
179       return NS_ERROR_FAILURE;
180     *error = pfNP_GetEntryPoints(pFuncs);
181   }
182 
183   // Save pointers to functions that get called through PluginLibrary itself.
184   mNPP_New = pFuncs->newp;
185   mNPP_ClearSiteData = pFuncs->clearsitedata;
186   mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
187   return NS_OK;
188 }
189 #endif
190 
191 nsresult
NPP_New(NPMIMEType pluginType,NPP instance,uint16_t mode,int16_t argc,char * argn[],char * argv[],NPSavedData * saved,NPError * error)192 PluginPRLibrary::NPP_New(NPMIMEType pluginType, NPP instance,
193 			 uint16_t mode, int16_t argc, char* argn[],
194 			 char* argv[], NPSavedData* saved,
195 			 NPError* error)
196 {
197   if (!mNPP_New)
198     return NS_ERROR_FAILURE;
199 
200   MAIN_THREAD_JNI_REF_GUARD;
201   *error = mNPP_New(pluginType, instance, mode, argc, argn, argv, saved);
202   return NS_OK;
203 }
204 
205 nsresult
NPP_ClearSiteData(const char * site,uint64_t flags,uint64_t maxAge,nsCOMPtr<nsIClearSiteDataCallback> callback)206 PluginPRLibrary::NPP_ClearSiteData(const char* site, uint64_t flags,
207                                    uint64_t maxAge, nsCOMPtr<nsIClearSiteDataCallback> callback)
208 {
209   if (!mNPP_ClearSiteData) {
210     return NS_ERROR_NOT_AVAILABLE;
211   }
212 
213   MAIN_THREAD_JNI_REF_GUARD;
214   NPError result = mNPP_ClearSiteData(site, flags, maxAge);
215 
216   nsresult rv;
217   switch (result) {
218   case NPERR_NO_ERROR:
219     rv = NS_OK;
220     break;
221   case NPERR_TIME_RANGE_NOT_SUPPORTED:
222     rv = NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED;
223     break;
224   case NPERR_MALFORMED_SITE:
225     rv = NS_ERROR_INVALID_ARG;
226     break;
227   default:
228     rv = NS_ERROR_FAILURE;
229   }
230   callback->Callback(rv);
231   return NS_OK;
232 }
233 
234 nsresult
NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback)235 PluginPRLibrary::NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback)
236 {
237   if (!mNPP_GetSitesWithData) {
238     return NS_ERROR_NOT_AVAILABLE;
239   }
240 
241   MAIN_THREAD_JNI_REF_GUARD;
242   char** sites = mNPP_GetSitesWithData();
243   if (!sites) {
244     return NS_OK;
245   }
246   InfallibleTArray<nsCString> result;
247   char** iterator = sites;
248   while (*iterator) {
249     result.AppendElement(*iterator);
250     free(*iterator);
251     ++iterator;
252   }
253   callback->SitesWithData(result);
254   free(sites);
255 
256   return NS_OK;
257 }
258 
259 nsresult
AsyncSetWindow(NPP instance,NPWindow * window)260 PluginPRLibrary::AsyncSetWindow(NPP instance, NPWindow* window)
261 {
262   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
263   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
264   return NS_ERROR_NOT_IMPLEMENTED;
265 }
266 
267 nsresult
GetImageContainer(NPP instance,ImageContainer ** aContainer)268 PluginPRLibrary::GetImageContainer(NPP instance, ImageContainer** aContainer)
269 {
270   return NS_ERROR_NOT_IMPLEMENTED;
271 }
272 
273 #if defined(XP_MACOSX)
274 nsresult
IsRemoteDrawingCoreAnimation(NPP instance,bool * aDrawing)275 PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
276 {
277   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
278   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
279   *aDrawing = false;
280   return NS_OK;
281 }
282 #endif
283 #if defined(XP_MACOSX) || defined(XP_WIN)
284 nsresult
ContentsScaleFactorChanged(NPP instance,double aContentsScaleFactor)285 PluginPRLibrary::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
286 {
287   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
288   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
289   return NS_OK;
290 }
291 #endif
292 
293 nsresult
GetImageSize(NPP instance,nsIntSize * aSize)294 PluginPRLibrary::GetImageSize(NPP instance, nsIntSize* aSize)
295 {
296   return NS_ERROR_NOT_IMPLEMENTED;
297 }
298 
299 nsresult
SetBackgroundUnknown(NPP instance)300 PluginPRLibrary::SetBackgroundUnknown(NPP instance)
301 {
302   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
303   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
304   NS_ERROR("Unexpected use of async APIs for in-process plugin.");
305   return NS_ERROR_NOT_IMPLEMENTED;
306 }
307 
308 nsresult
BeginUpdateBackground(NPP instance,const nsIntRect &,DrawTarget ** aDrawTarget)309 PluginPRLibrary::BeginUpdateBackground(NPP instance, const nsIntRect&,
310                                        DrawTarget** aDrawTarget)
311 {
312   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
313   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
314   NS_ERROR("Unexpected use of async APIs for in-process plugin.");
315   *aDrawTarget = nullptr;
316   return NS_OK;
317 }
318 
319 nsresult
EndUpdateBackground(NPP instance,const nsIntRect &)320 PluginPRLibrary::EndUpdateBackground(NPP instance, const nsIntRect&)
321 {
322   NS_RUNTIMEABORT("This should never be called");
323   return NS_ERROR_NOT_AVAILABLE;
324 }
325 
326 #if defined(XP_WIN)
327 nsresult
GetScrollCaptureContainer(NPP aInstance,ImageContainer ** aContainer)328 PluginPRLibrary::GetScrollCaptureContainer(NPP aInstance, ImageContainer** aContainer)
329 {
330   return NS_ERROR_NOT_IMPLEMENTED;
331 }
332 #endif
333 
334 nsresult
HandledWindowedPluginKeyEvent(NPP aInstance,const NativeEventData & aNativeKeyData,bool aIsConsumed)335 PluginPRLibrary::HandledWindowedPluginKeyEvent(
336                    NPP aInstance,
337                    const NativeEventData& aNativeKeyData,
338                    bool aIsConsumed)
339 {
340   nsNPAPIPluginInstance* instance = (nsNPAPIPluginInstance*)aInstance->ndata;
341   if (NS_WARN_IF(!instance)) {
342     return NS_ERROR_NULL_POINTER;
343   }
344   return NS_OK;
345 }
346 
347 } // namespace mozilla
348