1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "base/basictypes.h"
7 
8 /* This must occur *after* layers/PLayerTransaction.h to avoid typedefs
9  * conflicts. */
10 #include "mozilla/ArrayUtils.h"
11 
12 #include "pratom.h"
13 #include "prenv.h"
14 
15 #include "jsfriendapi.h"
16 
17 #include "nsPluginHost.h"
18 #include "nsNPAPIPlugin.h"
19 #include "nsNPAPIPluginInstance.h"
20 #include "nsNPAPIPluginStreamListener.h"
21 #include "nsPluginStreamListenerPeer.h"
22 #include "nsThreadUtils.h"
23 #include "mozilla/CycleCollectedJSContext.h"  // for nsAutoMicroTask
24 #include "mozilla/Preferences.h"
25 #include "nsPluginInstanceOwner.h"
26 
27 #include "nsPluginsDir.h"
28 #include "nsPluginLogging.h"
29 
30 #include "nsPIDOMWindow.h"
31 #include "nsGlobalWindow.h"
32 #include "mozilla/dom/Document.h"
33 #include "nsIContent.h"
34 #include "nsIIDNService.h"
35 #include "nsIScriptGlobalObject.h"
36 #include "nsIScriptContext.h"
37 #include "nsDOMJSUtils.h"
38 #include "nsIPrincipal.h"
39 #include "nsWildCard.h"
40 #include "nsContentUtils.h"
41 #include "mozilla/dom/Element.h"
42 #include "mozilla/dom/ScriptSettings.h"
43 #include "mozilla/dom/ToJSValue.h"
44 #include "nsIXPConnect.h"
45 
46 #include <prinrval.h>
47 
48 #ifdef MOZ_WIDGET_COCOA
49 #  include <Carbon/Carbon.h>
50 #  include <ApplicationServices/ApplicationServices.h>
51 #  include <OpenGL/OpenGL.h>
52 #  include "nsCocoaFeatures.h"
53 #  include "PluginUtilsOSX.h"
54 #endif
55 
56 // needed for nppdf plugin
57 #if (MOZ_WIDGET_GTK)
58 #  include <gdk/gdk.h>
59 #  include <gdk/gdkx.h>
60 #endif
61 
62 #include "nsJSUtils.h"
63 #include "nsJSNPRuntime.h"
64 
65 #include "nsNetUtil.h"
66 #include "nsNetCID.h"
67 
68 #include "mozilla/Mutex.h"
69 #include "mozilla/PluginLibrary.h"
70 using mozilla::PluginLibrary;
71 
72 #include "mozilla/plugins/PluginModuleParent.h"
73 using mozilla::plugins::PluginModuleChromeParent;
74 using mozilla::plugins::PluginModuleContentParent;
75 
76 #ifdef MOZ_X11
77 #  include "mozilla/X11Util.h"
78 #endif
79 
80 #ifdef XP_WIN
81 #  include <windows.h>
82 #  include "mozilla/WindowsVersion.h"
83 #  ifdef ACCESSIBILITY
84 #    include "mozilla/a11y/Compatibility.h"
85 #  endif
86 #endif
87 
88 #include "AudioChannelService.h"
89 
90 using namespace mozilla;
91 using namespace mozilla::plugins::parent;
92 using mozilla::dom::Document;
93 
94 // We should make this const...
95 static NPNetscapeFuncs sBrowserFuncs = {
96     sizeof(sBrowserFuncs),
97     (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
98     _geturl,
99     _posturl,
100     _requestread,
101     nullptr,  // _newstream, unimplemented
102     nullptr,  // _write, unimplemented
103     nullptr,  // _destroystream, unimplemented
104     _status,
105     _useragent,
106     _memalloc,
107     _memfree,
108     _memflush,
109     _reloadplugins,
110     _getJavaEnv,
111     _getJavaPeer,
112     _geturlnotify,
113     _posturlnotify,
114     _getvalue,
115     _setvalue,
116     _invalidaterect,
117     _invalidateregion,
118     _forceredraw,
119     _getstringidentifier,
120     _getstringidentifiers,
121     _getintidentifier,
122     _identifierisstring,
123     _utf8fromidentifier,
124     _intfromidentifier,
125     _createobject,
126     _retainobject,
127     _releaseobject,
128     _invoke,
129     _invokeDefault,
130     _evaluate,
131     _getproperty,
132     _setproperty,
133     _removeproperty,
134     _hasproperty,
135     _hasmethod,
136     _releasevariantvalue,
137     _setexception,
138     _pushpopupsenabledstate,
139     _poppopupsenabledstate,
140     _enumerate,
141     nullptr,  // pluginthreadasynccall, not used
142     _construct,
143     _getvalueforurl,
144     _setvalueforurl,
145     nullptr,  // NPN GetAuthenticationInfo, not supported
146     _scheduletimer,
147     _unscheduletimer,
148     _popupcontextmenu,
149     _convertpoint,
150     nullptr,  // handleevent, unimplemented
151     nullptr,  // unfocusinstance, unimplemented
152     _urlredirectresponse,
153     _initasyncsurface,
154     _finalizeasyncsurface,
155     _setcurrentasyncsurface};
156 
157 // POST/GET stream type
158 enum eNPPStreamTypeInternal {
159   eNPPStreamTypeInternal_Get,
160   eNPPStreamTypeInternal_Post
161 };
162 
NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState)163 void NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState) {
164   nsNPAPIPluginInstance::BeginPluginCall(aReentryState);
165 }
166 
NS_NotifyPluginCall(NSPluginCallReentry aReentryState)167 void NS_NotifyPluginCall(NSPluginCallReentry aReentryState) {
168   nsNPAPIPluginInstance::EndPluginCall(aReentryState);
169 }
170 
nsNPAPIPlugin()171 nsNPAPIPlugin::nsNPAPIPlugin() {
172   memset((void*)&mPluginFuncs, 0, sizeof(mPluginFuncs));
173   mPluginFuncs.size = sizeof(mPluginFuncs);
174   mPluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
175 
176   mLibrary = nullptr;
177 }
178 
~nsNPAPIPlugin()179 nsNPAPIPlugin::~nsNPAPIPlugin() {
180   delete mLibrary;
181   mLibrary = nullptr;
182 }
183 
PluginCrashed(const nsAString & aPluginDumpID,const nsACString & aAdditionalMinidumps)184 void nsNPAPIPlugin::PluginCrashed(const nsAString& aPluginDumpID,
185                                   const nsACString& aAdditionalMinidumps) {
186   RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
187   host->PluginCrashed(this, aPluginDumpID, aAdditionalMinidumps);
188 }
189 
GetNewPluginLibrary(nsPluginTag * aPluginTag)190 inline PluginLibrary* GetNewPluginLibrary(nsPluginTag* aPluginTag) {
191   AUTO_PROFILER_LABEL("GetNewPluginLibrary", OTHER);
192 
193   if (!aPluginTag) {
194     return nullptr;
195   }
196 
197   if (XRE_IsContentProcess()) {
198     return PluginModuleContentParent::LoadModule(aPluginTag->mId, aPluginTag);
199   }
200 
201   return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(),
202                                               aPluginTag->mId, aPluginTag);
203 }
204 
205 // Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin
206 // (not instance).
CreatePlugin(nsPluginTag * aPluginTag,nsNPAPIPlugin ** aResult)207 nsresult nsNPAPIPlugin::CreatePlugin(nsPluginTag* aPluginTag,
208                                      nsNPAPIPlugin** aResult) {
209   AUTO_PROFILER_LABEL("nsNPAPIPlugin::CreatePlugin", OTHER);
210   *aResult = nullptr;
211 
212   if (!aPluginTag) {
213     return NS_ERROR_FAILURE;
214   }
215 
216   RefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
217 
218   PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
219   if (!pluginLib) {
220     return NS_ERROR_FAILURE;
221   }
222 
223 #if defined(XP_MACOSX)
224   if (!pluginLib->HasRequiredFunctions()) {
225     NS_WARNING(
226         "Not all necessary functions exposed by plugin, it will not load.");
227     delete pluginLib;
228     return NS_ERROR_FAILURE;
229   }
230 #endif
231 
232   plugin->mLibrary = pluginLib;
233   pluginLib->SetPlugin(plugin);
234 
235 // Exchange NPAPI entry points.
236 #if defined(XP_WIN)
237   // NP_GetEntryPoints must be called before NP_Initialize on Windows.
238   NPError pluginCallError;
239   nsresult rv =
240       pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
241   if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
242     return NS_ERROR_FAILURE;
243   }
244 
245   // NP_Initialize must be called after NP_GetEntryPoints on Windows.
246   rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
247   if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
248     return NS_ERROR_FAILURE;
249   }
250 #elif defined(XP_MACOSX)
251   // NP_Initialize must be called before NP_GetEntryPoints on Mac OS X.
252   // We need to match WebKit's behavior.
253   NPError pluginCallError;
254   nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
255   if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
256     return NS_ERROR_FAILURE;
257   }
258 
259   rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
260   if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
261     return NS_ERROR_FAILURE;
262   }
263 #else
264   NPError pluginCallError;
265   nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs,
266                                          &pluginCallError);
267   if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
268     return NS_ERROR_FAILURE;
269   }
270 #endif
271 
272   plugin.forget(aResult);
273   return NS_OK;
274 }
275 
GetLibrary()276 PluginLibrary* nsNPAPIPlugin::GetLibrary() { return mLibrary; }
277 
PluginFuncs()278 NPPluginFuncs* nsNPAPIPlugin::PluginFuncs() { return &mPluginFuncs; }
279 
Shutdown()280 nsresult nsNPAPIPlugin::Shutdown() {
281   NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
282                  ("NPP Shutdown to be called: this=%p\n", this));
283 
284   NPError shutdownError;
285   mLibrary->NP_Shutdown(&shutdownError);
286 
287   return NS_OK;
288 }
289 
RetainStream(NPStream * pstream,nsISupports ** aRetainedPeer)290 nsresult nsNPAPIPlugin::RetainStream(NPStream* pstream,
291                                      nsISupports** aRetainedPeer) {
292   if (!aRetainedPeer) return NS_ERROR_NULL_POINTER;
293 
294   *aRetainedPeer = nullptr;
295 
296   if (!pstream || !pstream->ndata) return NS_ERROR_NULL_POINTER;
297 
298   nsNPAPIStreamWrapper* streamWrapper =
299       static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
300   nsNPAPIPluginStreamListener* listener = streamWrapper->GetStreamListener();
301   if (!listener) {
302     return NS_ERROR_NULL_POINTER;
303   }
304 
305   nsIStreamListener* streamListener = listener->GetStreamListenerPeer();
306   if (!streamListener) {
307     return NS_ERROR_NULL_POINTER;
308   }
309 
310   *aRetainedPeer = streamListener;
311   NS_ADDREF(*aRetainedPeer);
312   return NS_OK;
313 }
314 
315 // Create a new NPP GET or POST (given in the type argument) url
316 // stream that may have a notify callback
MakeNewNPAPIStreamInternal(NPP npp,const char * relativeURL,const char * target,eNPPStreamTypeInternal type,bool bDoNotify=false,void * notifyData=nullptr,uint32_t len=0,const char * buf=nullptr)317 NPError MakeNewNPAPIStreamInternal(NPP npp, const char* relativeURL,
318                                    const char* target,
319                                    eNPPStreamTypeInternal type,
320                                    bool bDoNotify = false,
321                                    void* notifyData = nullptr, uint32_t len = 0,
322                                    const char* buf = nullptr) {
323   if (!npp) return NPERR_INVALID_INSTANCE_ERROR;
324 
325   PluginDestructionGuard guard(npp);
326 
327   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
328   if (!inst || !inst->IsRunning()) return NPERR_INVALID_INSTANCE_ERROR;
329 
330   nsCOMPtr<nsIPluginHost> pluginHostCOM =
331       do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
332   nsPluginHost* pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
333   if (!pluginHost) {
334     return NPERR_GENERIC_ERROR;
335   }
336 
337   RefPtr<nsNPAPIPluginStreamListener> listener;
338   // Set aCallNotify here to false.  If pluginHost->GetURL or PostURL fail,
339   // the listener's destructor will do the notification while we are about to
340   // return a failure code.
341   // Call SetCallNotify(true) below after we are sure we cannot return a failure
342   // code.
343   if (!target) {
344     inst->NewStreamListener(relativeURL, notifyData, getter_AddRefs(listener));
345     if (listener) {
346       listener->SetCallNotify(false);
347     }
348   }
349 
350   switch (type) {
351     case eNPPStreamTypeInternal_Get: {
352       if (NS_FAILED(pluginHost->GetURL(inst, relativeURL, target, listener,
353                                        nullptr, nullptr, false)))
354         return NPERR_GENERIC_ERROR;
355       break;
356     }
357     case eNPPStreamTypeInternal_Post: {
358       if (NS_FAILED(pluginHost->PostURL(inst, relativeURL, len, buf, target,
359                                         listener, nullptr, nullptr, false, 0,
360                                         nullptr)))
361         return NPERR_GENERIC_ERROR;
362       break;
363     }
364     default:
365       NS_ERROR("how'd I get here");
366   }
367 
368   if (listener) {
369     // SetCallNotify(bDoNotify) here, see comment above.
370     listener->SetCallNotify(bDoNotify);
371   }
372 
373   return NPERR_NO_ERROR;
374 }
375 
376 #if defined(MOZ_MEMORY) && defined(XP_WIN)
377 extern "C" size_t malloc_usable_size(const void* ptr);
378 #endif
379 
380 namespace {
381 
382 static char* gNPPException;
383 
GetDocumentFromNPP(NPP npp)384 static Document* GetDocumentFromNPP(NPP npp) {
385   NS_ENSURE_TRUE(npp, nullptr);
386 
387   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
388   NS_ENSURE_TRUE(inst, nullptr);
389 
390   PluginDestructionGuard guard(inst);
391 
392   RefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
393   NS_ENSURE_TRUE(owner, nullptr);
394 
395   nsCOMPtr<Document> doc;
396   owner->GetDocument(getter_AddRefs(doc));
397 
398   return doc;
399 }
400 
doGetIdentifier(JSContext * cx,const NPUTF8 * name)401 static NPIdentifier doGetIdentifier(JSContext* cx, const NPUTF8* name) {
402   NS_ConvertUTF8toUTF16 utf16name(name);
403 
404   JSString* str =
405       ::JS_AtomizeAndPinUCStringN(cx, utf16name.get(), utf16name.Length());
406 
407   if (!str) return nullptr;
408 
409   return StringToNPIdentifier(cx, str);
410 }
411 
412 #if defined(MOZ_MEMORY) && defined(XP_WIN)
InHeap(HANDLE hHeap,LPVOID lpMem)413 BOOL InHeap(HANDLE hHeap, LPVOID lpMem) {
414   BOOL success = FALSE;
415   PROCESS_HEAP_ENTRY he;
416   he.lpData = nullptr;
417   while (HeapWalk(hHeap, &he) != 0) {
418     if (he.lpData == lpMem) {
419       success = TRUE;
420       break;
421     }
422   }
423   HeapUnlock(hHeap);
424   return success;
425 }
426 #endif
427 
428 } /* anonymous namespace */
429 
NPPExceptionAutoHolder()430 NPPExceptionAutoHolder::NPPExceptionAutoHolder()
431     : mOldException(gNPPException) {
432   gNPPException = nullptr;
433 }
434 
~NPPExceptionAutoHolder()435 NPPExceptionAutoHolder::~NPPExceptionAutoHolder() {
436   NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
437 
438   gNPPException = mOldException;
439 }
440 
441 NPP NPPStack::sCurrentNPP = nullptr;
442 
PeekException()443 const char* PeekException() { return gNPPException; }
444 
PopException()445 void PopException() {
446   NS_ASSERTION(gNPPException, "Uh, no NPP exception to pop!");
447 
448   if (gNPPException) {
449     free(gNPPException);
450 
451     gNPPException = nullptr;
452   }
453 }
454 
455 //
456 // Static callbacks that get routed back through the new C++ API
457 //
458 
459 namespace mozilla::plugins::parent {
460 
_geturl(NPP npp,const char * relativeURL,const char * target)461 NPError _geturl(NPP npp, const char* relativeURL, const char* target) {
462   if (!NS_IsMainThread()) {
463     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
464                    ("NPN_geturl called from the wrong thread\n"));
465     return NPERR_INVALID_PARAM;
466   }
467 
468   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetURL: npp=%p, target=%s, url=%s\n",
469                                      (void*)npp, target, relativeURL));
470 
471   PluginDestructionGuard guard(npp);
472 
473   return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
474                                     eNPPStreamTypeInternal_Get);
475 }
476 
_geturlnotify(NPP npp,const char * relativeURL,const char * target,void * notifyData)477 NPError _geturlnotify(NPP npp, const char* relativeURL, const char* target,
478                       void* notifyData) {
479   if (!NS_IsMainThread()) {
480     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
481                    ("NPN_geturlnotify called from the wrong thread\n"));
482     return NPERR_INVALID_PARAM;
483   }
484 
485   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
486                  ("NPN_GetURLNotify: npp=%p, target=%s, notify=%p, url=%s\n",
487                   (void*)npp, target, notifyData, relativeURL));
488 
489   PluginDestructionGuard guard(npp);
490 
491   return MakeNewNPAPIStreamInternal(
492       npp, relativeURL, target, eNPPStreamTypeInternal_Get, true, notifyData);
493 }
494 
_posturlnotify(NPP npp,const char * relativeURL,const char * target,uint32_t len,const char * buf,NPBool file,void * notifyData)495 NPError _posturlnotify(NPP npp, const char* relativeURL, const char* target,
496                        uint32_t len, const char* buf, NPBool file,
497                        void* notifyData) {
498   if (!NS_IsMainThread()) {
499     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
500                    ("NPN_posturlnotify called from the wrong thread\n"));
501     return NPERR_INVALID_PARAM;
502   }
503   if (!buf) return NPERR_INVALID_PARAM;
504 
505   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
506                  ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, "
507                   "notify=%p, url=%s, buf=%s\n",
508                   (void*)npp, target, len, file, notifyData, relativeURL, buf));
509 
510   PluginDestructionGuard guard(npp);
511 
512   return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
513                                     eNPPStreamTypeInternal_Post, true,
514                                     notifyData, len, buf);
515 }
516 
_posturl(NPP npp,const char * relativeURL,const char * target,uint32_t len,const char * buf,NPBool file)517 NPError _posturl(NPP npp, const char* relativeURL, const char* target,
518                  uint32_t len, const char* buf, NPBool file) {
519   if (!NS_IsMainThread()) {
520     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
521                    ("NPN_posturl called from the wrong thread\n"));
522     return NPERR_INVALID_PARAM;
523   }
524   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
525                  ("NPN_PostURL: npp=%p, target=%s, file=%d, len=%d, url=%s, "
526                   "buf=%s\n",
527                   (void*)npp, target, file, len, relativeURL, buf));
528 
529   PluginDestructionGuard guard(npp);
530 
531   return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
532                                     eNPPStreamTypeInternal_Post, false, nullptr,
533                                     len, buf);
534 }
535 
_status(NPP npp,const char * message)536 void _status(NPP npp, const char* message) {
537   // NPN_Status is no longer supported.
538 }
539 
_memfree(void * ptr)540 void _memfree(void* ptr) {
541   if (!NS_IsMainThread()) {
542     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
543                    ("NPN_memfree called from the wrong thread\n"));
544   }
545   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFree: ptr=%p\n", ptr));
546 
547   if (ptr) free(ptr);
548 }
549 
_memflush(uint32_t size)550 uint32_t _memflush(uint32_t size) {
551   if (!NS_IsMainThread()) {
552     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
553                    ("NPN_memflush called from the wrong thread\n"));
554   }
555   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFlush: size=%d\n", size));
556 
557   nsMemory::HeapMinimize(true);
558   return 0;
559 }
560 
_reloadplugins(NPBool reloadPages)561 void _reloadplugins(NPBool reloadPages) {
562   if (!NS_IsMainThread()) {
563     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
564                    ("NPN_reloadplugins called from the wrong thread\n"));
565     return;
566   }
567   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
568                  ("NPN_ReloadPlugins: reloadPages=%d\n", reloadPages));
569 
570   nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
571   if (!pluginHost) return;
572 
573   pluginHost->ReloadPlugins();
574 }
575 
_invalidaterect(NPP npp,NPRect * invalidRect)576 void _invalidaterect(NPP npp, NPRect* invalidRect) {
577   if (!NS_IsMainThread()) {
578     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
579                    ("NPN_invalidaterect called from the wrong thread\n"));
580     return;
581   }
582   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
583                  ("NPN_InvalidateRect: npp=%p, top=%d, left=%d, bottom=%d, "
584                   "right=%d\n",
585                   (void*)npp, invalidRect->top, invalidRect->left,
586                   invalidRect->bottom, invalidRect->right));
587 
588   if (!npp || !npp->ndata) {
589     NS_WARNING("_invalidaterect: npp or npp->ndata == 0");
590     return;
591   }
592 
593   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
594 
595   PluginDestructionGuard guard(inst);
596 
597   inst->InvalidateRect((NPRect*)invalidRect);
598 }
599 
_invalidateregion(NPP npp,NPRegion invalidRegion)600 void _invalidateregion(NPP npp, NPRegion invalidRegion) {
601   if (!NS_IsMainThread()) {
602     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
603                    ("NPN_invalidateregion called from the wrong thread\n"));
604     return;
605   }
606   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
607                  ("NPN_InvalidateRegion: npp=%p, region=%p\n", (void*)npp,
608                   (void*)invalidRegion));
609 
610   if (!npp || !npp->ndata) {
611     NS_WARNING("_invalidateregion: npp or npp->ndata == 0");
612     return;
613   }
614 
615   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
616 
617   PluginDestructionGuard guard(inst);
618 
619   inst->InvalidateRegion((NPRegion)invalidRegion);
620 }
621 
_forceredraw(NPP npp)622 void _forceredraw(NPP npp) {}
623 
_getwindowobject(NPP npp)624 NPObject* _getwindowobject(NPP npp) {
625   if (!NS_IsMainThread()) {
626     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
627                    ("NPN_getwindowobject called from the wrong thread\n"));
628     return nullptr;
629   }
630 
631   // The window want to return here is the outer window, *not* the inner (since
632   // we don't know what the plugin will do with it).
633   Document* doc = GetDocumentFromNPP(npp);
634   NS_ENSURE_TRUE(doc, nullptr);
635   nsCOMPtr<nsPIDOMWindowOuter> outer = doc->GetWindow();
636   NS_ENSURE_TRUE(outer, nullptr);
637 
638   JS::Rooted<JSObject*> windowProxy(
639       dom::RootingCx(), nsGlobalWindowOuter::Cast(outer)->GetGlobalJSObject());
640   JS::Rooted<JSObject*> global(dom::RootingCx(),
641                                JS::GetNonCCWObjectGlobal(windowProxy));
642   return nsJSObjWrapper::GetNewOrUsed(npp, windowProxy, global);
643 }
644 
_getpluginelement(NPP npp)645 NPObject* _getpluginelement(NPP npp) {
646   if (!NS_IsMainThread()) {
647     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
648                    ("NPN_getpluginelement called from the wrong thread\n"));
649     return nullptr;
650   }
651 
652   nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
653   if (!inst) return nullptr;
654 
655   RefPtr<dom::Element> element;
656   inst->GetDOMElement(getter_AddRefs(element));
657 
658   if (!element) return nullptr;
659 
660   Document* doc = GetDocumentFromNPP(npp);
661   if (NS_WARN_IF(!doc)) {
662     return nullptr;
663   }
664 
665   dom::AutoJSAPI jsapi;
666   if (NS_WARN_IF(!jsapi.Init(doc->GetInnerWindow()))) {
667     return nullptr;
668   }
669   JSContext* cx = jsapi.cx();
670 
671   nsCOMPtr<nsIXPConnect> xpc(nsIXPConnect::XPConnect());
672   NS_ENSURE_TRUE(xpc, nullptr);
673 
674   JS::RootedValue val(cx);
675   if (!ToJSValue(cx, element, &val)) {
676     return nullptr;
677   }
678 
679   if (NS_WARN_IF(!val.isObject())) {
680     return nullptr;
681   }
682 
683   JS::RootedObject obj(cx, &val.toObject());
684   JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
685   return nsJSObjWrapper::GetNewOrUsed(npp, obj, global);
686 }
687 
_getstringidentifier(const NPUTF8 * name)688 NPIdentifier _getstringidentifier(const NPUTF8* name) {
689   if (!name) {
690     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
691                    ("NPN_getstringidentifier: passed null name"));
692     return nullptr;
693   }
694   if (!NS_IsMainThread()) {
695     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
696                    ("NPN_getstringidentifier called from the wrong thread\n"));
697   }
698 
699   AutoSafeJSContext cx;
700   return doGetIdentifier(cx, name);
701 }
702 
_getstringidentifiers(const NPUTF8 ** names,int32_t nameCount,NPIdentifier * identifiers)703 void _getstringidentifiers(const NPUTF8** names, int32_t nameCount,
704                            NPIdentifier* identifiers) {
705   if (!NS_IsMainThread()) {
706     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
707                    ("NPN_getstringidentifiers called from the wrong thread\n"));
708   }
709 
710   AutoSafeJSContext cx;
711 
712   for (int32_t i = 0; i < nameCount; ++i) {
713     if (names[i]) {
714       identifiers[i] = doGetIdentifier(cx, names[i]);
715     } else {
716       NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
717                      ("NPN_getstringidentifiers: passed null name"));
718       identifiers[i] = nullptr;
719     }
720   }
721 }
722 
_getintidentifier(int32_t intid)723 NPIdentifier _getintidentifier(int32_t intid) {
724   if (!NS_IsMainThread()) {
725     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
726                    ("NPN_getstringidentifier called from the wrong thread\n"));
727   }
728   return IntToNPIdentifier(intid);
729 }
730 
_utf8fromidentifier(NPIdentifier id)731 NPUTF8* _utf8fromidentifier(NPIdentifier id) {
732   if (!NS_IsMainThread()) {
733     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
734                    ("NPN_utf8fromidentifier called from the wrong thread\n"));
735   }
736   if (!id) return nullptr;
737 
738   if (!NPIdentifierIsString(id)) {
739     return nullptr;
740   }
741 
742   JSString* str = NPIdentifierToString(id);
743   nsAutoString autoStr;
744   AssignJSLinearString(autoStr, JS_ASSERT_STRING_IS_LINEAR(str));
745 
746   return ToNewUTF8String(autoStr);
747 }
748 
_intfromidentifier(NPIdentifier id)749 int32_t _intfromidentifier(NPIdentifier id) {
750   if (!NS_IsMainThread()) {
751     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
752                    ("NPN_intfromidentifier called from the wrong thread\n"));
753   }
754 
755   if (!NPIdentifierIsInt(id)) {
756     return INT32_MIN;
757   }
758 
759   return NPIdentifierToInt(id);
760 }
761 
_identifierisstring(NPIdentifier id)762 bool _identifierisstring(NPIdentifier id) {
763   if (!NS_IsMainThread()) {
764     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
765                    ("NPN_identifierisstring called from the wrong thread\n"));
766   }
767 
768   return NPIdentifierIsString(id);
769 }
770 
_createobject(NPP npp,NPClass * aClass)771 NPObject* _createobject(NPP npp, NPClass* aClass) {
772   if (!NS_IsMainThread()) {
773     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
774                    ("NPN_createobject called from the wrong thread\n"));
775     return nullptr;
776   }
777   if (!npp) {
778     NS_ERROR("Null npp passed to _createobject()!");
779 
780     return nullptr;
781   }
782 
783   PluginDestructionGuard guard(npp);
784 
785   if (!aClass) {
786     NS_ERROR("Null class passed to _createobject()!");
787 
788     return nullptr;
789   }
790 
791   NPPAutoPusher nppPusher(npp);
792 
793   NPObject* npobj;
794 
795   if (aClass->allocate) {
796     npobj = aClass->allocate(npp, aClass);
797   } else {
798     npobj = (NPObject*)malloc(sizeof(NPObject));
799   }
800 
801   if (npobj) {
802     npobj->_class = aClass;
803     npobj->referenceCount = 1;
804     NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
805   }
806 
807   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
808                  ("Created NPObject %p, NPClass %p\n", npobj, aClass));
809 
810   return npobj;
811 }
812 
_retainobject(NPObject * npobj)813 NPObject* _retainobject(NPObject* npobj) {
814   if (!NS_IsMainThread()) {
815     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
816                    ("NPN_retainobject called from the wrong thread\n"));
817   }
818   if (npobj) {
819 #ifdef NS_BUILD_REFCNT_LOGGING
820     int32_t refCnt =
821 #endif
822         PR_ATOMIC_INCREMENT((int32_t*)&npobj->referenceCount);
823     NS_LOG_ADDREF(npobj, refCnt, "BrowserNPObject", sizeof(NPObject));
824   }
825 
826   return npobj;
827 }
828 
_releaseobject(NPObject * npobj)829 void _releaseobject(NPObject* npobj) {
830   // If nothing is passed, just return, even if we're on the wrong thread.
831   if (!npobj) {
832     return;
833   }
834 
835   int32_t refCnt = PR_ATOMIC_DECREMENT((int32_t*)&npobj->referenceCount);
836   NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
837 
838   if (refCnt == 0) {
839     nsNPObjWrapper::OnDestroy(npobj);
840 
841     NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
842                    ("Deleting NPObject %p, refcount hit 0\n", npobj));
843 
844     if (npobj->_class && npobj->_class->deallocate) {
845       npobj->_class->deallocate(npobj);
846     } else {
847       free(npobj);
848     }
849   }
850 }
851 
_invoke(NPP npp,NPObject * npobj,NPIdentifier method,const NPVariant * args,uint32_t argCount,NPVariant * result)852 bool _invoke(NPP npp, NPObject* npobj, NPIdentifier method,
853              const NPVariant* args, uint32_t argCount, NPVariant* result) {
854   if (!NS_IsMainThread()) {
855     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
856                    ("NPN_invoke called from the wrong thread\n"));
857     return false;
858   }
859   if (!npp || !npobj || !npobj->_class || !npobj->_class->invoke) return false;
860 
861   PluginDestructionGuard guard(npp);
862 
863   NPPExceptionAutoHolder nppExceptionHolder;
864   NPPAutoPusher nppPusher(npp);
865 
866   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
867                  ("NPN_Invoke(npp %p, npobj %p, method %p, args %d\n", npp,
868                   npobj, method, argCount));
869 
870   return npobj->_class->invoke(npobj, method, args, argCount, result);
871 }
872 
_invokeDefault(NPP npp,NPObject * npobj,const NPVariant * args,uint32_t argCount,NPVariant * result)873 bool _invokeDefault(NPP npp, NPObject* npobj, const NPVariant* args,
874                     uint32_t argCount, NPVariant* result) {
875   if (!NS_IsMainThread()) {
876     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
877                    ("NPN_invokedefault called from the wrong thread\n"));
878     return false;
879   }
880   if (!npp || !npobj || !npobj->_class || !npobj->_class->invokeDefault)
881     return false;
882 
883   NPPExceptionAutoHolder nppExceptionHolder;
884   NPPAutoPusher nppPusher(npp);
885 
886   NPN_PLUGIN_LOG(
887       PLUGIN_LOG_NOISY,
888       ("NPN_InvokeDefault(npp %p, npobj %p, args %d\n", npp, npobj, argCount));
889 
890   return npobj->_class->invokeDefault(npobj, args, argCount, result);
891 }
892 
_evaluate(NPP npp,NPObject * npobj,NPString * script,NPVariant * result)893 bool _evaluate(NPP npp, NPObject* npobj, NPString* script, NPVariant* result) {
894   if (!NS_IsMainThread()) {
895     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
896                    ("NPN_evaluate called from the wrong thread\n"));
897     return false;
898   }
899   if (!npp) return false;
900 
901   NPPAutoPusher nppPusher(npp);
902 
903   Document* doc = GetDocumentFromNPP(npp);
904   NS_ENSURE_TRUE(doc, false);
905 
906   nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(doc->GetInnerWindow());
907   if (NS_WARN_IF(!win || !win->HasJSGlobal())) {
908     return false;
909   }
910 
911   nsAutoMicroTask mt;
912   dom::AutoEntryScript aes(win, "NPAPI NPN_evaluate");
913   JSContext* cx = aes.cx();
914 
915   JS::Rooted<JSObject*> obj(cx, nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj));
916 
917   if (!obj) {
918     return false;
919   }
920 
921   obj = js::ToWindowIfWindowProxy(obj);
922   MOZ_ASSERT(obj, "ToWindowIfWindowProxy should never return null");
923 
924   if (result) {
925     // Initialize the out param to void
926     VOID_TO_NPVARIANT(*result);
927   }
928 
929   if (!script || !script->UTF8Length || !script->UTF8Characters) {
930     // Nothing to evaluate.
931 
932     return true;
933   }
934 
935   NS_ConvertUTF8toUTF16 utf16script(script->UTF8Characters, script->UTF8Length);
936 
937   nsIPrincipal* principal = doc->NodePrincipal();
938 
939   nsCString specStr;
940   const char* spec;
941 
942   principal->GetAsciiSpec(specStr);
943   spec = specStr.get();
944 
945   if (specStr.IsEmpty()) {
946     // No URI in a principal means it's the system principal. If the
947     // document URI is a chrome:// URI, pass that in as the URI of the
948     // script, else pass in null for the filename as there's no way to
949     // know where this document really came from. Passing in null here
950     // also means that the script gets treated by XPConnect as if it
951     // needs additional protection, which is what we want for unknown
952     // chrome code anyways.
953     nsCOMPtr<nsIURI> uri = doc->GetDocumentURI();
954     if (uri && uri->SchemeIs("chrome")) {
955       uri->GetSpec(specStr);
956       spec = specStr.get();
957     } else {
958       spec = nullptr;
959     }
960   }
961 
962   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
963                  ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n",
964                   npp, npobj, script->UTF8Characters));
965 
966   JS::CompileOptions options(cx);
967   options.setFileAndLine(spec, 0);
968   JS::Rooted<JS::Value> rval(cx);
969   JS::RootedVector<JSObject*> scopeChain(cx);
970   if (!JS_IsGlobalObject(obj) && !scopeChain.append(obj)) {
971     return false;
972   }
973   // nsNPObjWrapper::GetNewOrUsed returns an object in the current compartment
974   // of the JSContext (it might be a CCW).
975   MOZ_RELEASE_ASSERT(
976       js::GetObjectCompartment(obj) == js::GetContextCompartment(cx),
977       "nsNPObjWrapper::GetNewOrUsed must wrap its return value");
978   obj = JS::CurrentGlobalOrNull(cx);
979   MOZ_ASSERT(obj);
980   nsresult rv = NS_OK;
981   {
982     nsJSUtils::ExecutionContext exec(cx, obj);
983     exec.SetScopeChain(scopeChain);
984     exec.Compile(options, utf16script);
985     rv = exec.ExecScript(&rval);
986   }
987 
988   if (!JS_WrapValue(cx, &rval)) {
989     return false;
990   }
991 
992   return NS_SUCCEEDED(rv) &&
993          (!result || JSValToNPVariant(npp, cx, rval, result));
994 }
995 
_getproperty(NPP npp,NPObject * npobj,NPIdentifier property,NPVariant * result)996 bool _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
997                   NPVariant* result) {
998   if (!NS_IsMainThread()) {
999     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1000                    ("NPN_getproperty called from the wrong thread\n"));
1001     return false;
1002   }
1003   if (!npp || !npobj || !npobj->_class || !npobj->_class->getProperty)
1004     return false;
1005 
1006   NPPExceptionAutoHolder nppExceptionHolder;
1007   NPPAutoPusher nppPusher(npp);
1008 
1009   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1010                  ("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
1011                   npp, npobj, property));
1012 
1013   if (!npobj->_class->getProperty(npobj, property, result)) return false;
1014 
1015   return true;
1016 }
1017 
_setproperty(NPP npp,NPObject * npobj,NPIdentifier property,const NPVariant * value)1018 bool _setproperty(NPP npp, NPObject* npobj, NPIdentifier property,
1019                   const NPVariant* value) {
1020   if (!NS_IsMainThread()) {
1021     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1022                    ("NPN_setproperty called from the wrong thread\n"));
1023     return false;
1024   }
1025   if (!npp || !npobj || !npobj->_class || !npobj->_class->setProperty)
1026     return false;
1027 
1028   NPPExceptionAutoHolder nppExceptionHolder;
1029   NPPAutoPusher nppPusher(npp);
1030 
1031   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1032                  ("NPN_SetProperty(npp %p, npobj %p, property %p) called\n",
1033                   npp, npobj, property));
1034 
1035   return npobj->_class->setProperty(npobj, property, value);
1036 }
1037 
_removeproperty(NPP npp,NPObject * npobj,NPIdentifier property)1038 bool _removeproperty(NPP npp, NPObject* npobj, NPIdentifier property) {
1039   if (!NS_IsMainThread()) {
1040     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1041                    ("NPN_removeproperty called from the wrong thread\n"));
1042     return false;
1043   }
1044   if (!npp || !npobj || !npobj->_class || !npobj->_class->removeProperty)
1045     return false;
1046 
1047   NPPExceptionAutoHolder nppExceptionHolder;
1048   NPPAutoPusher nppPusher(npp);
1049 
1050   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1051                  ("NPN_RemoveProperty(npp %p, npobj %p, property %p) called\n",
1052                   npp, npobj, property));
1053 
1054   return npobj->_class->removeProperty(npobj, property);
1055 }
1056 
_hasproperty(NPP npp,NPObject * npobj,NPIdentifier propertyName)1057 bool _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName) {
1058   if (!NS_IsMainThread()) {
1059     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1060                    ("NPN_hasproperty called from the wrong thread\n"));
1061     return false;
1062   }
1063   if (!npp || !npobj || !npobj->_class || !npobj->_class->hasProperty)
1064     return false;
1065 
1066   NPPExceptionAutoHolder nppExceptionHolder;
1067   NPPAutoPusher nppPusher(npp);
1068 
1069   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1070                  ("NPN_HasProperty(npp %p, npobj %p, property %p) called\n",
1071                   npp, npobj, propertyName));
1072 
1073   return npobj->_class->hasProperty(npobj, propertyName);
1074 }
1075 
_hasmethod(NPP npp,NPObject * npobj,NPIdentifier methodName)1076 bool _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName) {
1077   if (!NS_IsMainThread()) {
1078     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1079                    ("NPN_hasmethod called from the wrong thread\n"));
1080     return false;
1081   }
1082   if (!npp || !npobj || !npobj->_class || !npobj->_class->hasMethod)
1083     return false;
1084 
1085   NPPExceptionAutoHolder nppExceptionHolder;
1086   NPPAutoPusher nppPusher(npp);
1087 
1088   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1089                  ("NPN_HasMethod(npp %p, npobj %p, property %p) called\n", npp,
1090                   npobj, methodName));
1091 
1092   return npobj->_class->hasMethod(npobj, methodName);
1093 }
1094 
_enumerate(NPP npp,NPObject * npobj,NPIdentifier ** identifier,uint32_t * count)1095 bool _enumerate(NPP npp, NPObject* npobj, NPIdentifier** identifier,
1096                 uint32_t* count) {
1097   if (!NS_IsMainThread()) {
1098     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1099                    ("NPN_enumerate called from the wrong thread\n"));
1100     return false;
1101   }
1102   if (!npp || !npobj || !npobj->_class) return false;
1103 
1104   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1105                  ("NPN_Enumerate(npp %p, npobj %p) called\n", npp, npobj));
1106 
1107   if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
1108       !npobj->_class->enumerate) {
1109     *identifier = 0;
1110     *count = 0;
1111     return true;
1112   }
1113 
1114   NPPExceptionAutoHolder nppExceptionHolder;
1115   NPPAutoPusher nppPusher(npp);
1116 
1117   return npobj->_class->enumerate(npobj, identifier, count);
1118 }
1119 
_construct(NPP npp,NPObject * npobj,const NPVariant * args,uint32_t argCount,NPVariant * result)1120 bool _construct(NPP npp, NPObject* npobj, const NPVariant* args,
1121                 uint32_t argCount, NPVariant* result) {
1122   if (!NS_IsMainThread()) {
1123     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1124                    ("NPN_construct called from the wrong thread\n"));
1125     return false;
1126   }
1127   if (!npp || !npobj || !npobj->_class ||
1128       !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) ||
1129       !npobj->_class->construct) {
1130     return false;
1131   }
1132 
1133   NPPExceptionAutoHolder nppExceptionHolder;
1134   NPPAutoPusher nppPusher(npp);
1135 
1136   return npobj->_class->construct(npobj, args, argCount, result);
1137 }
1138 
_releasevariantvalue(NPVariant * variant)1139 void _releasevariantvalue(NPVariant* variant) {
1140   if (!NS_IsMainThread()) {
1141     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1142                    ("NPN_releasevariantvalue called from the wrong thread\n"));
1143   }
1144   switch (variant->type) {
1145     case NPVariantType_Void:
1146     case NPVariantType_Null:
1147     case NPVariantType_Bool:
1148     case NPVariantType_Int32:
1149     case NPVariantType_Double:
1150       break;
1151     case NPVariantType_String: {
1152       const NPString* s = &NPVARIANT_TO_STRING(*variant);
1153 
1154       if (s->UTF8Characters) {
1155 #if defined(MOZ_MEMORY) && defined(XP_WIN)
1156         if (malloc_usable_size((void*)s->UTF8Characters) != 0) {
1157           free((void*)s->UTF8Characters);
1158         } else {
1159           void* p = (void*)s->UTF8Characters;
1160           DWORD nheaps = 0;
1161           AutoTArray<HANDLE, 50> heaps;
1162           nheaps = GetProcessHeaps(0, heaps.Elements());
1163           heaps.AppendElements(nheaps);
1164           GetProcessHeaps(nheaps, heaps.Elements());
1165           for (DWORD i = 0; i < nheaps; i++) {
1166             if (InHeap(heaps[i], p)) {
1167               HeapFree(heaps[i], 0, p);
1168               break;
1169             }
1170           }
1171         }
1172 #else
1173         free((void*)s->UTF8Characters);
1174 #endif
1175       }
1176       break;
1177     }
1178     case NPVariantType_Object: {
1179       NPObject* npobj = NPVARIANT_TO_OBJECT(*variant);
1180 
1181       if (npobj) _releaseobject(npobj);
1182 
1183       break;
1184     }
1185     default:
1186       NS_ERROR("Unknown NPVariant type!");
1187   }
1188 
1189   VOID_TO_NPVARIANT(*variant);
1190 }
1191 
_setexception(NPObject * npobj,const NPUTF8 * message)1192 void _setexception(NPObject* npobj, const NPUTF8* message) {
1193   if (!NS_IsMainThread()) {
1194     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1195                    ("NPN_setexception called from the wrong thread\n"));
1196     return;
1197   }
1198 
1199   if (!message) return;
1200 
1201   if (gNPPException) {
1202     // If a plugin throws multiple exceptions, we'll only report the
1203     // last one for now.
1204     free(gNPPException);
1205   }
1206 
1207   gNPPException = strdup(message);
1208 }
1209 
_getvalue(NPP npp,NPNVariable variable,void * result)1210 NPError _getvalue(NPP npp, NPNVariable variable, void* result) {
1211   if (!NS_IsMainThread()) {
1212     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1213                    ("NPN_getvalue called from the wrong thread\n"));
1214     return NPERR_INVALID_PARAM;
1215   }
1216   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
1217                  ("NPN_GetValue: npp=%p, var=%d\n", (void*)npp, (int)variable));
1218 
1219   nsresult res;
1220 
1221   PluginDestructionGuard guard(npp);
1222 
1223   // Cast NPNVariable enum to int to avoid warnings about including switch
1224   // cases for android_npapi.h's non-standard ANPInterface values.
1225   switch (static_cast<int>(variable)) {
1226 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1227     case NPNVxDisplay: {
1228 #  if defined(MOZ_X11)
1229       if (npp) {
1230         nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1231         bool windowless = false;
1232         inst->IsWindowless(&windowless);
1233         // The documentation on the types for many variables in NP(N|P)_GetValue
1234         // is vague.  Often boolean values are NPBool (1 byte), but
1235         // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
1236         // treats NPPVpluginNeedsXEmbed as PRBool (int), and
1237         // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
1238         // thus we can't use NPBool for needsXEmbed, or the three bytes above
1239         // it on the stack would get clobbered. so protect with the larger bool.
1240         int needsXEmbed = 0;
1241         if (!windowless) {
1242           res = inst->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needsXEmbed);
1243           // If the call returned an error code make sure we still use our
1244           // default value.
1245           if (NS_FAILED(res)) {
1246             needsXEmbed = 0;
1247           }
1248         }
1249         if (windowless || needsXEmbed) {
1250           (*(Display**)result) = mozilla::DefaultXDisplay();
1251           return NPERR_NO_ERROR;
1252         }
1253       }
1254 #  endif
1255       return NPERR_GENERIC_ERROR;
1256     }
1257 
1258     case NPNVxtAppContext:
1259       return NPERR_GENERIC_ERROR;
1260 #endif
1261 
1262 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1263     case NPNVnetscapeWindow: {
1264       if (!npp || !npp->ndata) return NPERR_INVALID_INSTANCE_ERROR;
1265 
1266       nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1267 
1268       RefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
1269       NS_ENSURE_TRUE(owner, NPERR_NO_ERROR);
1270 
1271       if (NS_SUCCEEDED(owner->GetNetscapeWindow(result))) {
1272         return NPERR_NO_ERROR;
1273       }
1274       return NPERR_GENERIC_ERROR;
1275     }
1276 #endif
1277 
1278     case NPNVjavascriptEnabledBool: {
1279       *(NPBool*)result = false;
1280       bool js = false;
1281       res = Preferences::GetBool("javascript.enabled", &js);
1282       if (NS_SUCCEEDED(res)) {
1283         *(NPBool*)result = js;
1284       }
1285       return NPERR_NO_ERROR;
1286     }
1287 
1288     case NPNVasdEnabledBool:
1289       *(NPBool*)result = false;
1290       return NPERR_NO_ERROR;
1291 
1292     case NPNVisOfflineBool: {
1293       bool offline = false;
1294       nsCOMPtr<nsIIOService> ioservice =
1295           do_GetService(NS_IOSERVICE_CONTRACTID, &res);
1296       if (NS_SUCCEEDED(res)) res = ioservice->GetOffline(&offline);
1297       if (NS_FAILED(res)) return NPERR_GENERIC_ERROR;
1298 
1299       *(NPBool*)result = offline;
1300       return NPERR_NO_ERROR;
1301     }
1302 
1303     case NPNVToolkit: {
1304 #ifdef MOZ_WIDGET_GTK
1305       *((NPNToolkitType*)result) = NPNVGtk2;
1306 #endif
1307 
1308       if (*(NPNToolkitType*)result) return NPERR_NO_ERROR;
1309 
1310       return NPERR_GENERIC_ERROR;
1311     }
1312 
1313     case NPNVSupportsXEmbedBool: {
1314 #ifdef MOZ_WIDGET_GTK
1315       *(NPBool*)result = true;
1316 #else
1317       *(NPBool*)result = false;
1318 #endif
1319       return NPERR_NO_ERROR;
1320     }
1321 
1322     case NPNVWindowNPObject: {
1323       *(NPObject**)result = _getwindowobject(npp);
1324 
1325       return *(NPObject**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1326     }
1327 
1328     case NPNVPluginElementNPObject: {
1329       *(NPObject**)result = _getpluginelement(npp);
1330 
1331       return *(NPObject**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1332     }
1333 
1334     case NPNVSupportsWindowless: {
1335 #if defined(XP_WIN) || defined(XP_MACOSX) || \
1336     (defined(MOZ_X11) && defined(MOZ_WIDGET_GTK))
1337       *(NPBool*)result = true;
1338 #else
1339       *(NPBool*)result = false;
1340 #endif
1341       return NPERR_NO_ERROR;
1342     }
1343 
1344     case NPNVprivateModeBool: {
1345       bool privacy;
1346       nsNPAPIPluginInstance* inst =
1347           static_cast<nsNPAPIPluginInstance*>(npp->ndata);
1348       if (!inst) return NPERR_GENERIC_ERROR;
1349 
1350       nsresult rv = inst->IsPrivateBrowsing(&privacy);
1351       if (NS_FAILED(rv)) return NPERR_GENERIC_ERROR;
1352       *(NPBool*)result = (NPBool)privacy;
1353       return NPERR_NO_ERROR;
1354     }
1355 
1356     case NPNVdocumentOrigin: {
1357       nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1358       if (!inst) {
1359         return NPERR_GENERIC_ERROR;
1360       }
1361 
1362       RefPtr<dom::Element> element;
1363       inst->GetDOMElement(getter_AddRefs(element));
1364       if (!element) {
1365         return NPERR_GENERIC_ERROR;
1366       }
1367 
1368       nsIPrincipal* principal = element->NodePrincipal();
1369 
1370       nsAutoString utf16Origin;
1371       res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
1372       if (NS_FAILED(res)) {
1373         return NPERR_GENERIC_ERROR;
1374       }
1375 
1376       nsCOMPtr<nsIIDNService> idnService =
1377           do_GetService(NS_IDNSERVICE_CONTRACTID);
1378       if (!idnService) {
1379         return NPERR_GENERIC_ERROR;
1380       }
1381 
1382       // This is a bit messy: we convert to UTF-8 here, but then
1383       // nsIDNService::Normalize will convert back to UTF-16 for processing,
1384       // and back to UTF-8 again to return the result.
1385       // Alternative: perhaps we should add a NormalizeUTF16 version of the API,
1386       // and just convert to UTF-8 for the final return (resulting in one
1387       // encoding form conversion instead of three).
1388       NS_ConvertUTF16toUTF8 utf8Origin(utf16Origin);
1389       nsAutoCString normalizedUTF8Origin;
1390       res = idnService->Normalize(utf8Origin, normalizedUTF8Origin);
1391       if (NS_FAILED(res)) {
1392         return NPERR_GENERIC_ERROR;
1393       }
1394 
1395       *(char**)result = ToNewCString(normalizedUTF8Origin);
1396       return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1397     }
1398 
1399 #ifdef XP_MACOSX
1400     case NPNVpluginDrawingModel: {
1401       if (npp) {
1402         nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1403         if (inst) {
1404           NPDrawingModel drawingModel;
1405           inst->GetDrawingModel((int32_t*)&drawingModel);
1406           *(NPDrawingModel*)result = drawingModel;
1407           return NPERR_NO_ERROR;
1408         }
1409       }
1410       return NPERR_GENERIC_ERROR;
1411     }
1412 
1413 #  ifndef NP_NO_QUICKDRAW
1414     case NPNVsupportsQuickDrawBool: {
1415       *(NPBool*)result = false;
1416 
1417       return NPERR_NO_ERROR;
1418     }
1419 #  endif
1420 
1421     case NPNVsupportsCoreGraphicsBool: {
1422       *(NPBool*)result = true;
1423 
1424       return NPERR_NO_ERROR;
1425     }
1426 
1427     case NPNVsupportsCoreAnimationBool: {
1428       *(NPBool*)result = true;
1429 
1430       return NPERR_NO_ERROR;
1431     }
1432 
1433     case NPNVsupportsInvalidatingCoreAnimationBool: {
1434       *(NPBool*)result = true;
1435 
1436       return NPERR_NO_ERROR;
1437     }
1438 
1439     case NPNVsupportsCompositingCoreAnimationPluginsBool: {
1440       *(NPBool*)result = PR_TRUE;
1441 
1442       return NPERR_NO_ERROR;
1443     }
1444 
1445 #  ifndef NP_NO_CARBON
1446     case NPNVsupportsCarbonBool: {
1447       *(NPBool*)result = false;
1448 
1449       return NPERR_NO_ERROR;
1450     }
1451 #  endif
1452     case NPNVsupportsCocoaBool: {
1453       *(NPBool*)result = true;
1454 
1455       return NPERR_NO_ERROR;
1456     }
1457 
1458     case NPNVsupportsUpdatedCocoaTextInputBool: {
1459       *(NPBool*)result = true;
1460       return NPERR_NO_ERROR;
1461     }
1462 #endif
1463 
1464 #if defined(XP_MACOSX) || defined(XP_WIN)
1465     case NPNVcontentsScaleFactor: {
1466       nsNPAPIPluginInstance* inst =
1467           (nsNPAPIPluginInstance*)(npp ? npp->ndata : nullptr);
1468       double scaleFactor = inst ? inst->GetContentsScaleFactor() : 1.0;
1469       *(double*)result = scaleFactor;
1470       return NPERR_NO_ERROR;
1471     }
1472 #endif
1473 
1474     case NPNVCSSZoomFactor: {
1475       nsNPAPIPluginInstance* inst =
1476           (nsNPAPIPluginInstance*)(npp ? npp->ndata : nullptr);
1477       double scaleFactor = inst ? inst->GetCSSZoomFactor() : 1.0;
1478       *(double*)result = scaleFactor;
1479       return NPERR_NO_ERROR;
1480     }
1481 
1482     // we no longer hand out any XPCOM objects
1483     case NPNVDOMElement:
1484     case NPNVDOMWindow:
1485     case NPNVserviceManager:
1486       // old XPCOM objects, no longer supported, but null out the out
1487       // param to avoid crashing plugins that still try to use this.
1488       *(nsISupports**)result = nullptr;
1489       [[fallthrough]];
1490 
1491     default:
1492       NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
1493                      ("NPN_getvalue unhandled get value: %d\n", variable));
1494       return NPERR_GENERIC_ERROR;
1495   }
1496 }
1497 
_setvalue(NPP npp,NPPVariable variable,void * result)1498 NPError _setvalue(NPP npp, NPPVariable variable, void* result) {
1499   if (!NS_IsMainThread()) {
1500     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1501                    ("NPN_setvalue called from the wrong thread\n"));
1502     return NPERR_INVALID_PARAM;
1503   }
1504   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
1505                  ("NPN_SetValue: npp=%p, var=%d\n", (void*)npp, (int)variable));
1506 
1507   if (!npp) return NPERR_INVALID_INSTANCE_ERROR;
1508 
1509   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1510 
1511   NS_ASSERTION(inst, "null instance");
1512 
1513   if (!inst) return NPERR_INVALID_INSTANCE_ERROR;
1514 
1515   PluginDestructionGuard guard(inst);
1516 
1517   // Cast NPNVariable enum to int to avoid warnings about including switch
1518   // cases for android_npapi.h's non-standard ANPInterface values.
1519   switch (static_cast<int>(variable)) {
1520     // we should keep backward compatibility with NPAPI where the
1521     // actual pointer value is checked rather than its content
1522     // when passing booleans
1523     case NPPVpluginWindowBool: {
1524 #ifdef XP_MACOSX
1525       // This setting doesn't apply to OS X (only to Windows and Unix/Linux).
1526       // See https://developer.mozilla.org/En/NPN_SetValue#section_5.  Return
1527       // NPERR_NO_ERROR here to conform to other browsers' behavior on OS X
1528       // (e.g. Safari and Opera).
1529       return NPERR_NO_ERROR;
1530 #else
1531       NPBool bWindowless = (result == nullptr);
1532       return inst->SetWindowless(bWindowless);
1533 #endif
1534     }
1535     case NPPVpluginTransparentBool: {
1536       NPBool bTransparent = (result != nullptr);
1537       return inst->SetTransparent(bTransparent);
1538     }
1539 
1540     case NPPVjavascriptPushCallerBool: {
1541       return NPERR_NO_ERROR;
1542     }
1543 
1544     case NPPVpluginKeepLibraryInMemory: {
1545       NPBool bCached = (result != nullptr);
1546       inst->SetCached(bCached);
1547       return NPERR_NO_ERROR;
1548     }
1549 
1550     case NPPVpluginUsesDOMForCursorBool: {
1551       bool useDOMForCursor = (result != nullptr);
1552       return inst->SetUsesDOMForCursor(useDOMForCursor);
1553     }
1554 
1555     case NPPVpluginIsPlayingAudio: {
1556       const bool isPlaying = result;
1557 
1558       nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)npp->ndata;
1559       MOZ_ASSERT(inst);
1560 
1561       if (!isPlaying && !inst->HasAudioChannelAgent()) {
1562         return NPERR_NO_ERROR;
1563       }
1564 
1565       if (isPlaying) {
1566         inst->NotifyStartedPlaying();
1567       } else {
1568         inst->NotifyStoppedPlaying();
1569       }
1570 
1571       return NPERR_NO_ERROR;
1572     }
1573 
1574     case NPPVpluginDrawingModel: {
1575       if (inst) {
1576         inst->SetDrawingModel((NPDrawingModel)NS_PTR_TO_INT32(result));
1577         return NPERR_NO_ERROR;
1578       }
1579       return NPERR_GENERIC_ERROR;
1580     }
1581 
1582 #ifdef XP_MACOSX
1583     case NPPVpluginEventModel: {
1584       if (inst) {
1585         inst->SetEventModel((NPEventModel)NS_PTR_TO_INT32(result));
1586         return NPERR_NO_ERROR;
1587       } else {
1588         return NPERR_GENERIC_ERROR;
1589       }
1590     }
1591 #endif
1592     default:
1593       return NPERR_GENERIC_ERROR;
1594   }
1595 }
1596 
_requestread(NPStream * pstream,NPByteRange * rangeList)1597 NPError _requestread(NPStream* pstream, NPByteRange* rangeList) {
1598   return NPERR_STREAM_NOT_SEEKABLE;
1599 }
1600 
1601 // Deprecated, only stubbed out
1602 void* /* OJI type: JRIEnv* */
_getJavaEnv()1603 _getJavaEnv() {
1604   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
1605   return nullptr;
1606 }
1607 
_useragent(NPP npp)1608 const char* _useragent(NPP npp) {
1609   if (!NS_IsMainThread()) {
1610     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1611                    ("NPN_useragent called from the wrong thread\n"));
1612     return nullptr;
1613   }
1614   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_UserAgent: npp=%p\n", (void*)npp));
1615 
1616   nsCOMPtr<nsIPluginHost> pluginHostCOM(
1617       do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
1618   nsPluginHost* pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
1619   if (!pluginHost) {
1620     return nullptr;
1621   }
1622 
1623   const char* retstr;
1624   nsresult rv = pluginHost->UserAgent(&retstr);
1625   if (NS_FAILED(rv)) return nullptr;
1626 
1627   return retstr;
1628 }
1629 
_memalloc(uint32_t size)1630 void* _memalloc(uint32_t size) {
1631   if (!NS_IsMainThread()) {
1632     NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
1633                    ("NPN_memalloc called from the wrong thread\n"));
1634   }
1635   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemAlloc: size=%d\n", size));
1636   return moz_xmalloc(size);
1637 }
1638 
1639 // Deprecated, only stubbed out
1640 void* /* OJI type: jref */
_getJavaPeer(NPP npp)1641 _getJavaPeer(NPP npp) {
1642   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
1643   return nullptr;
1644 }
1645 
_pushpopupsenabledstate(NPP npp,NPBool enabled)1646 void _pushpopupsenabledstate(NPP npp, NPBool enabled) {
1647   if (!NS_IsMainThread()) {
1648     NPN_PLUGIN_LOG(
1649         PLUGIN_LOG_ALWAYS,
1650         ("NPN_pushpopupsenabledstate called from the wrong thread\n"));
1651     return;
1652   }
1653   nsNPAPIPluginInstance* inst =
1654       npp ? (nsNPAPIPluginInstance*)npp->ndata : nullptr;
1655   if (!inst) return;
1656 
1657   inst->PushPopupsEnabledState(enabled);
1658 }
1659 
_poppopupsenabledstate(NPP npp)1660 void _poppopupsenabledstate(NPP npp) {
1661   if (!NS_IsMainThread()) {
1662     NPN_PLUGIN_LOG(
1663         PLUGIN_LOG_ALWAYS,
1664         ("NPN_poppopupsenabledstate called from the wrong thread\n"));
1665     return;
1666   }
1667   nsNPAPIPluginInstance* inst =
1668       npp ? (nsNPAPIPluginInstance*)npp->ndata : nullptr;
1669   if (!inst) return;
1670 
1671   inst->PopPopupsEnabledState();
1672 }
1673 
_getvalueforurl(NPP instance,NPNURLVariable variable,const char * url,char ** value,uint32_t * len)1674 NPError _getvalueforurl(NPP instance, NPNURLVariable variable, const char* url,
1675                         char** value, uint32_t* len) {
1676   if (!NS_IsMainThread()) {
1677     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1678                    ("NPN_getvalueforurl called from the wrong thread\n"));
1679     return NPERR_GENERIC_ERROR;
1680   }
1681 
1682   if (!instance) {
1683     return NPERR_INVALID_PARAM;
1684   }
1685 
1686   if (!url || !*url || !len) {
1687     return NPERR_INVALID_URL;
1688   }
1689 
1690   *len = 0;
1691 
1692   switch (variable) {
1693     case NPNURLVProxy:
1694       // NPNURLVProxy is no longer supported.
1695       *value = nullptr;
1696       return NPERR_GENERIC_ERROR;
1697 
1698     case NPNURLVCookie:
1699       // NPNURLVCookie is no longer supported.
1700       *value = nullptr;
1701       return NPERR_GENERIC_ERROR;
1702 
1703     default:
1704         // Fall through and return an error...
1705         ;
1706   }
1707 
1708   return NPERR_GENERIC_ERROR;
1709 }
1710 
_setvalueforurl(NPP instance,NPNURLVariable variable,const char * url,const char * value,uint32_t len)1711 NPError _setvalueforurl(NPP instance, NPNURLVariable variable, const char* url,
1712                         const char* value, uint32_t len) {
1713   if (!NS_IsMainThread()) {
1714     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1715                    ("NPN_setvalueforurl called from the wrong thread\n"));
1716     return NPERR_GENERIC_ERROR;
1717   }
1718 
1719   if (!instance) {
1720     return NPERR_INVALID_PARAM;
1721   }
1722 
1723   if (!url || !*url) {
1724     return NPERR_INVALID_URL;
1725   }
1726 
1727   switch (variable) {
1728     case NPNURLVCookie:
1729       // NPNURLVCookie is no longer supported.
1730       return NPERR_GENERIC_ERROR;
1731 
1732     case NPNURLVProxy:
1733       // We don't support setting proxy values, fall through...
1734     default:
1735         // Fall through and return an error...
1736         ;
1737   }
1738 
1739   return NPERR_GENERIC_ERROR;
1740 }
1741 
_scheduletimer(NPP instance,uint32_t interval,NPBool repeat,PluginTimerFunc timerFunc)1742 uint32_t _scheduletimer(NPP instance, uint32_t interval, NPBool repeat,
1743                         PluginTimerFunc timerFunc) {
1744   if (!NS_IsMainThread()) {
1745     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1746                    ("NPN_scheduletimer called from the wrong thread\n"));
1747     return 0;
1748   }
1749 
1750   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1751   if (!inst) return 0;
1752 
1753   return inst->ScheduleTimer(interval, repeat, timerFunc);
1754 }
1755 
_unscheduletimer(NPP instance,uint32_t timerID)1756 void _unscheduletimer(NPP instance, uint32_t timerID) {
1757   if (!NS_IsMainThread()) {
1758     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1759                    ("NPN_unscheduletimer called from the wrong thread\n"));
1760     return;
1761   }
1762 
1763   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1764   if (!inst) return;
1765 
1766   inst->UnscheduleTimer(timerID);
1767 }
1768 
_popupcontextmenu(NPP instance,NPMenu * menu)1769 NPError _popupcontextmenu(NPP instance, NPMenu* menu) {
1770   if (!NS_IsMainThread()) {
1771     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1772                    ("NPN_popupcontextmenu called from the wrong thread\n"));
1773     return 0;
1774   }
1775 
1776 #ifdef MOZ_WIDGET_COCOA
1777   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1778 
1779   double pluginX, pluginY;
1780   double screenX, screenY;
1781 
1782   const NPCocoaEvent* currentEvent =
1783       static_cast<NPCocoaEvent*>(inst->GetCurrentEvent());
1784   if (!currentEvent) {
1785     return NPERR_GENERIC_ERROR;
1786   }
1787 
1788   // Ensure that the events has an x/y value.
1789   if (currentEvent->type != NPCocoaEventMouseDown &&
1790       currentEvent->type != NPCocoaEventMouseUp &&
1791       currentEvent->type != NPCocoaEventMouseMoved &&
1792       currentEvent->type != NPCocoaEventMouseEntered &&
1793       currentEvent->type != NPCocoaEventMouseExited &&
1794       currentEvent->type != NPCocoaEventMouseDragged) {
1795     return NPERR_GENERIC_ERROR;
1796   }
1797 
1798   pluginX = currentEvent->data.mouse.pluginX;
1799   pluginY = currentEvent->data.mouse.pluginY;
1800 
1801   if ((pluginX < 0.0) || (pluginY < 0.0)) return NPERR_GENERIC_ERROR;
1802 
1803   NPBool success =
1804       _convertpoint(instance, pluginX, pluginY, NPCoordinateSpacePlugin,
1805                     &screenX, &screenY, NPCoordinateSpaceScreen);
1806 
1807   if (success) {
1808     return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(
1809         menu, screenX, screenY, nullptr, nullptr);
1810   } else {
1811     NS_WARNING("Convertpoint failed, could not created contextmenu.");
1812     return NPERR_GENERIC_ERROR;
1813   }
1814 #else
1815   NS_WARNING("Not supported on this platform!");
1816   return NPERR_GENERIC_ERROR;
1817 #endif
1818 }
1819 
_convertpoint(NPP instance,double sourceX,double sourceY,NPCoordinateSpace sourceSpace,double * destX,double * destY,NPCoordinateSpace destSpace)1820 NPBool _convertpoint(NPP instance, double sourceX, double sourceY,
1821                      NPCoordinateSpace sourceSpace, double* destX,
1822                      double* destY, NPCoordinateSpace destSpace) {
1823   if (!NS_IsMainThread()) {
1824     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1825                    ("NPN_convertpoint called from the wrong thread\n"));
1826     return 0;
1827   }
1828 
1829   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1830   if (!inst) return false;
1831 
1832   return inst->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY,
1833                             destSpace);
1834 }
1835 
_urlredirectresponse(NPP instance,void * notifyData,NPBool allow)1836 void _urlredirectresponse(NPP instance, void* notifyData, NPBool allow) {
1837   if (!NS_IsMainThread()) {
1838     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,
1839                    ("NPN_convertpoint called from the wrong thread\n"));
1840     return;
1841   }
1842 
1843   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1844   if (!inst) {
1845     return;
1846   }
1847 
1848   inst->URLRedirectResponse(notifyData, allow);
1849 }
1850 
_initasyncsurface(NPP instance,NPSize * size,NPImageFormat format,void * initData,NPAsyncSurface * surface)1851 NPError _initasyncsurface(NPP instance, NPSize* size, NPImageFormat format,
1852                           void* initData, NPAsyncSurface* surface) {
1853   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1854   if (!inst) {
1855     return NPERR_GENERIC_ERROR;
1856   }
1857 
1858   return inst->InitAsyncSurface(size, format, initData, surface);
1859 }
1860 
_finalizeasyncsurface(NPP instance,NPAsyncSurface * surface)1861 NPError _finalizeasyncsurface(NPP instance, NPAsyncSurface* surface) {
1862   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1863   if (!inst) {
1864     return NPERR_GENERIC_ERROR;
1865   }
1866 
1867   return inst->FinalizeAsyncSurface(surface);
1868 }
1869 
_setcurrentasyncsurface(NPP instance,NPAsyncSurface * surface,NPRect * changed)1870 void _setcurrentasyncsurface(NPP instance, NPAsyncSurface* surface,
1871                              NPRect* changed) {
1872   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
1873   if (!inst) {
1874     return;
1875   }
1876 
1877   inst->SetCurrentAsyncSurface(surface, changed);
1878 }
1879 
1880 }  // namespace mozilla::plugins::parent
1881