Backout 76cdc8296409 and 9baa220b27c0 (Bug 521377 - 'NPRuntime: Segfault when NPP_GetValue_NPPVpluginScriptableNPObject returns a null actor') to try fo fix orange.
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 19 Jan 2010 13:00:58 +0100
changeset 37307 ffab97de1041b4ef62a31b104dd399033c7c773d
parent 37306 e6fa7005b86abe15cc16fbb7d397409313d336ff
child 37308 784f0004101e3597fc7581c05c203178d3294a1f
push idunknown
push userunknown
push dateunknown
bugs521377
milestone1.9.3a1pre
backs out76cdc829640917cfeddfb7324c761ea9609560fe
Backout 76cdc8296409 and 9baa220b27c0 (Bug 521377 - 'NPRuntime: Segfault when NPP_GetValue_NPPVpluginScriptableNPObject returns a null actor') to try fo fix orange.
dom/plugins/Makefile.in
dom/plugins/PPluginInstance.ipdl
dom/plugins/PPluginScriptableObject.ipdl
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceChild.h
dom/plugins/PluginInstanceParent.cpp
dom/plugins/PluginInstanceParent.h
dom/plugins/PluginMessageUtils.cpp
dom/plugins/PluginMessageUtils.h
dom/plugins/PluginModuleChild.cpp
dom/plugins/PluginModuleChild.h
dom/plugins/PluginModuleParent.cpp
dom/plugins/PluginScriptableObjectChild.cpp
dom/plugins/PluginScriptableObjectChild.h
dom/plugins/PluginScriptableObjectParent.cpp
dom/plugins/PluginScriptableObjectParent.h
dom/plugins/PluginScriptableObjectUtils-inl.h
dom/plugins/PluginScriptableObjectUtils.h
modules/plugin/base/src/nsNPAPIPlugin.cpp
--- a/dom/plugins/Makefile.in
+++ b/dom/plugins/Makefile.in
@@ -64,18 +64,16 @@ EXPORTS_mozilla/plugins = \
   PluginInstanceChild.h \
   PluginInstanceParent.h \
   PluginMessageUtils.h \
   PluginModuleChild.h \
   PluginModuleParent.h \
   PluginProcessParent.h \
   PluginScriptableObjectChild.h \
   PluginScriptableObjectParent.h \
-  PluginScriptableObjectUtils.h \
-  PluginScriptableObjectUtils-inl.h \
   PluginInstanceChild.h \
   PluginInstanceParent.h \
   AStream.h \
   BrowserStreamChild.h \
   BrowserStreamParent.h \
   PluginStreamChild.h \
   PluginStreamParent.h \
   PluginMessageUtils.h \
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -58,17 +58,18 @@ rpc protocol PPluginInstance
   manager PPluginModule;
 
   manages PPluginScriptableObject;
   manages PBrowserStream;
   manages PPluginStream;
   manages PStreamNotify;
 
 child:
-  rpc __delete__();
+  rpc __delete__()
+    returns (NPError rv);
 
   rpc NPP_SetWindow(NPRemoteWindow window)
     returns (NPError rv);
 
   rpc NPP_GetValue_NPPVpluginWindow()
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginTransparent()
     returns (bool value, NPError result);
@@ -76,19 +77,16 @@ child:
   rpc NPP_GetValue_NPPVpluginNeedsXEmbed()
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginScriptableNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
 
   rpc NPP_HandleEvent(NPRemoteEvent event)
     returns (int16_t handled);
 
-  rpc NPP_Destroy()
-    returns (NPError rv);
-
 parent:
   rpc NPN_GetValue_NPNVjavascriptEnabledBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVisOfflineBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVWindowNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
   rpc NPN_GetValue_NPNVPluginElementNPObject()
--- a/dom/plugins/PPluginScriptableObject.ipdl
+++ b/dom/plugins/PPluginScriptableObject.ipdl
@@ -67,21 +67,20 @@ rpc protocol PPluginScriptableObject
 both:
   rpc __delete__();
 
 parent:
   rpc NPN_Evaluate(nsCString aScript)
     returns (Variant aResult,
              bool aSuccess);
 
-child:
+both:
+  // NPClass methods
   rpc Invalidate();
 
-both:
-  // NPClass methods
   rpc HasMethod(NPRemoteIdentifier aId)
     returns (bool aHasMethod);
 
   rpc Invoke(NPRemoteIdentifier aId,
              Variant[] aArgs)
     returns (Variant aResult,
              bool aSuccess);
 
@@ -105,22 +104,12 @@ both:
 
   rpc Enumerate()
     returns (NPRemoteIdentifier[] aProperties,
              bool aSuccess);
 
   rpc Construct(Variant[] aArgs)
     returns (Variant aResult,
              bool aSuccess);
-
-  // Objects are initially unprotected, and the Protect and Unprotect functions
-  // only affect protocol objects that represent NPObjects created in the same
-  // process (rather than protocol objects that are a proxy for an NPObject
-  // created in another process). Protocol objects representing local NPObjects
-  // are protected after an NPObject has been associated with the protocol
-  // object. Sending the protocol object as an argument to the other process
-  // temporarily protects the protocol object again for the duration of the call.
-  rpc Protect();
-  rpc Unprotect();
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -58,45 +58,52 @@ using namespace mozilla::plugins;
 using mozilla::gfx::SharedDIB;
 
 #include <windows.h>
 
 #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
 #endif
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) :
-    mPluginIface(aPluginIface)
+        mPluginIface(aPluginIface)
 #if defined(OS_WIN)
-    , mPluginWindowHWND(0)
-    , mPluginWndProc(0)
-    , mPluginParentHWND(0)
-#endif // OS_WIN
-{
-    memset(&mWindow, 0, sizeof(mWindow));
-    mData.ndata = (void*) this;
+        , mPluginWindowHWND(0)
+        , mPluginWndProc(0)
+        , mPluginParentHWND(0)
+#endif
+    {
+        memset(&mWindow, 0, sizeof(mWindow));
+        mData.ndata = (void*) this;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
-    mWindow.ws_info = &mWsInfo;
-    memset(&mWsInfo, 0, sizeof(mWsInfo));
-#ifdef MOZ_WIDGET_GTK2
-    mWsInfo.display = GDK_DISPLAY();
-#endif // MOZ_WIDGET_GTK2
-#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
+        mWindow.ws_info = &mWsInfo;
+        memset(&mWsInfo, 0, sizeof(mWsInfo));
+#  ifdef MOZ_WIDGET_GTK2
+        mWsInfo.display = GDK_DISPLAY();
+#  endif
+#endif
 #if defined(OS_WIN)
     memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
     mAlphaExtract.doublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
-#endif // OS_WIN
-}
+#endif
+    }
 
 PluginInstanceChild::~PluginInstanceChild()
 {
 #if defined(OS_WIN)
   DestroyPluginWindow();
 #endif
 }
 
+bool
+PluginInstanceChild::Answer__delete__(NPError* rv)
+{
+    return static_cast<PluginModuleChild*>(Manager())->
+        PluginInstanceDestroyed(this, rv);
+}
+
 NPError
 PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
                                   void* aValue)
 {
     PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION, (int) aVar));
     AssertPluginThread();
 
     switch(aVar) {
@@ -162,17 +169,17 @@ PluginInstanceChild::NPN_GetValue(NPNVar
 
         if (result != NPERR_NO_ERROR) {
             return result;
         }
 
         NS_ASSERTION(actor, "Null actor!");
 
         NPObject* object =
-            static_cast<PluginScriptableObjectChild*>(actor)->GetObject(true);
+            static_cast<PluginScriptableObjectChild*>(actor)->GetObject();
         NS_ASSERTION(object, "Null object?!");
 
         PluginModuleChild::sBrowserFuncs.retainobject(object);
         *((NPObject**)aValue) = object;
         return NPERR_NO_ERROR;
     }
 
     case NPNVPluginElementNPObject: {
@@ -185,17 +192,17 @@ PluginInstanceChild::NPN_GetValue(NPNVar
 
         if (result != NPERR_NO_ERROR) {
             return result;
         }
 
         NS_ASSERTION(actor, "Null actor!");
 
         NPObject* object =
-            static_cast<PluginScriptableObjectChild*>(actor)->GetObject(true);
+            static_cast<PluginScriptableObjectChild*>(actor)->GetObject();
         NS_ASSERTION(object, "Null object?!");
 
         PluginModuleChild::sBrowserFuncs.retainobject(object);
         *((NPObject**)aValue) = object;
         return NPERR_NO_ERROR;
     }
 
     case NPNVnetscapeWindow: {
@@ -513,16 +520,40 @@ PluginInstanceChild::AnswerNPP_SetWindow
 }
 
 bool
 PluginInstanceChild::Initialize()
 {
     return true;
 }
 
+void
+PluginInstanceChild::Destroy()
+{
+    // Copy the actors here so we don't enumerate a mutating array.
+    nsAutoTArray<PluginScriptableObjectChild*, 10> objects;
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        objects.AppendElement(mScriptableObjects[index]);
+    }
+
+    count = objects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        PluginScriptableObjectChild*& actor = objects[index];
+        NPObject* object = actor->GetObject();
+        if (object->_class == PluginScriptableObjectChild::GetClass()) {
+          PluginScriptableObjectChild::ScriptableInvalidate(object);
+        }
+    }
+
+#if defined(OS_WIN)
+    SharedSurfaceRelease();
+#endif
+}
+
 #if defined(OS_WIN)
 
 static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow");
 static const TCHAR kPluginInstanceChildProperty[] = TEXT("PluginInstanceChildProperty");
 
 // static
 bool
 PluginInstanceChild::RegisterWindowClass()
@@ -845,52 +876,75 @@ PluginInstanceChild::SharedSurfacePaint(
 }
 
 #endif // OS_WIN
 
 PPluginScriptableObjectChild*
 PluginInstanceChild::AllocPPluginScriptableObject()
 {
     AssertPluginThread();
-    return new PluginScriptableObjectChild(Proxy);
+
+    nsAutoPtr<PluginScriptableObjectChild>* object =
+        mScriptableObjects.AppendElement();
+    NS_ENSURE_TRUE(object, nsnull);
+
+    *object = new PluginScriptableObjectChild();
+    NS_ENSURE_TRUE(*object, nsnull);
+
+    return object->get();
 }
 
 bool
 PluginInstanceChild::DeallocPPluginScriptableObject(
     PPluginScriptableObjectChild* aObject)
 {
     AssertPluginThread();
 
-    PluginScriptableObjectChild* actor =
+    PluginScriptableObjectChild* object =
         reinterpret_cast<PluginScriptableObjectChild*>(aObject);
 
-    NPObject* object = actor->GetObject(false);
-    if (object) {
-        PluginModuleChild::current()->UnregisterNPObject(object);
+    NPObject* npobject = object->GetObject();
+    if (npobject &&
+        npobject->_class != PluginScriptableObjectChild::GetClass()) {
+        PluginModuleChild::current()->UnregisterNPObject(npobject);
     }
 
-    delete actor;
-    return true;
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        if (mScriptableObjects[index] == object) {
+            mScriptableObjects.RemoveElementAt(index);
+            return true;
+        }
+    }
+    NS_NOTREACHED("An actor we don't know about?!");
+    return false;
 }
 
 bool
 PluginInstanceChild::AnswerPPluginScriptableObjectConstructor(
                                            PPluginScriptableObjectChild* aActor)
 {
     AssertPluginThread();
 
     // This is only called in response to the parent process requesting the
     // creation of an actor. This actor will represent an NPObject that is
     // created by the browser and returned to the plugin.
+    NPClass* npclass =
+        const_cast<NPClass*>(PluginScriptableObjectChild::GetClass());
+
+    ChildNPObject* object = reinterpret_cast<ChildNPObject*>(
+        PluginModuleChild::sBrowserFuncs.createobject(GetNPP(), npclass));
+    if (!object) {
+        NS_WARNING("Failed to create NPObject!");
+        return false;
+    }
+
     PluginScriptableObjectChild* actor =
         static_cast<PluginScriptableObjectChild*>(aActor);
-    NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!");
-
-    actor->InitializeProxy();
-    NS_ASSERTION(actor->GetObject(false), "Actor should have an object!");
+    actor->Initialize(const_cast<PluginInstanceChild*>(this), object);
 
     return true;
 }
 
 bool
 PluginInstanceChild::AnswerPBrowserStreamConstructor(
     PBrowserStreamChild* aActor,
     const nsCString& url,
@@ -990,40 +1044,45 @@ PluginInstanceChild::DeallocPStreamNotif
     delete notifyData;
     return true;
 }
 
 PluginScriptableObjectChild*
 PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
 {
     AssertPluginThread();
-    NS_ASSERTION(aObject, "Null pointer!");
+  NS_ASSERTION(aObject, "Null pointer!");
 
-    if (aObject->_class == PluginScriptableObjectChild::GetClass()) {
-        // One of ours! It's a browser-provided object.
-        ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
-        NS_ASSERTION(object->parent, "Null actor!");
-        return object->parent;
-    }
+  if (aObject->_class == PluginScriptableObjectChild::GetClass()) {
+      // One of ours! It's a browser-provided object.
+      ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
+      NS_ASSERTION(object->parent, "Null actor!");
+      return object->parent;
+  }
 
-    PluginScriptableObjectChild* actor =
-        PluginModuleChild::current()->GetActorForNPObject(aObject);
-    if (actor) {
-        // Plugin-provided object that we've previously wrapped.
-        return actor;
-    }
+  PluginScriptableObjectChild* actor =
+      PluginModuleChild::current()->GetActorForNPObject(aObject);
+  if (actor) {
+      // Plugin-provided object that we've previously wrapped.
+      return actor;
+  }
 
-    actor = new PluginScriptableObjectChild(LocalObject);
-    if (!CallPPluginScriptableObjectConstructor(actor)) {
-        NS_ERROR("Failed to send constructor message!");
-        return nsnull;
-    }
+  actor = reinterpret_cast<PluginScriptableObjectChild*>(
+      CallPPluginScriptableObjectConstructor());
+  NS_ENSURE_TRUE(actor, nsnull);
+
+  actor->Initialize(this, aObject);
 
-    actor->InitializeLocal(aObject);
-    return actor;
+#ifdef DEBUG
+  bool ok =
+#endif
+  PluginModuleChild::current()->RegisterNPObject(aObject, actor);
+  NS_ASSERTION(ok, "Out of memory?");
+
+  return actor;
 }
 
 NPError
 PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
                                    NPStream** aStream)
 {
     AssertPluginThread();
 
@@ -1055,21 +1114,8 @@ PluginInstanceChild::InvalidateRect(NPRe
                     aInvalidRect->right, aInvalidRect->bottom };
       ::InvalidateRect(mPluginWindowHWND, &rect, FALSE);
       return;
     }
 #endif
 
     SendNPN_InvalidateRect(*aInvalidRect);
 }
-
-bool
-PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
-{
-    PluginModuleChild* module = PluginModuleChild::current();
-    bool retval = module->PluginInstanceDestroyed(this, aResult);
-
-#if defined(OS_WIN)
-    SharedSurfaceRelease();
-#endif
-
-    return retval;
-}
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -66,32 +66,32 @@ class PluginInstanceChild : public PPlug
                                              UINT message,
                                              WPARAM wParam,
                                              LPARAM lParam);
 #endif
 
 protected:
     virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window, NPError* rv);
 
+    virtual bool Answer__delete__(NPError* rv);
+
+
     virtual bool
     AnswerNPP_GetValue_NPPVpluginWindow(bool* windowed, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginTransparent(bool* transparent, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginScriptableNPObject(PPluginScriptableObjectChild** value,
                                                     NPError* result);
 
     virtual bool
     AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
 
-    virtual bool
-    AnswerNPP_Destroy(NPError* result);
-
     virtual PPluginScriptableObjectChild*
     AllocPPluginScriptableObject();
 
     virtual bool
     DeallocPPluginScriptableObject(PPluginScriptableObjectChild* aObject);
 
     virtual bool
     AnswerPPluginScriptableObjectConstructor(PPluginScriptableObjectChild* aActor);
@@ -141,16 +141,17 @@ protected:
     DeallocPStreamNotify(PStreamNotifyChild* notifyData);
 
 public:
     PluginInstanceChild(const NPPluginFuncs* aPluginIface);
 
     virtual ~PluginInstanceChild();
 
     bool Initialize();
+    void Destroy();
 
     NPP GetNPP()
     {
         return &mData;
     }
 
     NPError
     NPN_GetValue(NPNVariable aVariable, void* aValue);
@@ -185,25 +186,26 @@ private:
                                              UINT message,
                                              WPARAM wParam,
                                              LPARAM lParam);
 #endif
 
     const NPPluginFuncs* mPluginIface;
     NPP_t mData;
     NPWindow mWindow;
-
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     NPSetWindowCallbackStruct mWsInfo;
 #elif defined(OS_WIN)
     HWND mPluginWindowHWND;
     WNDPROC mPluginWndProc;
     HWND mPluginParentHWND;
 #endif
 
+    nsTArray<nsAutoPtr<PluginScriptableObjectChild> > mScriptableObjects;
+
 #if defined(OS_WIN)
 private:
     // Shared dib rendering management for windowless plugins.
     bool SharedSurfaceSetWindow(const NPRemoteWindow& aWindow, NPError* rv);
     int16_t SharedSurfacePaint(NPEvent& evcopy);
     void SharedSurfaceRelease();
     bool AlphaExtractCacheSetup();
     void AlphaExtractCacheRelease();
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginInstanceParent.h"
 
 #include "BrowserStreamParent.h"
 #include "PluginModuleParent.h"
 #include "PluginStreamParent.h"
 #include "StreamNotifyParent.h"
+
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 
 #if defined(OS_WIN)
 #include <windowsx.h>
 #endif
 
 using namespace mozilla::plugins;
@@ -63,50 +64,37 @@ PluginInstanceParent::PluginInstancePare
 }
 
 PluginInstanceParent::~PluginInstanceParent()
 {
     if (mNPP)
         mNPP->pdata = NULL;
 }
 
-bool
-PluginInstanceParent::Init()
-{
-    return !!mScriptableObjects.Init();
-}
-
-namespace {
-
-PLDHashOperator
-ActorCollect(const void* aKey,
-             PluginScriptableObjectParent* aData,
-             void* aUserData)
-{
-    nsTArray<PluginScriptableObjectParent*>* objects =
-        reinterpret_cast<nsTArray<PluginScriptableObjectParent*>*>(aUserData);
-    return objects->AppendElement(aData) ? PL_DHASH_NEXT : PL_DHASH_STOP;
-}
-
-} // anonymous namespace
-
-NPError
+void
 PluginInstanceParent::Destroy()
 {
-    NPError retval;
-    if (!CallNPP_Destroy(&retval)) {
-        NS_WARNING("Failed to send message!");
-        return NPERR_GENERIC_ERROR;
+    // Copy the actors here so we don't enumerate a mutating array.
+    nsAutoTArray<PluginScriptableObjectParent*, 10> objects;
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        objects.AppendElement(mScriptableObjects[index]);
+    }
+
+    count = objects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        NPObject* object = objects[index]->GetObject();
+        if (object->_class == PluginScriptableObjectParent::GetClass()) {
+          PluginScriptableObjectParent::ScriptableInvalidate(object);
+        }
     }
 
 #if defined(OS_WIN)
     SharedSurfaceRelease();
 #endif
-
-    return retval;
 }
 
 PBrowserStreamParent*
 PluginInstanceParent::AllocPBrowserStream(const nsCString& url,
                                           const uint32_t& length,
                                           const uint32_t& lastmodified,
                                           PStreamNotifyParent* notifyData,
                                           const nsCString& headers,
@@ -460,17 +448,17 @@ PluginInstanceParent::NPP_GetValue(NPPVa
 
         const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
         if (!npn) {
             NS_WARNING("No netscape functions?!");
             return NPERR_GENERIC_ERROR;
         }
 
         NPObject* object =
-            static_cast<PluginScriptableObjectParent*>(actor)->GetObject(true);
+            static_cast<PluginScriptableObjectParent*>(actor)->GetObject();
         NS_ASSERTION(object, "This shouldn't ever be null!");
 
         (*(NPObject**)_retval) = npn->retainobject(object);
         return NPERR_NO_ERROR;
     }
 
     default:
         PR_LOG(gPluginLog, PR_LOG_WARNING,
@@ -589,147 +577,111 @@ PluginInstanceParent::NPP_DestroyStream(
         PPluginStreamParent::Call__delete__(sp, reason, false);
         return NPERR_NO_ERROR;
     }
 }
 
 PPluginScriptableObjectParent*
 PluginInstanceParent::AllocPPluginScriptableObject()
 {
-    return new PluginScriptableObjectParent(Proxy);
-}
-
-#ifdef DEBUG
-namespace {
-
-struct ActorSearchData
-{
-    PluginScriptableObjectParent* actor;
-    bool found;
-};
+    nsAutoPtr<PluginScriptableObjectParent>* object =
+        mScriptableObjects.AppendElement();
+    NS_ENSURE_TRUE(object, nsnull);
 
-PLDHashOperator
-ActorSearch(const void* aKey,
-            PluginScriptableObjectParent* aData,
-            void* aUserData)
-{
-    ActorSearchData* asd = reinterpret_cast<ActorSearchData*>(aUserData);
-    if (asd->actor == aData) {
-        asd->found = true;
-        return PL_DHASH_STOP;
-    }
-    return PL_DHASH_NEXT;
+    *object = new PluginScriptableObjectParent();
+    NS_ENSURE_TRUE(*object, nsnull);
+
+    return object->get();
 }
 
-} // anonymous namespace
-#endif // DEBUG
-
 bool
 PluginInstanceParent::DeallocPPluginScriptableObject(
                                          PPluginScriptableObjectParent* aObject)
 {
-    PluginScriptableObjectParent* actor =
-        static_cast<PluginScriptableObjectParent*>(aObject);
+    PluginScriptableObjectParent* object =
+        reinterpret_cast<PluginScriptableObjectParent*>(aObject);
 
-    NPObject* object = actor->GetObject(false);
-    if (object) {
-        NS_ASSERTION(mScriptableObjects.Get(object, nsnull),
-                     "NPObject not in the hash!");
-        mScriptableObjects.Remove(object);
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        if (mScriptableObjects[index] == object) {
+            mScriptableObjects.RemoveElementAt(index);
+            return true;
+        }
     }
-#ifdef DEBUG
-    else {
-        ActorSearchData asd = { actor, false };
-        mScriptableObjects.EnumerateRead(ActorSearch, &asd);
-        NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!");
-    }
-#endif
-
-    delete actor;
-    return true;
+    NS_NOTREACHED("An actor we don't know about?!");
+    return false;
 }
 
 bool
 PluginInstanceParent::AnswerPPluginScriptableObjectConstructor(
                                           PPluginScriptableObjectParent* aActor)
 {
     // This is only called in response to the child process requesting the
     // creation of an actor. This actor will represent an NPObject that is
     // created by the plugin and returned to the browser.
-    PluginScriptableObjectParent* actor =
-        static_cast<PluginScriptableObjectParent*>(aActor);
-    NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!");
+    const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
+    if (!npn) {
+        NS_WARNING("No netscape function pointers?!");
+        return false;
+    }
+
+    NPClass* npclass =
+        const_cast<NPClass*>(PluginScriptableObjectParent::GetClass());
 
-    actor->InitializeProxy();
-    NS_ASSERTION(actor->GetObject(false), "Actor should have an object!");
+    ParentNPObject* object = reinterpret_cast<ParentNPObject*>(
+        npn->createobject(mNPP, npclass));
+    if (!object) {
+        NS_WARNING("Failed to create NPObject!");
+        return false;
+    }
 
+    static_cast<PluginScriptableObjectParent*>(aActor)->Initialize(
+        const_cast<PluginInstanceParent*>(this), object);
     return true;
 }
 
 void
 PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason,
                                     void* notifyData)
 {
     PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)",
                       FULLFUNCTION, url, (int) reason, notifyData));
 
     PStreamNotifyParent* streamNotify =
         static_cast<PStreamNotifyParent*>(notifyData);
     PStreamNotifyParent::Call__delete__(streamNotify, reason);
 }
 
-bool
-PluginInstanceParent::RegisterNPObjectForActor(
-                                           NPObject* aObject,
-                                           PluginScriptableObjectParent* aActor)
-{
-    NS_ASSERTION(aObject && aActor, "Null pointers!");
-    NS_ASSERTION(mScriptableObjects.IsInitialized(), "Hash not initialized!");
-    NS_ASSERTION(!mScriptableObjects.Get(aObject, nsnull), "Duplicate entry!");
-    return !!mScriptableObjects.Put(aObject, aActor);
-}
-
-void
-PluginInstanceParent::UnregisterNPObject(NPObject* aObject)
-{
-    NS_ASSERTION(aObject, "Null pointer!");
-    NS_ASSERTION(mScriptableObjects.IsInitialized(), "Hash not initialized!");
-    NS_ASSERTION(mScriptableObjects.Get(aObject, nsnull), "Unknown entry!");
-    mScriptableObjects.Remove(aObject);
-}
-
 PluginScriptableObjectParent*
 PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
 {
     NS_ASSERTION(aObject, "Null pointer!");
 
     if (aObject->_class == PluginScriptableObjectParent::GetClass()) {
         // One of ours!
         ParentNPObject* object = static_cast<ParentNPObject*>(aObject);
         NS_ASSERTION(object->parent, "Null actor!");
         return object->parent;
     }
 
-    PluginScriptableObjectParent* actor;
-    if (mScriptableObjects.Get(aObject, &actor)) {
-        return actor;
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        nsAutoPtr<PluginScriptableObjectParent>& actor =
+            mScriptableObjects[index];
+        if (actor->GetObject() == aObject) {
+            return actor;
+        }
     }
 
-    actor = new PluginScriptableObjectParent(LocalObject);
-    if (!actor) {
-        NS_ERROR("Out of memory!");
-        return nsnull;
-    }
+    PluginScriptableObjectParent* actor =
+        static_cast<PluginScriptableObjectParent*>(
+            CallPPluginScriptableObjectConstructor());
+    NS_ENSURE_TRUE(actor, nsnull);
 
-    if (!CallPPluginScriptableObjectConstructor(actor)) {
-        NS_WARNING("Failed to send constructor message!");
-        return nsnull;
-    }
-
-    actor->InitializeLocal(aObject);
+    actor->Initialize(const_cast<PluginInstanceParent*>(this), aObject);
     return actor;
 }
 
 bool
 PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState,
                                                        bool* aSuccess)
 {
     *aSuccess = mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0);
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -42,18 +42,17 @@
 #include "mozilla/plugins/PPluginInstanceParent.h"
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
 #if defined(OS_WIN)
 #include "mozilla/gfx/SharedDIBWin.h"
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
-#include "nsDataHashtable.h"
-#include "nsHashKeys.h"
+#include "nsTArray.h"
 #include "nsRect.h"
 
 namespace mozilla {
 namespace plugins {
 
 class PBrowserStreamParent;
 class PluginModuleParent;
 
@@ -65,18 +64,17 @@ class PluginInstanceParent : public PPlu
 
 public:
     PluginInstanceParent(PluginModuleParent* parent,
                          NPP npp,
                          const NPNetscapeFuncs* npniface);
 
     virtual ~PluginInstanceParent();
 
-    bool Init();
-    NPError Destroy();
+    void Destroy();
 
     virtual PPluginScriptableObjectParent*
     AllocPPluginScriptableObject();
 
     virtual bool
     AnswerPPluginScriptableObjectConstructor(PPluginScriptableObjectParent* aActor);
 
     virtual bool
@@ -187,23 +185,16 @@ public:
         return mParent;
     }
 
     const NPNetscapeFuncs* GetNPNIface()
     {
         return mNPNIface;
     }
 
-    bool
-    RegisterNPObjectForActor(NPObject* aObject,
-                             PluginScriptableObjectParent* aActor);
-
-    void
-    UnregisterNPObject(NPObject* aObject);
-
     PluginScriptableObjectParent*
     GetActorForNPObject(NPObject* aObject);
 
     NPP
     GetNPP()
     {
       return mNPP;
     }
@@ -214,17 +205,17 @@ private:
                                      NPError* aResult);
 
 private:
     PluginModuleParent* mParent;
     NPP mNPP;
     const NPNetscapeFuncs* mNPNIface;
     NPWindowType mWindowType;
 
-    nsDataHashtable<nsVoidPtrHashKey, PluginScriptableObjectParent*> mScriptableObjects;
+    nsTArray<nsAutoPtr<PluginScriptableObjectParent> > mScriptableObjects;
 
 #if defined(OS_WIN)
 private:
     // Used in rendering windowless plugins in other processes.
     bool SharedSurfaceSetWindow(const NPWindow* aWindow, NPRemoteWindow& aRemoteWindow);
     void SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent);
     void SharedSurfaceAfterPaint(NPEvent* npevent);
     void SharedSurfaceRelease();
--- a/dom/plugins/PluginMessageUtils.cpp
+++ b/dom/plugins/PluginMessageUtils.cpp
@@ -1,106 +1,101 @@
-/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
-/* vim: set sw=2 ts=8 et tw=80 : */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Content App.
- *
- * The Initial Developer of the Original Code is
- *   The Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "PluginMessageUtils.h"
-#include "nsIRunnable.h"
-#include "nsThreadUtils.h"
-
-#include "PluginInstanceParent.h"
-#include "PluginInstanceChild.h"
-#include "PluginScriptableObjectParent.h"
-#include "PluginScriptableObjectChild.h"
-
-namespace {
-
-class DeferNPObjectReleaseRunnable : public nsRunnable
-{
-public:
-  DeferNPObjectReleaseRunnable(const NPNetscapeFuncs* f, NPObject* o)
-    : mFuncs(f)
-    , mObject(o)
-  {
-    NS_ASSERTION(o, "no release null objects");
-  }
-
-  NS_IMETHOD Run();
-
-private:
-  const NPNetscapeFuncs* mFuncs;
-  NPObject* mObject;
-};
-
-NS_IMETHODIMP
-DeferNPObjectReleaseRunnable::Run()
-{
-  mFuncs->releaseobject(mObject);
-  return NS_OK;
-}
-
-} // anonymous namespace
-
-namespace mozilla {
-namespace plugins {
-
-PRLogModuleInfo* gPluginLog = PR_NewLogModule("IPCPlugins");
-
-void
-DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o)
-{
-  if (!o)
-    return;
-
-  if (o->referenceCount > 1) {
-    f->releaseobject(o);
-    return;
-  }
-
-  NS_DispatchToCurrentThread(new DeferNPObjectReleaseRunnable(f, o));
-}
-
-void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
-{
-  if (!NPVARIANT_IS_OBJECT(*v)) {
-    f->releasevariantvalue(v);
-    return;
-  }
-  DeferNPObjectLastRelease(f, v->value.objectValue);
-  VOID_TO_NPVARIANT(*v);
-}
-
-} // namespace plugins
-} // namespace mozilla
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "PluginMessageUtils.h"
+#include "nsIRunnable.h"
+#include "nsThreadUtils.h"
+
+namespace {
+
+class DeferNPObjectReleaseRunnable : public nsRunnable
+{
+public:
+  DeferNPObjectReleaseRunnable(const NPNetscapeFuncs* f, NPObject* o)
+    : mFuncs(f)
+    , mObject(o)
+  {
+    NS_ASSERTION(o, "no release null objects");
+  }
+
+  NS_IMETHOD Run();
+
+private:
+  const NPNetscapeFuncs* mFuncs;
+  NPObject* mObject;
+};
+
+NS_IMETHODIMP
+DeferNPObjectReleaseRunnable::Run()
+{
+  mFuncs->releaseobject(mObject);
+  return NS_OK;
+}
+
+} // anonymous namespace
+
+namespace mozilla {
+namespace plugins {
+
+PRLogModuleInfo* gPluginLog = PR_NewLogModule("IPCPlugins");
+
+void
+DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o)
+{
+  if (!o)
+    return;
+
+  if (o->referenceCount > 1) {
+    f->releaseobject(o);
+    return;
+  }
+
+  NS_DispatchToCurrentThread(new DeferNPObjectReleaseRunnable(f, o));
+}
+
+void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
+{
+  if (!NPVARIANT_IS_OBJECT(*v)) {
+    f->releasevariantvalue(v);
+    return;
+  }
+  DeferNPObjectLastRelease(f, v->value.objectValue);
+  VOID_TO_NPVARIANT(*v);
+}
+
+} // namespace plugins
+} // namespace mozilla
--- a/dom/plugins/PluginMessageUtils.h
+++ b/dom/plugins/PluginMessageUtils.h
@@ -41,17 +41,16 @@
 
 #include "IPC/IPCMessageUtils.h"
 
 #include "npapi.h"
 #include "npruntime.h"
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsStringGlue.h"
-#include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
 
 namespace mozilla {
 
 // XXX might want to move these to nscore.h or something, they can be
 // generally useful
 struct void_t { };
@@ -60,22 +59,16 @@ struct null_t { };
 namespace ipc {
 
 typedef intptr_t NPRemoteIdentifier;
 
 } /* namespace ipc */
 
 namespace plugins {
 
-enum ScriptableObjectType
-{
-  LocalObject,
-  Proxy
-};
-
 extern PRLogModuleInfo* gPluginLog;
 
 #if defined(_MSC_VER)
 #define FULLFUNCTION __FUNCSIG__
 #elif (__GNUC__ >= 4)
 #define FULLFUNCTION __PRETTY_FUNCTION__
 #else
 #define FULLFUNCTION __FUNCTION__
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -241,16 +241,18 @@ PluginModuleChild::RegisterNPObject(NPOb
 }
 
 void
 PluginModuleChild::UnregisterNPObject(NPObject* aObject)
 {
     AssertPluginThread();
     NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!");
     NS_ASSERTION(aObject, "Null pointer!");
+    NS_ASSERTION(mObjectMap.Get(aObject, nsnull),
+                 "Unregistering an object that was never added!");
     mObjectMap.Remove(aObject);
 }
 
 PluginScriptableObjectChild*
 PluginModuleChild::GetActorForNPObject(NPObject* aObject)
 {
     AssertPluginThread();
     NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!");
@@ -281,22 +283,16 @@ ActorSearch(const void* aKey,
   }
 
   return PL_DHASH_NEXT;
 }
 
 } // anonymous namespace
 
 bool
-PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
-{
-    return !!mObjectMap.Get(aObject, nsnull);
-}
-
-bool
 PluginModuleChild::NPObjectIsRegisteredForActor(
                                             PluginScriptableObjectChild* aActor)
 {
     AssertPluginThread();
     NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!");
     NS_ASSERTION(aActor, "Null actor!");
 
     SearchInfo info = { aActor, false };
@@ -1475,15 +1471,14 @@ PluginModuleChild::DeallocPPluginInstanc
 
 bool
 PluginModuleChild::PluginInstanceDestroyed(PluginInstanceChild* aActor,
                                            NPError* rv)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
-    NPP npp = aActor->GetNPP();
-
-    *rv = mFunctions.destroy(npp, 0);
-    npp->ndata = 0;
+    *rv = mFunctions.destroy(aActor->GetNPP(), 0);
+    aActor->Destroy();
+    aActor->GetNPP()->ndata = 0;
 
     return true;
 }
--- a/dom/plugins/PluginModuleChild.h
+++ b/dom/plugins/PluginModuleChild.h
@@ -141,17 +141,16 @@ public:
     bool RegisterNPObject(NPObject* aObject,
                           PluginScriptableObjectChild* aActor);
 
     void UnregisterNPObject(NPObject* aObject);
 
     PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
 
 #ifdef DEBUG
-    bool NPObjectIsRegistered(NPObject* aObject);
     bool NPObjectIsRegisteredForActor(PluginScriptableObjectChild* aActor);
 #endif
 
     bool
     PluginInstanceDestroyed(PluginInstanceChild* aActor,
                             NPError* rv);
 
 private:
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -155,39 +155,40 @@ PluginModuleParent::SetPluginFuncs(NPPlu
     aFuncs->event = NPP_HandleEvent;
     aFuncs->urlnotify = NPP_URLNotify;
     aFuncs->getvalue = NPP_GetValue;
     aFuncs->setvalue = NPP_SetValue;
 }
 
 NPError
 PluginModuleParent::NPP_Destroy(NPP instance,
-                                NPSavedData** /*saved*/)
+                                NPSavedData** save)
 {
     // FIXME/cjones:
     //  (1) send a "destroy" message to the child
     //  (2) the child shuts down its instance
     //  (3) remove both parent and child IDs from map
     //  (4) free parent
     PLUGIN_LOG_DEBUG_FUNCTION;
 
     PluginInstanceParent* parentInstance =
         static_cast<PluginInstanceParent*>(instance->pdata);
 
     if (!parentInstance)
         return NPERR_NO_ERROR;
 
-    NPError retval = parentInstance->Destroy();
+    parentInstance->Destroy();
+
+    NPError prv;
+    if (!PPluginInstanceParent::Call__delete__(parentInstance, &prv)) {
+        prv = NPERR_GENERIC_ERROR;
+    }
     instance->pdata = nsnull;
 
-    if (!PluginInstanceParent::Call__delete__(parentInstance)) {
-        NS_ERROR("Failed to delete instance!");
-    }
-
-    return retval;
+    return prv;
 }
 
 bool
 PluginModuleParent::EnsureValidNPIdentifier(NPIdentifier aIdentifier)
 {
     if (!mValidIdentifiers.GetEntry(aIdentifier)) {
         nsVoidPtrHashKey* newEntry = mValidIdentifiers.PutEntry(aIdentifier);
         if (!newEntry) {
@@ -635,39 +636,35 @@ PluginModuleParent::NPP_New(NPMIMEType p
     for (int i = 0; i < argc; ++i) {
         names.AppendElement(NullableString(argn[i]));
         values.AppendElement(NullableString(argv[i]));
     }
 
     PluginInstanceParent* parentInstance =
         new PluginInstanceParent(this, instance, mNPNIface);
 
-    if (!parentInstance->Init()) {
-        delete parentInstance;
-        return NS_ERROR_FAILURE;
-    }
-
     instance->pdata = parentInstance;
 
     if (!CallPPluginInstanceConstructor(parentInstance,
                                         nsDependentCString(pluginType), mode,
                                         names, values, error)) {
         // |parentInstance| is automatically deleted.
         instance->pdata = nsnull;
         // if IPC is down, we'll get an immediate "failed" return, but
         // without *error being set.  So make sure that the error
         // condition is signaled to nsNPAPIPluginInstance
         if (NPERR_NO_ERROR == *error)
             *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
     if (*error != NPERR_NO_ERROR) {
-        NPP_Destroy(instance, 0);
-        return *error;
+        PPluginInstanceParent::Call__delete__(parentInstance, error);
+        instance->pdata = nsnull;
+        return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
 
 bool
 PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
                                                       NPError* aError,
--- a/dom/plugins/PluginScriptableObjectChild.cpp
+++ b/dom/plugins/PluginScriptableObjectChild.cpp
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=4 ts=4 et :
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -32,139 +32,296 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginScriptableObjectChild.h"
-#include "PluginScriptableObjectUtils.h"
+
+#include "npapi.h"
+#include "npruntime.h"
+#include "nsDebug.h"
+
+#include "PluginModuleChild.h"
+#include "PluginInstanceChild.h"
 
 using namespace mozilla::plugins;
 using mozilla::ipc::NPRemoteIdentifier;
 
+namespace {
+
+inline NPObject*
+NPObjectFromVariant(const Variant& aRemoteVariant)
+{
+  NS_ASSERTION(aRemoteVariant.type() ==
+               Variant::TPPluginScriptableObjectChild,
+               "Wrong variant type!");
+  PluginScriptableObjectChild* actor =
+    const_cast<PluginScriptableObjectChild*>(
+      reinterpret_cast<const PluginScriptableObjectChild*>(
+        aRemoteVariant.get_PPluginScriptableObjectChild()));
+  return actor->GetObject();
+}
+
+inline NPObject*
+NPObjectFromVariant(const NPVariant& aVariant)
+{
+  NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!");
+  return NPVARIANT_TO_OBJECT(aVariant);
+}
+
+void
+ConvertToVariant(const Variant& aRemoteVariant,
+                 NPVariant& aVariant)
+{
+  switch (aRemoteVariant.type()) {
+    case Variant::Tvoid_t: {
+      VOID_TO_NPVARIANT(aVariant);
+      break;
+    }
+
+    case Variant::Tnull_t: {
+      NULL_TO_NPVARIANT(aVariant);
+      break;
+    }
+
+    case Variant::Tbool: {
+      BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant);
+      break;
+    }
+
+    case Variant::Tint: {
+      INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant);
+      break;
+    }
+
+    case Variant::Tdouble: {
+      DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant);
+      break;
+    }
+
+    case Variant::TnsCString: {
+      const nsCString& string = aRemoteVariant.get_nsCString();
+      NPUTF8* buffer = reinterpret_cast<NPUTF8*>(strdup(string.get()));
+      NS_ASSERTION(buffer, "Out of memory!");
+      STRINGN_TO_NPVARIANT(buffer, string.Length(), aVariant);
+      break;
+    }
+
+    case Variant::TPPluginScriptableObjectChild: {
+      NPObject* object = NPObjectFromVariant(aRemoteVariant);
+      NS_ASSERTION(object, "Null object?!");
+      PluginModuleChild::sBrowserFuncs.retainobject(object);
+      OBJECT_TO_NPVARIANT(object, aVariant);
+      break;
+    }
+
+    default:
+      NS_RUNTIMEABORT("Shouldn't get here!");
+  }
+}
+
+bool
+ConvertToRemoteVariant(const NPVariant& aVariant,
+                       Variant& aRemoteVariant,
+                       PluginInstanceChild* aInstance)
+{
+  if (NPVARIANT_IS_VOID(aVariant)) {
+    aRemoteVariant = mozilla::void_t();
+  }
+  else if (NPVARIANT_IS_NULL(aVariant)) {
+    aRemoteVariant = mozilla::null_t();
+  }
+  else if (NPVARIANT_IS_BOOLEAN(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_BOOLEAN(aVariant);
+  }
+  else if (NPVARIANT_IS_INT32(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_INT32(aVariant);
+  }
+  else if (NPVARIANT_IS_DOUBLE(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_DOUBLE(aVariant);
+  }
+  else if (NPVARIANT_IS_STRING(aVariant)) {
+    NPString str = NPVARIANT_TO_STRING(aVariant);
+    nsCString string(str.UTF8Characters, str.UTF8Length);
+    aRemoteVariant = string;
+  }
+  else if (NPVARIANT_IS_OBJECT(aVariant)) {
+    NS_ASSERTION(aInstance, "Must have an instance to wrap!");
+
+    NPObject* object = NPVARIANT_TO_OBJECT(aVariant);
+    NS_ASSERTION(object, "Null object?!");
+
+    PluginScriptableObjectChild* actor = aInstance->GetActorForNPObject(object);
+    if (!actor) {
+      NS_ERROR("Failed to create actor!");
+      return false;
+    }
+    aRemoteVariant = actor;
+  }
+  else {
+    NS_NOTREACHED("Shouldn't get here!");
+    return false;
+  }
+
+  return true;
+}
+
+} // anonymous namespace
+
 // static
 NPObject*
 PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
                                                 NPClass* aClass)
 {
   AssertPluginThread();
 
-  if (aClass != GetClass()) {
-    NS_RUNTIMEABORT("Huh?! Wrong class!");
+  NS_ASSERTION(aClass == PluginScriptableObjectChild::GetClass(),
+               "Huh?! Wrong class!");
+
+  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(
+    PluginModuleChild::sBrowserFuncs.memalloc(sizeof(ChildNPObject)));
+  if (object) {
+    memset(object, 0, sizeof(ChildNPObject));
   }
-
-  return new ChildNPObject();
+  return object;
 }
 
 // static
 void
 PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     // This can happen more than once, and is just fine.
     return;
   }
 
+  PluginScriptableObjectChild* actor = object->parent;
+
+  PluginInstanceChild* instance = actor ? actor->GetInstance() : nsnull;
+  NS_WARN_IF_FALSE(instance, "No instance!");
+
+  if (actor && !actor->CallInvalidate()) {
+    NS_WARNING("Failed to send message!");
+  }
+
   object->invalidated = true;
+
+  if (instance &&
+      !PPluginScriptableObjectChild::Call__delete__(object->parent)) {
+    NS_WARNING("Failed to send message!");
+  }
 }
 
 // static
 void
 PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (!object->invalidated) {
     ScriptableInvalidate(aObject);
   }
-  NS_ASSERTION(object->invalidated, "Should have invalidated already!");
 
-  PluginScriptableObjectChild* actor = object->parent;
-  if (actor) {
-    NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-    actor->DropNPObject();
-  }
+  NS_ASSERTION(object->invalidated, "Should be invalidated!");
 
-  delete object;
+  NS_Free(aObject);
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject,
                                                  NPIdentifier aName)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  actor->CallHasMethod((NPRemoteIdentifier)aName, &result);
+  if (!actor->CallHasMethod((NPRemoteIdentifier)aName, &result)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   return result;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
                                               NPIdentifier aName,
                                               const NPVariant* aArgs,
                                               uint32_t aArgCount,
                                               NPVariant* aResult)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
+  }
+
   Variant remoteResult;
   bool success;
-  actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult, &success);
+  if (!actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult,
+                          &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(remoteResult, *aResult);
   return true;
 }
@@ -173,100 +330,117 @@ PluginScriptableObjectChild::ScriptableI
 bool
 PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject,
                                                      const NPVariant* aArgs,
                                                      uint32_t aArgCount,
                                                      NPVariant* aResult)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
+  }
+
   Variant remoteResult;
   bool success;
-  actor->CallInvokeDefault(args, &remoteResult, &success);
+  if (!actor->CallInvokeDefault(args, &remoteResult, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(remoteResult, *aResult);
   return true;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject,
                                                    NPIdentifier aName)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  actor->CallHasProperty((NPRemoteIdentifier)aName, &result);
+  if (!actor->CallHasProperty((NPRemoteIdentifier)aName, &result)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   return result;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
                                                    NPIdentifier aName,
                                                    NPVariant* aResult)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   Variant result;
   bool success;
-  actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success);
+  if (!actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(result, *aResult);
   return true;
 }
@@ -274,94 +448,103 @@ PluginScriptableObjectChild::ScriptableG
 // static
 bool
 PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject,
                                                    NPIdentifier aName,
                                                    const NPVariant* aValue)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
-  ProtectedVariant value(*aValue, actor->GetInstance());
-  if (!value.IsOk()) {
+  Variant value;
+  if (!ConvertToRemoteVariant(*aValue, value, actor->GetInstance())) {
     NS_WARNING("Failed to convert variant!");
     return false;
   }
 
   bool success;
-  actor->CallSetProperty((NPRemoteIdentifier)aName, value, &success);
+  if (!actor->CallSetProperty((NPRemoteIdentifier)aName, value, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
                                                       NPIdentifier aName)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool success;
-  actor->CallRemoveProperty((NPRemoteIdentifier)aName, &success);
+  if (!actor->CallRemoveProperty((NPRemoteIdentifier)aName, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
                                                  NPIdentifier** aIdentifiers,
                                                  uint32_t* aCount)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   nsAutoTArray<NPRemoteIdentifier, 10> identifiers;
   bool success;
-  actor->CallEnumerate(&identifiers, &success);
+  if (!actor->CallEnumerate(&identifiers, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   if (!success) {
     return false;
   }
 
   *aCount = identifiers.Length();
   if (!*aCount) {
     *aIdentifiers = nsnull;
@@ -385,39 +568,50 @@ PluginScriptableObjectChild::ScriptableE
 bool
 PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject,
                                                  const NPVariant* aArgs,
                                                  uint32_t aArgCount,
                                                  NPVariant* aResult)
 {
   AssertPluginThread();
 
-  if (aObject->_class != GetClass()) {
-    NS_RUNTIMEABORT("Don't know what kind of object this is!");
+  if (aObject->_class != PluginScriptableObjectChild::GetClass()) {
+    NS_ERROR("Don't know what kind of object this is!");
+    return false;
   }
 
   ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
+  PluginScriptableObjectChild* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
+  }
+
   Variant remoteResult;
   bool success;
-  actor->CallConstruct(args, &remoteResult, &success);
+  if (!actor->CallConstruct(args, &remoteResult, &success)) {
+    NS_WARNING("Failed to send message!");
+    return false;
+  }
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(remoteResult, *aResult);
   return true;
 }
@@ -433,227 +627,108 @@ const NPClass PluginScriptableObjectChil
   PluginScriptableObjectChild::ScriptableHasProperty,
   PluginScriptableObjectChild::ScriptableGetProperty,
   PluginScriptableObjectChild::ScriptableSetProperty,
   PluginScriptableObjectChild::ScriptableRemoveProperty,
   PluginScriptableObjectChild::ScriptableEnumerate,
   PluginScriptableObjectChild::ScriptableConstruct
 };
 
-PluginScriptableObjectChild::PluginScriptableObjectChild(
-                                                     ScriptableObjectType aType)
+PluginScriptableObjectChild::PluginScriptableObjectChild()
 : mInstance(nsnull),
-  mObject(nsnull),
-  mInvalidated(false),
-  mProtectCount(0),
-  mType(aType)
+  mObject(nsnull)
 {
   AssertPluginThread();
 }
 
 PluginScriptableObjectChild::~PluginScriptableObjectChild()
 {
   AssertPluginThread();
 
   if (mObject) {
     if (mObject->_class == GetClass()) {
-      NS_ASSERTION(mType == Proxy, "Wrong type!");
-      static_cast<ChildNPObject*>(mObject)->parent = nsnull;
+      if (!static_cast<ChildNPObject*>(mObject)->invalidated) {
+        NS_WARNING("This should have happened already!");
+        ScriptableInvalidate(mObject);
+      }
     }
     else {
-      NS_ASSERTION(mType == LocalObject, "Wrong type!");
-      PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
+      // Make sure we've invalidated our NPObject so that the plugin doesn't
+      // hold an object with a dangling pointer.
+
+      // Calling a virtual in the destructor, make sure we call the right one.
+      PluginScriptableObjectChild::AnswerInvalidate();
     }
   }
-
   NS_ASSERTION(!PluginModuleChild::current()->
                NPObjectIsRegisteredForActor(this),
                "NPObjects still registered for this actor!");
 }
 
 void
-PluginScriptableObjectChild::InitializeProxy()
+PluginScriptableObjectChild::Initialize(PluginInstanceChild* aInstance,
+                                        NPObject* aObject)
 {
   AssertPluginThread();
-  NS_ASSERTION(mType == Proxy, "Bad type!");
-  NS_ASSERTION(!mObject, "Calling Initialize more than once!");
-  NS_ASSERTION(!mInvalidated, "Already invalidated?!");
 
-  mInstance = static_cast<PluginInstanceChild*>(Manager());
-  NS_ASSERTION(mInstance, "Null manager?!");
+  NS_ASSERTION(!(mInstance && mObject), "Calling Initialize class twice!");
 
-  NPObject* object = CreateProxyObject();
-  NS_ASSERTION(object, "Failed to create object!");
+  if (aObject->_class == GetClass()) {
+    ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
 
-  if (!PluginModuleChild::current()->RegisterNPObject(object, this)) {
-    NS_ERROR("Out of memory?");
-  }
-
-  mObject = object;
-}
+    NS_ASSERTION(!object->parent, "Bad object!");
+    object->parent = const_cast<PluginScriptableObjectChild*>(this);
 
-void
-PluginScriptableObjectChild::InitializeLocal(NPObject* aObject)
-{
-  AssertPluginThread();
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-  NS_ASSERTION(!mObject, "Calling Initialize more than once!");
-  NS_ASSERTION(!mInvalidated, "Already invalidated?!");
-
-  mInstance = static_cast<PluginInstanceChild*>(Manager());
-  NS_ASSERTION(mInstance, "Null manager?!");
-
-  PluginModuleChild::sBrowserFuncs.retainobject(aObject);
-
-  NS_ASSERTION(!mProtectCount, "Should be zero!");
-  mProtectCount++;
-
-  if (!PluginModuleChild::current()->RegisterNPObject(aObject, this)) {
-      NS_ERROR("Out of memory?");
+    // We don't want to have the actor own this object but rather let the object
+    // own this actor. Set the reference count to 0 here so that when the object
+    // dies we will send the destructor message to the parent.
+    NS_ASSERTION(aObject->referenceCount == 1, "Some kind of live object!");
+    aObject->referenceCount = 0;
+    NS_LOG_RELEASE(aObject, 0, "ChildNPObject");
+  }
+  else {
+    // Plugin-provided object, retain here. This should be the only reference we
+    // ever need.
+    PluginModuleChild::sBrowserFuncs.retainobject(aObject);
   }
 
+  mInstance = aInstance;
   mObject = aObject;
 }
 
-NPObject*
-PluginScriptableObjectChild::CreateProxyObject()
-{
-  NS_ASSERTION(mInstance, "Must have an instance!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  NPClass* proxyClass = const_cast<NPClass*>(GetClass());
-  NPObject* npobject =
-    PluginModuleChild::sBrowserFuncs.createobject(mInstance->GetNPP(),
-                                                  proxyClass);
-  NS_ASSERTION(npobject, "Failed to create object?!");
-  NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
-  NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
-
-  ChildNPObject* object = static_cast<ChildNPObject*>(npobject);
-  NS_ASSERTION(!object->invalidated, "Bad object!");
-  NS_ASSERTION(!object->parent, "Bad object!");
-
-  // We don't want to have the actor own this object but rather let the object
-  // own this actor. Set the reference count to 0 here so that when the object
-  // dies we will send the destructor message to the child.
-  object->referenceCount = 0;
-  NS_LOG_RELEASE(object, 0, "ChildNPObject");
-
-  object->parent = const_cast<PluginScriptableObjectChild*>(this);
-  return object;
-}
-
-bool
-PluginScriptableObjectChild::ResurrectProxyObject()
-{
-  NS_ASSERTION(mInstance, "Must have an instance already!");
-  NS_ASSERTION(!mObject, "Should not have an object already!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  NPObject* object = CreateProxyObject();
-  if (!object) {
-    NS_WARNING("Failed to create object!");
-    return false;
-  }
-
-  InitializeProxy();
-  NS_ASSERTION(mObject, "Initialize failed!");
-
-  CallProtect();
-  return true;
-}
-
-NPObject*
-PluginScriptableObjectChild::GetObject(bool aCanResurrect)
-{
-  if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
-    NS_ERROR("Null object!");
-    return nsnull;
-  }
-  return mObject;
-}
-
-void
-PluginScriptableObjectChild::Protect()
-{
-  NS_ASSERTION(mObject, "No object!");
-  NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
-
-  if (mType == LocalObject) {
-    ++mProtectCount;
-  }
-}
-
-void
-PluginScriptableObjectChild::Unprotect()
-{
-  NS_ASSERTION(mObject, "Bad state!");
-  NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
-
-  if (mType == LocalObject) {
-    if (--mProtectCount == 0) {
-      PluginScriptableObjectChild::Call__delete__(this);
-    }
-  }
-}
-
-void
-PluginScriptableObjectChild::DropNPObject()
-{
-  NS_ASSERTION(mObject, "Invalidated object!");
-  NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  // We think we're about to be deleted, but we could be racing with the other
-  // process.
-  PluginModuleChild::current()->UnregisterNPObject(mObject);
-  mObject = nsnull;
-
-  CallUnprotect();
-}
-
 bool
 PluginScriptableObjectChild::AnswerInvalidate()
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
-    NS_WARNING("Called invalidate more than once?!");
-    return true;
+  if (mObject) {
+    NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
+    if (mObject->_class && mObject->_class->invalidate) {
+      mObject->_class->invalidate(mObject);
+    }
+    PluginModuleChild::current()->UnregisterNPObject(mObject);
+    PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
+    mObject = nsnull;
   }
-
-  mInvalidated = true;
-
-  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-
-  if (mObject->_class && mObject->_class->invalidate) {
-    mObject->_class->invalidate(mObject);
-  }
-
-  PluginModuleChild::current()->UnregisterNPObject(mObject);
-  Unprotect();
-
   return true;
 }
 
 bool
 PluginScriptableObjectChild::AnswerHasMethod(const NPRemoteIdentifier& aId,
                                              bool* aHasMethod)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
     *aHasMethod = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->hasMethod)) {
     *aHasMethod = false;
     return true;
   }
 
   *aHasMethod = mObject->_class->hasMethod(mObject, (NPIdentifier)aId);
   return true;
@@ -662,25 +737,24 @@ PluginScriptableObjectChild::AnswerHasMe
 bool
 PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId,
                                           const nsTArray<Variant>& aArgs,
                                           Variant* aResult,
                                           bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerInvoke with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->invoke)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   nsAutoTArray<NPVariant, 10> convertedArgs;
@@ -707,18 +781,17 @@ PluginScriptableObjectChild::AnswerInvok
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
-  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
-                                   false);
+  success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
 
   DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -730,25 +803,24 @@ PluginScriptableObjectChild::AnswerInvok
 
 bool
 PluginScriptableObjectChild::AnswerInvokeDefault(const nsTArray<Variant>& aArgs,
                                                  Variant* aResult,
                                                  bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->invokeDefault)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   nsAutoTArray<NPVariant, 10> convertedArgs;
@@ -775,18 +847,17 @@ PluginScriptableObjectChild::AnswerInvok
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
-  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
-                                   false);
+  success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
 
   DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -797,24 +868,23 @@ PluginScriptableObjectChild::AnswerInvok
 }
 
 bool
 PluginScriptableObjectChild::AnswerHasProperty(const NPRemoteIdentifier& aId,
                                                bool* aHasProperty)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
     *aHasProperty = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->hasProperty)) {
     *aHasProperty = false;
     return true;
   }
 
   *aHasProperty = mObject->_class->hasProperty(mObject, (NPIdentifier)aId);
   return true;
@@ -822,42 +892,40 @@ PluginScriptableObjectChild::AnswerHasPr
 
 bool
 PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId,
                                                Variant* aResult,
                                                bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->getProperty)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NPVariant result;
   if (!mObject->_class->getProperty(mObject, (NPIdentifier)aId, &result)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant converted;
-  if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
-                                          false))) {
+  if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance()))) {
     DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
     *aResult = converted;
   }
   else {
     *aResult = void_t();
   }
 
   return true;
@@ -865,24 +933,23 @@ PluginScriptableObjectChild::AnswerGetPr
 
 bool
 PluginScriptableObjectChild::AnswerSetProperty(const NPRemoteIdentifier& aId,
                                                const Variant& aValue,
                                                bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->setProperty)) {
     *aSuccess = false;
     return true;
   }
 
   NPVariant converted;
   ConvertToVariant(aValue, converted);
@@ -895,48 +962,46 @@ PluginScriptableObjectChild::AnswerSetPr
 }
 
 bool
 PluginScriptableObjectChild::AnswerRemoveProperty(const NPRemoteIdentifier& aId,
                                                   bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->removeProperty)) {
     *aSuccess = false;
     return true;
   }
 
   *aSuccess = mObject->_class->removeProperty(mObject, (NPIdentifier)aId);
   return true;
 }
 
 bool
 PluginScriptableObjectChild::AnswerEnumerate(nsTArray<NPRemoteIdentifier>* aProperties,
                                              bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->enumerate)) {
     *aSuccess = false;
     return true;
   }
 
   NPIdentifier* ids;
   uint32_t idCount;
@@ -966,25 +1031,24 @@ PluginScriptableObjectChild::AnswerEnume
 
 bool
 PluginScriptableObjectChild::AnswerConstruct(const nsTArray<Variant>& aArgs,
                                              Variant* aResult,
                                              bool* aSuccess)
 {
   AssertPluginThread();
 
-  if (mInvalidated) {
+  if (!mObject) {
     NS_WARNING("Calling AnswerConstruct with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->construct)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   nsAutoTArray<NPVariant, 10> convertedArgs;
@@ -1010,64 +1074,41 @@ PluginScriptableObjectChild::AnswerConst
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
-  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
-                                   false);
+  success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
 
   DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   *aResult = convertedResult;
   *aSuccess = true;
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerProtect()
-{
-  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-
-  Protect();
-  return true;
-}
-
-bool
-PluginScriptableObjectChild::AnswerUnprotect()
-{
-  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-
-  Unprotect();
-  return true;
-}
-
-bool
 PluginScriptableObjectChild::Evaluate(NPString* aScript,
                                       NPVariant* aResult)
 {
   nsDependentCString script("");
   if (aScript->UTF8Characters && aScript->UTF8Length) {
     script.Rebind(aScript->UTF8Characters, aScript->UTF8Length);
   }
 
   bool success;
   Variant result;
-  CallNPN_Evaluate(script, &result, &success);
-
-  if (!success) {
+  if (!(CallNPN_Evaluate(script, &result, &success) && success)) {
     return false;
   }
 
   ConvertToVariant(result, *aResult);
   return true;
 }
--- a/dom/plugins/PluginScriptableObjectChild.h
+++ b/dom/plugins/PluginScriptableObjectChild.h
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -46,40 +46,28 @@
 namespace mozilla {
 namespace plugins {
 
 class PluginInstanceChild;
 class PluginScriptableObjectChild;
 
 struct ChildNPObject : NPObject
 {
-  ChildNPObject()
-    : NPObject(), parent(NULL), invalidated(false) { }
-
-  // |parent| is always valid as long as the actor is alive. Once the actor is
-  // destroyed this will be set to null.
   PluginScriptableObjectChild* parent;
   bool invalidated;
 };
 
 class PluginScriptableObjectChild : public PPluginScriptableObjectChild
 {
   friend class PluginInstanceChild;
 
 public:
-  PluginScriptableObjectChild(ScriptableObjectType aType);
+  PluginScriptableObjectChild();
   virtual ~PluginScriptableObjectChild();
 
-  void
-  InitializeProxy();
-
-  void
-  InitializeLocal(NPObject* aObject);
-
-
   virtual bool
   AnswerInvalidate();
 
   virtual bool
   AnswerHasMethod(const NPRemoteIdentifier& aId,
                   bool* aHasMethod);
 
   virtual bool
@@ -115,65 +103,42 @@ public:
   AnswerEnumerate(nsTArray<NPRemoteIdentifier>* aProperties,
                   bool* aSuccess);
 
   virtual bool
   AnswerConstruct(const nsTArray<Variant>& aArgs,
                   Variant* aResult,
                   bool* aSuccess);
 
-  virtual bool
-  AnswerProtect();
-
-  virtual bool
-  AnswerUnprotect();
+  void
+  Initialize(PluginInstanceChild* aInstance,
+             NPObject* aObject);
 
   NPObject*
-  GetObject(bool aCanResurrect);
+  GetObject()
+  {
+    return mObject;
+  }
 
   static const NPClass*
   GetClass()
   {
     return &sNPClass;
   }
 
   PluginInstanceChild*
-  GetInstance() const
+  GetInstance()
   {
     return mInstance;
   }
 
-  // Protect only affects LocalObject actors. It is called by the
-  // ProtectedVariant/Actor helper classes before the actor is used as an
-  // argument to an IPC call and when the parent process resurrects a
-  // proxy object to the NPObject associated with this actor.
-  void Protect();
-
-  // Unprotect only affects LocalObject actors. It is called by the
-  // ProtectedVariant/Actor helper classes after the actor is used as an
-  // argument to an IPC call and when the parent process is no longer using
-  // this actor.
-  void Unprotect();
-
-  // DropNPObject is only used for Proxy actors and is called when the child
-  // process is no longer using the NPObject associated with this actor. The
-  // parent process may subsequently use this actor again in which case a new
-  // NPObject will be created and associated with this actor (see
-  // ResurrectProxyObject).
-  void DropNPObject();
-
   bool
   Evaluate(NPString* aScript,
            NPVariant* aResult);
 
-  ScriptableObjectType
-  Type() const {
-    return mType;
-  }
-
 private:
   static NPObject*
   ScriptableAllocate(NPP aInstance,
                      NPClass* aClass);
 
   static void
   ScriptableInvalidate(NPObject* aObject);
 
@@ -221,31 +186,19 @@ private:
                       uint32_t* aCount);
 
   static bool
   ScriptableConstruct(NPObject* aObject,
                       const NPVariant* aArgs,
                       uint32_t aArgCount,
                       NPVariant* aResult);
 
-  NPObject*
-  CreateProxyObject();
-
-  // ResurrectProxyObject is only used with Proxy actors. It is called when the
-  // parent process uses an actor whose NPObject was deleted by the child
-  // process.
-  bool ResurrectProxyObject();
-
 private:
   PluginInstanceChild* mInstance;
   NPObject* mObject;
-  bool mInvalidated;
-  int mProtectCount;
-
-  ScriptableObjectType mType;
 
   static const NPClass sNPClass;
 };
 
 } /* namespace plugins */
 } /* namespace mozilla */
 
 #endif /* dom_plugins_PluginScriptableObjectChild_h */
--- a/dom/plugins/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/PluginScriptableObjectParent.cpp
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=4 ts=4 et :
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -32,23 +32,85 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginScriptableObjectParent.h"
-#include "PluginScriptableObjectUtils.h"
+#include "PluginInstanceParent.h"
+#include "PluginModuleParent.h"
+
+#include "npapi.h"
+#include "nsDebug.h"
 
 using namespace mozilla::plugins;
+
 using mozilla::ipc::NPRemoteIdentifier;
 
 namespace {
 
+inline PluginInstanceParent*
+GetInstance(NPObject* aObject)
+{
+  NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
+               "Bad class!");
+
+  ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
+  if (!object->parent) {
+    NS_WARNING("Calling method on an invalidated object!");
+    return nsnull;
+  }
+  return object->parent->GetInstance();
+}
+
+inline const NPNetscapeFuncs*
+GetNetscapeFuncs(PluginInstanceParent* aInstance)
+{
+  PluginModuleParent* module = aInstance->Module();
+  if (!module) {
+    NS_WARNING("Null module?!");
+    return nsnull;
+  }
+  return module->GetNetscapeFuncs();
+}
+
+inline const NPNetscapeFuncs*
+GetNetscapeFuncs(NPObject* aObject)
+{
+  NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
+               "Bad class!");
+
+  PluginInstanceParent* instance = GetInstance(aObject);
+  if (!instance) {
+    return nsnull;
+  }
+
+  return GetNetscapeFuncs(instance);
+}
+
+inline NPObject*
+NPObjectFromVariant(const Variant& aRemoteVariant) {
+  NS_ASSERTION(aRemoteVariant.type() ==
+               Variant::TPPluginScriptableObjectParent,
+               "Wrong variant type!");
+  PluginScriptableObjectParent* actor =
+    const_cast<PluginScriptableObjectParent*>(
+      reinterpret_cast<const PluginScriptableObjectParent*>(
+        aRemoteVariant.get_PPluginScriptableObjectParent()));
+  return actor->GetObject();
+}
+
+inline NPObject*
+NPObjectFromVariant(const NPVariant& aVariant) {
+  NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!");
+  return NPVARIANT_TO_OBJECT(aVariant);
+}
+
 inline void
 ReleaseVariant(NPVariant& aVariant,
                PluginInstanceParent* aInstance)
 {
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
   if (npn) {
     npn->releasevariantvalue(&aVariant);
   }
@@ -75,104 +137,220 @@ EnsureValidIdentifier(NPObject* aObject,
   if (!instance) {
     NS_WARNING("Huh?!");
     return false;
   }
 
   return EnsureValidIdentifier(instance, aIdentifier);
 }
 
+bool
+ConvertToVariant(const Variant& aRemoteVariant,
+                 NPVariant& aVariant,
+                 PluginInstanceParent* aInstance)
+{
+  switch (aRemoteVariant.type()) {
+    case Variant::Tvoid_t: {
+      VOID_TO_NPVARIANT(aVariant);
+      break;
+    }
+
+    case Variant::Tnull_t: {
+      NULL_TO_NPVARIANT(aVariant);
+      break;
+    }
+
+    case Variant::Tbool: {
+      BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant);
+      break;
+    }
+
+    case Variant::Tint: {
+      INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant);
+      break;
+    }
+
+    case Variant::Tdouble: {
+      DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant);
+      break;
+    }
+
+    case Variant::TnsCString: {
+      const nsCString& string = aRemoteVariant.get_nsCString();
+      NPUTF8* buffer = reinterpret_cast<NPUTF8*>(strdup(string.get()));
+      if (!buffer) {
+        NS_ERROR("Out of memory!");
+        return false;
+      }
+      STRINGN_TO_NPVARIANT(buffer, string.Length(), aVariant);
+      break;
+    }
+
+    case Variant::TPPluginScriptableObjectParent: {
+      NPObject* object = NPObjectFromVariant(aRemoteVariant);
+      if (!object) {
+        NS_ERROR("Er, this shouldn't fail!");
+        return false;
+      }
+
+      const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
+      if (!npn) {
+        NS_ERROR("Null netscape funcs!");
+        return false;
+      }
+      npn->retainobject(object);
+      OBJECT_TO_NPVARIANT(object, aVariant);
+      break;
+    }
+
+    default:
+      NS_NOTREACHED("Shouldn't get here!");
+      return false;
+  }
+
+  return true;
+}
+
+bool
+ConvertToRemoteVariant(const NPVariant& aVariant,
+                       Variant& aRemoteVariant,
+                       PluginInstanceParent* aInstance)
+{
+  if (NPVARIANT_IS_VOID(aVariant)) {
+    aRemoteVariant = mozilla::void_t();
+  }
+  else if (NPVARIANT_IS_NULL(aVariant)) {
+    aRemoteVariant = mozilla::null_t();
+  }
+  else if (NPVARIANT_IS_BOOLEAN(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_BOOLEAN(aVariant);
+  }
+  else if (NPVARIANT_IS_INT32(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_INT32(aVariant);
+  }
+  else if (NPVARIANT_IS_DOUBLE(aVariant)) {
+    aRemoteVariant = NPVARIANT_TO_DOUBLE(aVariant);
+  }
+  else if (NPVARIANT_IS_STRING(aVariant)) {
+    NPString str = NPVARIANT_TO_STRING(aVariant);
+    nsCString string(str.UTF8Characters, str.UTF8Length);
+    aRemoteVariant = string;
+  }
+  else if (NPVARIANT_IS_OBJECT(aVariant)) {
+    NPObject* object = NPVARIANT_TO_OBJECT(aVariant);
+    PluginScriptableObjectParent* actor = aInstance->GetActorForNPObject(object);
+    if (!actor) {
+      NS_ERROR("Null actor!");
+      return false;
+    }
+    aRemoteVariant = actor;
+  }
+  else {
+    NS_NOTREACHED("Shouldn't get here!");
+    return false;
+  }
+
+  return true;
+}
+
 } // anonymous namespace
 
 // static
 NPObject*
 PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance,
                                                  NPClass* aClass)
 {
-  if (aClass != GetClass()) {
-    NS_ERROR("Huh?! Wrong class!");
+  NS_ASSERTION(aClass == PluginScriptableObjectParent::GetClass(),
+               "Huh?! Wrong class!");
+
+  PluginInstanceParent* instance = PluginModuleParent::InstCast(aInstance);
+  NS_ASSERTION(instance, "This should never be null!");
+
+  const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
+  if (!npn) {
+    NS_WARNING("Can't allocate!");
     return nsnull;
   }
 
   return new ParentNPObject();
 }
 
 // static
 void
 PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     // This can happen more than once, and is just fine.
     return;
   }
 
-  object->invalidated = true;
+  PluginScriptableObjectParent* actor = object->parent;
+
+  object->parent = NULL;
+
+  PluginInstanceParent* instance = actor->GetInstance();
+  NS_WARN_IF_FALSE(instance, "No instance?!");
 
-  // |object->parent| may be null already if the instance has gone away.
-  if (object->parent && !object->parent->CallInvalidate()) {
-    NS_ERROR("Failed to send message!");
+  if (!actor->CallInvalidate()) {
+    NS_WARNING("Failed to send message!");
+  }
+
+  if (instance &&
+      !PPluginScriptableObjectParent::Call__delete__(actor)) {
+    NS_WARNING("Failed to send message!");
   }
 }
 
 // static
 void
 PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (!object->invalidated) {
+  if (object->parent) {
     ScriptableInvalidate(aObject);
   }
-  NS_ASSERTION(object->invalidated, "Should have invalidated already!");
 
-  PluginScriptableObjectParent* actor = object->parent;
-  if (actor) {
-    NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-    actor->DropNPObject();
-  }
+  NS_ASSERTION(!object->parent, "Should be invalidated!");
 
   delete object;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject,
                                                   NPIdentifier aName)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
-
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   bool result;
   if (!actor->CallHasMethod((NPRemoteIdentifier)aName, &result)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return result;
@@ -181,48 +359,52 @@ PluginScriptableObjectParent::Scriptable
 // static
 bool
 PluginScriptableObjectParent::ScriptableInvoke(NPObject* aObject,
                                                NPIdentifier aName,
                                                const NPVariant* aArgs,
                                                uint32_t aArgCount,
                                                NPVariant* aResult)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
+
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
-    return false;
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
   }
 
   Variant remoteResult;
   bool success;
   if (!actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult,
-                         &success)) {
+       &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   if (!success) {
     return false;
   }
 
@@ -235,38 +417,42 @@ PluginScriptableObjectParent::Scriptable
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableInvokeDefault(NPObject* aObject,
                                                       const NPVariant* aArgs,
                                                       uint32_t aArgCount,
                                                       NPVariant* aResult)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
+
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
-    return false;
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
   }
 
   Variant remoteResult;
   bool success;
   if (!actor->CallInvokeDefault(args, &remoteResult, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
@@ -282,74 +468,66 @@ PluginScriptableObjectParent::Scriptable
   return true;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject,
                                                     NPIdentifier aName)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
-
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   bool result;
   if (!actor->CallHasProperty((NPRemoteIdentifier)aName, &result)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return result;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject,
                                                     NPIdentifier aName,
                                                     NPVariant* aResult)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
-
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   Variant result;
   bool success;
   if (!actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
@@ -366,40 +544,36 @@ PluginScriptableObjectParent::Scriptable
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject,
                                                     NPIdentifier aName,
                                                     const NPVariant* aValue)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-
-  ProtectedVariant value(*aValue, actor->GetInstance());
-  if (!value.IsOk()) {
+  Variant value;
+  if (!ConvertToRemoteVariant(*aValue, value, actor->GetInstance())) {
     NS_WARNING("Failed to convert variant!");
     return false;
   }
 
   bool success;
   if (!actor->CallSetProperty((NPRemoteIdentifier)aName, value, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
@@ -408,70 +582,62 @@ PluginScriptableObjectParent::Scriptable
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject,
                                                        NPIdentifier aName)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
-
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   bool success;
   if (!actor->CallRemoveProperty((NPRemoteIdentifier)aName, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
                                                   NPIdentifier** aIdentifiers,
                                                   uint32_t* aCount)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
-    return false;
-  }
-
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject);
   if (!npn) {
     NS_ERROR("No netscape funcs!");
     return false;
   }
 
   nsAutoTArray<NPRemoteIdentifier, 10> identifiers;
@@ -509,38 +675,42 @@ PluginScriptableObjectParent::Scriptable
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject,
                                                   const NPVariant* aArgs,
                                                   uint32_t aArgCount,
                                                   NPVariant* aResult)
 {
-  if (aObject->_class != GetClass()) {
+  if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
-  if (!actor) {
+  PluginScriptableObjectParent* actor = object->parent;
+  NS_ASSERTION(actor, "This shouldn't ever be null!");
+
+  nsAutoTArray<Variant, 10> args;
+  if (!args.SetLength(aArgCount)) {
+    NS_ERROR("Out of memory?!");
     return false;
   }
 
-  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
-
-  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
-  if (!args.IsOk()) {
-    NS_ERROR("Failed to convert arguments!");
-    return false;
+  for (PRUint32 index = 0; index < aArgCount; index++) {
+    Variant& arg = args[index];
+    if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) {
+      NS_WARNING("Failed to convert argument!");
+      return false;
+    }
   }
 
   Variant remoteResult;
   bool success;
   if (!actor->CallConstruct(args, &remoteResult, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
@@ -567,191 +737,87 @@ const NPClass PluginScriptableObjectPare
   PluginScriptableObjectParent::ScriptableHasProperty,
   PluginScriptableObjectParent::ScriptableGetProperty,
   PluginScriptableObjectParent::ScriptableSetProperty,
   PluginScriptableObjectParent::ScriptableRemoveProperty,
   PluginScriptableObjectParent::ScriptableEnumerate,
   PluginScriptableObjectParent::ScriptableConstruct
 };
 
-PluginScriptableObjectParent::PluginScriptableObjectParent(
-                                                     ScriptableObjectType aType)
+PluginScriptableObjectParent::PluginScriptableObjectParent()
 : mInstance(nsnull),
-  mObject(nsnull),
-  mProtectCount(0),
-  mType(aType)
+  mObject(nsnull)
 {
 }
 
 PluginScriptableObjectParent::~PluginScriptableObjectParent()
 {
   if (mObject) {
-    if (mObject->_class == GetClass()) {
-      NS_ASSERTION(mType == Proxy, "Wrong type!");
-      static_cast<ParentNPObject*>(mObject)->parent = nsnull;
+    if (GetClass() == mObject->_class) {
+      static_cast<ParentNPObject*>(mObject)->parent = NULL;
     }
     else {
-      NS_ASSERTION(mType == LocalObject, "Wrong type!");
-      GetInstance()->GetNPNIface()->releaseobject(mObject);
+      mInstance->GetNPNIface()->releaseobject(mObject);
     }
   }
 }
 
 void
-PluginScriptableObjectParent::InitializeProxy()
+PluginScriptableObjectParent::Initialize(PluginInstanceParent* aInstance,
+                                         NPObject* aObject)
 {
-  NS_ASSERTION(mType == Proxy, "Bad type!");
-  NS_ASSERTION(!mObject, "Calling Initialize more than once!");
-
-  mInstance = static_cast<PluginInstanceParent*>(Manager());
-  NS_ASSERTION(mInstance, "Null manager?!");
-
-  NPObject* object = CreateProxyObject();
-  NS_ASSERTION(object, "Failed to create object!");
-
-  if (!mInstance->RegisterNPObjectForActor(object, this)) {
-    NS_ERROR("Out of memory?");
-  }
-
-  mObject = object;
-}
-
-void
-PluginScriptableObjectParent::InitializeLocal(NPObject* aObject)
-{
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
+  NS_ASSERTION(aInstance && aObject, "Null pointers!");
   NS_ASSERTION(!(mInstance && mObject), "Calling Initialize more than once!");
 
-  mInstance = static_cast<PluginInstanceParent*>(Manager());
-  NS_ASSERTION(mInstance, "Null manager?!");
+  if (aObject->_class == GetClass()) {
+    ParentNPObject* object = static_cast<ParentNPObject*>(aObject);
 
-  mInstance->GetNPNIface()->retainobject(aObject);
+    NS_ASSERTION(!object->parent, "Bad object!");
+    object->parent = const_cast<PluginScriptableObjectParent*>(this);
 
-  NS_ASSERTION(!mProtectCount, "Should be zero!");
-  mProtectCount++;
-
-  if (!mInstance->RegisterNPObjectForActor(aObject, this)) {
-    NS_ERROR("Out of memory?");
+    // We don't want to have the actor own this object but rather let the object
+    // own this actor. Set the reference count to 0 here so that when the object
+    // dies we will send the destructor message to the child.
+    NS_ASSERTION(aObject->referenceCount == 1, "Some kind of live object!");
+    object->referenceCount = 0;
+    NS_LOG_RELEASE(aObject, 0, "BrowserNPObject");
+  }
+  else {
+    aInstance->GetNPNIface()->retainobject(aObject);
   }
 
+  mInstance = aInstance;
   mObject = aObject;
 }
 
-NPObject*
-PluginScriptableObjectParent::CreateProxyObject()
-{
-  NS_ASSERTION(mInstance, "Must have an instance!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance);
-
-  NPObject* npobject = npn->createobject(mInstance->GetNPP(),
-                                         const_cast<NPClass*>(GetClass()));
-  NS_ASSERTION(npobject, "Failed to create object?!");
-  NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
-  NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
-
-  ParentNPObject* object = static_cast<ParentNPObject*>(npobject);
-  NS_ASSERTION(!object->invalidated, "Bad object!");
-  NS_ASSERTION(!object->parent, "Bad object!");
-
-  // We don't want to have the actor own this object but rather let the object
-  // own this actor. Set the reference count to 0 here so that when the object
-  // dies we will send the destructor message to the child.
-  object->referenceCount = 0;
-  NS_LOG_RELEASE(object, 0, "BrowserNPObject");
-
-  object->parent = const_cast<PluginScriptableObjectParent*>(this);
-  return object;
-}
-
 bool
-PluginScriptableObjectParent::ResurrectProxyObject()
-{
-  NS_ASSERTION(mInstance, "Must have an instance already!");
-  NS_ASSERTION(!mObject, "Should not have an object already!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  InitializeProxy();
-  NS_ASSERTION(mObject, "Initialize failed!");
-
-  if (!CallProtect()) {
-    NS_WARNING("Failed to send message!");
-    return false;
-  }
-
-  return true;
-}
-
-NPObject*
-PluginScriptableObjectParent::GetObject(bool aCanResurrect)
-{
-  if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
-    NS_ERROR("Null object!");
-    return nsnull;
-  }
-  return mObject;
-}
-
-void
-PluginScriptableObjectParent::Protect()
+PluginScriptableObjectParent::AnswerInvalidate()
 {
-  NS_ASSERTION(mObject, "No object!");
-  NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
-
-  if (mType == LocalObject) {
-    ++mProtectCount;
-  }
-}
-
-void
-PluginScriptableObjectParent::Unprotect()
-{
-  NS_ASSERTION(mObject, "No object!");
-  NS_ASSERTION(mProtectCount >= 0, "Negative protect count?!");
-
-  if (mType == LocalObject) {
-    if (--mProtectCount == 0) {
-      PluginScriptableObjectParent::Call__delete__(this);
+  if (mObject) {
+    NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
+    const NPNetscapeFuncs* npn = GetNetscapeFuncs(GetInstance());
+    if (npn) {
+      npn->releaseobject(mObject);
     }
+    mObject = nsnull;
   }
-}
-
-void
-PluginScriptableObjectParent::DropNPObject()
-{
-  NS_ASSERTION(mObject, "Invalidated object!");
-  NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!");
-  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
-
-  // We think we're about to be deleted, but we could be racing with the other
-  // process.
-  PluginInstanceParent* instance = GetInstance();
-  NS_ASSERTION(instance, "Must have an instance!");
-
-  instance->UnregisterNPObject(mObject);
-  mObject = nsnull;
-
-  if (!CallUnprotect()) {
-    NS_WARNING("Failed to send message!");
-  }
+  return true;
 }
 
 bool
 PluginScriptableObjectParent::AnswerHasMethod(const NPRemoteIdentifier& aId,
                                               bool* aHasMethod)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
     *aHasMethod = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aHasMethod = false;
     return true;
   }
 
@@ -781,17 +847,16 @@ PluginScriptableObjectParent::AnswerInvo
   if (!mObject) {
     NS_WARNING("Calling AnswerInvoke with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -844,17 +909,17 @@ PluginScriptableObjectParent::AnswerInvo
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
   success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
 
-  DeferNPVariantLastRelease(npn, &result);
+  ReleaseVariant(result, instance);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   *aResult = convertedResult;
@@ -870,17 +935,16 @@ PluginScriptableObjectParent::AnswerInvo
   if (!mObject) {
     NS_WARNING("Calling AnswerInvoke with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -927,17 +991,17 @@ PluginScriptableObjectParent::AnswerInvo
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
   success = ConvertToRemoteVariant(result, convertedResult, GetInstance());
 
-  DeferNPVariantLastRelease(npn, &result);
+  ReleaseVariant(result, instance);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   *aResult = convertedResult;
@@ -951,17 +1015,16 @@ PluginScriptableObjectParent::AnswerHasP
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
     *aHasProperty = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aHasProperty = false;
     return true;
   }
 
@@ -991,17 +1054,16 @@ PluginScriptableObjectParent::AnswerGetP
   if (!mObject) {
     NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -1026,17 +1088,17 @@ PluginScriptableObjectParent::AnswerGetP
                         &result)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant converted;
   if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) {
-    DeferNPVariantLastRelease(npn, &result);
+    ReleaseVariant(result, instance);
     *aResult = converted;
   }
   else {
     *aResult = void_t();
   }
 
   return true;
 }
@@ -1048,17 +1110,16 @@ PluginScriptableObjectParent::AnswerSetP
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return true;
   }
 
@@ -1094,17 +1155,16 @@ PluginScriptableObjectParent::AnswerRemo
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return true;
   }
 
@@ -1132,17 +1192,16 @@ PluginScriptableObjectParent::AnswerEnum
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return true;
   }
 
@@ -1189,17 +1248,16 @@ PluginScriptableObjectParent::AnswerCons
   if (!mObject) {
     NS_WARNING("Calling AnswerConstruct with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -1245,50 +1303,30 @@ PluginScriptableObjectParent::AnswerCons
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
   success = ConvertToRemoteVariant(result, convertedResult, instance);
 
-  DeferNPVariantLastRelease(npn, &result);
+  ReleaseVariant(result, instance);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   *aSuccess = true;
   *aResult = convertedResult;
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerProtect()
-{
-  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-
-  Protect();
-  return true;
-}
-
-bool
-PluginScriptableObjectParent::AnswerUnprotect()
-{
-  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
-  NS_ASSERTION(mType == LocalObject, "Bad type!");
-
-  Unprotect();
-  return true;
-}
-
-bool
 PluginScriptableObjectParent::AnswerNPN_Evaluate(const nsCString& aScript,
                                                  Variant* aResult,
                                                  bool* aSuccess)
 {
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
@@ -1312,17 +1350,17 @@ PluginScriptableObjectParent::AnswerNPN_
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant convertedResult;
   success = ConvertToRemoteVariant(result, convertedResult, instance);
 
-  DeferNPVariantLastRelease(npn, &result);
+  ReleaseVariant(result, instance);
 
   if (!success) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   *aSuccess = true;
--- a/dom/plugins/PluginScriptableObjectParent.h
+++ b/dom/plugins/PluginScriptableObjectParent.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
+ * vim: sw=4 ts=4 et :
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -48,37 +48,31 @@ namespace mozilla {
 namespace plugins {
 
 class PluginInstanceParent;
 class PluginScriptableObjectParent;
 
 struct ParentNPObject : NPObject
 {
   ParentNPObject()
-    : NPObject(), parent(NULL), invalidated(false) { }
+    : parent(NULL) { }
 
-  // |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;
 };
 
 class PluginScriptableObjectParent : public PPluginScriptableObjectParent
 {
   friend class PluginInstanceParent;
 
 public:
-  PluginScriptableObjectParent(ScriptableObjectType aType);
+  PluginScriptableObjectParent();
   virtual ~PluginScriptableObjectParent();
 
-  void
-  InitializeProxy();
-
-  void
-  InitializeLocal(NPObject* aObject);
+  virtual bool
+  AnswerInvalidate();
 
   virtual bool
   AnswerHasMethod(const NPRemoteIdentifier& aId,
                   bool* aHasMethod);
 
   virtual bool
   AnswerInvoke(const NPRemoteIdentifier& aId,
                const nsTArray<Variant>& aArgs,
@@ -117,59 +111,36 @@ public:
                   Variant* aResult,
                   bool* aSuccess);
 
   virtual bool
   AnswerNPN_Evaluate(const nsCString& aScript,
                      Variant* aResult,
                      bool* aSuccess);
 
-  virtual bool
-  AnswerProtect();
-
-  virtual bool
-  AnswerUnprotect();
+  void
+  Initialize(PluginInstanceParent* aInstance,
+             NPObject* aObject);
 
   static const NPClass*
   GetClass()
   {
     return &sNPClass;
   }
 
   PluginInstanceParent*
-  GetInstance() const
+  GetInstance()
   {
     return mInstance;
   }
 
   NPObject*
-  GetObject(bool aCanResurrect);
-
-  // Protect only affects LocalObject actors. It is called by the
-  // ProtectedVariant/Actor helper classes before the actor is used as an
-  // argument to an IPC call and when the child process resurrects a
-  // proxy object to the NPObject associated with this actor.
-  void Protect();
-
-  // Unprotect only affects LocalObject actors. It is called by the
-  // ProtectedVariant/Actor helper classes after the actor is used as an
-  // argument to an IPC call and when the child process is no longer using this
-  // actor.
-  void Unprotect();
-
-  // DropNPObject is only used for Proxy actors and is called when the parent
-  // process is no longer using the NPObject associated with this actor. The
-  // child process may subsequently use this actor again in which case a new
-  // NPObject will be created and associated with this actor (see
-  // ResurrectProxyObject).
-  void DropNPObject();
-
-  ScriptableObjectType
-  Type() const {
-    return mType;
+  GetObject()
+  {
+    return mObject;
   }
 
 private:
   static NPObject*
   ScriptableAllocate(NPP aInstance,
                      NPClass* aClass);
 
   static void
@@ -219,33 +190,22 @@ private:
                       uint32_t* aCount);
 
   static bool
   ScriptableConstruct(NPObject* aObject,
                       const NPVariant* aArgs,
                       uint32_t aArgCount,
                       NPVariant* aResult);
 
-  NPObject*
-  CreateProxyObject();
-
-  // ResurrectProxyObject is only used with Proxy actors. It is called when the
-  // child process uses an actor whose NPObject was deleted by the parent
-  // process.
-  bool ResurrectProxyObject();
-
 private:
   PluginInstanceParent* mInstance;
 
   // This may be a ParentNPObject or some other kind depending on who created
   // it. Have to check its class to find out.
   NPObject* mObject;
-  int mProtectCount;
-
-  ScriptableObjectType mType;
 
   static const NPClass sNPClass;
 };
 
 } /* namespace plugins */
 } /* namespace mozilla */
 
 #endif /* dom_plugins_PluginScriptableObjectParent_h */
deleted file mode 100644
--- a/dom/plugins/PluginScriptableObjectUtils-inl.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Plugin App.
- *
- * The Initial Developer of the Original Code is
- *   The Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ben Turner <bent.mozilla@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "PluginScriptableObjectUtils.h"
-
-namespace {
-
-template<class InstanceType>
-class VariantTraits;
-
-template<>
-class VariantTraits<mozilla::plugins::PluginInstanceParent>
-{
-public:
-  typedef mozilla::plugins::PluginScriptableObjectParent ScriptableObjectType;
-};
-
-template<>
-class VariantTraits<mozilla::plugins::PluginInstanceChild>
-{
-public:
-  typedef mozilla::plugins::PluginScriptableObjectChild ScriptableObjectType;
-};
-
-} /* anonymous namespace */
-
-inline bool
-mozilla::plugins::ConvertToVariant(const Variant& aRemoteVariant,
-                                   NPVariant& aVariant,
-                                   PluginInstanceParent* aInstance)
-{
-  switch (aRemoteVariant.type()) {
-    case Variant::Tvoid_t: {
-      VOID_TO_NPVARIANT(aVariant);
-      break;
-    }
-
-    case Variant::Tnull_t: {
-      NULL_TO_NPVARIANT(aVariant);
-      break;
-    }
-
-    case Variant::Tbool: {
-      BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant);
-      break;
-    }
-
-    case Variant::Tint: {
-      INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant);
-      break;
-    }
-
-    case Variant::Tdouble: {
-      DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant);
-      break;
-    }
-
-    case Variant::TnsCString: {
-      const nsCString& string = aRemoteVariant.get_nsCString();
-      NPUTF8* buffer = reinterpret_cast<NPUTF8*>(strdup(string.get()));
-      if (!buffer) {
-        NS_ERROR("Out of memory!");
-        return false;
-      }
-      STRINGN_TO_NPVARIANT(buffer, string.Length(), aVariant);
-      break;
-    }
-
-    case Variant::TPPluginScriptableObjectParent: {
-      NS_ASSERTION(aInstance, "Must have an instance!");
-      NPObject* object = NPObjectFromVariant(aRemoteVariant);
-      if (!object) {
-        NS_ERROR("Er, this shouldn't fail!");
-        return false;
-      }
-
-      const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
-      if (!npn) {
-        NS_ERROR("Null netscape funcs!");
-        return false;
-      }
-
-      npn->retainobject(object);
-      OBJECT_TO_NPVARIANT(object, aVariant);
-      break;
-    }
-
-    case Variant::TPPluginScriptableObjectChild: {
-      NS_ASSERTION(!aInstance, "No instance should be given!");
-      NS_ASSERTION(PluginModuleChild::current(),
-                   "Should be running on child only!");
-
-      NPObject* object = NPObjectFromVariant(aRemoteVariant);
-      NS_ASSERTION(object, "Null object?!");
-
-      PluginModuleChild::sBrowserFuncs.retainobject(object);
-      OBJECT_TO_NPVARIANT(object, aVariant);
-      break;
-    }
-
-    default:
-      NS_NOTREACHED("Shouldn't get here!");
-      return false;
-  }
-
-  return true;
-}
-
-template <class InstanceType>
-bool
-mozilla::plugins::ConvertToRemoteVariant(const NPVariant& aVariant,
-                                         Variant& aRemoteVariant,
-                                         InstanceType* aInstance,
-                                         bool aProtectActors)
-{
-  if (NPVARIANT_IS_VOID(aVariant)) {
-    aRemoteVariant = mozilla::void_t();
-  }
-  else if (NPVARIANT_IS_NULL(aVariant)) {
-    aRemoteVariant = mozilla::null_t();
-  }
-  else if (NPVARIANT_IS_BOOLEAN(aVariant)) {
-    aRemoteVariant = NPVARIANT_TO_BOOLEAN(aVariant);
-  }
-  else if (NPVARIANT_IS_INT32(aVariant)) {
-    aRemoteVariant = NPVARIANT_TO_INT32(aVariant);
-  }
-  else if (NPVARIANT_IS_DOUBLE(aVariant)) {
-    aRemoteVariant = NPVARIANT_TO_DOUBLE(aVariant);
-  }
-  else if (NPVARIANT_IS_STRING(aVariant)) {
-    NPString str = NPVARIANT_TO_STRING(aVariant);
-    nsCString string(str.UTF8Characters, str.UTF8Length);
-    aRemoteVariant = string;
-  }
-  else if (NPVARIANT_IS_OBJECT(aVariant)) {
-    NPObject* object = NPVARIANT_TO_OBJECT(aVariant);
-
-    typename VariantTraits<InstanceType>::ScriptableObjectType* actor =
-      aInstance->GetActorForNPObject(object);
-
-    if (!actor) {
-      NS_ERROR("Null actor!");
-      return false;
-    }
-
-    if (aProtectActors) {
-      actor->Protect();
-    }
-
-    aRemoteVariant = actor;
-  }
-  else {
-    NS_NOTREACHED("Shouldn't get here!");
-    return false;
-  }
-
-  return true;
-}
deleted file mode 100644
--- a/dom/plugins/PluginScriptableObjectUtils.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 et :
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Plugin App.
- *
- * The Initial Developer of the Original Code is
- *   The Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ben Turner <bent.mozilla@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef dom_plugins_PluginScriptableObjectUtils_h
-#define dom_plugins_PluginScriptableObjectUtils_h
-
-#include "PluginModuleParent.h"
-#include "PluginModuleChild.h"
-#include "PluginInstanceParent.h"
-#include "PluginInstanceChild.h"
-#include "PluginScriptableObjectParent.h"
-#include "PluginScriptableObjectChild.h"
-
-#include "npapi.h"
-#include "npfunctions.h"
-#include "npruntime.h"
-
-#include "nsDebug.h"
-
-namespace mozilla {
-namespace plugins {
-
-inline PluginInstanceParent*
-GetInstance(NPObject* aObject)
-{
-  NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
-               "Bad class!");
-
-  ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
-    NS_WARNING("Calling method on an invalidated object!");
-    return nsnull;
-  }
-  if (!object->parent) {
-    return nsnull;
-  }
-  return object->parent->GetInstance();
-}
-
-inline NPObject*
-NPObjectFromVariant(const Variant& aRemoteVariant)
-{
-  switch (aRemoteVariant.type()) {
-    case Variant::TPPluginScriptableObjectParent: {
-      PluginScriptableObjectParent* actor =
-        const_cast<PluginScriptableObjectParent*>(
-          reinterpret_cast<const PluginScriptableObjectParent*>(
-            aRemoteVariant.get_PPluginScriptableObjectParent()));
-      return actor->GetObject(true);
-    }
-
-    case Variant::TPPluginScriptableObjectChild: {
-      PluginScriptableObjectChild* actor =
-        const_cast<PluginScriptableObjectChild*>(
-          reinterpret_cast<const PluginScriptableObjectChild*>(
-            aRemoteVariant.get_PPluginScriptableObjectChild()));
-      return actor->GetObject(true);
-    }
-
-    default:
-      NS_NOTREACHED("Shouldn't get here!");
-      return nsnull;
-  }
-}
-
-inline NPObject*
-NPObjectFromVariant(const NPVariant& aVariant)
-{
-  NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!");
-  return NPVARIANT_TO_OBJECT(aVariant);
-}
-
-inline const NPNetscapeFuncs*
-GetNetscapeFuncs(PluginInstanceParent* aInstance)
-{
-  PluginModuleParent* module = aInstance->Module();
-  if (!module) {
-    NS_WARNING("Null module?!");
-    return nsnull;
-  }
-  return module->GetNetscapeFuncs();
-}
-
-inline const NPNetscapeFuncs*
-GetNetscapeFuncs(NPObject* aObject)
-{
-  NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
-               "Bad class!");
-
-  PluginInstanceParent* instance = GetInstance(aObject);
-  if (!instance) {
-    return nsnull;
-  }
-
-  return GetNetscapeFuncs(instance);
-}
-
-inline void
-ReleaseRemoteVariant(Variant& aVariant)
-{
-  switch (aVariant.type()) {
-    case Variant::TPPluginScriptableObjectParent: {
-      PluginScriptableObjectParent* actor =
-        const_cast<PluginScriptableObjectParent*>(
-          reinterpret_cast<const PluginScriptableObjectParent*>(
-            aVariant.get_PPluginScriptableObjectParent()));
-      actor->Unprotect();
-      break;
-    }
-
-    case Variant::TPPluginScriptableObjectChild: {
-      NS_ASSERTION(PluginModuleChild::current(),
-                   "Should only be running in the child!");
-      PluginScriptableObjectChild* actor =
-        const_cast<PluginScriptableObjectChild*>(
-          reinterpret_cast<const PluginScriptableObjectChild*>(
-            aVariant.get_PPluginScriptableObjectChild()));
-      actor->Unprotect();
-      break;
-    }
-
-  default:
-    break; // Intentional fall-through for other variant types.
-  }
-
-  aVariant = mozilla::void_t();
-}
-
-bool
-ConvertToVariant(const Variant& aRemoteVariant,
-                 NPVariant& aVariant,
-                 PluginInstanceParent* aInstance = nsnull);
-
-template <class InstanceType>
-bool
-ConvertToRemoteVariant(const NPVariant& aVariant,
-                       Variant& aRemoteVariant,
-                       InstanceType* aInstance,
-                       bool aProtectActors = false);
-
-class ProtectedVariant
-{
-public:
-  ProtectedVariant(const NPVariant& aVariant,
-                   PluginInstanceParent* aInstance)
-  {
-    mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true);
-  }
-
-  ProtectedVariant(const NPVariant& aVariant,
-                   PluginInstanceChild* aInstance)
-  {
-    mOk = ConvertToRemoteVariant(aVariant, mVariant, aInstance, true);
-  }
-
-  ~ProtectedVariant() {
-    ReleaseRemoteVariant(mVariant);
-  }
-
-  PRBool IsOk() {
-    return mOk;
-  }
-
-  operator const Variant&() {
-    return mVariant;
-  }
-
-private:
-  Variant mVariant;
-  bool mOk;
-};
-
-class ProtectedVariantArray
-{
-public:
-  ProtectedVariantArray(const NPVariant* aArgs,
-                        PRUint32 aCount,
-                        PluginInstanceParent* aInstance)
-  {
-    for (PRUint32 index = 0; index < aCount; index++) {
-      Variant* remoteVariant = mArray.AppendElement();
-      if (!(remoteVariant && 
-            ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance,
-                                   true))) {
-        break;
-      }
-    }
-    mOk = mArray.Length() == aCount;
-  }
-
-  ProtectedVariantArray(const NPVariant* aArgs,
-                        PRUint32 aCount,
-                        PluginInstanceChild* aInstance)
-  {
-    for (PRUint32 index = 0; index < aCount; index++) {
-      Variant* remoteVariant = mArray.AppendElement();
-      if (!(remoteVariant && 
-            ConvertToRemoteVariant(aArgs[index], *remoteVariant, aInstance,
-                                   true))) {
-        break;
-      }
-    }
-    mOk = mArray.Length() == aCount;
-  }
-  ~ProtectedVariantArray()
-  {
-    PRUint32 count = mArray.Length();
-    for (PRUint32 index = 0; index < count; index++) {
-      ReleaseRemoteVariant(mArray[index]);
-    }
-  }
-
-  operator const nsTArray<Variant>&()
-  {
-    return mArray;
-  }
-
-  bool IsOk()
-  {
-    return mOk;
-  }
-
-private:
-  nsTArray<Variant> mArray;
-  bool mOk;
-};
-
-template<class ActorType>
-struct ProtectedActorTraits
-{
-  static bool Nullable();
-};
-
-template<class ActorType, class Traits=ProtectedActorTraits<ActorType> >
-class ProtectedActor
-{
-public:
-  ProtectedActor(ActorType* aActor) : mActor(aActor)
-  {
-    if (!Traits::Nullable()) {
-      NS_ASSERTION(mActor, "This should never be null!");
-    }
-  }
-
-  ~ProtectedActor()
-  {
-    if (Traits::Nullable() && !mActor)
-      return;
-    mActor->Unprotect();
-  }
-
-  ActorType* operator->()
-  {
-    return mActor;
-  }
-
-  operator bool()
-  {
-    return !!mActor;
-  }
-
-private:
-  ActorType* mActor;
-};
-
-template<>
-struct ProtectedActorTraits<PluginScriptableObjectParent>
-{
-  static bool Nullable() { return true; }
-};
-
-template<>
-struct ProtectedActorTraits<PluginScriptableObjectChild>
-{
-  static bool Nullable() { return false; }
-};
-
-} /* namespace plugins */
-} /* namespace mozilla */
-
-#include "PluginScriptableObjectUtils-inl.h"
-
-#endif /* dom_plugins_PluginScriptableObjectUtils_h */
--- a/modules/plugin/base/src/nsNPAPIPlugin.cpp
+++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp
@@ -328,23 +328,23 @@ OOPPluginsEnabled()
   PRBool oopPluginsEnabled = PR_FALSE;
   prefs->GetBoolPref("dom.ipc.plugins.enabled", &oopPluginsEnabled);
 
   if (!oopPluginsEnabled) {
     return PR_FALSE;
   }
 
 #ifdef XP_WIN
-  OSVERSIONINFO osVerInfo = {0};
-  osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
-  GetVersionEx(&osVerInfo);
-  // Always disabled on 2K or less. (bug 536303)
-  if (osVerInfo.dwMajorVersion < 5 ||
-      (osVerInfo.dwMajorVersion == 5 && osVerInfo.dwMinorVersion == 0))
-    return PR_FALSE;
+  OSVERSIONINFO osVerInfo = {0};
+  osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
+  GetVersionEx(&osVerInfo);
+  // Always disabled on 2K or less. (bug 536303)
+  if (osVerInfo.dwMajorVersion < 5 ||
+      (osVerInfo.dwMajorVersion == 5 && osVerInfo.dwMinorVersion == 0))
+    return PR_FALSE;
 #endif
 
   return PR_TRUE;
 }
 
 #endif // MOZ_IPC
 
 inline PluginLibrary*