Bug 1171453 - Make ParentNPObjects aware of AsyncNPObject wrappers. r=jimm, a=abillings
authorAaron Klotz <aklotz@mozilla.com>
Wed, 10 Jun 2015 12:20:56 -0600
changeset 266249 7898db26f3f8
parent 266248 056a30240fae
child 266250 aaf1311249a8
push id4800
push userryanvm@gmail.com
push date2015-06-12 15:43 +0000
treeherdermozilla-beta@aaf1311249a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, abillings
bugs1171453
milestone39.0
Bug 1171453 - Make ParentNPObjects aware of AsyncNPObject wrappers. r=jimm, a=abillings
dom/plugins/ipc/PluginAsyncSurrogate.cpp
dom/plugins/ipc/PluginAsyncSurrogate.h
dom/plugins/ipc/PluginScriptableObjectParent.cpp
dom/plugins/ipc/PluginScriptableObjectParent.h
--- a/dom/plugins/ipc/PluginAsyncSurrogate.cpp
+++ b/dom/plugins/ipc/PluginAsyncSurrogate.cpp
@@ -31,36 +31,45 @@ AsyncNPObject::AsyncNPObject(PluginAsync
   , mSurrogate(aSurrogate)
   , mRealObject(nullptr)
 {
 }
 
 AsyncNPObject::~AsyncNPObject()
 {
   if (mRealObject) {
+    --mRealObject->asyncWrapperCount;
     parent::_releaseobject(mRealObject);
     mRealObject = nullptr;
   }
 }
 
 NPObject*
 AsyncNPObject::GetRealObject()
 {
   if (mRealObject) {
     return mRealObject;
   }
   PluginInstanceParent* instance = PluginInstanceParent::Cast(mSurrogate->GetNPP());
   if (!instance) {
     return nullptr;
   }
+  NPObject* realObject = nullptr;
   NPError err = instance->NPP_GetValue(NPPVpluginScriptableNPObject,
-                                       &mRealObject);
+                                       &realObject);
   if (err != NPERR_NO_ERROR) {
     return nullptr;
   }
+  if (realObject->_class != PluginScriptableObjectParent::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    parent::_releaseobject(realObject);
+    return nullptr;
+  }
+  mRealObject = static_cast<ParentNPObject*>(realObject);
+  ++mRealObject->asyncWrapperCount;
   return mRealObject;
 }
 
 class MOZ_STACK_CLASS RecursionGuard
 {
 public:
   RecursionGuard()
     : mIsRecursive(sHasEntered)
--- a/dom/plugins/ipc/PluginAsyncSurrogate.h
+++ b/dom/plugins/ipc/PluginAsyncSurrogate.h
@@ -16,16 +16,17 @@
 #include "nsPluginHost.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "PluginDataResolver.h"
 
 namespace mozilla {
 namespace plugins {
 
+struct ParentNPObject;
 class PluginInstanceParent;
 class PluginModuleParent;
 
 class PluginAsyncSurrogate : public PluginDataResolver
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(PluginAsyncSurrogate)
 
@@ -163,17 +164,17 @@ private:
 struct AsyncNPObject : NPObject
 {
   explicit AsyncNPObject(PluginAsyncSurrogate* aSurrogate);
   ~AsyncNPObject();
 
   NPObject* GetRealObject();
 
   nsRefPtr<PluginAsyncSurrogate>  mSurrogate;
-  NPObject*                       mRealObject;
+  ParentNPObject*                 mRealObject;
 };
 
 class MOZ_STACK_CLASS PushSurrogateAcceptCalls
 {
 public:
   explicit PushSurrogateAcceptCalls(PluginInstanceParent* aInstance);
   ~PushSurrogateAcceptCalls();
 
--- a/dom/plugins/ipc/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/ipc/PluginScriptableObjectParent.cpp
@@ -161,16 +161,25 @@ void
 PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
 {
   if (aObject->_class != GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
+
+  if (object->asyncWrapperCount > 0) {
+    // In this case we should just drop the refcount to the asyncWrapperCount
+    // instead of deallocating because there are still some async wrappers
+    // out there that are referencing this object.
+    object->referenceCount = object->asyncWrapperCount;
+    return;
+  }
+
   PluginScriptableObjectParent* actor = object->parent;
   if (actor) {
     NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
     actor->DropNPObject();
   }
 
   delete object;
 }
--- a/dom/plugins/ipc/PluginScriptableObjectParent.h
+++ b/dom/plugins/ipc/PluginScriptableObjectParent.h
@@ -18,22 +18,27 @@ namespace plugins {
 
 class PluginAsyncSurrogate;
 class PluginInstanceParent;
 class PluginScriptableObjectParent;
 
 struct ParentNPObject : NPObject
 {
   ParentNPObject()
-    : NPObject(), parent(nullptr), invalidated(false) { }
+    : NPObject()
+    , parent(nullptr)
+    , invalidated(false)
+    , asyncWrapperCount(0)
+  {}
 
   // |parent| is always valid as long as the actor is alive. Once the actor is
   // destroyed this will be set to null.
   PluginScriptableObjectParent* parent;
   bool invalidated;
+  int32_t asyncWrapperCount;
 };
 
 class PluginScriptableObjectParent : public PPluginScriptableObjectParent
 {
   friend class PluginInstanceParent;
 
 public:
   explicit PluginScriptableObjectParent(ScriptableObjectType aType);