dom/plugins/base/nsNPAPIPluginInstance.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 "mozilla/DebugOnly.h"
     8 #ifdef MOZ_WIDGET_ANDROID
     9 // For ScreenOrientation.h and Hal.h
    10 #include "base/basictypes.h"
    11 #endif
    13 #include "prlog.h"
    14 #include "prmem.h"
    15 #include "nscore.h"
    16 #include "prenv.h"
    18 #include "nsNPAPIPluginInstance.h"
    19 #include "nsNPAPIPlugin.h"
    20 #include "nsNPAPIPluginStreamListener.h"
    21 #include "nsPluginHost.h"
    22 #include "nsPluginLogging.h"
    23 #include "nsContentUtils.h"
    24 #include "nsPluginInstanceOwner.h"
    26 #include "nsThreadUtils.h"
    27 #include "nsIDOMElement.h"
    28 #include "nsIDocument.h"
    29 #include "nsIDocShell.h"
    30 #include "nsIScriptGlobalObject.h"
    31 #include "nsIScriptContext.h"
    32 #include "nsDirectoryServiceDefs.h"
    33 #include "nsJSNPRuntime.h"
    34 #include "nsPluginStreamListenerPeer.h"
    35 #include "nsSize.h"
    36 #include "nsNetCID.h"
    37 #include "nsIContent.h"
    38 #include "nsVersionComparator.h"
    39 #include "mozilla/Preferences.h"
    40 #include "mozilla/unused.h"
    41 #include "nsILoadContext.h"
    43 using namespace mozilla;
    45 #ifdef MOZ_WIDGET_ANDROID
    46 #include "ANPBase.h"
    47 #include <android/log.h>
    48 #include "android_npapi.h"
    49 #include "mozilla/Mutex.h"
    50 #include "mozilla/CondVar.h"
    51 #include "AndroidBridge.h"
    52 #include "mozilla/dom/ScreenOrientation.h"
    53 #include "mozilla/Hal.h"
    54 #include "GLContextProvider.h"
    55 #include "GLContext.h"
    56 #include "TexturePoolOGL.h"
    57 #include "GLSharedHandleHelpers.h"
    59 using namespace mozilla::gl;
    61 typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
    63 class PluginEventRunnable : public nsRunnable
    64 {
    65 public:
    66   PluginEventRunnable(nsNPAPIPluginInstance* instance, ANPEvent* event)
    67     : mInstance(instance), mEvent(*event), mCanceled(false) {}
    69   virtual nsresult Run() {
    70     if (mCanceled)
    71       return NS_OK;
    73     mInstance->HandleEvent(&mEvent, nullptr);
    74     mInstance->PopPostedEvent(this);
    75     return NS_OK;
    76   }
    78   void Cancel() { mCanceled = true; }
    79 private:
    80   nsNPAPIPluginInstance* mInstance;
    81   ANPEvent mEvent;
    82   bool mCanceled;
    83 };
    85 static nsRefPtr<GLContext> sPluginContext = nullptr;
    87 static bool EnsureGLContext()
    88 {
    89   if (!sPluginContext) {
    90     gfxIntSize dummySize(16, 16);
    91     sPluginContext = GLContextProvider::CreateOffscreen(dummySize,
    92                                                         GLContext::SurfaceCaps::Any());
    93   }
    95   return sPluginContext != nullptr;
    96 }
    98 class SharedPluginTexture MOZ_FINAL {
    99 public:
   100   NS_INLINE_DECL_REFCOUNTING(SharedPluginTexture)
   102   SharedPluginTexture() : mLock("SharedPluginTexture.mLock")
   103   {
   104   }
   106   nsNPAPIPluginInstance::TextureInfo Lock()
   107   {
   108     if (!EnsureGLContext()) {
   109       mTextureInfo.mTexture = 0;
   110       return mTextureInfo;
   111     }
   113     if (!mTextureInfo.mTexture && sPluginContext->MakeCurrent()) {
   114       sPluginContext->fGenTextures(1, &mTextureInfo.mTexture);
   115     }
   117     mLock.Lock();
   118     return mTextureInfo;
   119   }
   121   void Release(nsNPAPIPluginInstance::TextureInfo& aTextureInfo)
   122   {
   123     mTextureInfo = aTextureInfo;
   124     mLock.Unlock();
   125   }
   127   SharedTextureHandle CreateSharedHandle()
   128   {
   129     MutexAutoLock lock(mLock);
   131     if (!EnsureGLContext())
   132       return 0;
   134     if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
   135       return 0;
   137     SharedTextureHandle handle =
   138       gl::CreateSharedHandle(sPluginContext,
   139                              gl::SharedTextureShareType::SameProcess,
   140                              (void*)mTextureInfo.mTexture,
   141                              gl::SharedTextureBufferType::TextureID);
   143     // We want forget about this now, so delete the texture. Assigning it to zero
   144     // ensures that we create a new one in Lock()
   145     sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
   146     mTextureInfo.mTexture = 0;
   148     return handle;
   149   }
   151 private:
   152   // Private destructor, to discourage deletion outside of Release():
   153   ~SharedPluginTexture()
   154   {
   155   }
   157   nsNPAPIPluginInstance::TextureInfo mTextureInfo;
   159   Mutex mLock;
   160 };
   162 static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
   164 #endif
   166 using namespace mozilla;
   167 using namespace mozilla::plugins::parent;
   168 using namespace mozilla::layers;
   170 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
   172 NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
   174 nsNPAPIPluginInstance::nsNPAPIPluginInstance()
   175   :
   176     mDrawingModel(kDefaultDrawingModel),
   177 #ifdef MOZ_WIDGET_ANDROID
   178     mANPDrawingModel(0),
   179     mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
   180     mWakeLocked(false),
   181     mFullScreen(false),
   182     mInverted(false),
   183 #endif
   184     mRunning(NOT_STARTED),
   185     mWindowless(false),
   186     mTransparent(false),
   187     mCached(false),
   188     mUsesDOMForCursor(false),
   189     mInPluginInitCall(false),
   190     mPlugin(nullptr),
   191     mMIMEType(nullptr),
   192     mOwner(nullptr),
   193     mCurrentPluginEvent(nullptr)
   194 #ifdef MOZ_WIDGET_ANDROID
   195   , mOnScreen(true)
   196 #endif
   197   , mHaveJavaC2PJSObjectQuirk(false)
   198 {
   199   mNPP.pdata = nullptr;
   200   mNPP.ndata = this;
   202   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
   204 #ifdef MOZ_WIDGET_ANDROID
   205   sPluginNPPMap[&mNPP] = this;
   206 #endif
   207 }
   209 nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
   210 {
   211   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
   213 #ifdef MOZ_WIDGET_ANDROID
   214   sPluginNPPMap.erase(&mNPP);
   215 #endif
   217   if (mMIMEType) {
   218     PR_Free((void *)mMIMEType);
   219     mMIMEType = nullptr;
   220   }
   221 }
   223 uint32_t nsNPAPIPluginInstance::gInUnsafePluginCalls = 0;
   225 void
   226 nsNPAPIPluginInstance::Destroy()
   227 {
   228   Stop();
   229   mPlugin = nullptr;
   231 #if MOZ_WIDGET_ANDROID
   232   if (mContentSurface)
   233     mContentSurface->SetFrameAvailableCallback(nullptr);
   235   mContentTexture = nullptr;
   236   mContentSurface = nullptr;
   238   std::map<void*, VideoInfo*>::iterator it;
   239   for (it = mVideos.begin(); it != mVideos.end(); it++) {
   240     it->second->mSurfaceTexture->SetFrameAvailableCallback(nullptr);
   241     delete it->second;
   242   }
   243   mVideos.clear();
   244   SetWakeLock(false);
   245 #endif
   246 }
   248 TimeStamp
   249 nsNPAPIPluginInstance::StopTime()
   250 {
   251   return mStopTime;
   252 }
   254 nsresult nsNPAPIPluginInstance::Initialize(nsNPAPIPlugin *aPlugin, nsPluginInstanceOwner* aOwner, const char* aMIMEType)
   255 {
   256   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this));
   258   NS_ENSURE_ARG_POINTER(aPlugin);
   259   NS_ENSURE_ARG_POINTER(aOwner);
   261   mPlugin = aPlugin;
   262   mOwner = aOwner;
   264   if (aMIMEType) {
   265     mMIMEType = (char*)PR_Malloc(strlen(aMIMEType) + 1);
   266     if (mMIMEType) {
   267       PL_strcpy(mMIMEType, aMIMEType);
   268     }
   269   }
   271   return Start();
   272 }
   274 nsresult nsNPAPIPluginInstance::Stop()
   275 {
   276   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Stop this=%p\n",this));
   278   // Make sure the plugin didn't leave popups enabled.
   279   if (mPopupStates.Length() > 0) {
   280     nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
   282     if (window) {
   283       window->PopPopupControlState(openAbused);
   284     }
   285   }
   287   if (RUNNING != mRunning) {
   288     return NS_OK;
   289   }
   291   // clean up all outstanding timers
   292   for (uint32_t i = mTimers.Length(); i > 0; i--)
   293     UnscheduleTimer(mTimers[i - 1]->id);
   295   // If there's code from this plugin instance on the stack, delay the
   296   // destroy.
   297   if (PluginDestructionGuard::DelayDestroy(this)) {
   298     return NS_OK;
   299   }
   301   // Make sure we lock while we're writing to mRunning after we've
   302   // started as other threads might be checking that inside a lock.
   303   {
   304     AsyncCallbackAutoLock lock;
   305     mRunning = DESTROYING;
   306     mStopTime = TimeStamp::Now();
   307   }
   309   OnPluginDestroy(&mNPP);
   311   // clean up open streams
   312   while (mStreamListeners.Length() > 0) {
   313     nsRefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
   314     currentListener->CleanUpStream(NPRES_USER_BREAK);
   315     mStreamListeners.RemoveElement(currentListener);
   316   }
   318   if (!mPlugin || !mPlugin->GetLibrary())
   319     return NS_ERROR_FAILURE;
   321   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
   323   NPError error = NPERR_GENERIC_ERROR;
   324   if (pluginFunctions->destroy) {
   325     NPSavedData *sdata = 0;
   327     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata), this,
   328                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
   330     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   331                    ("NPP Destroy called: this=%p, npp=%p, return=%d\n", this, &mNPP, error));
   332   }
   333   mRunning = DESTROYED;
   335 #if MOZ_WIDGET_ANDROID
   336   for (uint32_t i = 0; i < mPostedEvents.Length(); i++) {
   337     mPostedEvents[i]->Cancel();
   338   }
   340   mPostedEvents.Clear();
   341 #endif
   343   nsJSNPRuntime::OnPluginDestroy(&mNPP);
   345   if (error != NPERR_NO_ERROR)
   346     return NS_ERROR_FAILURE;
   347   else
   348     return NS_OK;
   349 }
   351 already_AddRefed<nsPIDOMWindow>
   352 nsNPAPIPluginInstance::GetDOMWindow()
   353 {
   354   if (!mOwner)
   355     return nullptr;
   357   nsRefPtr<nsPluginInstanceOwner> deathGrip(mOwner);
   359   nsCOMPtr<nsIDocument> doc;
   360   mOwner->GetDocument(getter_AddRefs(doc));
   361   if (!doc)
   362     return nullptr;
   364   nsRefPtr<nsPIDOMWindow> window = doc->GetWindow();
   366   return window.forget();
   367 }
   369 nsresult
   370 nsNPAPIPluginInstance::GetTagType(nsPluginTagType *result)
   371 {
   372   if (!mOwner) {
   373     return NS_ERROR_FAILURE;
   374   }
   376   return mOwner->GetTagType(result);
   377 }
   379 nsresult
   380 nsNPAPIPluginInstance::GetAttributes(uint16_t& n, const char*const*& names,
   381                                      const char*const*& values)
   382 {
   383   if (!mOwner) {
   384     return NS_ERROR_FAILURE;
   385   }
   387   return mOwner->GetAttributes(n, names, values);
   388 }
   390 nsresult
   391 nsNPAPIPluginInstance::GetParameters(uint16_t& n, const char*const*& names,
   392                                      const char*const*& values)
   393 {
   394   if (!mOwner) {
   395     return NS_ERROR_FAILURE;
   396   }
   398   return mOwner->GetParameters(n, names, values);
   399 }
   401 nsresult
   402 nsNPAPIPluginInstance::GetMode(int32_t *result)
   403 {
   404   if (mOwner)
   405     return mOwner->GetMode(result);
   406   else
   407     return NS_ERROR_FAILURE;
   408 }
   410 nsTArray<nsNPAPIPluginStreamListener*>*
   411 nsNPAPIPluginInstance::StreamListeners()
   412 {
   413   return &mStreamListeners;
   414 }
   416 nsTArray<nsPluginStreamListenerPeer*>*
   417 nsNPAPIPluginInstance::FileCachedStreamListeners()
   418 {
   419   return &mFileCachedStreamListeners;
   420 }
   422 nsresult
   423 nsNPAPIPluginInstance::Start()
   424 {
   425   if (mRunning == RUNNING) {
   426     return NS_OK;
   427   }
   429   PluginDestructionGuard guard(this);
   431   uint16_t count = 0;
   432   const char* const* names = nullptr;
   433   const char* const* values = nullptr;
   434   nsPluginTagType tagtype;
   435   nsresult rv = GetTagType(&tagtype);
   436   if (NS_SUCCEEDED(rv)) {
   437     // Note: If we failed to get the tag type, we may be a full page plugin, so no arguments
   438     rv = GetAttributes(count, names, values);
   439     NS_ENSURE_SUCCESS(rv, rv);
   441     // nsPluginTagType_Object or Applet may also have PARAM tags
   442     // Note: The arrays handed back by GetParameters() are
   443     // crafted specially to be directly behind the arrays from GetAttributes()
   444     // with a null entry as a separator. This is for 4.x backwards compatibility!
   445     // see bug 111008 for details
   446     if (tagtype != nsPluginTagType_Embed) {
   447       uint16_t pcount = 0;
   448       const char* const* pnames = nullptr;
   449       const char* const* pvalues = nullptr;
   450       if (NS_SUCCEEDED(GetParameters(pcount, pnames, pvalues))) {
   451         // Android expects an empty string as the separator instead of null
   452 #ifdef MOZ_WIDGET_ANDROID
   453         NS_ASSERTION(PL_strcmp(values[count], "") == 0, "attribute/parameter array not setup correctly for Android NPAPI plugins");
   454 #else
   455         NS_ASSERTION(!values[count], "attribute/parameter array not setup correctly for NPAPI plugins");
   456 #endif
   457         if (pcount)
   458           count += ++pcount; // if it's all setup correctly, then all we need is to
   459                              // change the count (attrs + PARAM/blank + params)
   460       }
   461     }
   462   }
   464   int32_t       mode;
   465   const char*   mimetype;
   466   NPError       error = NPERR_GENERIC_ERROR;
   468   GetMode(&mode);
   469   GetMIMEType(&mimetype);
   471   CheckJavaC2PJSObjectQuirk(count, names, values);
   473   // Some older versions of Flash have a bug in them
   474   // that causes the stack to become currupt if we
   475   // pass swliveconnect=1 in the NPP_NewProc arrays.
   476   // See bug 149336 (UNIX), bug 186287 (Mac)
   477   //
   478   // The code below disables the attribute unless
   479   // the environment variable:
   480   // MOZILLA_PLUGIN_DISABLE_FLASH_SWLIVECONNECT_HACK
   481   // is set.
   482   //
   483   // It is okay to disable this attribute because
   484   // back in 4.x, scripting required liveconnect to
   485   // start Java which was slow. Scripting no longer
   486   // requires starting Java and is quick plus controled
   487   // from the browser, so Flash now ignores this attribute.
   488   //
   489   // This code can not be put at the time of creating
   490   // the array because we may need to examine the
   491   // stream header to determine we want Flash.
   493   static const char flashMimeType[] = "application/x-shockwave-flash";
   494   static const char blockedParam[] = "swliveconnect";
   495   if (count && !PL_strcasecmp(mimetype, flashMimeType)) {
   496     static int cachedDisableHack = 0;
   497     if (!cachedDisableHack) {
   498        if (PR_GetEnv("MOZILLA_PLUGIN_DISABLE_FLASH_SWLIVECONNECT_HACK"))
   499          cachedDisableHack = -1;
   500        else
   501          cachedDisableHack = 1;
   502     }
   503     if (cachedDisableHack > 0) {
   504       for (uint16_t i=0; i<count; i++) {
   505         if (!PL_strcasecmp(names[i], blockedParam)) {
   506           // BIG FAT WARNIG:
   507           // I'm ugly casting |const char*| to |char*| and altering it
   508           // because I know we do malloc it values in
   509           // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/layout/html/base/src/nsObjectFrame.cpp&rev=1.349&root=/cvsroot#3020
   510           // and free it at line #2096, so it couldn't be a const ptr to string literal
   511           char *val = (char*) values[i];
   512           if (val && *val) {
   513             // we cannot just *val=0, it won't be free properly in such case
   514             val[0] = '0';
   515             val[1] = 0;
   516           }
   517           break;
   518         }
   519       }
   520     }
   521   }
   523   bool oldVal = mInPluginInitCall;
   524   mInPluginInitCall = true;
   526   // Need this on the stack before calling NPP_New otherwise some callbacks that
   527   // the plugin may make could fail (NPN_HasProperty, for example).
   528   NPPAutoPusher autopush(&mNPP);
   530   if (!mPlugin)
   531     return NS_ERROR_FAILURE;
   533   PluginLibrary* library = mPlugin->GetLibrary();
   534   if (!library)
   535     return NS_ERROR_FAILURE;
   537   // Mark this instance as running before calling NPP_New because the plugin may
   538   // call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
   539   // before returning. If the plugin returns failure, we'll clear it out below.
   540   mRunning = RUNNING;
   542   nsresult newResult = library->NPP_New((char*)mimetype, &mNPP, (uint16_t)mode,
   543                                         count, (char**)names, (char**)values,
   544                                         nullptr, &error);
   545   mInPluginInitCall = oldVal;
   547   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   548   ("NPP New called: this=%p, npp=%p, mime=%s, mode=%d, argc=%d, return=%d\n",
   549   this, &mNPP, mimetype, mode, count, error));
   551   if (NS_FAILED(newResult) || error != NPERR_NO_ERROR) {
   552     mRunning = DESTROYED;
   553     nsJSNPRuntime::OnPluginDestroy(&mNPP);
   554     return NS_ERROR_FAILURE;
   555   }
   557   return NS_OK;
   558 }
   560 nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window)
   561 {
   562   // NPAPI plugins don't want a SetWindow(nullptr).
   563   if (!window || RUNNING != mRunning)
   564     return NS_OK;
   566 #if MOZ_WIDGET_GTK
   567   // bug 108347, flash plugin on linux doesn't like window->width <=
   568   // 0, but Java needs wants this call.
   569   if (!nsPluginHost::IsJavaMIMEType(mMIMEType) && window->type == NPWindowTypeWindow &&
   570       (window->width <= 0 || window->height <= 0)) {
   571     return NS_OK;
   572   }
   573 #endif
   575   if (!mPlugin || !mPlugin->GetLibrary())
   576     return NS_ERROR_FAILURE;
   578   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
   580   if (pluginFunctions->setwindow) {
   581     PluginDestructionGuard guard(this);
   583     // XXX Turns out that NPPluginWindow and NPWindow are structurally
   584     // identical (on purpose!), so there's no need to make a copy.
   586     PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",this));
   588     bool oldVal = mInPluginInitCall;
   589     mInPluginInitCall = true;
   591     NPPAutoPusher nppPusher(&mNPP);
   593     DebugOnly<NPError> error;
   594     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setwindow)(&mNPP, (NPWindow*)window), this,
   595                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
   597     mInPluginInitCall = oldVal;
   599     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   600     ("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
   601     this, window->x, window->y, window->width, window->height,
   602     window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, (NPError)error));
   603   }
   604   return NS_OK;
   605 }
   607 nsresult
   608 nsNPAPIPluginInstance::NewStreamFromPlugin(const char* type, const char* target,
   609                                            nsIOutputStream* *result)
   610 {
   611   nsPluginStreamToFile* stream = new nsPluginStreamToFile(target, mOwner);
   612   if (!stream)
   613     return NS_ERROR_OUT_OF_MEMORY;
   615   return stream->QueryInterface(kIOutputStreamIID, (void**)result);
   616 }
   618 nsresult
   619 nsNPAPIPluginInstance::NewStreamListener(const char* aURL, void* notifyData,
   620                                          nsNPAPIPluginStreamListener** listener)
   621 {
   622   nsRefPtr<nsNPAPIPluginStreamListener> sl = new nsNPAPIPluginStreamListener(this, notifyData, aURL);
   624   mStreamListeners.AppendElement(sl);
   626   sl.forget(listener);
   628   return NS_OK;
   629 }
   631 nsresult nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
   632 {
   633   NS_ENSURE_TRUE(platformPrint, NS_ERROR_NULL_POINTER);
   635   PluginDestructionGuard guard(this);
   637   if (!mPlugin || !mPlugin->GetLibrary())
   638     return NS_ERROR_FAILURE;
   640   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
   642   NPPrint* thePrint = (NPPrint *)platformPrint;
   644   // to be compatible with the older SDK versions and to match what
   645   // NPAPI and other browsers do, overwrite |window.type| field with one
   646   // more copy of |platformPrint|. See bug 113264
   647   uint16_t sdkmajorversion = (pluginFunctions->version & 0xff00)>>8;
   648   uint16_t sdkminorversion = pluginFunctions->version & 0x00ff;
   649   if ((sdkmajorversion == 0) && (sdkminorversion < 11)) {
   650     // Let's copy platformPrint bytes over to where it was supposed to be
   651     // in older versions -- four bytes towards the beginning of the struct
   652     // but we should be careful about possible misalignments
   653     if (sizeof(NPWindowType) >= sizeof(void *)) {
   654       void* source = thePrint->print.embedPrint.platformPrint;
   655       void** destination = (void **)&(thePrint->print.embedPrint.window.type);
   656       *destination = source;
   657     } else {
   658       NS_ERROR("Incompatible OS for assignment");
   659     }
   660   }
   662   if (pluginFunctions->print)
   663       NS_TRY_SAFE_CALL_VOID((*pluginFunctions->print)(&mNPP, thePrint), this,
   664                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
   666   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   667   ("NPP PrintProc called: this=%p, pDC=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d]\n",
   668   this,
   669   platformPrint->print.embedPrint.platformPrint,
   670   platformPrint->print.embedPrint.window.x,
   671   platformPrint->print.embedPrint.window.y,
   672   platformPrint->print.embedPrint.window.width,
   673   platformPrint->print.embedPrint.window.height,
   674   platformPrint->print.embedPrint.window.clipRect.top,
   675   platformPrint->print.embedPrint.window.clipRect.bottom,
   676   platformPrint->print.embedPrint.window.clipRect.left,
   677   platformPrint->print.embedPrint.window.clipRect.right));
   679   return NS_OK;
   680 }
   682 nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
   683                                             NSPluginCallReentry aSafeToReenterGecko)
   684 {
   685   if (RUNNING != mRunning)
   686     return NS_OK;
   688   if (!event)
   689     return NS_ERROR_FAILURE;
   691   PluginDestructionGuard guard(this);
   693   if (!mPlugin || !mPlugin->GetLibrary())
   694     return NS_ERROR_FAILURE;
   696   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
   698   int16_t tmpResult = kNPEventNotHandled;
   700   if (pluginFunctions->event) {
   701     mCurrentPluginEvent = event;
   702 #if defined(XP_WIN)
   703     NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this,
   704                             aSafeToReenterGecko);
   705 #else
   706     MAIN_THREAD_JNI_REF_GUARD;
   707     tmpResult = (*pluginFunctions->event)(&mNPP, event);
   708 #endif
   709     NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
   710       ("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n",
   711       this, &mNPP, event, tmpResult));
   713     if (result)
   714       *result = tmpResult;
   715     mCurrentPluginEvent = nullptr;
   716   }
   718   return NS_OK;
   719 }
   721 nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, void* value)
   722 {
   723   if (!mPlugin || !mPlugin->GetLibrary())
   724     return NS_ERROR_FAILURE;
   726   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
   728   nsresult rv = NS_ERROR_FAILURE;
   730   if (pluginFunctions->getvalue && RUNNING == mRunning) {
   731     PluginDestructionGuard guard(this);
   733     NPError pluginError = NPERR_GENERIC_ERROR;
   734     NS_TRY_SAFE_CALL_RETURN(pluginError, (*pluginFunctions->getvalue)(&mNPP, variable, value), this,
   735                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
   736     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   737     ("NPP GetValue called: this=%p, npp=%p, var=%d, value=%d, return=%d\n",
   738     this, &mNPP, variable, value, pluginError));
   740     if (pluginError == NPERR_NO_ERROR) {
   741       rv = NS_OK;
   742     }
   743   }
   745   return rv;
   746 }
   748 nsNPAPIPlugin* nsNPAPIPluginInstance::GetPlugin()
   749 {
   750   return mPlugin;
   751 }
   753 nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP)
   754 {
   755   if (aNPP)
   756     *aNPP = &mNPP;
   757   else
   758     return NS_ERROR_NULL_POINTER;
   760   return NS_OK;
   761 }
   763 NPError nsNPAPIPluginInstance::SetWindowless(bool aWindowless)
   764 {
   765   mWindowless = aWindowless;
   767   if (mMIMEType) {
   768     // bug 558434 - Prior to 3.6.4, we assumed windowless was transparent.
   769     // Silverlight apparently relied on this quirk, so we default to
   770     // transparent unless they specify otherwise after setting the windowless
   771     // property. (Last tested version: sl 4.0).
   772     // Changes to this code should be matched with changes in
   773     // PluginInstanceChild::InitQuirksMode.
   774     NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
   775     if (!PL_strncasecmp(mMIMEType, silverlight.get(), silverlight.Length())) {
   776       mTransparent = true;
   777     }
   778   }
   780   return NPERR_NO_ERROR;
   781 }
   783 NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent)
   784 {
   785   mTransparent = aTransparent;
   786   return NPERR_NO_ERROR;
   787 }
   789 NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(bool aUsesDOMForCursor)
   790 {
   791   mUsesDOMForCursor = aUsesDOMForCursor;
   792   return NPERR_NO_ERROR;
   793 }
   795 bool
   796 nsNPAPIPluginInstance::UsesDOMForCursor()
   797 {
   798   return mUsesDOMForCursor;
   799 }
   801 void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel)
   802 {
   803   mDrawingModel = aModel;
   804 }
   806 void nsNPAPIPluginInstance::RedrawPlugin()
   807 {
   808   mOwner->RedrawPlugin();
   809 }
   811 #if defined(XP_MACOSX)
   812 void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel)
   813 {
   814   // the event model needs to be set for the object frame immediately
   815   if (!mOwner) {
   816     NS_WARNING("Trying to set event model without a plugin instance owner!");
   817     return;
   818   }
   820   mOwner->SetEventModel(aModel);
   821 }
   822 #endif
   824 #if defined(MOZ_WIDGET_ANDROID)
   826 static void SendLifecycleEvent(nsNPAPIPluginInstance* aInstance, uint32_t aAction)
   827 {
   828   ANPEvent event;
   829   event.inSize = sizeof(ANPEvent);
   830   event.eventType = kLifecycle_ANPEventType;
   831   event.data.lifecycle.action = aAction;
   832   aInstance->HandleEvent(&event, nullptr);
   833 }
   835 void nsNPAPIPluginInstance::NotifyForeground(bool aForeground)
   836 {
   837   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetForeground this=%p\n foreground=%d",this, aForeground));
   838   if (RUNNING != mRunning)
   839     return;
   841   SendLifecycleEvent(this, aForeground ? kResume_ANPLifecycleAction : kPause_ANPLifecycleAction);
   842 }
   844 void nsNPAPIPluginInstance::NotifyOnScreen(bool aOnScreen)
   845 {
   846   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetOnScreen this=%p\n onScreen=%d",this, aOnScreen));
   847   if (RUNNING != mRunning || mOnScreen == aOnScreen)
   848     return;
   850   mOnScreen = aOnScreen;
   851   SendLifecycleEvent(this, aOnScreen ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction);
   852 }
   854 void nsNPAPIPluginInstance::MemoryPressure()
   855 {
   856   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::MemoryPressure this=%p\n",this));
   857   if (RUNNING != mRunning)
   858     return;
   860   SendLifecycleEvent(this, kFreeMemory_ANPLifecycleAction);
   861 }
   863 void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen)
   864 {
   865   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::NotifyFullScreen this=%p\n",this));
   867   if (RUNNING != mRunning || mFullScreen == aFullScreen)
   868     return;
   870   mFullScreen = aFullScreen;
   871   SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction);
   873   if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) {
   874     mozilla::widget::android::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
   875   }
   876 }
   878 void nsNPAPIPluginInstance::NotifySize(nsIntSize size)
   879 {
   880   if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() ||
   881       size == mCurrentSize)
   882     return;
   884   mCurrentSize = size;
   886   ANPEvent event;
   887   event.inSize = sizeof(ANPEvent);
   888   event.eventType = kDraw_ANPEventType;
   889   event.data.draw.model = kOpenGL_ANPDrawingModel;
   890   event.data.draw.data.surfaceSize.width = size.width;
   891   event.data.draw.data.surfaceSize.height = size.height;
   893   HandleEvent(&event, nullptr);
   894 }
   896 void nsNPAPIPluginInstance::SetANPDrawingModel(uint32_t aModel)
   897 {
   898   mANPDrawingModel = aModel;
   899 }
   901 void* nsNPAPIPluginInstance::GetJavaSurface()
   902 {
   903   void* surface = nullptr;
   904   nsresult rv = GetValueFromPlugin(kJavaSurface_ANPGetValue, &surface);
   905   if (NS_FAILED(rv))
   906     return nullptr;
   908   return surface;
   909 }
   911 void nsNPAPIPluginInstance::PostEvent(void* event)
   912 {
   913   PluginEventRunnable *r = new PluginEventRunnable(this, (ANPEvent*)event);
   914   mPostedEvents.AppendElement(nsRefPtr<PluginEventRunnable>(r));
   916   NS_DispatchToMainThread(r);
   917 }
   919 void nsNPAPIPluginInstance::SetFullScreenOrientation(uint32_t orientation)
   920 {
   921   if (mFullScreenOrientation == orientation)
   922     return;
   924   uint32_t oldOrientation = mFullScreenOrientation;
   925   mFullScreenOrientation = orientation;
   927   if (mFullScreen) {
   928     // We're already fullscreen so immediately apply the orientation change
   930     if (mFullScreenOrientation != dom::eScreenOrientation_None) {
   931       mozilla::widget::android::GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
   932     } else if (oldOrientation != dom::eScreenOrientation_None) {
   933       // We applied an orientation when we entered fullscreen, but
   934       // we don't want it anymore
   935       mozilla::widget::android::GeckoAppShell::UnlockScreenOrientation();
   936     }
   937   }
   938 }
   940 void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r)
   941 {
   942   mPostedEvents.RemoveElement(r);
   943 }
   945 void nsNPAPIPluginInstance::SetWakeLock(bool aLocked)
   946 {
   947   if (aLocked == mWakeLocked)
   948     return;
   950   mWakeLocked = aLocked;
   951   hal::ModifyWakeLock(NS_LITERAL_STRING("nsNPAPIPluginInstance"),
   952                       mWakeLocked ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE,
   953                       hal::WAKE_LOCK_NO_CHANGE);
   954 }
   956 void nsNPAPIPluginInstance::EnsureSharedTexture()
   957 {
   958   if (!mContentTexture)
   959     mContentTexture = new SharedPluginTexture();
   960 }
   962 GLContext* nsNPAPIPluginInstance::GLContext()
   963 {
   964   if (!EnsureGLContext())
   965     return nullptr;
   967   return sPluginContext;
   968 }
   970 nsNPAPIPluginInstance::TextureInfo nsNPAPIPluginInstance::LockContentTexture()
   971 {
   972   EnsureSharedTexture();
   973   return mContentTexture->Lock();
   974 }
   976 void nsNPAPIPluginInstance::ReleaseContentTexture(nsNPAPIPluginInstance::TextureInfo& aTextureInfo)
   977 {
   978   EnsureSharedTexture();
   979   mContentTexture->Release(aTextureInfo);
   980 }
   982 nsSurfaceTexture* nsNPAPIPluginInstance::CreateSurfaceTexture()
   983 {
   984   if (!EnsureGLContext())
   985     return nullptr;
   987   GLuint texture = TexturePoolOGL::AcquireTexture();
   988   if (!texture)
   989     return nullptr;
   991   nsSurfaceTexture* surface = nsSurfaceTexture::Create(texture);
   992   if (!surface)
   993     return nullptr;
   995   nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
   996   surface->SetFrameAvailableCallback(frameCallback);
   997   return surface;
   998 }
  1000 void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
  1002   if (mRunning == RUNNING && mOwner)
  1003     AndroidBridge::Bridge()->ScheduleComposite();
  1006 void* nsNPAPIPluginInstance::AcquireContentWindow()
  1008   if (!mContentSurface) {
  1009     mContentSurface = CreateSurfaceTexture();
  1011     if (!mContentSurface)
  1012       return nullptr;
  1015   return mContentSurface->GetNativeWindow();
  1018 SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
  1020   if (mContentTexture) {
  1021     return mContentTexture->CreateSharedHandle();
  1022   } else if (mContentSurface) {
  1023     EnsureGLContext();
  1024     return gl::CreateSharedHandle(sPluginContext,
  1025                                   gl::SharedTextureShareType::SameProcess,
  1026                                   mContentSurface,
  1027                                   gl::SharedTextureBufferType::SurfaceTexture);
  1028   } else return 0;
  1031 void* nsNPAPIPluginInstance::AcquireVideoWindow()
  1033   nsSurfaceTexture* surface = CreateSurfaceTexture();
  1034   if (!surface)
  1035     return nullptr;
  1037   VideoInfo* info = new VideoInfo(surface);
  1039   void* window = info->mSurfaceTexture->GetNativeWindow();
  1040   mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
  1042   return window;
  1045 void nsNPAPIPluginInstance::ReleaseVideoWindow(void* window)
  1047   std::map<void*, VideoInfo*>::iterator it = mVideos.find(window);
  1048   if (it == mVideos.end())
  1049     return;
  1051   delete it->second;
  1052   mVideos.erase(window);
  1055 void nsNPAPIPluginInstance::SetVideoDimensions(void* window, gfxRect aDimensions)
  1057   std::map<void*, VideoInfo*>::iterator it;
  1059   it = mVideos.find(window);
  1060   if (it == mVideos.end())
  1061     return;
  1063   it->second->mDimensions = aDimensions;
  1066 void nsNPAPIPluginInstance::GetVideos(nsTArray<VideoInfo*>& aVideos)
  1068   std::map<void*, VideoInfo*>::iterator it;
  1069   for (it = mVideos.begin(); it != mVideos.end(); it++)
  1070     aVideos.AppendElement(it->second);
  1073 void nsNPAPIPluginInstance::SetInverted(bool aInverted)
  1075   if (aInverted == mInverted)
  1076     return;
  1078   mInverted = aInverted;
  1081 nsNPAPIPluginInstance* nsNPAPIPluginInstance::GetFromNPP(NPP npp)
  1083   std::map<NPP, nsNPAPIPluginInstance*>::iterator it;
  1085   it = sPluginNPPMap.find(npp);
  1086   if (it == sPluginNPPMap.end())
  1087     return nullptr;
  1089   return it->second;
  1092 #endif
  1094 nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel)
  1096 #if defined(XP_MACOSX)
  1097   *aModel = (int32_t)mDrawingModel;
  1098   return NS_OK;
  1099 #else
  1100   return NS_ERROR_FAILURE;
  1101 #endif
  1104 nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing)
  1106 #ifdef XP_MACOSX
  1107   if (!mPlugin)
  1108       return NS_ERROR_FAILURE;
  1110   PluginLibrary* library = mPlugin->GetLibrary();
  1111   if (!library)
  1112       return NS_ERROR_FAILURE;
  1114   return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
  1115 #else
  1116   return NS_ERROR_FAILURE;
  1117 #endif
  1120 nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor)
  1122 #ifdef XP_MACOSX
  1123   if (!mPlugin)
  1124       return NS_ERROR_FAILURE;
  1126   PluginLibrary* library = mPlugin->GetLibrary();
  1127   if (!library)
  1128       return NS_ERROR_FAILURE;
  1130   // We only need to call this if the plugin is running OOP.
  1131   if (!library->IsOOP())
  1132       return NS_OK;
  1134   return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
  1135 #else
  1136   return NS_ERROR_FAILURE;
  1137 #endif
  1140 nsresult
  1141 nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
  1143   if (mHaveJavaC2PJSObjectQuirk) {
  1144     return NS_ERROR_FAILURE;
  1147   NPObject *npobj = nullptr;
  1148   nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
  1149   if (NS_FAILED(rv) || !npobj)
  1150     return NS_ERROR_FAILURE;
  1152   *outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
  1154   _releaseobject(npobj);
  1156   return NS_OK;
  1159 void
  1160 nsNPAPIPluginInstance::SetCached(bool aCache)
  1162   mCached = aCache;
  1165 bool
  1166 nsNPAPIPluginInstance::ShouldCache()
  1168   return mCached;
  1171 nsresult
  1172 nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
  1174 #ifdef MOZ_WIDGET_ANDROID
  1175   // On android, pre-honeycomb, all plugins are treated as windowless.
  1176   *isWindowless = true;
  1177 #else
  1178   *isWindowless = mWindowless;
  1179 #endif
  1180   return NS_OK;
  1183 class MOZ_STACK_CLASS AutoPluginLibraryCall
  1185 public:
  1186   AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
  1187     : mThis(aThis), mGuard(aThis), mLibrary(nullptr)
  1189     nsNPAPIPlugin* plugin = mThis->GetPlugin();
  1190     if (plugin)
  1191       mLibrary = plugin->GetLibrary();
  1193   operator bool() { return !!mLibrary; }
  1194   PluginLibrary* operator->() { return mLibrary; }
  1196 private:
  1197   nsNPAPIPluginInstance* mThis;
  1198   PluginDestructionGuard mGuard;
  1199   PluginLibrary* mLibrary;
  1200 };
  1202 nsresult
  1203 nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
  1205   if (RUNNING != mRunning)
  1206     return NS_OK;
  1208   AutoPluginLibraryCall library(this);
  1209   if (!library)
  1210     return NS_ERROR_FAILURE;
  1212   return library->AsyncSetWindow(&mNPP, window);
  1215 nsresult
  1216 nsNPAPIPluginInstance::GetImageContainer(ImageContainer**aContainer)
  1218   *aContainer = nullptr;
  1220   if (RUNNING != mRunning)
  1221     return NS_OK;
  1223   AutoPluginLibraryCall library(this);
  1224   return !library ? NS_ERROR_FAILURE : library->GetImageContainer(&mNPP, aContainer);
  1227 nsresult
  1228 nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize)
  1230   *aSize = nsIntSize(0, 0);
  1232   if (RUNNING != mRunning)
  1233     return NS_OK;
  1235   AutoPluginLibraryCall library(this);
  1236   return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
  1239 nsresult
  1240 nsNPAPIPluginInstance::NotifyPainted(void)
  1242   NS_NOTREACHED("Dead code, shouldn't be called.");
  1243   return NS_ERROR_NOT_IMPLEMENTED;
  1246 nsresult
  1247 nsNPAPIPluginInstance::GetIsOOP(bool* aIsAsync)
  1249   AutoPluginLibraryCall library(this);
  1250   if (!library)
  1251     return NS_ERROR_FAILURE;
  1253   *aIsAsync = library->IsOOP();
  1254   return NS_OK;
  1257 nsresult
  1258 nsNPAPIPluginInstance::SetBackgroundUnknown()
  1260   if (RUNNING != mRunning)
  1261     return NS_OK;
  1263   AutoPluginLibraryCall library(this);
  1264   if (!library)
  1265     return NS_ERROR_FAILURE;
  1267   return library->SetBackgroundUnknown(&mNPP);
  1270 nsresult
  1271 nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
  1272                                              gfxContext** aContext)
  1274   if (RUNNING != mRunning)
  1275     return NS_OK;
  1277   AutoPluginLibraryCall library(this);
  1278   if (!library)
  1279     return NS_ERROR_FAILURE;
  1281   return library->BeginUpdateBackground(&mNPP, *aRect, aContext);
  1284 nsresult
  1285 nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
  1286                                            nsIntRect* aRect)
  1288   if (RUNNING != mRunning)
  1289     return NS_OK;
  1291   AutoPluginLibraryCall library(this);
  1292   if (!library)
  1293     return NS_ERROR_FAILURE;
  1295   return library->EndUpdateBackground(&mNPP, aContext, *aRect);
  1298 nsresult
  1299 nsNPAPIPluginInstance::IsTransparent(bool* isTransparent)
  1301   *isTransparent = mTransparent;
  1302   return NS_OK;
  1305 nsresult
  1306 nsNPAPIPluginInstance::GetFormValue(nsAString& aValue)
  1308   aValue.Truncate();
  1310   char *value = nullptr;
  1311   nsresult rv = GetValueFromPlugin(NPPVformValue, &value);
  1312   if (NS_FAILED(rv) || !value)
  1313     return NS_ERROR_FAILURE;
  1315   CopyUTF8toUTF16(value, aValue);
  1317   // NPPVformValue allocates with NPN_MemAlloc(), which uses
  1318   // nsMemory.
  1319   nsMemory::Free(value);
  1321   return NS_OK;
  1324 nsresult
  1325 nsNPAPIPluginInstance::PushPopupsEnabledState(bool aEnabled)
  1327   nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
  1328   if (!window)
  1329     return NS_ERROR_FAILURE;
  1331   PopupControlState oldState =
  1332     window->PushPopupControlState(aEnabled ? openAllowed : openAbused,
  1333                                   true);
  1335   if (!mPopupStates.AppendElement(oldState)) {
  1336     // Appending to our state stack failed, pop what we just pushed.
  1337     window->PopPopupControlState(oldState);
  1338     return NS_ERROR_FAILURE;
  1341   return NS_OK;
  1344 nsresult
  1345 nsNPAPIPluginInstance::PopPopupsEnabledState()
  1347   int32_t last = mPopupStates.Length() - 1;
  1349   if (last < 0) {
  1350     // Nothing to pop.
  1351     return NS_OK;
  1354   nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
  1355   if (!window)
  1356     return NS_ERROR_FAILURE;
  1358   PopupControlState &oldState = mPopupStates[last];
  1360   window->PopPopupControlState(oldState);
  1362   mPopupStates.RemoveElementAt(last);
  1364   return NS_OK;
  1367 nsresult
  1368 nsNPAPIPluginInstance::GetPluginAPIVersion(uint16_t* version)
  1370   NS_ENSURE_ARG_POINTER(version);
  1372   if (!mPlugin)
  1373     return NS_ERROR_FAILURE;
  1375   if (!mPlugin->GetLibrary())
  1376     return NS_ERROR_FAILURE;
  1378   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
  1380   *version = pluginFunctions->version;
  1382   return NS_OK;
  1385 nsresult
  1386 nsNPAPIPluginInstance::PrivateModeStateChanged(bool enabled)
  1388   if (RUNNING != mRunning)
  1389     return NS_OK;
  1391   PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of private mode state change this=%p\n",this));
  1393   if (!mPlugin || !mPlugin->GetLibrary())
  1394     return NS_ERROR_FAILURE;
  1396   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
  1398   if (!pluginFunctions->setvalue)
  1399     return NS_ERROR_FAILURE;
  1401   PluginDestructionGuard guard(this);
  1403   NPError error;
  1404   NPBool value = static_cast<NPBool>(enabled);
  1405   NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value), this,
  1406                           NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
  1407   return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
  1410 nsresult
  1411 nsNPAPIPluginInstance::IsPrivateBrowsing(bool* aEnabled)
  1413   if (!mOwner)
  1414     return NS_ERROR_FAILURE;
  1416   nsCOMPtr<nsIDocument> doc;
  1417   mOwner->GetDocument(getter_AddRefs(doc));
  1418   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
  1420   nsCOMPtr<nsPIDOMWindow> domwindow = doc->GetWindow();
  1421   NS_ENSURE_TRUE(domwindow, NS_ERROR_FAILURE);
  1423   nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
  1424   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
  1425   *aEnabled = (loadContext && loadContext->UsePrivateBrowsing());
  1426   return NS_OK;
  1429 static void
  1430 PluginTimerCallback(nsITimer *aTimer, void *aClosure)
  1432   nsNPAPITimer* t = (nsNPAPITimer*)aClosure;
  1433   NPP npp = t->npp;
  1434   uint32_t id = t->id;
  1436   PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsNPAPIPluginInstance running plugin timer callback this=%p\n", npp->ndata));
  1438   MAIN_THREAD_JNI_REF_GUARD;
  1439   // Some plugins (Flash on Android) calls unscheduletimer
  1440   // from this callback.
  1441   t->inCallback = true;
  1442   (*(t->callback))(npp, id);
  1443   t->inCallback = false;
  1445   // Make sure we still have an instance and the timer is still alive
  1446   // after the callback.
  1447   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
  1448   if (!inst || !inst->TimerWithID(id, nullptr))
  1449     return;
  1451   // use UnscheduleTimer to clean up if this is a one-shot timer
  1452   uint32_t timerType;
  1453   t->timer->GetType(&timerType);
  1454   if (t->needUnschedule || timerType == nsITimer::TYPE_ONE_SHOT)
  1455     inst->UnscheduleTimer(id);
  1458 nsNPAPITimer*
  1459 nsNPAPIPluginInstance::TimerWithID(uint32_t id, uint32_t* index)
  1461   uint32_t len = mTimers.Length();
  1462   for (uint32_t i = 0; i < len; i++) {
  1463     if (mTimers[i]->id == id) {
  1464       if (index)
  1465         *index = i;
  1466       return mTimers[i];
  1469   return nullptr;
  1472 uint32_t
  1473 nsNPAPIPluginInstance::ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
  1475   if (RUNNING != mRunning)
  1476     return 0;
  1478   nsNPAPITimer *newTimer = new nsNPAPITimer();
  1480   newTimer->inCallback = newTimer->needUnschedule = false;
  1481   newTimer->npp = &mNPP;
  1483   // generate ID that is unique to this instance
  1484   uint32_t uniqueID = mTimers.Length();
  1485   while ((uniqueID == 0) || TimerWithID(uniqueID, nullptr))
  1486     uniqueID++;
  1487   newTimer->id = uniqueID;
  1489   // create new xpcom timer, scheduled correctly
  1490   nsresult rv;
  1491   nsCOMPtr<nsITimer> xpcomTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
  1492   if (NS_FAILED(rv)) {
  1493     delete newTimer;
  1494     return 0;
  1496   const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK : (short)nsITimer::TYPE_ONE_SHOT);
  1497   xpcomTimer->InitWithFuncCallback(PluginTimerCallback, newTimer, interval, timerType);
  1498   newTimer->timer = xpcomTimer;
  1500   // save callback function
  1501   newTimer->callback = timerFunc;
  1503   // add timer to timers array
  1504   mTimers.AppendElement(newTimer);
  1506   return newTimer->id;
  1509 void
  1510 nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID)
  1512   // find the timer struct by ID
  1513   uint32_t index;
  1514   nsNPAPITimer* t = TimerWithID(timerID, &index);
  1515   if (!t)
  1516     return;
  1518   if (t->inCallback) {
  1519     t->needUnschedule = true;
  1520     return;
  1523   // cancel the timer
  1524   t->timer->Cancel();
  1526   // remove timer struct from array
  1527   mTimers.RemoveElementAt(index);
  1529   // delete timer
  1530   delete t;
  1533 // Show the context menu at the location for the current event.
  1534 // This can only be called from within an NPP_SendEvent call.
  1535 NPError
  1536 nsNPAPIPluginInstance::PopUpContextMenu(NPMenu* menu)
  1538   if (mOwner && mCurrentPluginEvent)
  1539     return mOwner->ShowNativeContextMenu(menu, mCurrentPluginEvent);
  1541   return NPERR_GENERIC_ERROR;
  1544 NPBool
  1545 nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
  1546                                     double *destX, double *destY, NPCoordinateSpace destSpace)
  1548   if (mOwner)
  1549     return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
  1551   return false;
  1554 nsresult
  1555 nsNPAPIPluginInstance::GetDOMElement(nsIDOMElement* *result)
  1557   if (!mOwner) {
  1558     *result = nullptr;
  1559     return NS_ERROR_FAILURE;
  1562   return mOwner->GetDOMElement(result);
  1565 nsresult
  1566 nsNPAPIPluginInstance::InvalidateRect(NPRect *invalidRect)
  1568   if (RUNNING != mRunning)
  1569     return NS_OK;
  1571   if (!mOwner)
  1572     return NS_ERROR_FAILURE;
  1574   return mOwner->InvalidateRect(invalidRect);
  1577 nsresult
  1578 nsNPAPIPluginInstance::InvalidateRegion(NPRegion invalidRegion)
  1580   if (RUNNING != mRunning)
  1581     return NS_OK;
  1583   if (!mOwner)
  1584     return NS_ERROR_FAILURE;
  1586   return mOwner->InvalidateRegion(invalidRegion);
  1589 nsresult
  1590 nsNPAPIPluginInstance::GetMIMEType(const char* *result)
  1592   if (!mMIMEType)
  1593     *result = "";
  1594   else
  1595     *result = mMIMEType;
  1597   return NS_OK;
  1600 nsresult
  1601 nsNPAPIPluginInstance::GetJSContext(JSContext* *outContext)
  1603   if (!mOwner)
  1604     return NS_ERROR_FAILURE;
  1606   nsRefPtr<nsPluginInstanceOwner> deathGrip(mOwner);
  1608   *outContext = nullptr;
  1609   nsCOMPtr<nsIDocument> document;
  1611   nsresult rv = mOwner->GetDocument(getter_AddRefs(document));
  1613   if (NS_SUCCEEDED(rv) && document) {
  1614     nsCOMPtr<nsIScriptGlobalObject> global =
  1615       do_QueryInterface(document->GetWindow());
  1617     if (global) {
  1618       nsIScriptContext *context = global->GetContext();
  1620       if (context) {
  1621         *outContext = context->GetNativeContext();
  1626   return rv;
  1629 nsPluginInstanceOwner*
  1630 nsNPAPIPluginInstance::GetOwner()
  1632   return mOwner;
  1635 void
  1636 nsNPAPIPluginInstance::SetOwner(nsPluginInstanceOwner *aOwner)
  1638   mOwner = aOwner;
  1641 nsresult
  1642 nsNPAPIPluginInstance::ShowStatus(const char* message)
  1644   if (mOwner)
  1645     return mOwner->ShowStatus(message);
  1647   return NS_ERROR_FAILURE;
  1650 nsresult
  1651 nsNPAPIPluginInstance::AsyncSetWindow(NPWindow& window)
  1653   return NS_ERROR_NOT_IMPLEMENTED;
  1656 void
  1657 nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData, NPBool allow)
  1659   if (!notifyData) {
  1660     return;
  1663   uint32_t listenerCount = mStreamListeners.Length();
  1664   for (uint32_t i = 0; i < listenerCount; i++) {
  1665     nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
  1666     if (currentListener->GetNotifyData() == notifyData) {
  1667       currentListener->URLRedirectResponse(allow);
  1672 NPError
  1673 nsNPAPIPluginInstance::InitAsyncSurface(NPSize *size, NPImageFormat format,
  1674                                         void *initData, NPAsyncSurface *surface)
  1676   if (mOwner)
  1677     return mOwner->InitAsyncSurface(size, format, initData, surface);
  1679   return NPERR_GENERIC_ERROR;
  1682 NPError
  1683 nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface *surface)
  1685   if (mOwner)
  1686     return mOwner->FinalizeAsyncSurface(surface);
  1688   return NPERR_GENERIC_ERROR;
  1691 void
  1692 nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed)
  1694   if (mOwner)
  1695     mOwner->SetCurrentAsyncSurface(surface, changed);
  1698 class CarbonEventModelFailureEvent : public nsRunnable {
  1699 public:
  1700   nsCOMPtr<nsIContent> mContent;
  1702   CarbonEventModelFailureEvent(nsIContent* aContent)
  1703     : mContent(aContent)
  1704   {}
  1706   ~CarbonEventModelFailureEvent() {}
  1708   NS_IMETHOD Run();
  1709 };
  1711 NS_IMETHODIMP
  1712 CarbonEventModelFailureEvent::Run()
  1714   nsString type = NS_LITERAL_STRING("npapi-carbon-event-model-failure");
  1715   nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
  1716                                        type, true, true);
  1717   return NS_OK;
  1720 void
  1721 nsNPAPIPluginInstance::CarbonNPAPIFailure()
  1723   nsCOMPtr<nsIDOMElement> element;
  1724   GetDOMElement(getter_AddRefs(element));
  1725   if (!element) {
  1726     return;
  1729   nsCOMPtr<nsIContent> content(do_QueryInterface(element));
  1730   if (!content) {
  1731     return;
  1734   nsCOMPtr<nsIRunnable> e = new CarbonEventModelFailureEvent(content);
  1735   nsresult rv = NS_DispatchToCurrentThread(e);
  1736   if (NS_FAILED(rv)) {
  1737     NS_WARNING("Failed to dispatch CarbonEventModelFailureEvent.");
  1741 static bool
  1742 GetJavaVersionFromMimetype(nsPluginTag* pluginTag, nsCString& version)
  1744   for (uint32_t i = 0; i < pluginTag->mMimeTypes.Length(); ++i) {
  1745     nsCString type = pluginTag->mMimeTypes[i];
  1746     nsAutoCString jpi("application/x-java-applet;jpi-version=");
  1748     int32_t idx = type.Find(jpi, false, 0, -1);
  1749     if (idx != 0) {
  1750       continue;
  1753     type.Cut(0, jpi.Length());
  1754     if (type.IsEmpty()) {
  1755       continue;
  1758     type.ReplaceChar('_', '.');
  1759     version = type;
  1760     return true;
  1763   return false;
  1766 void
  1767 nsNPAPIPluginInstance::CheckJavaC2PJSObjectQuirk(uint16_t paramCount,
  1768                                                  const char* const* paramNames,
  1769                                                  const char* const* paramValues)
  1771   if (!mMIMEType || !mPlugin) {
  1772     return;
  1775   nsPluginTagType tagtype;
  1776   nsresult rv = GetTagType(&tagtype);
  1777   if (NS_FAILED(rv) ||
  1778       (tagtype != nsPluginTagType_Applet)) {
  1779     return;
  1782   nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
  1783   if (!pluginHost) {
  1784     return;
  1787   nsPluginTag* pluginTag = pluginHost->TagForPlugin(mPlugin);
  1788   if (!pluginTag ||
  1789       !pluginTag->mIsJavaPlugin) {
  1790     return;
  1793   // check the params for "code" being present and non-empty
  1794   bool haveCodeParam = false;
  1795   bool isCodeParamEmpty = true;
  1797   for (uint16_t i = paramCount; i > 0; --i) {
  1798     if (PL_strcasecmp(paramNames[i - 1], "code") == 0) {
  1799       haveCodeParam = true;
  1800       if (strlen(paramValues[i - 1]) > 0) {
  1801         isCodeParamEmpty = false;
  1803       break;
  1807   // Due to the Java version being specified inconsistently across platforms
  1808   // check the version via the mimetype for choosing specific Java versions
  1809   nsCString javaVersion;
  1810   if (!GetJavaVersionFromMimetype(pluginTag, javaVersion)) {
  1811     return;
  1814   mozilla::Version version = javaVersion.get();
  1816   if (version >= "1.7.0.4") {
  1817     return;
  1820   if (!haveCodeParam && version >= "1.6.0.34" && version < "1.7") {
  1821     return;
  1824   if (haveCodeParam && !isCodeParamEmpty) {
  1825     return;
  1828   mHaveJavaC2PJSObjectQuirk = true;
  1831 double
  1832 nsNPAPIPluginInstance::GetContentsScaleFactor()
  1834   double scaleFactor = 1.0;
  1835   if (mOwner) {
  1836     mOwner->GetContentsScaleFactor(&scaleFactor);
  1838   return scaleFactor;

mercurial