Bug 751885 - Cancel pending events when plugin is destroyed on Android r=blassey a=blassey
authorJames Willcox <jwillcox@mozilla.com>
Fri, 04 May 2012 11:48:41 -0400
changeset 94180 b96241e2daf054c2355a7b8d926c6cdb64a3ad01
parent 94179 4306b3474838c331360b102a173d6f1bb2e1a491
child 94181 4de94a39aef2c70e42d0258b2e7acd3808d2a7fd
push idunknown
push userunknown
push dateunknown
reviewersblassey, blassey
bugs751885
milestone14.0a2
Bug 751885 - Cancel pending events when plugin is destroyed on Android r=blassey a=blassey
dom/plugins/base/android/ANPEvent.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
--- a/dom/plugins/base/android/ANPEvent.cpp
+++ b/dom/plugins/base/android/ANPEvent.cpp
@@ -42,41 +42,24 @@
 #include "nsThreadUtils.h"
 #include "nsNPAPIPluginInstance.h"
 #include "AndroidBridge.h"
 #include "nsNPAPIPlugin.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
 #define ASSIGN(obj, name)   (obj)->name = anp_event_##name
 
-class PluginEventRunnable : public nsRunnable
-{
-public:
-  PluginEventRunnable(NPP inst, ANPEvent* event, NPPluginFuncs* aFuncs)
-    : mInstance(inst), mEvent(*event), mFuncs(aFuncs) {}
-  virtual nsresult Run() {
-    (*mFuncs->event)(mInstance, &mEvent);
-    return NS_OK;
-  }
-private:
-  NPP mInstance;
-  ANPEvent mEvent;
-  NPPluginFuncs* mFuncs;
-};
-
 void
-anp_event_postEvent(NPP inst, const ANPEvent* event)
+anp_event_postEvent(NPP instance, const ANPEvent* event)
 {
   LOG("%s", __PRETTY_FUNCTION__);
 
-  nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(inst->ndata);
-  NPPluginFuncs* pluginFunctions = pinst->GetPlugin()->PluginFuncs();
-  PluginEventRunnable* e = new PluginEventRunnable(inst, const_cast<ANPEvent*>(event), pluginFunctions);
+  nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
+  pinst->PostEvent((void*) event);
   
-  NS_DispatchToMainThread(e);
   LOG("returning from %s", __PRETTY_FUNCTION__);
 }
 
 
 void InitEventInterface(ANPEventInterfaceV0 *i) {
   _assert(i->inSize == sizeof(*i));
   ASSIGN(i, postEvent);
 }
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -65,16 +65,39 @@
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "ANPBase.h"
 #include <android/log.h>
 #include "android_npapi.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/CondVar.h"
 #include "AndroidBridge.h"
+
+class PluginEventRunnable : public nsRunnable
+{
+public:
+  PluginEventRunnable(nsNPAPIPluginInstance* instance, ANPEvent* event)
+    : mInstance(instance), mEvent(*event), mCanceled(false) {}
+
+  virtual nsresult Run() {
+    if (mCanceled)
+      return NS_OK;
+
+    mInstance->HandleEvent(&mEvent, nsnull);
+    mInstance->PopPostedEvent(this);
+    return NS_OK;
+  }
+
+  void Cancel() { mCanceled = true; }
+private:
+  nsNPAPIPluginInstance* mInstance;
+  ANPEvent mEvent;
+  bool mCanceled;
+};
+
 #endif
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
 
@@ -211,16 +234,24 @@ nsresult nsNPAPIPluginInstance::Stop()
 
     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata), this);
 
     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
                    ("NPP Destroy called: this=%p, npp=%p, return=%d\n", this, &mNPP, error));
   }
   mRunning = DESTROYED;
 
+#if MOZ_WIDGET_ANDROID
+  for (PRUint32 i = 0; i < mPostedEvents.Length(); i++) {
+    mPostedEvents[i]->Cancel();
+  }
+
+  mPostedEvents.Clear();
+#endif
+
   nsJSNPRuntime::OnPluginDestroy(&mNPP);
 
   if (error != NPERR_NO_ERROR)
     return NS_ERROR_FAILURE;
   else
     return NS_OK;
 }
 
@@ -788,16 +819,29 @@ void nsNPAPIPluginInstance::RequestJavaS
   if (mSurfaceGetter.get())
     return;
 
   mSurfaceGetter = new SurfaceGetter(this, mPlugin->PluginFuncs(), mNPP);
 
   ((SurfaceGetter*)mSurfaceGetter.get())->RequestSurface();
 }
 
+void nsNPAPIPluginInstance::PostEvent(void* event)
+{
+  PluginEventRunnable *r = new PluginEventRunnable(this, (ANPEvent*)event);
+  mPostedEvents.AppendElement(nsRefPtr<PluginEventRunnable>(r));
+
+  NS_DispatchToMainThread(r);
+}
+
+void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r)
+{
+  mPostedEvents.RemoveElement(r);
+}
+
 #endif
 
 nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel)
 {
 #if defined(XP_MACOSX)
   *aModel = (PRInt32)mDrawingModel;
   return NS_OK;
 #else
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -46,16 +46,17 @@
 #include "nsITimer.h"
 #include "nsIPluginTagInfo.h"
 #include "nsIURI.h"
 #include "nsIChannel.h"
 #include "nsInterfaceHashtable.h"
 #include "nsHashKeys.h"
 #ifdef MOZ_WIDGET_ANDROID
 #include "nsIRunnable.h"
+class PluginEventRunnable;
 #endif
 
 #include "mozilla/TimeStamp.h"
 #include "mozilla/PluginLibrary.h"
 
 struct JSObject;
 
 class nsPluginStreamListenerPeer; // browser-initiated stream class
@@ -95,19 +96,16 @@ public:
   NS_DECL_ISUPPORTS
 
   nsresult Initialize(nsNPAPIPlugin *aPlugin, nsIPluginInstanceOwner* aOwner, const char* aMIMEType);
   nsresult Start();
   nsresult Stop();
   nsresult SetWindow(NPWindow* window);
   nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result);
   nsresult Print(NPPrint* platformPrint);
-#ifdef MOZ_WIDGET_ANDROID
-  nsresult PostEvent(void* event) { return 0; };
-#endif
   nsresult HandleEvent(void* event, PRInt16* result);
   nsresult GetValueFromPlugin(NPPVariable variable, void* value);
   nsresult GetDrawingModel(PRInt32* aModel);
   nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
   nsresult GetJSObject(JSContext *cx, JSObject** outObject);
   nsresult DefineJavaProperties();
   bool ShouldCache();
   nsresult IsWindowless(bool* isWindowless);
@@ -166,16 +164,18 @@ public:
 
   PRUint32 GetANPDrawingModel() { return mANPDrawingModel; }
   void SetANPDrawingModel(PRUint32 aModel);
 
   // This stuff is for kSurface_ANPDrawingModel
   void* GetJavaSurface();
   void SetJavaSurface(void* aSurface);
   void RequestJavaSurface();
+
+  void PostEvent(void* event);
 #endif
 
   nsresult NewStreamListener(const char* aURL, void* notifyData,
                              nsIPluginStreamListener** listener);
 
   nsNPAPIPluginInstance();
   virtual ~nsNPAPIPluginInstance();
 
@@ -245,16 +245,21 @@ protected:
   // the browser.
   NPP_t mNPP;
 
   NPDrawingModel mDrawingModel;
 
 #ifdef MOZ_WIDGET_ANDROID
   PRUint32 mANPDrawingModel;
   nsCOMPtr<nsIRunnable> mSurfaceGetter;
+
+  friend class PluginEventRunnable;
+
+  nsTArray<nsCOMPtr<PluginEventRunnable>> mPostedEvents;
+  void PopPostedEvent(PluginEventRunnable* r);
 #endif
 
   enum {
     NOT_STARTED,
     RUNNING,
     DESTROYING,
     DESTROYED
   } mRunning;