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