dom/plugins/base/nsNPAPIPlugin.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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;
  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;
  1018   nsIOutputStream* stream = wrapper->GetOutputStream();
  1019   if (!stream) {
  1020     return -1;
  1023   uint32_t count = 0;
  1024   nsresult rv = stream->Write((char *)buffer, len, &count);
  1026   if (NS_FAILED(rv)) {
  1027     return -1;
  1030   return (int32_t)count;
  1033 NPError
  1034 _destroystream(NPP npp, NPStream *pstream, NPError reason)
  1036   if (!NS_IsMainThread()) {
  1037     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_write called from the wrong thread\n"));
  1038     return NPERR_INVALID_PARAM;
  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;
  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;
  1077   // 'listener' and/or 'streamWrapper' may be invalid (deleted) at this point. Don't
  1078   // touch them again!
  1080   return NPERR_NO_ERROR;
  1083 void
  1084 _status(NPP npp, const char *message)
  1086   if (!NS_IsMainThread()) {
  1087     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_status called from the wrong thread\n"));
  1088     return;
  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;
  1098   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
  1100   PluginDestructionGuard guard(inst);
  1102   inst->ShowStatus(message);
  1105 void
  1106 _memfree (void *ptr)
  1108   if (!NS_IsMainThread()) {
  1109     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memfree called from the wrong thread\n"));
  1111   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFree: ptr=%p\n", ptr));
  1113   if (ptr)
  1114     nsMemory::Free(ptr);
  1117 uint32_t
  1118 _memflush(uint32_t size)
  1120   if (!NS_IsMainThread()) {
  1121     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_memflush called from the wrong thread\n"));
  1123   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemFlush: size=%d\n", size));
  1125   nsMemory::HeapMinimize(true);
  1126   return 0;
  1129 void
  1130 _reloadplugins(NPBool reloadPages)
  1132   if (!NS_IsMainThread()) {
  1133     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_reloadplugins called from the wrong thread\n"));
  1134     return;
  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();
  1146 void
  1147 _invalidaterect(NPP npp, NPRect *invalidRect)
  1149   if (!NS_IsMainThread()) {
  1150     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidaterect called from the wrong thread\n"));
  1151     return;
  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;
  1163   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
  1165   PluginDestructionGuard guard(inst);
  1167   inst->InvalidateRect((NPRect *)invalidRect);
  1170 void
  1171 _invalidateregion(NPP npp, NPRegion invalidRegion)
  1173   if (!NS_IsMainThread()) {
  1174     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invalidateregion called from the wrong thread\n"));
  1175     return;
  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;
  1186   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
  1188   PluginDestructionGuard guard(inst);
  1190   inst->InvalidateRegion((NPRegion)invalidRegion);
  1193 void
  1194 _forceredraw(NPP npp)
  1198 NPObject*
  1199 _getwindowobject(NPP npp)
  1201   if (!NS_IsMainThread()) {
  1202     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getwindowobject called from the wrong thread\n"));
  1203     return nullptr;
  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);
  1218 NPObject*
  1219 _getpluginelement(NPP npp)
  1221   if (!NS_IsMainThread()) {
  1222     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getpluginelement called from the wrong thread\n"));
  1223     return nullptr;
  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);
  1255 NPIdentifier
  1256 _getstringidentifier(const NPUTF8* name)
  1258   if (!name) {
  1259     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifier: passed null name"));
  1260     return nullptr;
  1262   if (!NS_IsMainThread()) {
  1263     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
  1266   AutoSafeJSContext cx;
  1267   return doGetIdentifier(cx, name);
  1270 void
  1271 _getstringidentifiers(const NPUTF8** names, int32_t nameCount,
  1272                       NPIdentifier *identifiers)
  1274   if (!NS_IsMainThread()) {
  1275     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifiers called from the wrong thread\n"));
  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;
  1290 NPIdentifier
  1291 _getintidentifier(int32_t intid)
  1293   if (!NS_IsMainThread()) {
  1294     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n"));
  1296   return IntToNPIdentifier(intid);
  1299 NPUTF8*
  1300 _utf8fromidentifier(NPIdentifier id)
  1302   if (!NS_IsMainThread()) {
  1303     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_utf8fromidentifier called from the wrong thread\n"));
  1305   if (!id)
  1306     return nullptr;
  1308   if (!NPIdentifierIsString(id)) {
  1309     return nullptr;
  1312   JSString *str = NPIdentifierToString(id);
  1314   return
  1315     ToNewUTF8String(nsDependentString(::JS_GetInternedStringChars(str),
  1316                                       ::JS_GetStringLength(str)));
  1319 int32_t
  1320 _intfromidentifier(NPIdentifier id)
  1322   if (!NS_IsMainThread()) {
  1323     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_intfromidentifier called from the wrong thread\n"));
  1326   if (!NPIdentifierIsInt(id)) {
  1327     return INT32_MIN;
  1330   return NPIdentifierToInt(id);
  1333 bool
  1334 _identifierisstring(NPIdentifier id)
  1336   if (!NS_IsMainThread()) {
  1337     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_identifierisstring called from the wrong thread\n"));
  1340   return NPIdentifierIsString(id);
  1343 NPObject*
  1344 _createobject(NPP npp, NPClass* aClass)
  1346   if (!NS_IsMainThread()) {
  1347     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_createobject called from the wrong thread\n"));
  1348     return nullptr;
  1350   if (!npp) {
  1351     NS_ERROR("Null npp passed to _createobject()!");
  1353     return nullptr;
  1356   PluginDestructionGuard guard(npp);
  1358   if (!aClass) {
  1359     NS_ERROR("Null class passed to _createobject()!");
  1361     return nullptr;
  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));
  1374   if (npobj) {
  1375     npobj->_class = aClass;
  1376     npobj->referenceCount = 1;
  1377     NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
  1380   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
  1381                  ("Created NPObject %p, NPClass %p\n", npobj, aClass));
  1383   return npobj;
  1386 NPObject*
  1387 _retainobject(NPObject* npobj)
  1389   if (!NS_IsMainThread()) {
  1390     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_retainobject called from the wrong thread\n"));
  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));
  1400   return npobj;
  1403 void
  1404 _releaseobject(NPObject* npobj)
  1406   if (!NS_IsMainThread()) {
  1407     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releaseobject called from the wrong thread\n"));
  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);
  1429 bool
  1430 _invoke(NPP npp, NPObject* npobj, NPIdentifier method, const NPVariant *args,
  1431         uint32_t argCount, NPVariant *result)
  1433   if (!NS_IsMainThread()) {
  1434     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invoke called from the wrong thread\n"));
  1435     return false;
  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);
  1452 bool
  1453 _invokeDefault(NPP npp, NPObject* npobj, const NPVariant *args,
  1454                uint32_t argCount, NPVariant *result)
  1456   if (!NS_IsMainThread()) {
  1457     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_invokedefault called from the wrong thread\n"));
  1458     return false;
  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);
  1473 bool
  1474 _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result)
  1476   if (!NS_IsMainThread()) {
  1477     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_evaluate called from the wrong thread\n"));
  1478     return false;
  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;
  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;
  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);
  1511   if (!script || !script->UTF8Length || !script->UTF8Characters) {
  1512     // Nothing to evaluate.
  1514     return true;
  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;
  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));
  1567 bool
  1568 _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
  1569              NPVariant *result)
  1571   if (!NS_IsMainThread()) {
  1572     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getproperty called from the wrong thread\n"));
  1573     return false;
  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;
  1635   } else {
  1636     return true;
  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;
  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;
  1673 bool
  1674 _setproperty(NPP npp, NPObject* npobj, NPIdentifier property,
  1675              const NPVariant *value)
  1677   if (!NS_IsMainThread()) {
  1678     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setproperty called from the wrong thread\n"));
  1679     return false;
  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);
  1694 bool
  1695 _removeproperty(NPP npp, NPObject* npobj, NPIdentifier property)
  1697   if (!NS_IsMainThread()) {
  1698     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_removeproperty called from the wrong thread\n"));
  1699     return false;
  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);
  1714 bool
  1715 _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName)
  1717   if (!NS_IsMainThread()) {
  1718     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasproperty called from the wrong thread\n"));
  1719     return false;
  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);
  1734 bool
  1735 _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName)
  1737   if (!NS_IsMainThread()) {
  1738     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_hasmethod called from the wrong thread\n"));
  1739     return false;
  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);
  1754 bool
  1755 _enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
  1756            uint32_t *count)
  1758   if (!NS_IsMainThread()) {
  1759     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_enumerate called from the wrong thread\n"));
  1760     return false;
  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;
  1775   NPPExceptionAutoHolder nppExceptionHolder;
  1776   NPPAutoPusher nppPusher(npp);
  1778   return npobj->_class->enumerate(npobj, identifier, count);
  1781 bool
  1782 _construct(NPP npp, NPObject* npobj, const NPVariant *args,
  1783                uint32_t argCount, NPVariant *result)
  1785   if (!NS_IsMainThread()) {
  1786     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_construct called from the wrong thread\n"));
  1787     return false;
  1789   if (!npp || !npobj || !npobj->_class ||
  1790       !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) ||
  1791       !npobj->_class->construct) {
  1792     return false;
  1795   NPPExceptionAutoHolder nppExceptionHolder;
  1796   NPPAutoPusher nppPusher(npp);
  1798   return npobj->_class->construct(npobj, args, argCount, result);
  1801 void
  1802 _releasevariantvalue(NPVariant* variant)
  1804   if (!NS_IsMainThread()) {
  1805     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releasevariantvalue called from the wrong thread\n"));
  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 :
  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;
  1836 #else
  1837         NS_Free((void *)s->UTF8Characters);
  1838 #endif
  1840       break;
  1842   case NPVariantType_Object:
  1844       NPObject *npobj = NPVARIANT_TO_OBJECT(*variant);
  1846       if (npobj)
  1847         _releaseobject(npobj);
  1849       break;
  1851   default:
  1852     NS_ERROR("Unknown NPVariant type!");
  1855   VOID_TO_NPVARIANT(*variant);
  1858 void
  1859 _setexception(NPObject* npobj, const NPUTF8 *message)
  1861   if (!NS_IsMainThread()) {
  1862     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setexception called from the wrong thread\n"));
  1863     return;
  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);
  1874   gNPPException = strdup(message);
  1877 NPError
  1878 _getvalue(NPP npp, NPNVariable variable, void *result)
  1880   if (!NS_IsMainThread()) {
  1881     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalue called from the wrong thread\n"));
  1882     return NPERR_INVALID_PARAM;
  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;
  1914       if (windowless || needsXEmbed) {
  1915         (*(Display **)result) = mozilla::DefaultXDisplay();
  1916         return NPERR_NO_ERROR;
  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);
  1929     (*(Display **)result) =  GTK_XTBIN(gtkXtBinHolder)->xtdisplay;
  1930     return NPERR_NO_ERROR;
  1931 #endif
  1932 #endif
  1933     return NPERR_GENERIC_ERROR;
  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;
  1953     return NPERR_GENERIC_ERROR;
  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;
  1964     return NPERR_NO_ERROR;
  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;
  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;
  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;
  2013   case NPNVWindowNPObject: {
  2014     *(NPObject **)result = _getwindowobject(npp);
  2016     return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
  2019   case NPNVPluginElementNPObject: {
  2020     *(NPObject **)result = _getpluginelement(npp);
  2022     return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
  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;
  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;
  2048   case NPNVdocumentOrigin: {
  2049     nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
  2050     if (!inst) {
  2051       return NPERR_GENERIC_ERROR;
  2054     nsCOMPtr<nsIDOMElement> element;
  2055     inst->GetDOMElement(getter_AddRefs(element));
  2056     if (!element) {
  2057       return NPERR_GENERIC_ERROR;
  2060     nsCOMPtr<nsIContent> content(do_QueryInterface(element));
  2061     if (!content) {
  2062       return NPERR_GENERIC_ERROR;
  2065     nsIPrincipal* principal = content->NodePrincipal();
  2067     nsAutoString utf16Origin;
  2068     res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
  2069     if (NS_FAILED(res)) {
  2070       return NPERR_GENERIC_ERROR;
  2073     nsCOMPtr<nsIUnicodeNormalizer> normalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
  2074     if (!normalizer) {
  2075       return NPERR_GENERIC_ERROR;
  2078     nsAutoString normalizedUTF16Origin;
  2079     res = normalizer->NormalizeUnicodeNFKC(utf16Origin, normalizedUTF16Origin);
  2080     if (NS_FAILED(res)) {
  2081       return NPERR_GENERIC_ERROR;
  2084     *(char**)result = ToNewUTF8String(normalizedUTF16Origin);
  2085     return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
  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;
  2099     else {
  2100       return NPERR_GENERIC_ERROR;
  2104 #ifndef NP_NO_QUICKDRAW
  2105   case NPNVsupportsQuickDrawBool: {
  2106     *(NPBool*)result = false;
  2108     return NPERR_NO_ERROR;
  2110 #endif
  2112   case NPNVsupportsCoreGraphicsBool: {
  2113     *(NPBool*)result = true;
  2115     return NPERR_NO_ERROR;
  2118   case NPNVsupportsCoreAnimationBool: {
  2119     *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
  2121     return NPERR_NO_ERROR;
  2124   case NPNVsupportsInvalidatingCoreAnimationBool: {
  2125     *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
  2127     return NPERR_NO_ERROR;
  2130   case NPNVsupportsCompositingCoreAnimationPluginsBool: {
  2131     *(NPBool*)result = PR_TRUE;
  2133     return NPERR_NO_ERROR;
  2136 #ifndef NP_NO_CARBON
  2137   case NPNVsupportsCarbonBool: {
  2138     *(NPBool*)result = false;
  2140     return NPERR_NO_ERROR;
  2142 #endif
  2143   case NPNVsupportsCocoaBool: {
  2144     *(NPBool*)result = true;
  2146     return NPERR_NO_ERROR;
  2149   case NPNVsupportsUpdatedCocoaTextInputBool: {
  2150     *(NPBool*)result = true;
  2151     return NPERR_NO_ERROR;
  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;
  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;
  2171     case kBitmapInterfaceV0_ANPGetValue: {
  2172       LOG("get bitmap interface");
  2173       ANPBitmapInterfaceV0 *i = (ANPBitmapInterfaceV0 *) result;
  2174       InitBitmapInterface(i);
  2175       return NPERR_NO_ERROR;
  2178     case kMatrixInterfaceV0_ANPGetValue: {
  2179       LOG("get matrix interface");
  2180       ANPMatrixInterfaceV0 *i = (ANPMatrixInterfaceV0 *) result;
  2181       InitMatrixInterface(i);
  2182       return NPERR_NO_ERROR;
  2185     case kPathInterfaceV0_ANPGetValue: {
  2186       LOG("get path interface");
  2187       ANPPathInterfaceV0 *i = (ANPPathInterfaceV0 *) result;
  2188       InitPathInterface(i);
  2189       return NPERR_NO_ERROR;
  2192     case kTypefaceInterfaceV0_ANPGetValue: {
  2193       LOG("get typeface interface");
  2194       ANPTypefaceInterfaceV0 *i = (ANPTypefaceInterfaceV0 *) result;
  2195       InitTypeFaceInterface(i);
  2196       return NPERR_NO_ERROR;
  2199     case kPaintInterfaceV0_ANPGetValue: {
  2200       LOG("get paint interface");
  2201       ANPPaintInterfaceV0 *i = (ANPPaintInterfaceV0 *) result;
  2202       InitPaintInterface(i);
  2203       return NPERR_NO_ERROR;
  2206     case kCanvasInterfaceV0_ANPGetValue: {
  2207       LOG("get canvas interface");
  2208       ANPCanvasInterfaceV0 *i = (ANPCanvasInterfaceV0 *) result;
  2209       InitCanvasInterface(i);
  2210       return NPERR_NO_ERROR;
  2213     case kWindowInterfaceV0_ANPGetValue: {
  2214       LOG("get window interface");
  2215       ANPWindowInterfaceV0 *i = (ANPWindowInterfaceV0 *) result;
  2216       InitWindowInterface(i);
  2217       return NPERR_NO_ERROR;
  2220     case kAudioTrackInterfaceV0_ANPGetValue: {
  2221       LOG("get audio interface");
  2222       ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result;
  2223       InitAudioTrackInterfaceV0(i);
  2224       return NPERR_NO_ERROR;
  2227     case kEventInterfaceV0_ANPGetValue: {
  2228       LOG("get event interface");
  2229       ANPEventInterfaceV0 *i = (ANPEventInterfaceV0 *) result;
  2230       InitEventInterface(i);
  2231       return NPERR_NO_ERROR;
  2234     case kSystemInterfaceV0_ANPGetValue: {
  2235       LOG("get system interface");
  2236       ANPSystemInterfaceV0* i = reinterpret_cast<ANPSystemInterfaceV0*>(result);
  2237       InitSystemInterface(i);
  2238       return NPERR_NO_ERROR;
  2241     case kSurfaceInterfaceV0_ANPGetValue: {
  2242       LOG("get surface interface");
  2243       ANPSurfaceInterfaceV0 *i = (ANPSurfaceInterfaceV0 *) result;
  2244       InitSurfaceInterface(i);
  2245       return NPERR_NO_ERROR;
  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;
  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;
  2265     case kAudioTrackInterfaceV1_ANPGetValue: {
  2266       LOG("get audio interface v1");
  2267       ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
  2268       InitAudioTrackInterfaceV1(i);
  2269       return NPERR_NO_ERROR;
  2272     case kNativeWindowInterfaceV0_ANPGetValue: {
  2273       LOG("get native window interface v0");
  2274       ANPNativeWindowInterfaceV0* i = (ANPNativeWindowInterfaceV0 *) result;
  2275       InitNativeWindowInterface(i);
  2276       return NPERR_NO_ERROR;
  2279     case kOpenGLInterfaceV0_ANPGetValue: {
  2280       LOG("get openGL interface");
  2281       ANPOpenGLInterfaceV0 *i = (ANPOpenGLInterfaceV0*) result;
  2282       InitOpenGLInterface(i);
  2283       return NPERR_NO_ERROR;
  2286     case kWindowInterfaceV1_ANPGetValue: {
  2287       LOG("get Window interface V1");
  2288       ANPWindowInterfaceV1 *i = (ANPWindowInterfaceV1 *) result;
  2289       InitWindowInterfaceV1(i);
  2290       return NPERR_NO_ERROR;
  2293     case kWindowInterfaceV2_ANPGetValue: {
  2294       LOG("get Window interface V2");
  2295       ANPWindowInterfaceV2 *i = (ANPWindowInterfaceV2 *) result;
  2296       InitWindowInterfaceV2(i);
  2297       return NPERR_NO_ERROR;
  2300     case kVideoInterfaceV0_ANPGetValue: {
  2301       LOG("get video interface");
  2302       ANPVideoInterfaceV0 *i = (ANPVideoInterfaceV0*) result;
  2303       InitVideoInterfaceV0(i);
  2304       return NPERR_NO_ERROR;
  2307     case kVideoInterfaceV1_ANPGetValue: {
  2308       LOG("get video interface");
  2309       ANPVideoInterfaceV1 *i = (ANPVideoInterfaceV1*) result;
  2310       InitVideoInterfaceV1(i);
  2311       return NPERR_NO_ERROR;
  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;
  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;
  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;
  2347 NPError
  2348 _setvalue(NPP npp, NPPVariable variable, void *result)
  2350   if (!NS_IsMainThread()) {
  2351     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setvalue called from the wrong thread\n"));
  2352     return NPERR_INVALID_PARAM;
  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
  2386     case NPPVpluginTransparentBool: {
  2387       NPBool bTransparent = (result != nullptr);
  2388       return inst->SetTransparent(bTransparent);
  2391     case NPPVjavascriptPushCallerBool: {
  2392       return NPERR_NO_ERROR;
  2395     case NPPVpluginKeepLibraryInMemory: {
  2396       NPBool bCached = (result != nullptr);
  2397       inst->SetCached(bCached);
  2398       return NPERR_NO_ERROR;
  2401     case NPPVpluginUsesDOMForCursorBool: {
  2402       bool useDOMForCursor = (result != nullptr);
  2403       return inst->SetUsesDOMForCursor(useDOMForCursor);
  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;
  2413       else {
  2414         return NPERR_GENERIC_ERROR;
  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;
  2425       else {
  2426         return NPERR_GENERIC_ERROR;
  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;
  2443 NPError
  2444 _requestread(NPStream *pstream, NPByteRange *rangeList)
  2446   if (!NS_IsMainThread()) {
  2447     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_requestread called from the wrong thread\n"));
  2448     return NPERR_INVALID_PARAM;
  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;
  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;
  2488 // Deprecated, only stubbed out
  2489 void* /* OJI type: JRIEnv* */
  2490 _getJavaEnv()
  2492   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
  2493   return nullptr;
  2496 const char *
  2497 _useragent(NPP npp)
  2499   if (!NS_IsMainThread()) {
  2500     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_useragent called from the wrong thread\n"));
  2501     return nullptr;
  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;
  2511   const char *retstr;
  2512   nsresult rv = pluginHost->UserAgent(&retstr);
  2513   if (NS_FAILED(rv))
  2514     return nullptr;
  2516   return retstr;
  2519 void *
  2520 _memalloc (uint32_t size)
  2522   if (!NS_IsMainThread()) {
  2523     NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN_memalloc called from the wrong thread\n"));
  2525   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemAlloc: size=%d\n", size));
  2526   return nsMemory::Alloc(size);
  2529 // Deprecated, only stubbed out
  2530 void* /* OJI type: jref */
  2531 _getJavaPeer(NPP npp)
  2533   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
  2534   return nullptr;
  2537 void
  2538 _pushpopupsenabledstate(NPP npp, NPBool enabled)
  2540   if (!NS_IsMainThread()) {
  2541     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_pushpopupsenabledstate called from the wrong thread\n"));
  2542     return;
  2544   nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
  2545   if (!inst)
  2546     return;
  2548   inst->PushPopupsEnabledState(enabled);
  2551 void
  2552 _poppopupsenabledstate(NPP npp)
  2554   if (!NS_IsMainThread()) {
  2555     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_poppopupsenabledstate called from the wrong thread\n"));
  2556     return;
  2558   nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
  2559   if (!inst)
  2560     return;
  2562   inst->PopPopupsEnabledState();
  2565 void
  2566 _pluginthreadasynccall(NPP instance, PluginThreadCallback func, void *userData)
  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"));
  2573   nsRefPtr<nsPluginThreadRunnable> evt =
  2574     new nsPluginThreadRunnable(instance, func, userData);
  2576   if (evt && evt->IsValid()) {
  2577     NS_DispatchToMainThread(evt);
  2581 NPError
  2582 _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
  2583                 char **value, uint32_t *len)
  2585   if (!instance) {
  2586     return NPERR_INVALID_PARAM;
  2589   if (!url || !*url || !len) {
  2590     return NPERR_INVALID_URL;
  2593   *len = 0;
  2595   switch (variable) {
  2596   case NPNURLVProxy:
  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;
  2604       break;
  2606   case NPNURLVCookie:
  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;
  2620       nsCOMPtr<nsIChannel> channel = GetChannelFromNPP(instance);
  2622       if (NS_FAILED(cookieService->GetCookieString(uri, channel, value)) ||
  2623           !*value) {
  2624         return NPERR_GENERIC_ERROR;
  2627       *len = strlen(*value);
  2628       return NPERR_NO_ERROR;
  2631     break;
  2632   default:
  2633     // Fall through and return an error...
  2637   return NPERR_GENERIC_ERROR;
  2640 NPError
  2641 _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
  2642                 const char *value, uint32_t len)
  2644   if (!instance) {
  2645     return NPERR_INVALID_PARAM;
  2648   if (!url || !*url) {
  2649     return NPERR_INVALID_URL;
  2652   switch (variable) {
  2653   case NPNURLVCookie:
  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;
  2683     break;
  2684   case NPNURLVProxy:
  2685     // We don't support setting proxy values, fall through...
  2686   default:
  2687     // Fall through and return an error...
  2691   return NPERR_GENERIC_ERROR;
  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)
  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;
  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;
  2753 uint32_t
  2754 _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc)
  2756   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2757   if (!inst)
  2758     return 0;
  2760   return inst->ScheduleTimer(interval, repeat, timerFunc);
  2763 void
  2764 _unscheduletimer(NPP instance, uint32_t timerID)
  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);
  2779 NPError
  2780 _popupcontextmenu(NPP instance, NPMenu* menu)
  2782   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2783   if (!inst)
  2784     return NPERR_GENERIC_ERROR;
  2786   return inst->PopUpContextMenu(menu);
  2789 NPError
  2790 _initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface)
  2792   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2793   if (!inst)
  2794     return NPERR_GENERIC_ERROR;
  2796   return inst->InitAsyncSurface(size, format, initData, surface);
  2799 NPError
  2800 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface)
  2802   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2803   if (!inst)
  2804     return NPERR_GENERIC_ERROR;
  2806   return inst->FinalizeAsyncSurface(surface);
  2809 void
  2810 _setcurrentasyncsurface(NPP instance, NPAsyncSurface *surface, NPRect *changed)
  2812   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2813   if (!inst)
  2814     return;
  2816   inst->SetCurrentAsyncSurface(surface, changed);
  2819 NPBool
  2820 _convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
  2822   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2823   if (!inst)
  2824     return false;
  2826   return inst->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
  2829 void
  2830 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
  2832   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
  2833   if (!inst) {
  2834     return;
  2837   inst->URLRedirectResponse(notifyData, allow);
  2840 } /* namespace parent */
  2841 } /* namespace plugins */
  2842 } /* namespace mozilla */

mercurial