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 conflicts. */
9 #include "mozilla/ArrayUtils.h"
10
11 #include "pratom.h"
12 #include "prmem.h"
13 #include "prenv.h"
14 #include "prclist.h"
15
16 #include "jsfriendapi.h"
17
18 #include "nsPluginHost.h"
19 #include "nsNPAPIPlugin.h"
20 #include "nsNPAPIPluginInstance.h"
21 #include "nsNPAPIPluginStreamListener.h"
22 #include "nsPluginStreamListenerPeer.h"
23 #include "nsIServiceManager.h"
24 #include "nsThreadUtils.h"
25 #include "mozilla/Preferences.h"
26 #include "nsPluginInstanceOwner.h"
27
28 #include "nsPluginsDir.h"
29 #include "nsPluginLogging.h"
30
31 #include "nsIDOMElement.h"
32 #include "nsPIDOMWindow.h"
33 #include "nsGlobalWindow.h"
34 #include "nsIDocument.h"
35 #include "nsIContent.h"
36 #include "nsIIDNService.h"
37 #include "nsIScriptGlobalObject.h"
38 #include "nsIScriptContext.h"
39 #include "nsDOMJSUtils.h"
40 #include "nsIPrincipal.h"
41 #include "nsWildCard.h"
42 #include "nsContentUtils.h"
43 #include "mozilla/dom/ScriptSettings.h"
44 #include "nsIXULRuntime.h"
45 #include "nsIXPConnect.h"
46
47 #include "nsIObserverService.h"
48 #include <prinrval.h>
49
50 #ifdef MOZ_WIDGET_COCOA
51 #include <Carbon/Carbon.h>
52 #include <ApplicationServices/ApplicationServices.h>
53 #include <OpenGL/OpenGL.h>
54 #include "nsCocoaFeatures.h"
55 #include "PluginUtilsOSX.h"
56 #endif
57
58 // needed for nppdf plugin
59 #if (MOZ_WIDGET_GTK)
60 #include <gdk/gdk.h>
61 #include <gdk/gdkx.h>
62 #if (MOZ_WIDGET_GTK == 2)
63 #include "gtk2xtbin.h"
64 #endif
65 #endif
66
67 #include "nsJSUtils.h"
68 #include "nsJSNPRuntime.h"
69 #include "nsIHttpAuthManager.h"
70 #include "nsICookieService.h"
71 #include "nsILoadContext.h"
72 #include "nsIDocShell.h"
73
74 #include "nsNetUtil.h"
75 #include "nsNetCID.h"
76
77 #include "mozilla/Mutex.h"
78 #include "mozilla/PluginLibrary.h"
79 using mozilla::PluginLibrary;
80
81 #include "mozilla/PluginPRLibrary.h"
82 using mozilla::PluginPRLibrary;
83
84 #include "mozilla/plugins/PluginModuleParent.h"
85 using mozilla::plugins::PluginModuleChromeParent;
86 using mozilla::plugins::PluginModuleContentParent;
87
88 #ifdef MOZ_X11
89 #include "mozilla/X11Util.h"
90 #endif
91
92 #ifdef XP_WIN
93 #include <windows.h>
94 #include "mozilla/WindowsVersion.h"
95 #ifdef ACCESSIBILITY
96 #include "mozilla/a11y/Compatibility.h"
97 #endif
98 #endif
99
100 #ifdef MOZ_WIDGET_ANDROID
101 #include <android/log.h>
102 #include "android_npapi.h"
103 #include "ANPBase.h"
104 #include "GeneratedJNIWrappers.h"
105 #undef LOG
106 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
107 #endif
108
109 #include "nsIAudioChannelAgent.h"
110 #include "AudioChannelService.h"
111
112 using namespace mozilla;
113 using namespace mozilla::plugins::parent;
114
115 // We should make this const...
116 static NPNetscapeFuncs sBrowserFuncs = {
117 sizeof(sBrowserFuncs),
118 (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
119 _geturl,
120 _posturl,
121 _requestread,
122 _newstream,
123 _write,
124 _destroystream,
125 _status,
126 _useragent,
127 _memalloc,
128 _memfree,
129 _memflush,
130 _reloadplugins,
131 _getJavaEnv,
132 _getJavaPeer,
133 _geturlnotify,
134 _posturlnotify,
135 _getvalue,
136 _setvalue,
137 _invalidaterect,
138 _invalidateregion,
139 _forceredraw,
140 _getstringidentifier,
141 _getstringidentifiers,
142 _getintidentifier,
143 _identifierisstring,
144 _utf8fromidentifier,
145 _intfromidentifier,
146 _createobject,
147 _retainobject,
148 _releaseobject,
149 _invoke,
150 _invokeDefault,
151 _evaluate,
152 _getproperty,
153 _setproperty,
154 _removeproperty,
155 _hasproperty,
156 _hasmethod,
157 _releasevariantvalue,
158 _setexception,
159 _pushpopupsenabledstate,
160 _poppopupsenabledstate,
161 _enumerate,
162 _pluginthreadasynccall,
163 _construct,
164 _getvalueforurl,
165 _setvalueforurl,
166 _getauthenticationinfo,
167 _scheduletimer,
168 _unscheduletimer,
169 _popupcontextmenu,
170 _convertpoint,
171 nullptr, // handleevent, unimplemented
172 nullptr, // unfocusinstance, unimplemented
173 _urlredirectresponse,
174 _initasyncsurface,
175 _finalizeasyncsurface,
176 _setcurrentasyncsurface
177 };
178
179 static Mutex *sPluginThreadAsyncCallLock = nullptr;
180 static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
181
182 // POST/GET stream type
183 enum eNPPStreamTypeInternal {
184 eNPPStreamTypeInternal_Get,
185 eNPPStreamTypeInternal_Post
186 };
187
NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState)188 void NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState)
189 {
190 nsNPAPIPluginInstance::BeginPluginCall(aReentryState);
191 }
192
NS_NotifyPluginCall(NSPluginCallReentry aReentryState)193 void NS_NotifyPluginCall(NSPluginCallReentry aReentryState)
194 {
195 nsNPAPIPluginInstance::EndPluginCall(aReentryState);
196 }
197
CheckClassInitialized()198 static void CheckClassInitialized()
199 {
200 static bool initialized = false;
201
202 if (initialized)
203 return;
204
205 if (!sPluginThreadAsyncCallLock)
206 sPluginThreadAsyncCallLock = new Mutex("nsNPAPIPlugin.sPluginThreadAsyncCallLock");
207
208 initialized = true;
209
210 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n"));
211 }
212
nsNPAPIPlugin()213 nsNPAPIPlugin::nsNPAPIPlugin()
214 {
215 memset((void*)&mPluginFuncs, 0, sizeof(mPluginFuncs));
216 mPluginFuncs.size = sizeof(mPluginFuncs);
217 mPluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
218
219 mLibrary = nullptr;
220 }
221
~nsNPAPIPlugin()222 nsNPAPIPlugin::~nsNPAPIPlugin()
223 {
224 delete mLibrary;
225 mLibrary = nullptr;
226 }
227
228 void
PluginCrashed(const nsAString & pluginDumpID,const nsAString & browserDumpID)229 nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID,
230 const nsAString& browserDumpID)
231 {
232 RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
233 host->PluginCrashed(this, pluginDumpID, browserDumpID);
234 }
235
236 bool
RunPluginOOP(const nsPluginTag * aPluginTag)237 nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
238 {
239 #ifdef MOZ_WIDGET_ANDROID
240 return false;
241 #else
242 return true;
243 #endif
244 }
245
246 inline PluginLibrary*
GetNewPluginLibrary(nsPluginTag * aPluginTag)247 GetNewPluginLibrary(nsPluginTag *aPluginTag)
248 {
249 PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
250
251 if (!aPluginTag) {
252 return nullptr;
253 }
254
255 if (XRE_IsContentProcess()) {
256 return PluginModuleContentParent::LoadModule(aPluginTag->mId, aPluginTag);
257 }
258
259 if (nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
260 return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId, aPluginTag);
261 }
262 return new PluginPRLibrary(aPluginTag->mFullPath.get(), aPluginTag->mLibrary);
263 }
264
265 // Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
266 nsresult
CreatePlugin(nsPluginTag * aPluginTag,nsNPAPIPlugin ** aResult)267 nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
268 {
269 PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
270 *aResult = nullptr;
271
272 if (!aPluginTag) {
273 return NS_ERROR_FAILURE;
274 }
275
276 CheckClassInitialized();
277
278 RefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
279
280 PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
281 if (!pluginLib) {
282 return NS_ERROR_FAILURE;
283 }
284
285 #if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
286 if (!pluginLib->HasRequiredFunctions()) {
287 NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
288 delete pluginLib;
289 return NS_ERROR_FAILURE;
290 }
291 #endif
292
293 plugin->mLibrary = pluginLib;
294 pluginLib->SetPlugin(plugin);
295
296 // Exchange NPAPI entry points.
297 #if defined(XP_WIN)
298 // NP_GetEntryPoints must be called before NP_Initialize on Windows.
299 NPError pluginCallError;
300 nsresult rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
301 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
302 return NS_ERROR_FAILURE;
303 }
304
305 // NP_Initialize must be called after NP_GetEntryPoints on Windows.
306 rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
307 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
308 return NS_ERROR_FAILURE;
309 }
310 #elif defined(XP_MACOSX)
311 // NP_Initialize must be called before NP_GetEntryPoints on Mac OS X.
312 // We need to match WebKit's behavior.
313 NPError pluginCallError;
314 nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
315 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
316 return NS_ERROR_FAILURE;
317 }
318
319 rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
320 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
321 return NS_ERROR_FAILURE;
322 }
323 #elif defined(MOZ_WIDGET_GONK)
324 #else
325 NPError pluginCallError;
326 nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError);
327 if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
328 return NS_ERROR_FAILURE;
329 }
330 #endif
331
332 plugin.forget(aResult);
333 return NS_OK;
334 }
335
336 PluginLibrary*
GetLibrary()337 nsNPAPIPlugin::GetLibrary()
338 {
339 return mLibrary;
340 }
341
342 NPPluginFuncs*
PluginFuncs()343 nsNPAPIPlugin::PluginFuncs()
344 {
345 return &mPluginFuncs;
346 }
347
348 nsresult
Shutdown()349 nsNPAPIPlugin::Shutdown()
350 {
351 NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
352 ("NPP Shutdown to be called: this=%p\n", this));
353
354 NPError shutdownError;
355 mLibrary->NP_Shutdown(&shutdownError);
356
357 return NS_OK;
358 }
359
360 nsresult
RetainStream(NPStream * pstream,nsISupports ** aRetainedPeer)361 nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer)
362 {
363 if (!aRetainedPeer)
364 return NS_ERROR_NULL_POINTER;
365
366 *aRetainedPeer = nullptr;
367
368 if (!pstream || !pstream->ndata)
369 return NS_ERROR_NULL_POINTER;
370
371 nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
372 nsNPAPIPluginStreamListener* listener = streamWrapper->GetStreamListener();
373 if (!listener) {
374 return NS_ERROR_NULL_POINTER;
375 }
376
377 nsIStreamListener* streamListener = listener->GetStreamListenerPeer();
378 if (!streamListener) {
379 return NS_ERROR_NULL_POINTER;
380 }
381
382 *aRetainedPeer = streamListener;
383 NS_ADDREF(*aRetainedPeer);
384 return NS_OK;
385 }
386
387 // Create a new NPP GET or POST (given in the type argument) url
388 // stream that may have a notify callback
389 NPError
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,NPBool file=false)390 MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
391 eNPPStreamTypeInternal type,
392 bool bDoNotify = false,
393 void *notifyData = nullptr, uint32_t len = 0,
394 const char *buf = nullptr, NPBool file = false)
395 {
396 if (!npp)
397 return NPERR_INVALID_INSTANCE_ERROR;
398
399 PluginDestructionGuard guard(npp);
400
401 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
402 if (!inst || !inst->IsRunning())
403 return NPERR_INVALID_INSTANCE_ERROR;
404
405 nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
406 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
407 if (!pluginHost) {
408 return NPERR_GENERIC_ERROR;
409 }
410
411 RefPtr<nsNPAPIPluginStreamListener> listener;
412 // Set aCallNotify here to false. If pluginHost->GetURL or PostURL fail,
413 // the listener's destructor will do the notification while we are about to
414 // return a failure code.
415 // Call SetCallNotify(true) below after we are sure we cannot return a failure
416 // code.
417 if (!target) {
418 inst->NewStreamListener(relativeURL, notifyData,
419 getter_AddRefs(listener));
420 if (listener) {
421 listener->SetCallNotify(false);
422 }
423 }
424
425 switch (type) {
426 case eNPPStreamTypeInternal_Get:
427 {
428 if (NS_FAILED(pluginHost->GetURL(inst, relativeURL, target, listener,
429 nullptr, nullptr, false)))
430 return NPERR_GENERIC_ERROR;
431 break;
432 }
433 case eNPPStreamTypeInternal_Post:
434 {
435 if (NS_FAILED(pluginHost->PostURL(inst, relativeURL, len, buf, file,
436 target, listener, nullptr, nullptr,
437 false, 0, nullptr)))
438 return NPERR_GENERIC_ERROR;
439 break;
440 }
441 default:
442 NS_ERROR("how'd I get here");
443 }
444
445 if (listener) {
446 // SetCallNotify(bDoNotify) here, see comment above.
447 listener->SetCallNotify(bDoNotify);
448 }
449
450 return NPERR_NO_ERROR;
451 }
452
453 #if defined(MOZ_MEMORY_WINDOWS)
454 extern "C" size_t malloc_usable_size(const void *ptr);
455 #endif
456
457 namespace {
458
459 static char *gNPPException;
460
461 class nsPluginThreadRunnable : public Runnable,
462 public PRCList
463 {
464 public:
465 nsPluginThreadRunnable(NPP instance, PluginThreadCallback func,
466 void *userData);
467 virtual ~nsPluginThreadRunnable();
468
469 NS_IMETHOD Run();
470
IsForInstance(NPP instance)471 bool IsForInstance(NPP instance)
472 {
473 return (mInstance == instance);
474 }
475
Invalidate()476 void Invalidate()
477 {
478 mFunc = nullptr;
479 }
480
IsValid()481 bool IsValid()
482 {
483 return (mFunc != nullptr);
484 }
485
486 private:
487 NPP mInstance;
488 PluginThreadCallback mFunc;
489 void *mUserData;
490 };
491
492 static nsIDocument *
GetDocumentFromNPP(NPP npp)493 GetDocumentFromNPP(NPP npp)
494 {
495 NS_ENSURE_TRUE(npp, nullptr);
496
497 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
498 NS_ENSURE_TRUE(inst, nullptr);
499
500 PluginDestructionGuard guard(inst);
501
502 RefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
503 NS_ENSURE_TRUE(owner, nullptr);
504
505 nsCOMPtr<nsIDocument> doc;
506 owner->GetDocument(getter_AddRefs(doc));
507
508 return doc;
509 }
510
511 static already_AddRefed<nsIChannel>
GetChannelFromNPP(NPP npp)512 GetChannelFromNPP(NPP npp)
513 {
514 nsCOMPtr<nsIDocument> doc = GetDocumentFromNPP(npp);
515 if (!doc)
516 return nullptr;
517 nsCOMPtr<nsPIDOMWindowOuter> domwindow = doc->GetWindow();
518 nsCOMPtr<nsIChannel> channel;
519 if (domwindow) {
520 nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
521 if (docShell) {
522 docShell->GetCurrentDocumentChannel(getter_AddRefs(channel));
523 }
524 }
525 return channel.forget();
526 }
527
528 static NPIdentifier
doGetIdentifier(JSContext * cx,const NPUTF8 * name)529 doGetIdentifier(JSContext *cx, const NPUTF8* name)
530 {
531 NS_ConvertUTF8toUTF16 utf16name(name);
532
533 JSString *str = ::JS_AtomizeAndPinUCStringN(cx, utf16name.get(), utf16name.Length());
534
535 if (!str)
536 return nullptr;
537
538 return StringToNPIdentifier(cx, str);
539 }
540
541 #if defined(MOZ_MEMORY_WINDOWS)
542 BOOL
InHeap(HANDLE hHeap,LPVOID lpMem)543 InHeap(HANDLE hHeap, LPVOID lpMem)
544 {
545 BOOL success = FALSE;
546 PROCESS_HEAP_ENTRY he;
547 he.lpData = nullptr;
548 while (HeapWalk(hHeap, &he) != 0) {
549 if (he.lpData == lpMem) {
550 success = TRUE;
551 break;
552 }
553 }
554 HeapUnlock(hHeap);
555 return success;
556 }
557 #endif
558
559 } /* anonymous namespace */
560
NPPExceptionAutoHolder()561 NPPExceptionAutoHolder::NPPExceptionAutoHolder()
562 : mOldException(gNPPException)
563 {
564 gNPPException = nullptr;
565 }
566
~NPPExceptionAutoHolder()567 NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
568 {
569 NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
570
571 gNPPException = mOldException;
572 }
573
nsPluginThreadRunnable(NPP instance,PluginThreadCallback func,void * userData)574 nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
575 PluginThreadCallback func,
576 void *userData)
577 : mInstance(instance), mFunc(func), mUserData(userData)
578 {
579 if (!sPluginThreadAsyncCallLock) {
580 // Failed to create lock, not much we can do here then...
581 mFunc = nullptr;
582
583 return;
584 }
585
586 PR_INIT_CLIST(this);
587
588 {
589 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
590
591 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
592 if (!inst || !inst->IsRunning()) {
593 // The plugin was stopped, ignore this async call.
594 mFunc = nullptr;
595
596 return;
597 }
598
599 PR_APPEND_LINK(this, &sPendingAsyncCalls);
600 }
601 }
602
~nsPluginThreadRunnable()603 nsPluginThreadRunnable::~nsPluginThreadRunnable()
604 {
605 if (!sPluginThreadAsyncCallLock) {
606 return;
607 }
608
609 {
610 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
611
612 PR_REMOVE_LINK(this);
613 }
614 }
615
616 NS_IMETHODIMP
Run()617 nsPluginThreadRunnable::Run()
618 {
619 if (mFunc) {
620 PluginDestructionGuard guard(mInstance);
621
622 NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nullptr,
623 NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
624 }
625
626 return NS_OK;
627 }
628
629 void
OnPluginDestroy(NPP instance)630 OnPluginDestroy(NPP instance)
631 {
632 if (!sPluginThreadAsyncCallLock) {
633 return;
634 }
635
636 {
637 MutexAutoLock lock(*sPluginThreadAsyncCallLock);
638
639 if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
640 return;
641 }
642
643 nsPluginThreadRunnable *r =
644 (nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
645
646 do {
647 if (r->IsForInstance(instance)) {
648 r->Invalidate();
649 }
650
651 r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
652 } while (r != &sPendingAsyncCalls);
653 }
654 }
655
656 void
OnShutdown()657 OnShutdown()
658 {
659 NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
660 "Pending async plugin call list not cleaned up!");
661
662 if (sPluginThreadAsyncCallLock) {
663 delete sPluginThreadAsyncCallLock;
664
665 sPluginThreadAsyncCallLock = nullptr;
666 }
667 }
668
AsyncCallbackAutoLock()669 AsyncCallbackAutoLock::AsyncCallbackAutoLock()
670 {
671 if (sPluginThreadAsyncCallLock) {
672 sPluginThreadAsyncCallLock->Lock();
673 }
674 }
675
~AsyncCallbackAutoLock()676 AsyncCallbackAutoLock::~AsyncCallbackAutoLock()
677 {
678 if (sPluginThreadAsyncCallLock) {
679 sPluginThreadAsyncCallLock->Unlock();
680 }
681 }
682
683 NPP NPPStack::sCurrentNPP = nullptr;
684
685 const char *
PeekException()686 PeekException()
687 {
688 return gNPPException;
689 }
690
691 void
PopException()692 PopException()
693 {
694 NS_ASSERTION(gNPPException, "Uh, no NPP exception to pop!");
695
696 if (gNPPException) {
697 free(gNPPException);
698
699 gNPPException = nullptr;
700 }
701 }
702
703 //
704 // Static callbacks that get routed back through the new C++ API
705 //
706
707 namespace mozilla {
708 namespace plugins {
709 namespace parent {
710
711 NPError
_geturl(NPP npp,const char * relativeURL,const char * target)712 _geturl(NPP npp, const char* relativeURL, const char* target)
713 {
714 if (!NS_IsMainThread()) {
715 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_geturl called from the wrong thread\n"));
716 return NPERR_INVALID_PARAM;
717 }
718
719 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
720 ("NPN_GetURL: npp=%p, target=%s, url=%s\n", (void *)npp, target,
721 relativeURL));
722
723 PluginDestructionGuard guard(npp);
724
725 // Block Adobe Acrobat from loading URLs that are not http:, https:,
726 // or ftp: URLs if the given target is null.
727 if (!target && relativeURL &&
728 (strncmp(relativeURL, "http:", 5) != 0) &&
729 (strncmp(relativeURL, "https:", 6) != 0) &&
730 (strncmp(relativeURL, "ftp:", 4) != 0)) {
731 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
732
733 const char *name = nullptr;
734 RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
735 host->GetPluginName(inst, &name);
736
737 if (name && strstr(name, "Adobe") && strstr(name, "Acrobat")) {
738 return NPERR_NO_ERROR;
739 }
740 }
741
742 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
743 eNPPStreamTypeInternal_Get);
744 }
745
746 NPError
_geturlnotify(NPP npp,const char * relativeURL,const char * target,void * notifyData)747 _geturlnotify(NPP npp, const char* relativeURL, const char* target,
748 void* notifyData)
749 {
750 if (!NS_IsMainThread()) {
751 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_geturlnotify called from the wrong thread\n"));
752 return NPERR_INVALID_PARAM;
753 }
754
755 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
756 ("NPN_GetURLNotify: npp=%p, target=%s, notify=%p, url=%s\n", (void*)npp,
757 target, notifyData, relativeURL));
758
759 PluginDestructionGuard guard(npp);
760
761 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
762 eNPPStreamTypeInternal_Get, true,
763 notifyData);
764 }
765
766 NPError
_posturlnotify(NPP npp,const char * relativeURL,const char * target,uint32_t len,const char * buf,NPBool file,void * notifyData)767 _posturlnotify(NPP npp, const char *relativeURL, const char *target,
768 uint32_t len, const char *buf, NPBool file, void *notifyData)
769 {
770 if (!NS_IsMainThread()) {
771 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_posturlnotify called from the wrong thread\n"));
772 return NPERR_INVALID_PARAM;
773 }
774 if (!buf)
775 return NPERR_INVALID_PARAM;
776
777 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
778 ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, "
779 "notify=%p, url=%s, buf=%s\n",
780 (void*)npp, target, len, file, notifyData, relativeURL,
781 buf));
782
783 PluginDestructionGuard guard(npp);
784
785 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
786 eNPPStreamTypeInternal_Post, true,
787 notifyData, len, buf, file);
788 }
789
790 NPError
_posturl(NPP npp,const char * relativeURL,const char * target,uint32_t len,const char * buf,NPBool file)791 _posturl(NPP npp, const char *relativeURL, const char *target,
792 uint32_t len, const char *buf, NPBool file)
793 {
794 if (!NS_IsMainThread()) {
795 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_posturl called from the wrong thread\n"));
796 return NPERR_INVALID_PARAM;
797 }
798 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
799 ("NPN_PostURL: npp=%p, target=%s, file=%d, len=%d, url=%s, "
800 "buf=%s\n",
801 (void*)npp, target, file, len, relativeURL, buf));
802
803 PluginDestructionGuard guard(npp);
804
805 return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
806 eNPPStreamTypeInternal_Post, false, nullptr,
807 len, buf, file);
808 }
809
810 NPError
_newstream(NPP npp,NPMIMEType type,const char * target,NPStream ** result)811 _newstream(NPP npp, NPMIMEType type, const char* target, NPStream* *result)
812 {
813 if (!NS_IsMainThread()) {
814 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_newstream called from the wrong thread\n"));
815 return NPERR_INVALID_PARAM;
816 }
817 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
818 ("NPN_NewStream: npp=%p, type=%s, target=%s\n", (void*)npp,
819 (const char *)type, target));
820
821 NPError err = NPERR_INVALID_INSTANCE_ERROR;
822 if (npp && npp->ndata) {
823 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
824
825 PluginDestructionGuard guard(inst);
826
827 nsCOMPtr<nsIOutputStream> stream;
828 if (NS_SUCCEEDED(inst->NewStreamFromPlugin((const char*) type, target,
829 getter_AddRefs(stream)))) {
830 nsNPAPIStreamWrapper* wrapper = new nsNPAPIStreamWrapper(stream, nullptr);
831 if (wrapper) {
832 (*result) = &wrapper->mNPStream;
833 err = NPERR_NO_ERROR;
834 } else {
835 err = NPERR_OUT_OF_MEMORY_ERROR;
836 }
837 } else {
838 err = NPERR_GENERIC_ERROR;
839 }
840 }
841 return err;
842 }
843
844 int32_t
_write(NPP npp,NPStream * pstream,int32_t len,void * buffer)845 _write(NPP npp, NPStream *pstream, int32_t len, void *buffer)
846 {
847 if (!NS_IsMainThread()) {
848 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_write called from the wrong thread\n"));
849 return 0;
850 }
851 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
852 ("NPN_Write: npp=%p, url=%s, len=%d, buffer=%s\n", (void*)npp,
853 pstream->url, len, (char*)buffer));
854
855 // negative return indicates failure to the plugin
856 if (!npp)
857 return -1;
858
859 PluginDestructionGuard guard(npp);
860
861 nsNPAPIStreamWrapper* wrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
862 if (!wrapper) {
863 return -1;
864 }
865
866 nsIOutputStream* stream = wrapper->GetOutputStream();
867 if (!stream) {
868 return -1;
869 }
870
871 uint32_t count = 0;
872 nsresult rv = stream->Write((char *)buffer, len, &count);
873
874 if (NS_FAILED(rv)) {
875 return -1;
876 }
877
878 return (int32_t)count;
879 }
880
881 NPError
_destroystream(NPP npp,NPStream * pstream,NPError reason)882 _destroystream(NPP npp, NPStream *pstream, NPError reason)
883 {
884 if (!NS_IsMainThread()) {
885 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_destroystream called from the wrong thread\n"));
886 return NPERR_INVALID_PARAM;
887 }
888 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
889 ("NPN_DestroyStream: npp=%p, url=%s, reason=%d\n", (void*)npp,
890 pstream->url, (int)reason));
891
892 if (!npp)
893 return NPERR_INVALID_INSTANCE_ERROR;
894
895 PluginDestructionGuard guard(npp);
896
897 nsNPAPIStreamWrapper *streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
898 if (!streamWrapper) {
899 return NPERR_INVALID_PARAM;
900 }
901
902 nsNPAPIPluginStreamListener *listener = streamWrapper->GetStreamListener();
903 if (listener) {
904 // This type of stream is going from the browser to the plugin. It's either the
905 // initial src/data stream or another stream resulting from NPN_GetURL* or
906 // NPN_PostURL*.
907 //
908 // Calling OnStopBinding on the listener may cause it to be deleted due to the
909 // releasing of its last references.
910 listener->OnStopBinding(nullptr, NS_BINDING_ABORTED);
911 } else {
912 // This type of stream (NPStream) was created via NPN_NewStream. The plugin holds
913 // the reference until it is to be deleted here. Deleting the wrapper will
914 // release the wrapped nsIOutputStream.
915 //
916 // The NPStream the plugin references should always be a sub-object of its own
917 // 'ndata', which is our nsNPAPIStramWrapper. See bug 548441.
918 NS_ASSERTION((char*)streamWrapper <= (char*)pstream &&
919 ((char*)pstream) + sizeof(*pstream)
920 <= ((char*)streamWrapper) + sizeof(*streamWrapper),
921 "pstream is not a subobject of wrapper");
922 delete streamWrapper;
923 }
924
925 // 'listener' and/or 'streamWrapper' may be invalid (deleted) at this point. Don't
926 // touch them again!
927
928 return NPERR_NO_ERROR;
929 }
930
931 void
_status(NPP npp,const char * message)932 _status(NPP npp, const char *message)
933 {
934 // NPN_Status is no longer supported.
935 }
936
937 void
_memfree(void * ptr)938 _memfree (void *ptr)
939 {
940 if (!NS_IsMainThread()) {
941 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memfree called from the wrong thread\n"));
942 }
943 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFree: ptr=%p\n", ptr));
944
945 if (ptr)
946 free(ptr);
947 }
948
949 uint32_t
_memflush(uint32_t size)950 _memflush(uint32_t size)
951 {
952 if (!NS_IsMainThread()) {
953 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memflush called from the wrong thread\n"));
954 }
955 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFlush: size=%d\n", size));
956
957 nsMemory::HeapMinimize(true);
958 return 0;
959 }
960
961 void
_reloadplugins(NPBool reloadPages)962 _reloadplugins(NPBool reloadPages)
963 {
964 if (!NS_IsMainThread()) {
965 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_reloadplugins called from the wrong thread\n"));
966 return;
967 }
968 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
969 ("NPN_ReloadPlugins: reloadPages=%d\n", reloadPages));
970
971 nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
972 if (!pluginHost)
973 return;
974
975 pluginHost->ReloadPlugins();
976 }
977
978 void
_invalidaterect(NPP npp,NPRect * invalidRect)979 _invalidaterect(NPP npp, NPRect *invalidRect)
980 {
981 if (!NS_IsMainThread()) {
982 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidaterect called from the wrong thread\n"));
983 return;
984 }
985 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
986 ("NPN_InvalidateRect: npp=%p, top=%d, left=%d, bottom=%d, "
987 "right=%d\n", (void *)npp, invalidRect->top,
988 invalidRect->left, invalidRect->bottom, invalidRect->right));
989
990 if (!npp || !npp->ndata) {
991 NS_WARNING("_invalidaterect: npp or npp->ndata == 0");
992 return;
993 }
994
995 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
996
997 PluginDestructionGuard guard(inst);
998
999 inst->InvalidateRect((NPRect *)invalidRect);
1000 }
1001
1002 void
_invalidateregion(NPP npp,NPRegion invalidRegion)1003 _invalidateregion(NPP npp, NPRegion invalidRegion)
1004 {
1005 if (!NS_IsMainThread()) {
1006 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidateregion called from the wrong thread\n"));
1007 return;
1008 }
1009 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
1010 ("NPN_InvalidateRegion: npp=%p, region=%p\n", (void*)npp,
1011 (void*)invalidRegion));
1012
1013 if (!npp || !npp->ndata) {
1014 NS_WARNING("_invalidateregion: npp or npp->ndata == 0");
1015 return;
1016 }
1017
1018 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
1019
1020 PluginDestructionGuard guard(inst);
1021
1022 inst->InvalidateRegion((NPRegion)invalidRegion);
1023 }
1024
1025 void
_forceredraw(NPP npp)1026 _forceredraw(NPP npp)
1027 {
1028 }
1029
1030 NPObject*
_getwindowobject(NPP npp)1031 _getwindowobject(NPP npp)
1032 {
1033 if (!NS_IsMainThread()) {
1034 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getwindowobject called from the wrong thread\n"));
1035 return nullptr;
1036 }
1037
1038 // The window want to return here is the outer window, *not* the inner (since
1039 // we don't know what the plugin will do with it).
1040 nsIDocument* doc = GetDocumentFromNPP(npp);
1041 NS_ENSURE_TRUE(doc, nullptr);
1042 nsCOMPtr<nsPIDOMWindowOuter> outer = doc->GetWindow();
1043 NS_ENSURE_TRUE(outer, nullptr);
1044
1045 JS::Rooted<JSObject*> global(dom::RootingCx(),
1046 nsGlobalWindow::Cast(outer)->GetGlobalJSObject());
1047 return nsJSObjWrapper::GetNewOrUsed(npp, global);
1048 }
1049
1050 NPObject*
_getpluginelement(NPP npp)1051 _getpluginelement(NPP npp)
1052 {
1053 if (!NS_IsMainThread()) {
1054 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getpluginelement called from the wrong thread\n"));
1055 return nullptr;
1056 }
1057
1058 nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
1059 if (!inst)
1060 return nullptr;
1061
1062 nsCOMPtr<nsIDOMElement> element;
1063 inst->GetDOMElement(getter_AddRefs(element));
1064
1065 if (!element)
1066 return nullptr;
1067
1068 nsIDocument *doc = GetDocumentFromNPP(npp);
1069 if (NS_WARN_IF(!doc)) {
1070 return nullptr;
1071 }
1072
1073 dom::AutoJSAPI jsapi;
1074 if (NS_WARN_IF(!jsapi.Init(doc->GetInnerWindow()))) {
1075 return nullptr;
1076 }
1077 JSContext* cx = jsapi.cx();
1078
1079 nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
1080 NS_ENSURE_TRUE(xpc, nullptr);
1081
1082 JS::RootedObject obj(cx);
1083 xpc->WrapNative(cx, ::JS::CurrentGlobalOrNull(cx), element,
1084 NS_GET_IID(nsIDOMElement), obj.address());
1085 NS_ENSURE_TRUE(obj, nullptr);
1086
1087 return nsJSObjWrapper::GetNewOrUsed(npp, obj);
1088 }
1089
1090 NPIdentifier
_getstringidentifier(const NPUTF8 * name)1091 _getstringidentifier(const NPUTF8* name)
1092 {
1093 if (!name) {
1094 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifier: passed null name"));
1095 return nullptr;
1096 }
1097 if (!NS_IsMainThread()) {
1098 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
1099 }
1100
1101 AutoSafeJSContext cx;
1102 return doGetIdentifier(cx, name);
1103 }
1104
1105 void
_getstringidentifiers(const NPUTF8 ** names,int32_t nameCount,NPIdentifier * identifiers)1106 _getstringidentifiers(const NPUTF8** names, int32_t nameCount,
1107 NPIdentifier *identifiers)
1108 {
1109 if (!NS_IsMainThread()) {
1110 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifiers called from the wrong thread\n"));
1111 }
1112
1113 AutoSafeJSContext cx;
1114
1115 for (int32_t i = 0; i < nameCount; ++i) {
1116 if (names[i]) {
1117 identifiers[i] = doGetIdentifier(cx, names[i]);
1118 } else {
1119 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifiers: passed null name"));
1120 identifiers[i] = nullptr;
1121 }
1122 }
1123 }
1124
1125 NPIdentifier
_getintidentifier(int32_t intid)1126 _getintidentifier(int32_t intid)
1127 {
1128 if (!NS_IsMainThread()) {
1129 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
1130 }
1131 return IntToNPIdentifier(intid);
1132 }
1133
1134 NPUTF8*
_utf8fromidentifier(NPIdentifier id)1135 _utf8fromidentifier(NPIdentifier id)
1136 {
1137 if (!NS_IsMainThread()) {
1138 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_utf8fromidentifier called from the wrong thread\n"));
1139 }
1140 if (!id)
1141 return nullptr;
1142
1143 if (!NPIdentifierIsString(id)) {
1144 return nullptr;
1145 }
1146
1147 JSString *str = NPIdentifierToString(id);
1148 nsAutoString autoStr;
1149 AssignJSFlatString(autoStr, JS_ASSERT_STRING_IS_FLAT(str));
1150
1151 return ToNewUTF8String(autoStr);
1152 }
1153
1154 int32_t
_intfromidentifier(NPIdentifier id)1155 _intfromidentifier(NPIdentifier id)
1156 {
1157 if (!NS_IsMainThread()) {
1158 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_intfromidentifier called from the wrong thread\n"));
1159 }
1160
1161 if (!NPIdentifierIsInt(id)) {
1162 return INT32_MIN;
1163 }
1164
1165 return NPIdentifierToInt(id);
1166 }
1167
1168 bool
_identifierisstring(NPIdentifier id)1169 _identifierisstring(NPIdentifier id)
1170 {
1171 if (!NS_IsMainThread()) {
1172 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_identifierisstring called from the wrong thread\n"));
1173 }
1174
1175 return NPIdentifierIsString(id);
1176 }
1177
1178 NPObject*
_createobject(NPP npp,NPClass * aClass)1179 _createobject(NPP npp, NPClass* aClass)
1180 {
1181 if (!NS_IsMainThread()) {
1182 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_createobject called from the wrong thread\n"));
1183 return nullptr;
1184 }
1185 if (!npp) {
1186 NS_ERROR("Null npp passed to _createobject()!");
1187
1188 return nullptr;
1189 }
1190
1191 PluginDestructionGuard guard(npp);
1192
1193 if (!aClass) {
1194 NS_ERROR("Null class passed to _createobject()!");
1195
1196 return nullptr;
1197 }
1198
1199 NPPAutoPusher nppPusher(npp);
1200
1201 NPObject *npobj;
1202
1203 if (aClass->allocate) {
1204 npobj = aClass->allocate(npp, aClass);
1205 } else {
1206 npobj = (NPObject *)PR_Malloc(sizeof(NPObject));
1207 }
1208
1209 if (npobj) {
1210 npobj->_class = aClass;
1211 npobj->referenceCount = 1;
1212 NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
1213 }
1214
1215 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1216 ("Created NPObject %p, NPClass %p\n", npobj, aClass));
1217
1218 return npobj;
1219 }
1220
1221 NPObject*
_retainobject(NPObject * npobj)1222 _retainobject(NPObject* npobj)
1223 {
1224 if (!NS_IsMainThread()) {
1225 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_retainobject called from the wrong thread\n"));
1226 }
1227 if (npobj) {
1228 #ifdef NS_BUILD_REFCNT_LOGGING
1229 int32_t refCnt =
1230 #endif
1231 PR_ATOMIC_INCREMENT((int32_t*)&npobj->referenceCount);
1232 NS_LOG_ADDREF(npobj, refCnt, "BrowserNPObject", sizeof(NPObject));
1233 }
1234
1235 return npobj;
1236 }
1237
1238 void
_releaseobject(NPObject * npobj)1239 _releaseobject(NPObject* npobj)
1240 {
1241 // If nothing is passed, just return, even if we're on the wrong thread.
1242 if (!npobj) {
1243 return;
1244 }
1245
1246 // THIS IS A KNOWN LEAK. SEE BUG 1221448.
1247 // If releaseobject is called off the main thread and we have a valid pointer,
1248 // we at least know it was created on the main thread (see _createobject
1249 // implementation). However, forwarding the deletion back to the main thread
1250 // without careful checking could cause bad memory management races. So, for
1251 // now, we leak by warning and then just returning early. But it should fix
1252 // java 7 crashes.
1253 if (!NS_IsMainThread()) {
1254 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releaseobject called from the wrong thread\n"));
1255 return;
1256 }
1257
1258 int32_t refCnt = PR_ATOMIC_DECREMENT((int32_t*)&npobj->referenceCount);
1259 NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
1260
1261 if (refCnt == 0) {
1262 nsNPObjWrapper::OnDestroy(npobj);
1263
1264 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1265 ("Deleting NPObject %p, refcount hit 0\n", npobj));
1266
1267 if (npobj->_class && npobj->_class->deallocate) {
1268 npobj->_class->deallocate(npobj);
1269 } else {
1270 PR_Free(npobj);
1271 }
1272 }
1273 }
1274
1275 bool
_invoke(NPP npp,NPObject * npobj,NPIdentifier method,const NPVariant * args,uint32_t argCount,NPVariant * result)1276 _invoke(NPP npp, NPObject* npobj, NPIdentifier method, const NPVariant *args,
1277 uint32_t argCount, NPVariant *result)
1278 {
1279 if (!NS_IsMainThread()) {
1280 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invoke called from the wrong thread\n"));
1281 return false;
1282 }
1283 if (!npp || !npobj || !npobj->_class || !npobj->_class->invoke)
1284 return false;
1285
1286 PluginDestructionGuard guard(npp);
1287
1288 NPPExceptionAutoHolder nppExceptionHolder;
1289 NPPAutoPusher nppPusher(npp);
1290
1291 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1292 ("NPN_Invoke(npp %p, npobj %p, method %p, args %d\n", npp,
1293 npobj, method, argCount));
1294
1295 return npobj->_class->invoke(npobj, method, args, argCount, result);
1296 }
1297
1298 bool
_invokeDefault(NPP npp,NPObject * npobj,const NPVariant * args,uint32_t argCount,NPVariant * result)1299 _invokeDefault(NPP npp, NPObject* npobj, const NPVariant *args,
1300 uint32_t argCount, NPVariant *result)
1301 {
1302 if (!NS_IsMainThread()) {
1303 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invokedefault called from the wrong thread\n"));
1304 return false;
1305 }
1306 if (!npp || !npobj || !npobj->_class || !npobj->_class->invokeDefault)
1307 return false;
1308
1309 NPPExceptionAutoHolder nppExceptionHolder;
1310 NPPAutoPusher nppPusher(npp);
1311
1312 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1313 ("NPN_InvokeDefault(npp %p, npobj %p, args %d\n", npp,
1314 npobj, argCount));
1315
1316 return npobj->_class->invokeDefault(npobj, args, argCount, result);
1317 }
1318
1319 bool
_evaluate(NPP npp,NPObject * npobj,NPString * script,NPVariant * result)1320 _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result)
1321 {
1322 if (!NS_IsMainThread()) {
1323 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_evaluate called from the wrong thread\n"));
1324 return false;
1325 }
1326 if (!npp)
1327 return false;
1328
1329 NPPAutoPusher nppPusher(npp);
1330
1331 nsIDocument *doc = GetDocumentFromNPP(npp);
1332 NS_ENSURE_TRUE(doc, false);
1333
1334 nsGlobalWindow* win = nsGlobalWindow::Cast(doc->GetInnerWindow());
1335 if (NS_WARN_IF(!win || !win->FastGetGlobalJSObject())) {
1336 return false;
1337 }
1338
1339 nsAutoMicroTask mt;
1340 dom::AutoEntryScript aes(win, "NPAPI NPN_evaluate");
1341 JSContext* cx = aes.cx();
1342
1343 JS::Rooted<JSObject*> obj(cx, nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj));
1344
1345 if (!obj) {
1346 return false;
1347 }
1348
1349 obj = js::ToWindowIfWindowProxy(obj);
1350 MOZ_ASSERT(obj, "ToWindowIfWindowProxy should never return null");
1351
1352 if (result) {
1353 // Initialize the out param to void
1354 VOID_TO_NPVARIANT(*result);
1355 }
1356
1357 if (!script || !script->UTF8Length || !script->UTF8Characters) {
1358 // Nothing to evaluate.
1359
1360 return true;
1361 }
1362
1363 NS_ConvertUTF8toUTF16 utf16script(script->UTF8Characters,
1364 script->UTF8Length);
1365
1366 nsIPrincipal *principal = doc->NodePrincipal();
1367
1368 nsAutoCString specStr;
1369 const char *spec;
1370
1371 nsCOMPtr<nsIURI> uri;
1372 principal->GetURI(getter_AddRefs(uri));
1373
1374 if (uri) {
1375 uri->GetSpec(specStr);
1376 spec = specStr.get();
1377 } else {
1378 // No URI in a principal means it's the system principal. If the
1379 // document URI is a chrome:// URI, pass that in as the URI of the
1380 // script, else pass in null for the filename as there's no way to
1381 // know where this document really came from. Passing in null here
1382 // also means that the script gets treated by XPConnect as if it
1383 // needs additional protection, which is what we want for unknown
1384 // chrome code anyways.
1385
1386 uri = doc->GetDocumentURI();
1387 bool isChrome = false;
1388
1389 if (uri && NS_SUCCEEDED(uri->SchemeIs("chrome", &isChrome)) && isChrome) {
1390 uri->GetSpec(specStr);
1391 spec = specStr.get();
1392 } else {
1393 spec = nullptr;
1394 }
1395 }
1396
1397 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1398 ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n",
1399 npp, npobj, script->UTF8Characters));
1400
1401 JS::CompileOptions options(cx);
1402 options.setFileAndLine(spec, 0)
1403 .setVersion(JSVERSION_DEFAULT);
1404 JS::Rooted<JS::Value> rval(cx);
1405 nsJSUtils::EvaluateOptions evalOptions(cx);
1406 if (obj != js::GetGlobalForObjectCrossCompartment(obj) &&
1407 !evalOptions.scopeChain.append(obj)) {
1408 return false;
1409 }
1410 obj = js::GetGlobalForObjectCrossCompartment(obj);
1411 nsresult rv = nsJSUtils::EvaluateString(cx, utf16script, obj, options,
1412 evalOptions, &rval);
1413
1414 return NS_SUCCEEDED(rv) &&
1415 (!result || JSValToNPVariant(npp, cx, rval, result));
1416 }
1417
1418 bool
_getproperty(NPP npp,NPObject * npobj,NPIdentifier property,NPVariant * result)1419 _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
1420 NPVariant *result)
1421 {
1422 if (!NS_IsMainThread()) {
1423 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getproperty called from the wrong thread\n"));
1424 return false;
1425 }
1426 if (!npp || !npobj || !npobj->_class || !npobj->_class->getProperty)
1427 return false;
1428
1429 NPPExceptionAutoHolder nppExceptionHolder;
1430 NPPAutoPusher nppPusher(npp);
1431
1432 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1433 ("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
1434 npp, npobj, property));
1435
1436 if (!npobj->_class->getProperty(npobj, property, result))
1437 return false;
1438
1439 // If a Java plugin tries to get the document.URL or document.documentURI
1440 // property from us, don't pass back a value that Java won't be able to
1441 // understand -- one that will make the URL(String) constructor throw a
1442 // MalformedURL exception. Passing such a value causes Java Plugin2 to
1443 // crash (to throw a RuntimeException in Plugin2Manager.getDocumentBase()).
1444 // Also don't pass back a value that Java is likely to mishandle.
1445
1446 nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*) npp->ndata;
1447 if (!inst)
1448 return false;
1449 nsNPAPIPlugin* plugin = inst->GetPlugin();
1450 if (!plugin)
1451 return false;
1452 RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
1453 nsPluginTag* pluginTag = host->TagForPlugin(plugin);
1454 if (!pluginTag->mIsJavaPlugin)
1455 return true;
1456
1457 if (!NPVARIANT_IS_STRING(*result))
1458 return true;
1459
1460 NPUTF8* propertyName = _utf8fromidentifier(property);
1461 if (!propertyName)
1462 return true;
1463 bool notURL =
1464 (PL_strcasecmp(propertyName, "URL") &&
1465 PL_strcasecmp(propertyName, "documentURI"));
1466 _memfree(propertyName);
1467 if (notURL)
1468 return true;
1469
1470 NPObject* window_obj = _getwindowobject(npp);
1471 if (!window_obj)
1472 return true;
1473
1474 NPVariant doc_v;
1475 NPObject* document_obj = nullptr;
1476 NPIdentifier doc_id = _getstringidentifier("document");
1477 bool ok = npobj->_class->getProperty(window_obj, doc_id, &doc_v);
1478 _releaseobject(window_obj);
1479 if (ok) {
1480 if (NPVARIANT_IS_OBJECT(doc_v)) {
1481 document_obj = NPVARIANT_TO_OBJECT(doc_v);
1482 } else {
1483 _releasevariantvalue(&doc_v);
1484 return true;
1485 }
1486 } else {
1487 return true;
1488 }
1489 _releaseobject(document_obj);
1490 if (document_obj != npobj)
1491 return true;
1492
1493 NPString urlnp = NPVARIANT_TO_STRING(*result);
1494 nsXPIDLCString url;
1495 url.Assign(urlnp.UTF8Characters, urlnp.UTF8Length);
1496
1497 bool javaCompatible = false;
1498 if (NS_FAILED(NS_CheckIsJavaCompatibleURLString(url, &javaCompatible)))
1499 javaCompatible = false;
1500 if (javaCompatible)
1501 return true;
1502
1503 // If Java won't be able to interpret the original value of document.URL or
1504 // document.documentURI, or is likely to mishandle it, pass back something
1505 // that Java will understand but won't be able to use to access the network,
1506 // and for which same-origin checks will always fail.
1507
1508 if (inst->mFakeURL.IsVoid()) {
1509 // Abort (do an error return) if NS_MakeRandomInvalidURLString() fails.
1510 if (NS_FAILED(NS_MakeRandomInvalidURLString(inst->mFakeURL))) {
1511 _releasevariantvalue(result);
1512 return false;
1513 }
1514 }
1515
1516 _releasevariantvalue(result);
1517 char* fakeurl = (char *) _memalloc(inst->mFakeURL.Length() + 1);
1518 strcpy(fakeurl, inst->mFakeURL);
1519 STRINGZ_TO_NPVARIANT(fakeurl, *result);
1520
1521 return true;
1522 }
1523
1524 bool
_setproperty(NPP npp,NPObject * npobj,NPIdentifier property,const NPVariant * value)1525 _setproperty(NPP npp, NPObject* npobj, NPIdentifier property,
1526 const NPVariant *value)
1527 {
1528 if (!NS_IsMainThread()) {
1529 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setproperty called from the wrong thread\n"));
1530 return false;
1531 }
1532 if (!npp || !npobj || !npobj->_class || !npobj->_class->setProperty)
1533 return false;
1534
1535 NPPExceptionAutoHolder nppExceptionHolder;
1536 NPPAutoPusher nppPusher(npp);
1537
1538 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1539 ("NPN_SetProperty(npp %p, npobj %p, property %p) called\n",
1540 npp, npobj, property));
1541
1542 return npobj->_class->setProperty(npobj, property, value);
1543 }
1544
1545 bool
_removeproperty(NPP npp,NPObject * npobj,NPIdentifier property)1546 _removeproperty(NPP npp, NPObject* npobj, NPIdentifier property)
1547 {
1548 if (!NS_IsMainThread()) {
1549 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_removeproperty called from the wrong thread\n"));
1550 return false;
1551 }
1552 if (!npp || !npobj || !npobj->_class || !npobj->_class->removeProperty)
1553 return false;
1554
1555 NPPExceptionAutoHolder nppExceptionHolder;
1556 NPPAutoPusher nppPusher(npp);
1557
1558 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1559 ("NPN_RemoveProperty(npp %p, npobj %p, property %p) called\n",
1560 npp, npobj, property));
1561
1562 return npobj->_class->removeProperty(npobj, property);
1563 }
1564
1565 bool
_hasproperty(NPP npp,NPObject * npobj,NPIdentifier propertyName)1566 _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName)
1567 {
1568 if (!NS_IsMainThread()) {
1569 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasproperty called from the wrong thread\n"));
1570 return false;
1571 }
1572 if (!npp || !npobj || !npobj->_class || !npobj->_class->hasProperty)
1573 return false;
1574
1575 NPPExceptionAutoHolder nppExceptionHolder;
1576 NPPAutoPusher nppPusher(npp);
1577
1578 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1579 ("NPN_HasProperty(npp %p, npobj %p, property %p) called\n",
1580 npp, npobj, propertyName));
1581
1582 return npobj->_class->hasProperty(npobj, propertyName);
1583 }
1584
1585 bool
_hasmethod(NPP npp,NPObject * npobj,NPIdentifier methodName)1586 _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName)
1587 {
1588 if (!NS_IsMainThread()) {
1589 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasmethod called from the wrong thread\n"));
1590 return false;
1591 }
1592 if (!npp || !npobj || !npobj->_class || !npobj->_class->hasMethod)
1593 return false;
1594
1595 NPPExceptionAutoHolder nppExceptionHolder;
1596 NPPAutoPusher nppPusher(npp);
1597
1598 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1599 ("NPN_HasMethod(npp %p, npobj %p, property %p) called\n",
1600 npp, npobj, methodName));
1601
1602 return npobj->_class->hasMethod(npobj, methodName);
1603 }
1604
1605 bool
_enumerate(NPP npp,NPObject * npobj,NPIdentifier ** identifier,uint32_t * count)1606 _enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
1607 uint32_t *count)
1608 {
1609 if (!NS_IsMainThread()) {
1610 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_enumerate called from the wrong thread\n"));
1611 return false;
1612 }
1613 if (!npp || !npobj || !npobj->_class)
1614 return false;
1615
1616 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
1617 ("NPN_Enumerate(npp %p, npobj %p) called\n", npp, npobj));
1618
1619 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
1620 !npobj->_class->enumerate) {
1621 *identifier = 0;
1622 *count = 0;
1623 return true;
1624 }
1625
1626 NPPExceptionAutoHolder nppExceptionHolder;
1627 NPPAutoPusher nppPusher(npp);
1628
1629 return npobj->_class->enumerate(npobj, identifier, count);
1630 }
1631
1632 bool
_construct(NPP npp,NPObject * npobj,const NPVariant * args,uint32_t argCount,NPVariant * result)1633 _construct(NPP npp, NPObject* npobj, const NPVariant *args,
1634 uint32_t argCount, NPVariant *result)
1635 {
1636 if (!NS_IsMainThread()) {
1637 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_construct called from the wrong thread\n"));
1638 return false;
1639 }
1640 if (!npp || !npobj || !npobj->_class ||
1641 !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) ||
1642 !npobj->_class->construct) {
1643 return false;
1644 }
1645
1646 NPPExceptionAutoHolder nppExceptionHolder;
1647 NPPAutoPusher nppPusher(npp);
1648
1649 return npobj->_class->construct(npobj, args, argCount, result);
1650 }
1651
1652 void
_releasevariantvalue(NPVariant * variant)1653 _releasevariantvalue(NPVariant* variant)
1654 {
1655 if (!NS_IsMainThread()) {
1656 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releasevariantvalue called from the wrong thread\n"));
1657 }
1658 switch (variant->type) {
1659 case NPVariantType_Void :
1660 case NPVariantType_Null :
1661 case NPVariantType_Bool :
1662 case NPVariantType_Int32 :
1663 case NPVariantType_Double :
1664 break;
1665 case NPVariantType_String :
1666 {
1667 const NPString *s = &NPVARIANT_TO_STRING(*variant);
1668
1669 if (s->UTF8Characters) {
1670 #if defined(MOZ_MEMORY_WINDOWS)
1671 if (malloc_usable_size((void *)s->UTF8Characters) != 0) {
1672 PR_Free((void *)s->UTF8Characters);
1673 } else {
1674 void *p = (void *)s->UTF8Characters;
1675 DWORD nheaps = 0;
1676 AutoTArray<HANDLE, 50> heaps;
1677 nheaps = GetProcessHeaps(0, heaps.Elements());
1678 heaps.AppendElements(nheaps);
1679 GetProcessHeaps(nheaps, heaps.Elements());
1680 for (DWORD i = 0; i < nheaps; i++) {
1681 if (InHeap(heaps[i], p)) {
1682 HeapFree(heaps[i], 0, p);
1683 break;
1684 }
1685 }
1686 }
1687 #else
1688 free((void *)s->UTF8Characters);
1689 #endif
1690 }
1691 break;
1692 }
1693 case NPVariantType_Object:
1694 {
1695 NPObject *npobj = NPVARIANT_TO_OBJECT(*variant);
1696
1697 if (npobj)
1698 _releaseobject(npobj);
1699
1700 break;
1701 }
1702 default:
1703 NS_ERROR("Unknown NPVariant type!");
1704 }
1705
1706 VOID_TO_NPVARIANT(*variant);
1707 }
1708
1709 void
_setexception(NPObject * npobj,const NPUTF8 * message)1710 _setexception(NPObject* npobj, const NPUTF8 *message)
1711 {
1712 if (!NS_IsMainThread()) {
1713 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setexception called from the wrong thread\n"));
1714 return;
1715 }
1716
1717 if (!message) return;
1718
1719 if (gNPPException) {
1720 // If a plugin throws multiple exceptions, we'll only report the
1721 // last one for now.
1722 free(gNPPException);
1723 }
1724
1725 gNPPException = strdup(message);
1726 }
1727
1728 NPError
_getvalue(NPP npp,NPNVariable variable,void * result)1729 _getvalue(NPP npp, NPNVariable variable, void *result)
1730 {
1731 if (!NS_IsMainThread()) {
1732 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalue called from the wrong thread\n"));
1733 return NPERR_INVALID_PARAM;
1734 }
1735 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetValue: npp=%p, var=%d\n",
1736 (void*)npp, (int)variable));
1737
1738 nsresult res;
1739
1740 PluginDestructionGuard guard(npp);
1741
1742 // Cast NPNVariable enum to int to avoid warnings about including switch
1743 // cases for android_npapi.h's non-standard ANPInterface values.
1744 switch (static_cast<int>(variable)) {
1745
1746 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1747 case NPNVxDisplay : {
1748 #if defined(MOZ_X11)
1749 if (npp) {
1750 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
1751 bool windowless = false;
1752 inst->IsWindowless(&windowless);
1753 // The documentation on the types for many variables in NP(N|P)_GetValue
1754 // is vague. Often boolean values are NPBool (1 byte), but
1755 // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
1756 // treats NPPVpluginNeedsXEmbed as PRBool (int), and
1757 // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
1758 // thus we can't use NPBool for needsXEmbed, or the three bytes above
1759 // it on the stack would get clobbered. so protect with the larger bool.
1760 int needsXEmbed = 0;
1761 if (!windowless) {
1762 res = inst->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needsXEmbed);
1763 // If the call returned an error code make sure we still use our default value.
1764 if (NS_FAILED(res)) {
1765 needsXEmbed = 0;
1766 }
1767 }
1768 if (windowless || needsXEmbed) {
1769 (*(Display **)result) = mozilla::DefaultXDisplay();
1770 return NPERR_NO_ERROR;
1771 }
1772 }
1773 #if (MOZ_WIDGET_GTK == 2)
1774 // adobe nppdf calls XtGetApplicationNameAndClass(display,
1775 // &instance, &class) we have to init Xt toolkit before get
1776 // XtDisplay just call gtk_xtbin_new(w,0) once
1777 static GtkWidget *gtkXtBinHolder = 0;
1778 if (!gtkXtBinHolder) {
1779 gtkXtBinHolder = gtk_xtbin_new(gdk_get_default_root_window(),0);
1780 // it crashes on destroy, let it leak
1781 // gtk_widget_destroy(gtkXtBinHolder);
1782 }
1783 (*(Display **)result) = GTK_XTBIN(gtkXtBinHolder)->xtdisplay;
1784 return NPERR_NO_ERROR;
1785 #endif
1786 #endif
1787 return NPERR_GENERIC_ERROR;
1788 }
1789
1790 case NPNVxtAppContext:
1791 return NPERR_GENERIC_ERROR;
1792 #endif
1793
1794 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1795 case NPNVnetscapeWindow: {
1796 if (!npp || !npp->ndata)
1797 return NPERR_INVALID_INSTANCE_ERROR;
1798
1799 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
1800
1801 RefPtr<nsPluginInstanceOwner> owner = inst->GetOwner();
1802 NS_ENSURE_TRUE(owner, NPERR_NO_ERROR);
1803
1804 if (NS_SUCCEEDED(owner->GetNetscapeWindow(result))) {
1805 return NPERR_NO_ERROR;
1806 }
1807 return NPERR_GENERIC_ERROR;
1808 }
1809 #endif
1810
1811 case NPNVjavascriptEnabledBool: {
1812 *(NPBool*)result = false;
1813 bool js = false;
1814 res = Preferences::GetBool("javascript.enabled", &js);
1815 if (NS_SUCCEEDED(res)) {
1816 *(NPBool*)result = js;
1817 }
1818 return NPERR_NO_ERROR;
1819 }
1820
1821 case NPNVasdEnabledBool:
1822 *(NPBool*)result = false;
1823 return NPERR_NO_ERROR;
1824
1825 case NPNVisOfflineBool: {
1826 bool offline = false;
1827 nsCOMPtr<nsIIOService> ioservice =
1828 do_GetService(NS_IOSERVICE_CONTRACTID, &res);
1829 if (NS_SUCCEEDED(res))
1830 res = ioservice->GetOffline(&offline);
1831 if (NS_FAILED(res))
1832 return NPERR_GENERIC_ERROR;
1833
1834 *(NPBool*)result = offline;
1835 return NPERR_NO_ERROR;
1836 }
1837
1838 case NPNVToolkit: {
1839 #ifdef MOZ_WIDGET_GTK
1840 *((NPNToolkitType*)result) = NPNVGtk2;
1841 #endif
1842
1843 if (*(NPNToolkitType*)result)
1844 return NPERR_NO_ERROR;
1845
1846 return NPERR_GENERIC_ERROR;
1847 }
1848
1849 case NPNVSupportsXEmbedBool: {
1850 #ifdef MOZ_WIDGET_GTK
1851 *(NPBool*)result = true;
1852 #else
1853 *(NPBool*)result = false;
1854 #endif
1855 return NPERR_NO_ERROR;
1856 }
1857
1858 case NPNVWindowNPObject: {
1859 *(NPObject **)result = _getwindowobject(npp);
1860
1861 return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1862 }
1863
1864 case NPNVPluginElementNPObject: {
1865 *(NPObject **)result = _getpluginelement(npp);
1866
1867 return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1868 }
1869
1870 case NPNVSupportsWindowless: {
1871 #if defined(XP_WIN) || defined(XP_MACOSX) || \
1872 (defined(MOZ_X11) && defined(MOZ_WIDGET_GTK))
1873 *(NPBool*)result = true;
1874 #else
1875 *(NPBool*)result = false;
1876 #endif
1877 return NPERR_NO_ERROR;
1878 }
1879
1880 case NPNVprivateModeBool: {
1881 bool privacy;
1882 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
1883 if (!inst)
1884 return NPERR_GENERIC_ERROR;
1885
1886 nsresult rv = inst->IsPrivateBrowsing(&privacy);
1887 if (NS_FAILED(rv))
1888 return NPERR_GENERIC_ERROR;
1889 *(NPBool*)result = (NPBool)privacy;
1890 return NPERR_NO_ERROR;
1891 }
1892
1893 case NPNVdocumentOrigin: {
1894 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
1895 if (!inst) {
1896 return NPERR_GENERIC_ERROR;
1897 }
1898
1899 nsCOMPtr<nsIDOMElement> element;
1900 inst->GetDOMElement(getter_AddRefs(element));
1901 if (!element) {
1902 return NPERR_GENERIC_ERROR;
1903 }
1904
1905 nsCOMPtr<nsIContent> content(do_QueryInterface(element));
1906 if (!content) {
1907 return NPERR_GENERIC_ERROR;
1908 }
1909
1910 nsIPrincipal* principal = content->NodePrincipal();
1911
1912 nsAutoString utf16Origin;
1913 res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
1914 if (NS_FAILED(res)) {
1915 return NPERR_GENERIC_ERROR;
1916 }
1917
1918 nsCOMPtr<nsIIDNService> idnService = do_GetService(NS_IDNSERVICE_CONTRACTID);
1919 if (!idnService) {
1920 return NPERR_GENERIC_ERROR;
1921 }
1922
1923 // This is a bit messy: we convert to UTF-8 here, but then
1924 // nsIDNService::Normalize will convert back to UTF-16 for processing,
1925 // and back to UTF-8 again to return the result.
1926 // Alternative: perhaps we should add a NormalizeUTF16 version of the API,
1927 // and just convert to UTF-8 for the final return (resulting in one
1928 // encoding form conversion instead of three).
1929 NS_ConvertUTF16toUTF8 utf8Origin(utf16Origin);
1930 nsAutoCString normalizedUTF8Origin;
1931 res = idnService->Normalize(utf8Origin, normalizedUTF8Origin);
1932 if (NS_FAILED(res)) {
1933 return NPERR_GENERIC_ERROR;
1934 }
1935
1936 *(char**)result = ToNewCString(normalizedUTF8Origin);
1937 return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
1938 }
1939
1940 #ifdef XP_MACOSX
1941 case NPNVpluginDrawingModel: {
1942 if (npp) {
1943 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
1944 if (inst) {
1945 NPDrawingModel drawingModel;
1946 inst->GetDrawingModel((int32_t*)&drawingModel);
1947 *(NPDrawingModel*)result = drawingModel;
1948 return NPERR_NO_ERROR;
1949 }
1950 }
1951 return NPERR_GENERIC_ERROR;
1952 }
1953
1954 #ifndef NP_NO_QUICKDRAW
1955 case NPNVsupportsQuickDrawBool: {
1956 *(NPBool*)result = false;
1957
1958 return NPERR_NO_ERROR;
1959 }
1960 #endif
1961
1962 case NPNVsupportsCoreGraphicsBool: {
1963 *(NPBool*)result = true;
1964
1965 return NPERR_NO_ERROR;
1966 }
1967
1968 case NPNVsupportsCoreAnimationBool: {
1969 *(NPBool*)result = true;
1970
1971 return NPERR_NO_ERROR;
1972 }
1973
1974 case NPNVsupportsInvalidatingCoreAnimationBool: {
1975 *(NPBool*)result = true;
1976
1977 return NPERR_NO_ERROR;
1978 }
1979
1980 case NPNVsupportsCompositingCoreAnimationPluginsBool: {
1981 *(NPBool*)result = PR_TRUE;
1982
1983 return NPERR_NO_ERROR;
1984 }
1985
1986 #ifndef NP_NO_CARBON
1987 case NPNVsupportsCarbonBool: {
1988 *(NPBool*)result = false;
1989
1990 return NPERR_NO_ERROR;
1991 }
1992 #endif
1993 case NPNVsupportsCocoaBool: {
1994 *(NPBool*)result = true;
1995
1996 return NPERR_NO_ERROR;
1997 }
1998
1999 case NPNVsupportsUpdatedCocoaTextInputBool: {
2000 *(NPBool*)result = true;
2001 return NPERR_NO_ERROR;
2002 }
2003 #endif
2004
2005 #if defined(XP_MACOSX) || defined(XP_WIN)
2006 case NPNVcontentsScaleFactor: {
2007 nsNPAPIPluginInstance *inst =
2008 (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
2009 double scaleFactor = inst ? inst->GetContentsScaleFactor() : 1.0;
2010 *(double*)result = scaleFactor;
2011 return NPERR_NO_ERROR;
2012 }
2013 #endif
2014
2015 case NPNVCSSZoomFactor: {
2016 nsNPAPIPluginInstance *inst =
2017 (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
2018 double scaleFactor = inst ? inst->GetCSSZoomFactor() : 1.0;
2019 *(double*)result = scaleFactor;
2020 return NPERR_NO_ERROR;
2021 }
2022
2023 #ifdef MOZ_WIDGET_ANDROID
2024 case kLogInterfaceV0_ANPGetValue: {
2025 LOG("get log interface");
2026 ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result;
2027 InitLogInterface(i);
2028 return NPERR_NO_ERROR;
2029 }
2030
2031 case kBitmapInterfaceV0_ANPGetValue: {
2032 LOG("get bitmap interface");
2033 return NPERR_GENERIC_ERROR;
2034 }
2035
2036 case kMatrixInterfaceV0_ANPGetValue: {
2037 LOG("get matrix interface");
2038 return NPERR_GENERIC_ERROR;
2039 }
2040
2041 case kPathInterfaceV0_ANPGetValue: {
2042 LOG("get path interface");
2043 return NPERR_GENERIC_ERROR;
2044 }
2045
2046 case kTypefaceInterfaceV0_ANPGetValue: {
2047 LOG("get typeface interface");
2048 ANPTypefaceInterfaceV0 *i = (ANPTypefaceInterfaceV0 *) result;
2049 InitTypeFaceInterface(i);
2050 return NPERR_NO_ERROR;
2051 }
2052
2053 case kPaintInterfaceV0_ANPGetValue: {
2054 LOG("get paint interface");
2055 ANPPaintInterfaceV0 *i = (ANPPaintInterfaceV0 *) result;
2056 InitPaintInterface(i);
2057 return NPERR_NO_ERROR;
2058 }
2059
2060 case kCanvasInterfaceV0_ANPGetValue: {
2061 LOG("get canvas interface");
2062 ANPCanvasInterfaceV0 *i = (ANPCanvasInterfaceV0 *) result;
2063 InitCanvasInterface(i);
2064 return NPERR_NO_ERROR;
2065 }
2066
2067 case kWindowInterfaceV0_ANPGetValue: {
2068 LOG("get window interface");
2069 ANPWindowInterfaceV0 *i = (ANPWindowInterfaceV0 *) result;
2070 InitWindowInterface(i);
2071 return NPERR_NO_ERROR;
2072 }
2073
2074 case kAudioTrackInterfaceV0_ANPGetValue: {
2075 LOG("get audio interface");
2076 ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result;
2077 InitAudioTrackInterfaceV0(i);
2078 return NPERR_NO_ERROR;
2079 }
2080
2081 case kEventInterfaceV0_ANPGetValue: {
2082 LOG("get event interface");
2083 ANPEventInterfaceV0 *i = (ANPEventInterfaceV0 *) result;
2084 InitEventInterface(i);
2085 return NPERR_NO_ERROR;
2086 }
2087
2088 case kSystemInterfaceV0_ANPGetValue: {
2089 LOG("get system interface");
2090 return NPERR_GENERIC_ERROR;
2091 }
2092
2093 case kSurfaceInterfaceV0_ANPGetValue: {
2094 LOG("get surface interface");
2095 ANPSurfaceInterfaceV0 *i = (ANPSurfaceInterfaceV0 *) result;
2096 InitSurfaceInterface(i);
2097 return NPERR_NO_ERROR;
2098 }
2099
2100 case kSupportedDrawingModel_ANPGetValue: {
2101 LOG("get supported drawing model");
2102 return NPERR_GENERIC_ERROR;
2103 }
2104
2105 case kJavaContext_ANPGetValue: {
2106 LOG("get java context");
2107 auto ret = java::GeckoAppShell::GetContext();
2108 if (!ret)
2109 return NPERR_GENERIC_ERROR;
2110
2111 *static_cast<jobject*>(result) = ret.Forget();
2112 return NPERR_NO_ERROR;
2113 }
2114
2115 case kAudioTrackInterfaceV1_ANPGetValue: {
2116 LOG("get audio interface v1");
2117 ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
2118 InitAudioTrackInterfaceV1(i);
2119 return NPERR_NO_ERROR;
2120 }
2121
2122 case kNativeWindowInterfaceV0_ANPGetValue: {
2123 LOG("get native window interface v0");
2124 ANPNativeWindowInterfaceV0* i = (ANPNativeWindowInterfaceV0 *) result;
2125 InitNativeWindowInterface(i);
2126 return NPERR_NO_ERROR;
2127 }
2128
2129 case kOpenGLInterfaceV0_ANPGetValue: {
2130 LOG("get openGL interface");
2131 return NPERR_GENERIC_ERROR;
2132 }
2133
2134 case kWindowInterfaceV1_ANPGetValue: {
2135 LOG("get Window interface V1");
2136 return NPERR_GENERIC_ERROR;
2137 }
2138
2139 case kWindowInterfaceV2_ANPGetValue: {
2140 LOG("get Window interface V2");
2141 ANPWindowInterfaceV2 *i = (ANPWindowInterfaceV2 *) result;
2142 InitWindowInterfaceV2(i);
2143 return NPERR_NO_ERROR;
2144 }
2145
2146 case kVideoInterfaceV0_ANPGetValue: {
2147 LOG("get video interface V0");
2148 return NPERR_GENERIC_ERROR;
2149 }
2150
2151 case kVideoInterfaceV1_ANPGetValue: {
2152 LOG("get video interface V1");
2153 ANPVideoInterfaceV1 *i = (ANPVideoInterfaceV1*) result;
2154 InitVideoInterfaceV1(i);
2155 return NPERR_NO_ERROR;
2156 }
2157
2158 case kSystemInterfaceV1_ANPGetValue: {
2159 LOG("get system interface v1");
2160 ANPSystemInterfaceV1* i = reinterpret_cast<ANPSystemInterfaceV1*>(result);
2161 InitSystemInterfaceV1(i);
2162 return NPERR_NO_ERROR;
2163 }
2164
2165 case kSystemInterfaceV2_ANPGetValue: {
2166 LOG("get system interface v2");
2167 ANPSystemInterfaceV2* i = reinterpret_cast<ANPSystemInterfaceV2*>(result);
2168 InitSystemInterfaceV2(i);
2169 return NPERR_NO_ERROR;
2170 }
2171 #endif
2172
2173 // we no longer hand out any XPCOM objects
2174 case NPNVDOMElement:
2175 case NPNVDOMWindow:
2176 case NPNVserviceManager:
2177 // old XPCOM objects, no longer supported, but null out the out
2178 // param to avoid crashing plugins that still try to use this.
2179 *(nsISupports**)result = nullptr;
2180 MOZ_FALLTHROUGH;
2181
2182 default:
2183 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_getvalue unhandled get value: %d\n", variable));
2184 return NPERR_GENERIC_ERROR;
2185 }
2186 }
2187
2188 NPError
_setvalue(NPP npp,NPPVariable variable,void * result)2189 _setvalue(NPP npp, NPPVariable variable, void *result)
2190 {
2191 if (!NS_IsMainThread()) {
2192 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setvalue called from the wrong thread\n"));
2193 return NPERR_INVALID_PARAM;
2194 }
2195 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_SetValue: npp=%p, var=%d\n",
2196 (void*)npp, (int)variable));
2197
2198 if (!npp)
2199 return NPERR_INVALID_INSTANCE_ERROR;
2200
2201 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
2202
2203 NS_ASSERTION(inst, "null instance");
2204
2205 if (!inst)
2206 return NPERR_INVALID_INSTANCE_ERROR;
2207
2208 PluginDestructionGuard guard(inst);
2209
2210 // Cast NPNVariable enum to int to avoid warnings about including switch
2211 // cases for android_npapi.h's non-standard ANPInterface values.
2212 switch (static_cast<int>(variable)) {
2213
2214 // we should keep backward compatibility with NPAPI where the
2215 // actual pointer value is checked rather than its content
2216 // when passing booleans
2217 case NPPVpluginWindowBool: {
2218 #ifdef XP_MACOSX
2219 // This setting doesn't apply to OS X (only to Windows and Unix/Linux).
2220 // See https://developer.mozilla.org/En/NPN_SetValue#section_5. Return
2221 // NPERR_NO_ERROR here to conform to other browsers' behavior on OS X
2222 // (e.g. Safari and Opera).
2223 return NPERR_NO_ERROR;
2224 #else
2225 NPBool bWindowless = (result == nullptr);
2226 return inst->SetWindowless(bWindowless);
2227 #endif
2228 }
2229 case NPPVpluginTransparentBool: {
2230 NPBool bTransparent = (result != nullptr);
2231 return inst->SetTransparent(bTransparent);
2232 }
2233
2234 case NPPVjavascriptPushCallerBool: {
2235 return NPERR_NO_ERROR;
2236 }
2237
2238 case NPPVpluginKeepLibraryInMemory: {
2239 NPBool bCached = (result != nullptr);
2240 inst->SetCached(bCached);
2241 return NPERR_NO_ERROR;
2242 }
2243
2244 case NPPVpluginUsesDOMForCursorBool: {
2245 bool useDOMForCursor = (result != nullptr);
2246 return inst->SetUsesDOMForCursor(useDOMForCursor);
2247 }
2248
2249 case NPPVpluginIsPlayingAudio: {
2250 bool isMuted = !result;
2251
2252 nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*) npp->ndata;
2253 MOZ_ASSERT(inst);
2254
2255 if (isMuted && !inst->HasAudioChannelAgent()) {
2256 return NPERR_NO_ERROR;
2257 }
2258
2259 nsCOMPtr<nsIAudioChannelAgent> agent;
2260 nsresult rv = inst->GetOrCreateAudioChannelAgent(getter_AddRefs(agent));
2261 if (NS_WARN_IF(NS_FAILED(rv))) {
2262 return NPERR_NO_ERROR;
2263 }
2264
2265 MOZ_ASSERT(agent);
2266
2267 if (isMuted) {
2268 rv = agent->NotifyStoppedPlaying();
2269 if (NS_WARN_IF(NS_FAILED(rv))) {
2270 return NPERR_NO_ERROR;
2271 }
2272 } else {
2273
2274 dom::AudioPlaybackConfig config;
2275 rv = agent->NotifyStartedPlaying(&config,
2276 dom::AudioChannelService::AudibleState::eAudible);
2277 if (NS_WARN_IF(NS_FAILED(rv))) {
2278 return NPERR_NO_ERROR;
2279 }
2280
2281 rv = inst->WindowVolumeChanged(config.mVolume, config.mMuted);
2282 if (NS_WARN_IF(NS_FAILED(rv))) {
2283 return NPERR_NO_ERROR;
2284 }
2285
2286 // Since we only support for muting now, the implementation of suspend
2287 // is equal to muting. Therefore, if we have already muted the plugin,
2288 // then we don't need to call WindowSuspendChanged() again.
2289 if (config.mMuted) {
2290 return NPERR_NO_ERROR;
2291 }
2292
2293 rv = inst->WindowSuspendChanged(config.mSuspend);
2294 if (NS_WARN_IF(NS_FAILED(rv))) {
2295 return NPERR_NO_ERROR;
2296 }
2297 }
2298
2299 return NPERR_NO_ERROR;
2300 }
2301
2302 #ifndef MOZ_WIDGET_ANDROID
2303 // On android, their 'drawing model' uses the same constant!
2304 case NPPVpluginDrawingModel: {
2305 if (inst) {
2306 inst->SetDrawingModel((NPDrawingModel)NS_PTR_TO_INT32(result));
2307 return NPERR_NO_ERROR;
2308 }
2309 else {
2310 return NPERR_GENERIC_ERROR;
2311 }
2312 }
2313 #endif
2314
2315 #ifdef XP_MACOSX
2316 case NPPVpluginEventModel: {
2317 if (inst) {
2318 inst->SetEventModel((NPEventModel)NS_PTR_TO_INT32(result));
2319 return NPERR_NO_ERROR;
2320 }
2321 else {
2322 return NPERR_GENERIC_ERROR;
2323 }
2324 }
2325 #endif
2326 #ifdef MOZ_WIDGET_ANDROID
2327 case kRequestDrawingModel_ANPSetValue:
2328 if (inst)
2329 inst->SetANPDrawingModel(NS_PTR_TO_INT32(result));
2330 return NPERR_NO_ERROR;
2331 case kAcceptEvents_ANPSetValue:
2332 return NPERR_NO_ERROR;
2333 #endif
2334 default:
2335 return NPERR_GENERIC_ERROR;
2336 }
2337 }
2338
2339 NPError
_requestread(NPStream * pstream,NPByteRange * rangeList)2340 _requestread(NPStream *pstream, NPByteRange *rangeList)
2341 {
2342 if (!NS_IsMainThread()) {
2343 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_requestread called from the wrong thread\n"));
2344 return NPERR_INVALID_PARAM;
2345 }
2346 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_RequestRead: stream=%p\n",
2347 (void*)pstream));
2348
2349 #ifdef PLUGIN_LOGGING
2350 for(NPByteRange * range = rangeList; range != nullptr; range = range->next)
2351 MOZ_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY,
2352 ("%i-%i", range->offset, range->offset + range->length - 1));
2353
2354 MOZ_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY, ("\n\n"));
2355 PR_LogFlush();
2356 #endif
2357
2358 if (!pstream || !rangeList || !pstream->ndata)
2359 return NPERR_INVALID_PARAM;
2360
2361 nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
2362 nsNPAPIPluginStreamListener* streamlistener = streamWrapper->GetStreamListener();
2363 if (!streamlistener) {
2364 return NPERR_GENERIC_ERROR;
2365 }
2366
2367 int32_t streamtype = NP_NORMAL;
2368
2369 streamlistener->GetStreamType(&streamtype);
2370
2371 if (streamtype != NP_SEEK)
2372 return NPERR_STREAM_NOT_SEEKABLE;
2373
2374 if (!streamlistener->mStreamListenerPeer)
2375 return NPERR_GENERIC_ERROR;
2376
2377 nsresult rv = streamlistener->mStreamListenerPeer->RequestRead((NPByteRange *)rangeList);
2378 if (NS_FAILED(rv))
2379 return NPERR_GENERIC_ERROR;
2380
2381 return NPERR_NO_ERROR;
2382 }
2383
2384 // Deprecated, only stubbed out
2385 void* /* OJI type: JRIEnv* */
_getJavaEnv()2386 _getJavaEnv()
2387 {
2388 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
2389 return nullptr;
2390 }
2391
2392 const char *
_useragent(NPP npp)2393 _useragent(NPP npp)
2394 {
2395 if (!NS_IsMainThread()) {
2396 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_useragent called from the wrong thread\n"));
2397 return nullptr;
2398 }
2399 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_UserAgent: npp=%p\n", (void*)npp));
2400
2401 nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
2402 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
2403 if (!pluginHost) {
2404 return nullptr;
2405 }
2406
2407 const char *retstr;
2408 nsresult rv = pluginHost->UserAgent(&retstr);
2409 if (NS_FAILED(rv))
2410 return nullptr;
2411
2412 return retstr;
2413 }
2414
2415 void *
_memalloc(uint32_t size)2416 _memalloc (uint32_t size)
2417 {
2418 if (!NS_IsMainThread()) {
2419 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN_memalloc called from the wrong thread\n"));
2420 }
2421 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemAlloc: size=%d\n", size));
2422 return moz_xmalloc(size);
2423 }
2424
2425 // Deprecated, only stubbed out
2426 void* /* OJI type: jref */
_getJavaPeer(NPP npp)2427 _getJavaPeer(NPP npp)
2428 {
2429 NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
2430 return nullptr;
2431 }
2432
2433 void
_pushpopupsenabledstate(NPP npp,NPBool enabled)2434 _pushpopupsenabledstate(NPP npp, NPBool enabled)
2435 {
2436 if (!NS_IsMainThread()) {
2437 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_pushpopupsenabledstate called from the wrong thread\n"));
2438 return;
2439 }
2440 nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
2441 if (!inst)
2442 return;
2443
2444 inst->PushPopupsEnabledState(enabled);
2445 }
2446
2447 void
_poppopupsenabledstate(NPP npp)2448 _poppopupsenabledstate(NPP npp)
2449 {
2450 if (!NS_IsMainThread()) {
2451 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_poppopupsenabledstate called from the wrong thread\n"));
2452 return;
2453 }
2454 nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
2455 if (!inst)
2456 return;
2457
2458 inst->PopPopupsEnabledState();
2459 }
2460
2461 void
_pluginthreadasynccall(NPP instance,PluginThreadCallback func,void * userData)2462 _pluginthreadasynccall(NPP instance, PluginThreadCallback func, void *userData)
2463 {
2464 if (NS_IsMainThread()) {
2465 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from the main thread\n"));
2466 } else {
2467 NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from a non main thread\n"));
2468 }
2469 RefPtr<nsPluginThreadRunnable> evt =
2470 new nsPluginThreadRunnable(instance, func, userData);
2471
2472 if (evt && evt->IsValid()) {
2473 NS_DispatchToMainThread(evt);
2474 }
2475 }
2476
2477 NPError
_getvalueforurl(NPP instance,NPNURLVariable variable,const char * url,char ** value,uint32_t * len)2478 _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
2479 char **value, uint32_t *len)
2480 {
2481 if (!NS_IsMainThread()) {
2482 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalueforurl called from the wrong thread\n"));
2483 return NPERR_GENERIC_ERROR;
2484 }
2485
2486 if (!instance) {
2487 return NPERR_INVALID_PARAM;
2488 }
2489
2490 if (!url || !*url || !len) {
2491 return NPERR_INVALID_URL;
2492 }
2493
2494 *len = 0;
2495
2496 switch (variable) {
2497 case NPNURLVProxy:
2498 {
2499 nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
2500 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
2501 if (pluginHost && NS_SUCCEEDED(pluginHost->FindProxyForURL(url, value))) {
2502 *len = *value ? strlen(*value) : 0;
2503 return NPERR_NO_ERROR;
2504 }
2505 break;
2506 }
2507 case NPNURLVCookie:
2508 {
2509 nsCOMPtr<nsICookieService> cookieService =
2510 do_GetService(NS_COOKIESERVICE_CONTRACTID);
2511
2512 if (!cookieService)
2513 return NPERR_GENERIC_ERROR;
2514
2515 // Make an nsURI from the url argument
2516 nsCOMPtr<nsIURI> uri;
2517 if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), nsDependentCString(url)))) {
2518 return NPERR_GENERIC_ERROR;
2519 }
2520
2521 nsCOMPtr<nsIChannel> channel = GetChannelFromNPP(instance);
2522
2523 if (NS_FAILED(cookieService->GetCookieString(uri, channel, value)) ||
2524 !*value) {
2525 return NPERR_GENERIC_ERROR;
2526 }
2527
2528 *len = strlen(*value);
2529 return NPERR_NO_ERROR;
2530 }
2531
2532 default:
2533 // Fall through and return an error...
2534 ;
2535 }
2536
2537 return NPERR_GENERIC_ERROR;
2538 }
2539
2540 NPError
_setvalueforurl(NPP instance,NPNURLVariable variable,const char * url,const char * value,uint32_t len)2541 _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
2542 const char *value, uint32_t len)
2543 {
2544 if (!NS_IsMainThread()) {
2545 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setvalueforurl called from the wrong thread\n"));
2546 return NPERR_GENERIC_ERROR;
2547 }
2548
2549 if (!instance) {
2550 return NPERR_INVALID_PARAM;
2551 }
2552
2553 if (!url || !*url) {
2554 return NPERR_INVALID_URL;
2555 }
2556
2557 switch (variable) {
2558 case NPNURLVCookie:
2559 {
2560 if (!value || 0 == len)
2561 return NPERR_INVALID_PARAM;
2562
2563 nsresult rv = NS_ERROR_FAILURE;
2564 nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
2565 if (NS_FAILED(rv))
2566 return NPERR_GENERIC_ERROR;
2567
2568 nsCOMPtr<nsICookieService> cookieService = do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv);
2569 if (NS_FAILED(rv))
2570 return NPERR_GENERIC_ERROR;
2571
2572 nsCOMPtr<nsIURI> uriIn;
2573 rv = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
2574 if (NS_FAILED(rv))
2575 return NPERR_GENERIC_ERROR;
2576
2577 nsCOMPtr<nsIChannel> channel = GetChannelFromNPP(instance);
2578
2579 char *cookie = (char*)value;
2580 char c = cookie[len];
2581 cookie[len] = '\0';
2582 rv = cookieService->SetCookieString(uriIn, nullptr, cookie, channel);
2583 cookie[len] = c;
2584 if (NS_SUCCEEDED(rv))
2585 return NPERR_NO_ERROR;
2586 }
2587
2588 break;
2589 case NPNURLVProxy:
2590 // We don't support setting proxy values, fall through...
2591 default:
2592 // Fall through and return an error...
2593 ;
2594 }
2595
2596 return NPERR_GENERIC_ERROR;
2597 }
2598
2599 NPError
_getauthenticationinfo(NPP instance,const char * protocol,const char * host,int32_t port,const char * scheme,const char * realm,char ** username,uint32_t * ulen,char ** password,uint32_t * plen)2600 _getauthenticationinfo(NPP instance, const char *protocol, const char *host,
2601 int32_t port, const char *scheme, const char *realm,
2602 char **username, uint32_t *ulen, char **password,
2603 uint32_t *plen)
2604 {
2605 if (!NS_IsMainThread()) {
2606 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getauthenticationinfo called from the wrong thread\n"));
2607 return NPERR_GENERIC_ERROR;
2608 }
2609
2610 if (!instance || !protocol || !host || !scheme || !realm || !username ||
2611 !ulen || !password || !plen)
2612 return NPERR_INVALID_PARAM;
2613
2614 *username = nullptr;
2615 *password = nullptr;
2616 *ulen = 0;
2617 *plen = 0;
2618
2619 nsDependentCString proto(protocol);
2620
2621 if (!proto.LowerCaseEqualsLiteral("http") &&
2622 !proto.LowerCaseEqualsLiteral("https"))
2623 return NPERR_GENERIC_ERROR;
2624
2625 nsCOMPtr<nsIHttpAuthManager> authManager =
2626 do_GetService("@mozilla.org/network/http-auth-manager;1");
2627 if (!authManager)
2628 return NPERR_GENERIC_ERROR;
2629
2630 nsNPAPIPluginInstance *inst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
2631 if (!inst)
2632 return NPERR_GENERIC_ERROR;
2633
2634 bool authPrivate = false;
2635 if (NS_FAILED(inst->IsPrivateBrowsing(&authPrivate)))
2636 return NPERR_GENERIC_ERROR;
2637
2638 nsIDocument *doc = GetDocumentFromNPP(instance);
2639 NS_ENSURE_TRUE(doc, NPERR_GENERIC_ERROR);
2640 nsIPrincipal *principal = doc->NodePrincipal();
2641
2642 nsAutoString unused, uname16, pwd16;
2643 if (NS_FAILED(authManager->GetAuthIdentity(proto, nsDependentCString(host),
2644 port, nsDependentCString(scheme),
2645 nsDependentCString(realm),
2646 EmptyCString(), unused, uname16,
2647 pwd16, authPrivate, principal))) {
2648 return NPERR_GENERIC_ERROR;
2649 }
2650
2651 NS_ConvertUTF16toUTF8 uname8(uname16);
2652 NS_ConvertUTF16toUTF8 pwd8(pwd16);
2653
2654 *username = ToNewCString(uname8);
2655 *ulen = *username ? uname8.Length() : 0;
2656
2657 *password = ToNewCString(pwd8);
2658 *plen = *password ? pwd8.Length() : 0;
2659
2660 return NPERR_NO_ERROR;
2661 }
2662
2663 uint32_t
_scheduletimer(NPP instance,uint32_t interval,NPBool repeat,PluginTimerFunc timerFunc)2664 _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc)
2665 {
2666 if (!NS_IsMainThread()) {
2667 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_scheduletimer called from the wrong thread\n"));
2668 return 0;
2669 }
2670
2671 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2672 if (!inst)
2673 return 0;
2674
2675 return inst->ScheduleTimer(interval, repeat, timerFunc);
2676 }
2677
2678 void
_unscheduletimer(NPP instance,uint32_t timerID)2679 _unscheduletimer(NPP instance, uint32_t timerID)
2680 {
2681 if (!NS_IsMainThread()) {
2682 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_unscheduletimer called from the wrong thread\n"));
2683 return;
2684 }
2685
2686 #ifdef MOZ_WIDGET_ANDROID
2687 // Sometimes Flash calls this with a dead NPP instance. Ensure the one we have
2688 // here is valid and maps to a nsNPAPIPluginInstance.
2689 nsNPAPIPluginInstance *inst = nsNPAPIPluginInstance::GetFromNPP(instance);
2690 #else
2691 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2692 #endif
2693 if (!inst)
2694 return;
2695
2696 inst->UnscheduleTimer(timerID);
2697 }
2698
2699 NPError
_popupcontextmenu(NPP instance,NPMenu * menu)2700 _popupcontextmenu(NPP instance, NPMenu* menu)
2701 {
2702 if (!NS_IsMainThread()) {
2703 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_popupcontextmenu called from the wrong thread\n"));
2704 return 0;
2705 }
2706
2707 #ifdef MOZ_WIDGET_COCOA
2708 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2709
2710 double pluginX, pluginY;
2711 double screenX, screenY;
2712
2713 const NPCocoaEvent* currentEvent = static_cast<NPCocoaEvent*>(inst->GetCurrentEvent());
2714 if (!currentEvent) {
2715 return NPERR_GENERIC_ERROR;
2716 }
2717
2718 // Ensure that the events has an x/y value.
2719 if (currentEvent->type != NPCocoaEventMouseDown &&
2720 currentEvent->type != NPCocoaEventMouseUp &&
2721 currentEvent->type != NPCocoaEventMouseMoved &&
2722 currentEvent->type != NPCocoaEventMouseEntered &&
2723 currentEvent->type != NPCocoaEventMouseExited &&
2724 currentEvent->type != NPCocoaEventMouseDragged) {
2725 return NPERR_GENERIC_ERROR;
2726 }
2727
2728 pluginX = currentEvent->data.mouse.pluginX;
2729 pluginY = currentEvent->data.mouse.pluginY;
2730
2731 if ((pluginX < 0.0) || (pluginY < 0.0))
2732 return NPERR_GENERIC_ERROR;
2733
2734 NPBool success = _convertpoint(instance,
2735 pluginX, pluginY, NPCoordinateSpacePlugin,
2736 &screenX, &screenY, NPCoordinateSpaceScreen);
2737
2738 if (success) {
2739 return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
2740 screenX, screenY,
2741 nullptr,
2742 nullptr);
2743 } else {
2744 NS_WARNING("Convertpoint failed, could not created contextmenu.");
2745 return NPERR_GENERIC_ERROR;
2746 }
2747 #else
2748 NS_WARNING("Not supported on this platform!");
2749 return NPERR_GENERIC_ERROR;
2750 #endif
2751 }
2752
2753 NPBool
_convertpoint(NPP instance,double sourceX,double sourceY,NPCoordinateSpace sourceSpace,double * destX,double * destY,NPCoordinateSpace destSpace)2754 _convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
2755 {
2756 if (!NS_IsMainThread()) {
2757 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_convertpoint called from the wrong thread\n"));
2758 return 0;
2759 }
2760
2761 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2762 if (!inst)
2763 return false;
2764
2765 return inst->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
2766 }
2767
2768 void
_urlredirectresponse(NPP instance,void * notifyData,NPBool allow)2769 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
2770 {
2771 if (!NS_IsMainThread()) {
2772 NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_convertpoint called from the wrong thread\n"));
2773 return;
2774 }
2775
2776 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2777 if (!inst) {
2778 return;
2779 }
2780
2781 inst->URLRedirectResponse(notifyData, allow);
2782 }
2783
2784 NPError
_initasyncsurface(NPP instance,NPSize * size,NPImageFormat format,void * initData,NPAsyncSurface * surface)2785 _initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface)
2786 {
2787 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2788 if (!inst) {
2789 return NPERR_GENERIC_ERROR;
2790 }
2791
2792 return inst->InitAsyncSurface(size, format, initData, surface);
2793 }
2794
2795 NPError
_finalizeasyncsurface(NPP instance,NPAsyncSurface * surface)2796 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
2797 {
2798 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2799 if (!inst) {
2800 return NPERR_GENERIC_ERROR;
2801 }
2802
2803 return inst->FinalizeAsyncSurface(surface);
2804 }
2805
2806 void
_setcurrentasyncsurface(NPP instance,NPAsyncSurface * surface,NPRect * changed)2807 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
2808 {
2809 nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
2810 if (!inst) {
2811 return;
2812 }
2813
2814 inst->SetCurrentAsyncSurface(surface, changed);
2815 }
2816
2817 } /* namespace parent */
2818 } /* namespace plugins */
2819 } /* namespace mozilla */
2820