diff --git a/dom/plugins/PPluginScriptableObject.ipdl b/dom/plugins/PPluginScriptableObject.ipdl index 7e5d77cf8568..85e650259561 100644 --- a/dom/plugins/PPluginScriptableObject.ipdl +++ b/dom/plugins/PPluginScriptableObject.ipdl @@ -48,8 +48,7 @@ using mozilla::ipc::NPRemoteIdentifier; using nsTArray; using mozilla::void_t; using mozilla::null_t; -using mozilla::ipc::NPRemoteVariant; -using nsTArray; +using nsTArray; namespace mozilla { namespace plugins { @@ -68,7 +67,7 @@ rpc protocol PPluginScriptableObject { manager PPluginInstance; -child: +both: // NPClass methods rpc Invalidate(); @@ -76,23 +75,23 @@ child: returns (bool aHasMethod); rpc Invoke(NPRemoteIdentifier aId, - nsTArray aArgs) - returns (NPRemoteVariant aResult, + nsTArray aArgs) + returns (Variant aResult, bool aSuccess); - rpc InvokeDefault(nsTArray aArgs) - returns (NPRemoteVariant aResult, + rpc InvokeDefault(nsTArray aArgs) + returns (Variant aResult, bool aSuccess); rpc HasProperty(NPRemoteIdentifier aId) returns (bool aHasProperty); rpc GetProperty(NPRemoteIdentifier aId) - returns (NPRemoteVariant aResult, + returns (Variant aResult, bool aSuccess); rpc SetProperty(NPRemoteIdentifier aId, - NPRemoteVariant aValue) + Variant aValue) returns (bool aSuccess); rpc RemoveProperty(NPRemoteIdentifier aId) @@ -102,8 +101,8 @@ child: returns (nsTArray aProperties, bool aSuccess); - rpc Construct(nsTArray aArgs) - returns (NPRemoteVariant aResult, + rpc Construct(nsTArray aArgs) + returns (Variant aResult, bool aSuccess); }; diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index 02be35efe825..66bfa697d5d2 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -124,6 +124,48 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar, return result; } + case NPNVWindowNPObject: { + PPluginScriptableObjectChild* actor; + NPError result; + if (!CallNPN_GetValue_NPNVWindowNPObject(&actor, &result)) { + NS_WARNING("Failed to send message!"); + return NPERR_GENERIC_ERROR; + } + + if (result != NPERR_NO_ERROR) { + return result; + } + + NPObject* object = + static_cast(actor)->GetObject(); + NS_ASSERTION(object, "Null object?!"); + + PluginModuleChild::sBrowserFuncs.retainobject(object); + *((NPObject**)aValue) = object; + return NPERR_NO_ERROR; + } + + case NPNVPluginElementNPObject: { + PPluginScriptableObjectChild* actor; + NPError result; + if (!CallNPN_GetValue_NPNVPluginElementNPObject(&actor, &result)) { + NS_WARNING("Failed to send message!"); + return NPERR_GENERIC_ERROR; + } + + if (result != NPERR_NO_ERROR) { + return result; + } + + NPObject* object = + static_cast(actor)->GetObject(); + NS_ASSERTION(object, "Null object?!"); + + PluginModuleChild::sBrowserFuncs.retainobject(object); + *((NPObject**)aValue) = object; + return NPERR_NO_ERROR; + } + default: printf(" unhandled var %s\n", NPNVariableToString(aVar)); return NPERR_GENERIC_ERROR; @@ -222,13 +264,16 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject( } PluginScriptableObjectChild* actor = GetActorForNPObject(object); + + // If we get an actor then it has retained. Otherwise we don't need it any + // longer. + PluginModuleChild::sBrowserFuncs.releaseobject(object); + if (!actor) { - PluginModuleChild::sBrowserFuncs.releaseobject(object); *result = NPERR_GENERIC_ERROR; return true; } - PluginModuleChild::sBrowserFuncs.releaseobject(object); *value = actor; return true; } @@ -345,11 +390,31 @@ bool PluginInstanceChild::Initialize() { #if defined(OS_WIN) - if (!CreatePluginWindow()) - return false; + if (!CreatePluginWindow()) + return false; #endif - return true; + return true; +} + +void +PluginInstanceChild::Destroy() +{ + // Copy the actors here so we don't enumerate a mutating array. + nsAutoTArray 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) @@ -509,11 +574,18 @@ PluginInstanceChild::AllocPPluginScriptableObject() } bool -PluginInstanceChild::DeallocPPluginScriptableObject(PPluginScriptableObjectChild* aObject) +PluginInstanceChild::DeallocPPluginScriptableObject( + PPluginScriptableObjectChild* aObject) { PluginScriptableObjectChild* object = reinterpret_cast(aObject); + NPObject* npobject = object->GetObject(); + if (npobject && + npobject->_class != PluginScriptableObjectChild::GetClass()) { + PluginModuleChild::current()->UnregisterNPObject(npobject); + } + PRUint32 count = mScriptableObjects.Length(); for (PRUint32 index = 0; index < count; index++) { if (mScriptableObjects[index] == object) { @@ -525,6 +597,30 @@ PluginInstanceChild::DeallocPPluginScriptableObject(PPluginScriptableObjectChild return false; } +bool +PluginInstanceChild::AnswerPPluginScriptableObjectConstructor( + PPluginScriptableObjectChild* aActor) +{ + // 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(PluginScriptableObjectChild::GetClass()); + + ChildNPObject* object = reinterpret_cast( + PluginModuleChild::sBrowserFuncs.createobject(GetNPP(), npclass)); + if (!object) { + NS_WARNING("Failed to create NPObject!"); + return false; + } + + PluginScriptableObjectChild* actor = + static_cast(aActor); + actor->Initialize(const_cast(this), object); + + return true; +} + PBrowserStreamChild* PluginInstanceChild::AllocPBrowserStream(const nsCString& url, const uint32_t& length, @@ -616,12 +712,18 @@ PluginInstanceChild::GetActorForNPObject(NPObject* aObject) { NS_ASSERTION(aObject, "Null pointer!"); + if (aObject->_class == PluginScriptableObjectChild::GetClass()) { + // One of ours! It's a browser-provided object. + ChildNPObject* object = static_cast(aObject); + NS_ASSERTION(object->parent, "Null actor!"); + return object->parent; + } PluginScriptableObjectChild* actor = PluginModuleChild::current()->GetActorForNPObject(aObject); if (actor) { - PluginModuleChild::sBrowserFuncs.retainobject(aObject); - return actor; + // Plugin-provided object that we've previously wrapped. + return actor; } actor = reinterpret_cast( diff --git a/dom/plugins/PluginInstanceChild.h b/dom/plugins/PluginInstanceChild.h index a1e88f1a2b89..ffce88d0d403 100644 --- a/dom/plugins/PluginInstanceChild.h +++ b/dom/plugins/PluginInstanceChild.h @@ -90,6 +90,9 @@ protected: virtual bool DeallocPPluginScriptableObject(PPluginScriptableObjectChild* aObject); + virtual bool + AnswerPPluginScriptableObjectConstructor(PPluginScriptableObjectChild* aActor); + virtual PBrowserStreamChild* AllocPBrowserStream(const nsCString& url, const uint32_t& length, @@ -158,6 +161,7 @@ public: virtual ~PluginInstanceChild(); bool Initialize(); + void Destroy(); NPP GetNPP() { diff --git a/dom/plugins/PluginInstanceParent.cpp b/dom/plugins/PluginInstanceParent.cpp index a4007e9b8f35..3e9906972b64 100644 --- a/dom/plugins/PluginInstanceParent.cpp +++ b/dom/plugins/PluginInstanceParent.cpp @@ -61,6 +61,25 @@ PluginInstanceParent::~PluginInstanceParent() { } +void +PluginInstanceParent::Destroy() +{ + // Copy the actors here so we don't enumerate a mutating array. + nsAutoTArray 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); + } + } +} + PBrowserStreamParent* PluginInstanceParent::AllocPBrowserStream(const nsCString& url, const uint32_t& length, @@ -138,25 +157,59 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVisOfflineBool(bool* value, } bool -PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject( - PPluginScriptableObjectParent** value, - NPError* result) +PluginInstanceParent::InternalGetValueForNPObject( + NPNVariable aVariable, + PPluginScriptableObjectParent** aValue, + NPError* aResult) { - // TODO NPRuntime - *value = NULL; - *result = NPERR_GENERIC_ERROR; + NPObject* npobject; + NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject); + if (result != NPERR_NO_ERROR || !npobject) { + *aValue = nsnull; + *aResult = result; + return true; + } + + PluginScriptableObjectParent* actor = + static_cast( + AllocPPluginScriptableObject()); + + if (!actor) { + mNPNIface->releaseobject(npobject); + *aValue = nsnull; + *aResult = NPERR_OUT_OF_MEMORY_ERROR; + return true; + } + + if (!CallPPluginScriptableObjectConstructor(actor)) { + mNPNIface->releaseobject(npobject); + DeallocPPluginScriptableObject(actor); + *aValue = nsnull; + *aResult = NPERR_GENERIC_ERROR; + return true; + } + + actor->Initialize(const_cast(this), npobject); + *aValue = actor; + *aResult = NPERR_NO_ERROR; return true; } bool -PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject( - PPluginScriptableObjectParent** value, - NPError* result) +PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject( + PPluginScriptableObjectParent** aValue, + NPError* aResult) { - // TODO NPRuntime - *value = NULL; - *result = NPERR_GENERIC_ERROR; - return true; + return InternalGetValueForNPObject(NPNVWindowNPObject, aValue, aResult); +} + +bool +PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject( + PPluginScriptableObjectParent** aValue, + NPError* aResult) +{ + return InternalGetValueForNPObject(NPNVPluginElementNPObject, aValue, + aResult); } bool @@ -360,8 +413,7 @@ PluginInstanceParent::NPP_GetValue(NPPVariable aVariable, } NPObject* object = - reinterpret_cast(actor)-> - GetObject(); + static_cast(actor)->GetObject(); NS_ASSERTION(object, "This shouldn't ever be null!"); (*(NPObject**)_retval) = npn->retainobject(object); @@ -486,19 +538,26 @@ 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. const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs(); if (!npn) { NS_WARNING("No netscape function pointers?!"); return false; } + NPClass* npclass = + const_cast(PluginScriptableObjectParent::GetClass()); + ParentNPObject* object = reinterpret_cast( - npn->createobject(mNPP, PluginScriptableObjectParent::GetClass())); + npn->createobject(mNPP, npclass)); if (!object) { + NS_WARNING("Failed to create NPObject!"); return false; } - reinterpret_cast(aActor)->Initialize( + static_cast(aActor)->Initialize( const_cast(this), object); return true; } @@ -513,3 +572,33 @@ PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason, static_cast(notifyData); CallPStreamNotifyDestructor(streamNotify, reason); } + +PluginScriptableObjectParent* +PluginInstanceParent::GetActorForNPObject(NPObject* aObject) +{ + NS_ASSERTION(aObject, "Null pointer!"); + + if (aObject->_class == PluginScriptableObjectParent::GetClass()) { + // One of ours! + ParentNPObject* object = static_cast(aObject); + NS_ASSERTION(object->parent, "Null actor!"); + return object->parent; + } + + PRUint32 count = mScriptableObjects.Length(); + for (PRUint32 index = 0; index < count; index++) { + nsAutoPtr& actor = + mScriptableObjects[index]; + if (actor->GetObject() == aObject) { + return actor; + } + } + + PluginScriptableObjectParent* actor = + static_cast( + CallPPluginScriptableObjectConstructor()); + NS_ENSURE_TRUE(actor, nsnull); + + actor->Initialize(const_cast(this), aObject); + return actor; +} diff --git a/dom/plugins/PluginInstanceParent.h b/dom/plugins/PluginInstanceParent.h index f7d57a3eb3e2..7a924464d036 100644 --- a/dom/plugins/PluginInstanceParent.h +++ b/dom/plugins/PluginInstanceParent.h @@ -69,6 +69,8 @@ public: virtual ~PluginInstanceParent(); + void Destroy(); + virtual PPluginScriptableObjectParent* AllocPPluginScriptableObject(); @@ -178,6 +180,25 @@ public: return mParent; } + const NPNetscapeFuncs* GetNPNIface() + { + return mNPNIface; + } + + PluginScriptableObjectParent* + GetActorForNPObject(NPObject* aObject); + + NPP + GetNPP() + { + return mNPP; + } + +private: + bool InternalGetValueForNPObject(NPNVariable aVariable, + PPluginScriptableObjectParent** aValue, + NPError* aResult); + private: PluginModuleParent* mParent; NPP mNPP; diff --git a/dom/plugins/PluginMessageUtils.h b/dom/plugins/PluginMessageUtils.h index 98950b43d4c8..d0e328689229 100644 --- a/dom/plugins/PluginMessageUtils.h +++ b/dom/plugins/PluginMessageUtils.h @@ -53,15 +53,9 @@ namespace mozilla { struct void_t { }; struct null_t { }; -// XXX Uberhack, remove this typedef and forward decl. -namespace plugins { -class Variant; -} - namespace ipc { typedef intptr_t NPRemoteIdentifier; -typedef mozilla::plugins::Variant NPRemoteVariant; } /* namespace ipc */ diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp index 9a58cc0f7be6..299551800a43 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -839,7 +839,10 @@ _createobject(NPP aNPP, NPObject* NP_CALLBACK _retainobject(NPObject* aNPObj) { - _MOZ_LOG(__FUNCTION__); +#ifdef DEBUG + printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__, + aNPObj, aNPObj->referenceCount + 1); +#endif ++aNPObj->referenceCount; return aNPObj; } @@ -847,8 +850,10 @@ _retainobject(NPObject* aNPObj) void NP_CALLBACK _releaseobject(NPObject* aNPObj) { - _MOZ_LOG(__FUNCTION__); - +#ifdef DEBUG + printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__, + aNPObj, aNPObj->referenceCount - 1); +#endif if (--aNPObj->referenceCount == 0) { if (aNPObj->_class && aNPObj->_class->deallocate) { aNPObj->_class->deallocate(aNPObj); @@ -868,7 +873,11 @@ _invoke(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invoke) + return false; + + return aNPObj->_class->invoke(aNPObj, aMethod, aArgs, aArgCount, aResult); } bool NP_CALLBACK @@ -879,7 +888,11 @@ _invokedefault(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invokeDefault) + return false; + + return aNPObj->_class->invokeDefault(aNPObj, aArgs, aArgCount, aResult); } bool NP_CALLBACK @@ -889,6 +902,7 @@ _evaluate(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -899,7 +913,11 @@ _getproperty(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->getProperty) + return false; + + return aNPObj->_class->getProperty(aNPObj, aPropertyName, aResult); } bool NP_CALLBACK @@ -909,7 +927,11 @@ _setproperty(NPP aNPP, const NPVariant* aValue) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->setProperty) + return false; + + return aNPObj->_class->setProperty(aNPObj, aPropertyName, aValue); } bool NP_CALLBACK @@ -918,7 +940,11 @@ _removeproperty(NPP aNPP, NPIdentifier aPropertyName) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->removeProperty) + return false; + + return aNPObj->_class->removeProperty(aNPObj, aPropertyName); } bool NP_CALLBACK @@ -927,7 +953,11 @@ _hasproperty(NPP aNPP, NPIdentifier aPropertyName) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasProperty) + return false; + + return aNPObj->_class->hasProperty(aNPObj, aPropertyName); } bool NP_CALLBACK @@ -936,7 +966,11 @@ _hasmethod(NPP aNPP, NPIdentifier aMethodName) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasMethod) + return false; + + return aNPObj->_class->hasMethod(aNPObj, aMethodName); } bool NP_CALLBACK @@ -946,7 +980,18 @@ _enumerate(NPP aNPP, uint32_t* aCount) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class) + return false; + + if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(aNPObj->_class) || + !aNPObj->_class->enumerate) { + *aIdentifiers = 0; + *aCount = 0; + return true; + } + + return aNPObj->_class->enumerate(aNPObj, aIdentifiers, aCount); } bool NP_CALLBACK @@ -957,13 +1002,31 @@ _construct(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); - return false; + + if (!aNPP || !aNPObj || !aNPObj->_class || + !NP_CLASS_STRUCT_VERSION_HAS_CTOR(aNPObj->_class) || + !aNPObj->_class->construct) { + return false; + } + + return aNPObj->_class->construct(aNPObj, aArgs, aArgCount, aResult); } void NP_CALLBACK _releasevariantvalue(NPVariant* aVariant) { _MOZ_LOG(__FUNCTION__); + if (NPVARIANT_IS_STRING(*aVariant)) { + NPString str = NPVARIANT_TO_STRING(*aVariant); + free(const_cast(str.UTF8Characters)); + } + else if (NPVARIANT_IS_OBJECT(*aVariant)) { + NPObject* object = NPVARIANT_TO_OBJECT(*aVariant); + if (object) { + _releaseobject(object); + } + } + VOID_TO_NPVARIANT(*aVariant); } void NP_CALLBACK @@ -971,6 +1034,7 @@ _setexception(NPObject* aNPObj, const NPUTF8* aMessage) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); } bool NP_CALLBACK @@ -978,6 +1042,7 @@ _pushpopupsenabledstate(NPP aNPP, NPBool aEnabled) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -985,6 +1050,7 @@ bool NP_CALLBACK _poppopupsenabledstate(NPP aNPP) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -994,6 +1060,7 @@ _pluginthreadasynccall(NPP aNPP, void* aUserData) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); } NPError NP_CALLBACK @@ -1001,6 +1068,7 @@ _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1009,6 +1077,7 @@ _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1020,6 +1089,7 @@ _getauthenticationinfo(NPP npp, const char *protocol, char **password, uint32_t *plen) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1028,12 +1098,14 @@ _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return 0; } void NP_CALLBACK _unscheduletimer(NPP instance, uint32_t timerID) { + NS_NOTYETIMPLEMENTED("Implement me!"); _MOZ_LOG(__FUNCTION__); } @@ -1041,6 +1113,7 @@ NPError NP_CALLBACK _popupcontextmenu(NPP instance, NPMenu* menu) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1050,6 +1123,7 @@ _convertpoint(NPP instance, double *destX, double *destY, NPCoordinateSpace destSpace) { _MOZ_LOG(__FUNCTION__); + NS_NOTYETIMPLEMENTED("Implement me!"); return 0; } @@ -1149,14 +1223,25 @@ PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor } bool -PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* actor, +PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor, NPError* rv) { _MOZ_LOG(__FUNCTION__); - PluginInstanceChild* inst = static_cast(actor); + delete aActor; + + return true; +} + +bool +PluginModuleChild::AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor, + NPError* rv) +{ + _MOZ_LOG(__FUNCTION__); + + PluginInstanceChild* inst = static_cast(aActor); *rv = mFunctions.destroy(inst->GetNPP(), 0); - delete actor; + inst->Destroy(); inst->GetNPP()->ndata = 0; return true; diff --git a/dom/plugins/PluginModuleChild.h b/dom/plugins/PluginModuleChild.h index 17c1d5cd814e..d0fd5a12efc1 100644 --- a/dom/plugins/PluginModuleChild.h +++ b/dom/plugins/PluginModuleChild.h @@ -112,6 +112,10 @@ protected: DeallocPPluginInstance(PPluginInstanceChild* aActor, NPError* rv); + virtual bool + AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor, + NPError* rv); + virtual bool AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor, const nsCString& aMimeType, diff --git a/dom/plugins/PluginModuleParent.cpp b/dom/plugins/PluginModuleParent.cpp index 6932686fae82..6521787d4cb0 100644 --- a/dom/plugins/PluginModuleParent.cpp +++ b/dom/plugins/PluginModuleParent.cpp @@ -102,6 +102,7 @@ PluginModuleParent::DeallocPPluginInstance(PPluginInstanceParent* aActor, { _MOZ_LOG(__FUNCTION__); delete aActor; + *_retval = NPERR_NO_ERROR; return true; } @@ -225,6 +226,8 @@ PluginModuleParent::NPP_Destroy(NPP instance, PluginInstanceParent* parentInstance = static_cast(instance->pdata); + parentInstance->Destroy(); + NPError prv; if (!Shim::HACK_target->CallPPluginInstanceDestructor(parentInstance, &prv)) { prv = NPERR_GENERIC_ERROR; diff --git a/dom/plugins/PluginScriptableObjectChild.cpp b/dom/plugins/PluginScriptableObjectChild.cpp index 6e2e2ebaba5e..00c42591e221 100644 --- a/dom/plugins/PluginScriptableObjectChild.cpp +++ b/dom/plugins/PluginScriptableObjectChild.cpp @@ -46,14 +46,15 @@ #include "PluginInstanceChild.h" using namespace mozilla::plugins; -using mozilla::ipc::NPRemoteVariant; +using mozilla::ipc::NPRemoteIdentifier; namespace { inline NPObject* -NPObjectFromVariant(const NPRemoteVariant& aRemoteVariant) { +NPObjectFromVariant(const Variant& aRemoteVariant) +{ NS_ASSERTION(aRemoteVariant.type() == - NPRemoteVariant::TPPluginScriptableObjectChild, + Variant::TPPluginScriptableObjectChild, "Wrong variant type!"); PluginScriptableObjectChild* actor = const_cast( @@ -63,73 +64,66 @@ NPObjectFromVariant(const NPRemoteVariant& aRemoteVariant) { } inline NPObject* -NPObjectFromVariant(const NPVariant& aVariant) { +NPObjectFromVariant(const NPVariant& aVariant) +{ NS_ASSERTION(NPVARIANT_IS_OBJECT(aVariant), "Wrong variant type!"); return NPVARIANT_TO_OBJECT(aVariant); } -bool -ConvertToVariant(const NPRemoteVariant& aRemoteVariant, +void +ConvertToVariant(const Variant& aRemoteVariant, NPVariant& aVariant) { switch (aRemoteVariant.type()) { - case NPRemoteVariant::Tvoid_t: { + case Variant::Tvoid_t: { VOID_TO_NPVARIANT(aVariant); break; } - case NPRemoteVariant::Tnull_t: { + case Variant::Tnull_t: { NULL_TO_NPVARIANT(aVariant); break; } - case NPRemoteVariant::Tbool: { + case Variant::Tbool: { BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant); break; } - case NPRemoteVariant::Tint: { + case Variant::Tint: { INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant); break; } - case NPRemoteVariant::Tdouble: { + case Variant::Tdouble: { DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant); break; } - case NPRemoteVariant::TnsCString: { + case Variant::TnsCString: { const nsCString& string = aRemoteVariant.get_nsCString(); NPUTF8* buffer = reinterpret_cast(strdup(string.get())); - if (!buffer) { - NS_ERROR("Out of memory!"); - return false; - } + NS_ASSERTION(buffer, "Out of memory!"); STRINGN_TO_NPVARIANT(buffer, string.Length(), aVariant); break; } - case NPRemoteVariant::TPPluginScriptableObjectChild: { + case Variant::TPPluginScriptableObjectChild: { NPObject* object = NPObjectFromVariant(aRemoteVariant); - if (!object) { - NS_ERROR("Er, this shouldn't fail!"); - return false; - } + NS_ASSERTION(object, "Null object?!"); + PluginModuleChild::sBrowserFuncs.retainobject(object); OBJECT_TO_NPVARIANT(object, aVariant); break; } default: - NS_NOTREACHED("Shouldn't get here!"); - return false; + NS_RUNTIMEABORT("Shouldn't get here!"); } - - return true; } bool ConvertToRemoteVariant(const NPVariant& aVariant, - NPRemoteVariant& aRemoteVariant, + Variant& aRemoteVariant, PluginInstanceChild* aInstance) { if (NPVARIANT_IS_VOID(aVariant)) { @@ -154,8 +148,11 @@ ConvertToRemoteVariant(const NPVariant& aVariant, } else if (NPVARIANT_IS_OBJECT(aVariant)) { NS_ASSERTION(aInstance, "Must have an instance to wrap!"); - PluginScriptableObjectChild* actor = - aInstance->GetActorForNPObject(NPVARIANT_TO_OBJECT(aVariant)); + + 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; @@ -172,6 +169,445 @@ ConvertToRemoteVariant(const NPVariant& aVariant, } // anonymous namespace +// static +NPObject* +PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance, + NPClass* aClass) +{ + NS_ASSERTION(aClass == PluginScriptableObjectChild::GetClass(), + "Huh?! Wrong class!"); + + ChildNPObject* object = reinterpret_cast( + PluginModuleChild::sBrowserFuncs.memalloc(sizeof(ChildNPObject))); + if (object) { + memset(object, 0, sizeof(ChildNPObject)); + } + return object; +} + +// static +void +PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return; + } + + ChildNPObject* object = reinterpret_cast(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 && + !instance->CallPPluginScriptableObjectDestructor(object->parent)) { + NS_WARNING("Failed to send message!"); + } +} + +// static +void +PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (!object->invalidated) { + ScriptableInvalidate(aObject); + } + + NS_ASSERTION(object->invalidated, "Should be invalidated!"); + + NS_Free(aObject); +} + +// static +bool +PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject, + NPIdentifier aName) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* 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; +} + +// static +bool +PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* actor = object->parent; + NS_ASSERTION(actor, "This shouldn't ever be null!"); + + nsAutoTArray 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; + 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; +} + +// static +bool +PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* actor = object->parent; + NS_ASSERTION(actor, "This shouldn't ever be null!"); + + nsAutoTArray 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; + 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) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* 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 +PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject, + NPIdentifier aName, + NPVariant* aResult) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* 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; + } + + if (!success) { + return false; + } + + ConvertToVariant(result, *aResult); + return true; +} + +// static +bool +PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aValue) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* actor = object->parent; + NS_ASSERTION(actor, "This shouldn't ever be null!"); + + 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; + } + + return success; +} + +// static +bool +PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject, + NPIdentifier aName) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* 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 +PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject, + NPIdentifier** aIdentifiers, + uint32_t* aCount) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* actor = object->parent; + NS_ASSERTION(actor, "This shouldn't ever be null!"); + + nsAutoTArray identifiers; + bool 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; + return true; + } + + *aIdentifiers = reinterpret_cast( + PluginModuleChild::sBrowserFuncs.memalloc(*aCount * sizeof(NPIdentifier))); + if (!*aIdentifiers) { + NS_ERROR("Out of memory!"); + return false; + } + + for (PRUint32 index = 0; index < *aCount; index++) { + *aIdentifiers[index] = (NPIdentifier)identifiers[index]; + } + return true; +} + +// static +bool +PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) +{ + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { + NS_ERROR("Don't know what kind of object this is!"); + return false; + } + + ChildNPObject* object = reinterpret_cast(aObject); + if (object->invalidated) { + NS_WARNING("Calling method on an invalidated object!"); + return false; + } + + PluginScriptableObjectChild* actor = object->parent; + NS_ASSERTION(actor, "This shouldn't ever be null!"); + + nsAutoTArray 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; + if (!actor->CallConstruct(args, &remoteResult, &success)) { + NS_WARNING("Failed to send message!"); + return false; + } + + if (!success) { + return false; + } + + ConvertToVariant(remoteResult, *aResult); + return true; +} + +const NPClass PluginScriptableObjectChild::sNPClass = { + NP_CLASS_STRUCT_VERSION, + PluginScriptableObjectChild::ScriptableAllocate, + PluginScriptableObjectChild::ScriptableDeallocate, + PluginScriptableObjectChild::ScriptableInvalidate, + PluginScriptableObjectChild::ScriptableHasMethod, + PluginScriptableObjectChild::ScriptableInvoke, + PluginScriptableObjectChild::ScriptableInvokeDefault, + PluginScriptableObjectChild::ScriptableHasProperty, + PluginScriptableObjectChild::ScriptableGetProperty, + PluginScriptableObjectChild::ScriptableSetProperty, + PluginScriptableObjectChild::ScriptableRemoveProperty, + PluginScriptableObjectChild::ScriptableEnumerate, + PluginScriptableObjectChild::ScriptableConstruct +}; + PluginScriptableObjectChild::PluginScriptableObjectChild() : mInstance(nsnull), mObject(nsnull) @@ -181,7 +617,15 @@ PluginScriptableObjectChild::PluginScriptableObjectChild() PluginScriptableObjectChild::~PluginScriptableObjectChild() { if (mObject) { - PluginModuleChild::sBrowserFuncs.releaseobject(mObject); + if (mObject->_class == GetClass()) { + if (!static_cast(mObject)->invalidated) { + NS_WARNING("This should have happened already!"); + ScriptableInvalidate(mObject); + } + } + else { + PluginModuleChild::sBrowserFuncs.releaseobject(mObject); + } } } @@ -190,14 +634,37 @@ PluginScriptableObjectChild::Initialize(PluginInstanceChild* aInstance, NPObject* aObject) { NS_ASSERTION(!(mInstance && mObject), "Calling Initialize class twice!"); + + if (aObject->_class == GetClass()) { + ChildNPObject* object = static_cast(aObject); + + NS_ASSERTION(!object->parent, "Bad object!"); + object->parent = const_cast(this); + + // 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; + } + else { + // Plugin-provided object, retain here. This should be the only reference we + // ever need. + PluginModuleChild::sBrowserFuncs.retainobject(aObject); + } + mInstance = aInstance; - mObject = PluginModuleChild::sBrowserFuncs.retainobject(aObject); + mObject = aObject; } bool PluginScriptableObjectChild::AnswerInvalidate() { if (mObject) { + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (mObject->_class && mObject->_class->invalidate) { + mObject->_class->invalidate(mObject); + } PluginModuleChild::sBrowserFuncs.releaseobject(mObject); mObject = nsnull; } @@ -209,11 +676,13 @@ PluginScriptableObjectChild::AnswerHasMethod(const NPRemoteIdentifier& aId, bool* aHasMethod) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerHasMethod with an invalidated object!"); + NS_WARNING("Calling AnswerHasMethod with an invalidated object!"); *aHasMethod = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->hasMethod)) { *aHasMethod = false; return true; @@ -225,16 +694,18 @@ PluginScriptableObjectChild::AnswerHasMethod(const NPRemoteIdentifier& aId, bool PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId, - const nsTArray& aArgs, - NPRemoteVariant* aResult, + const nsTArray& aArgs, + Variant* aResult, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerInvoke with an invalidated object!"); + NS_WARNING("Calling AnswerInvoke with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->invoke)) { *aSuccess = false; return true; @@ -249,23 +720,29 @@ PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId, } for (PRUint32 index = 0; index < argCount; index++) { - if (!ConvertToVariant(aArgs[index], convertedArgs[index])) { - *aSuccess = false; - return true; - } + ConvertToVariant(aArgs[index], convertedArgs[index]); } NPVariant result; bool success = mObject->_class->invoke(mObject, (NPIdentifier)aId, convertedArgs.Elements(), argCount, &result); + + for (PRUint32 index = 0; index < argCount; index++) { + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); + } + if (!success) { *aSuccess = false; return true; } - NPRemoteVariant convertedResult; - if (!ConvertToRemoteVariant(result, convertedResult, mInstance)) { + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, GetInstance()); + + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&result); + + if (!success) { *aSuccess = false; return true; } @@ -276,16 +753,18 @@ PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId, } bool -PluginScriptableObjectChild::AnswerInvokeDefault(const nsTArray& aArgs, - NPRemoteVariant* aResult, +PluginScriptableObjectChild::AnswerInvokeDefault(const nsTArray& aArgs, + Variant* aResult, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerInvokeDefault with an invalidated object!"); + NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->invokeDefault)) { *aSuccess = false; return true; @@ -300,23 +779,29 @@ PluginScriptableObjectChild::AnswerInvokeDefault(const nsTArray } for (PRUint32 index = 0; index < argCount; index++) { - if (!ConvertToVariant(aArgs[index], convertedArgs[index])) { - *aSuccess = false; - return true; - } + ConvertToVariant(aArgs[index], convertedArgs[index]); } NPVariant result; bool success = mObject->_class->invokeDefault(mObject, convertedArgs.Elements(), argCount, &result); + + for (PRUint32 index = 0; index < argCount; index++) { + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); + } + if (!success) { *aSuccess = false; return true; } - NPRemoteVariant convertedResult; - if (!ConvertToRemoteVariant(result, convertedResult, mInstance)) { + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, GetInstance()); + + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&result); + + if (!success) { *aSuccess = false; return true; } @@ -331,11 +816,13 @@ PluginScriptableObjectChild::AnswerHasProperty(const NPRemoteIdentifier& aId, bool* aHasProperty) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerHasProperty with an invalidated object!"); + NS_WARNING("Calling AnswerHasProperty with an invalidated object!"); *aHasProperty = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->hasProperty)) { *aHasProperty = false; return true; @@ -347,15 +834,17 @@ PluginScriptableObjectChild::AnswerHasProperty(const NPRemoteIdentifier& aId, bool PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId, - NPRemoteVariant* aResult, + Variant* aResult, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerGetProperty with an invalidated object!"); + NS_WARNING("Calling AnswerGetProperty with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->getProperty)) { *aSuccess = false; return true; @@ -367,8 +856,9 @@ PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId, return true; } - NPRemoteVariant converted; - if ((*aSuccess = ConvertToRemoteVariant(result, converted, mInstance))) { + Variant converted; + if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance()))) { + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&result); *aResult = converted; } return true; @@ -376,28 +866,29 @@ PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId, bool PluginScriptableObjectChild::AnswerSetProperty(const NPRemoteIdentifier& aId, - const NPRemoteVariant& aValue, + const Variant& aValue, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerSetProperty with an invalidated object!"); + NS_WARNING("Calling AnswerSetProperty with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->setProperty)) { *aSuccess = false; return true; } NPVariant converted; - if (!ConvertToVariant(aValue, converted)) { - *aSuccess = false; - return true; - } + ConvertToVariant(aValue, converted); - *aSuccess = mObject->_class->setProperty(mObject, (NPIdentifier)aId, - &converted); + if ((*aSuccess = mObject->_class->setProperty(mObject, (NPIdentifier)aId, + &converted))) { + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted); + } return true; } @@ -406,11 +897,13 @@ PluginScriptableObjectChild::AnswerRemoveProperty(const NPRemoteIdentifier& aId, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerRemoveProperty with an invalidated object!"); + NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->removeProperty)) { *aSuccess = false; return true; @@ -425,11 +918,13 @@ PluginScriptableObjectChild::AnswerEnumerate(nsTArray* aProp bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerEnumerate with an invalidated object!"); + NS_WARNING("Calling AnswerEnumerate with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->enumerate)) { *aSuccess = false; return true; @@ -462,16 +957,18 @@ PluginScriptableObjectChild::AnswerEnumerate(nsTArray* aProp } bool -PluginScriptableObjectChild::AnswerConstruct(const nsTArray& aArgs, - NPRemoteVariant* aResult, +PluginScriptableObjectChild::AnswerConstruct(const nsTArray& aArgs, + Variant* aResult, bool* aSuccess) { if (!mObject) { - NS_WARNING("Calling PluginScriptableObjectChild::AnswerConstruct with an invalidated object!"); + NS_WARNING("Calling AnswerConstruct with an invalidated object!"); *aSuccess = false; return true; } + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (!(mObject->_class && mObject->_class->construct)) { *aSuccess = false; return true; @@ -486,22 +983,28 @@ PluginScriptableObjectChild::AnswerConstruct(const nsTArray& aA } for (PRUint32 index = 0; index < argCount; index++) { - if (!ConvertToVariant(aArgs[index], convertedArgs[index])) { - *aSuccess = false; - return true; - } + ConvertToVariant(aArgs[index], convertedArgs[index]); } NPVariant result; bool success = mObject->_class->construct(mObject, convertedArgs.Elements(), argCount, &result); + + for (PRUint32 index = 0; index < argCount; index++) { + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]); + } + if (!success) { *aSuccess = false; return true; } - NPRemoteVariant convertedResult; - if (!ConvertToRemoteVariant(result, convertedResult, mInstance)) { + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, GetInstance()); + + PluginModuleChild::sBrowserFuncs.releasevariantvalue(&result); + + if (!success) { *aSuccess = false; return true; } diff --git a/dom/plugins/PluginScriptableObjectChild.h b/dom/plugins/PluginScriptableObjectChild.h index 1851f074422a..6e3198ea6475 100644 --- a/dom/plugins/PluginScriptableObjectChild.h +++ b/dom/plugins/PluginScriptableObjectChild.h @@ -41,15 +41,24 @@ #include "mozilla/plugins/PPluginScriptableObjectChild.h" -struct NPObject; +#include "npruntime.h" namespace mozilla { namespace plugins { class PluginInstanceChild; +class PluginScriptableObjectChild; + +struct ChildNPObject : NPObject +{ + PluginScriptableObjectChild* parent; + bool invalidated; +}; class PluginScriptableObjectChild : public PPluginScriptableObjectChild { + friend class PluginInstanceChild; + public: PluginScriptableObjectChild(); virtual ~PluginScriptableObjectChild(); @@ -63,13 +72,13 @@ public: virtual bool AnswerInvoke(const NPRemoteIdentifier& aId, - const nsTArray& aArgs, - NPRemoteVariant* aResult, + const nsTArray& aArgs, + Variant* aResult, bool* aSuccess); virtual bool - AnswerInvokeDefault(const nsTArray& aArgs, - NPRemoteVariant* aResult, + AnswerInvokeDefault(const nsTArray& aArgs, + Variant* aResult, bool* aSuccess); virtual bool @@ -78,12 +87,12 @@ public: virtual bool AnswerGetProperty(const NPRemoteIdentifier& aId, - NPRemoteVariant* aResult, + Variant* aResult, bool* aSuccess); virtual bool AnswerSetProperty(const NPRemoteIdentifier& aId, - const NPRemoteVariant& aValue, + const Variant& aValue, bool* aSuccess); virtual bool @@ -95,8 +104,8 @@ public: bool* aSuccess); virtual bool - AnswerConstruct(const nsTArray& aArgs, - NPRemoteVariant* aResult, + AnswerConstruct(const nsTArray& aArgs, + Variant* aResult, bool* aSuccess); void @@ -109,9 +118,80 @@ public: return mObject; } + static const NPClass* + GetClass() + { + return &sNPClass; + } + + PluginInstanceChild* + GetInstance() + { + return mInstance; + } + +private: + static NPObject* + ScriptableAllocate(NPP aInstance, + NPClass* aClass); + + static void + ScriptableInvalidate(NPObject* aObject); + + static void + ScriptableDeallocate(NPObject* aObject); + + static bool + ScriptableHasMethod(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableInvoke(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + + static bool + ScriptableInvokeDefault(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + + static bool + ScriptableHasProperty(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableGetProperty(NPObject* aObject, + NPIdentifier aName, + NPVariant* aResult); + + static bool + ScriptableSetProperty(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aValue); + + static bool + ScriptableRemoveProperty(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableEnumerate(NPObject* aObject, + NPIdentifier** aIdentifiers, + uint32_t* aCount); + + static bool + ScriptableConstruct(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + private: PluginInstanceChild* mInstance; NPObject* mObject; + + static const NPClass sNPClass; }; } /* namespace plugins */ diff --git a/dom/plugins/PluginScriptableObjectParent.cpp b/dom/plugins/PluginScriptableObjectParent.cpp index bed2976f3bdb..76b20e8443af 100644 --- a/dom/plugins/PluginScriptableObjectParent.cpp +++ b/dom/plugins/PluginScriptableObjectParent.cpp @@ -41,19 +41,20 @@ #include "PluginModuleParent.h" #include "npapi.h" -#include "npfunctions.h" #include "nsDebug.h" using namespace mozilla::plugins; using mozilla::ipc::NPRemoteIdentifier; -using mozilla::ipc::NPRemoteVariant; namespace { inline PluginInstanceParent* GetInstance(NPObject* aObject) { + NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(), + "Bad class!"); + ParentNPObject* object = reinterpret_cast(aObject); if (object->invalidated) { NS_WARNING("Calling method on an invalidated object!"); @@ -76,17 +77,21 @@ GetNetscapeFuncs(PluginInstanceParent* aInstance) 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 NPRemoteVariant& aRemoteVariant) { +NPObjectFromVariant(const Variant& aRemoteVariant) { NS_ASSERTION(aRemoteVariant.type() == - NPRemoteVariant::TPPluginScriptableObjectParent, + Variant::TPPluginScriptableObjectParent, "Wrong variant type!"); PluginScriptableObjectParent* actor = const_cast( @@ -101,6 +106,29 @@ NPObjectFromVariant(const NPVariant& aVariant) { return NPVARIANT_TO_OBJECT(aVariant); } +inline void +ReleaseVariant(NPVariant& aVariant, + PluginInstanceParent* aInstance) +{ + const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance); + if (npn) { + npn->releasevariantvalue(&aVariant); + } +} + +inline bool +EnsureValidIdentifier(PluginInstanceParent* aInstance, + NPIdentifier aIdentifier) +{ + PluginModuleParent* module = aInstance->GetModule(); + if (!module) { + NS_WARNING("Huh?!"); + return false; + } + + return module->EnsureValidNPIdentifier(aIdentifier); +} + inline bool EnsureValidIdentifier(NPObject* aObject, NPIdentifier aIdentifier) @@ -111,46 +139,41 @@ EnsureValidIdentifier(NPObject* aObject, return false; } - PluginModuleParent* module = instance->GetModule(); - if (!module) { - NS_WARNING("Huh?!"); - return false; - } - - return module->EnsureValidNPIdentifier(aIdentifier); + return EnsureValidIdentifier(instance, aIdentifier); } bool -ConvertToVariant(const NPRemoteVariant& aRemoteVariant, - NPVariant& aVariant) +ConvertToVariant(const Variant& aRemoteVariant, + NPVariant& aVariant, + PluginInstanceParent* aInstance) { switch (aRemoteVariant.type()) { - case NPRemoteVariant::Tvoid_t: { + case Variant::Tvoid_t: { VOID_TO_NPVARIANT(aVariant); break; } - case NPRemoteVariant::Tnull_t: { + case Variant::Tnull_t: { NULL_TO_NPVARIANT(aVariant); break; } - case NPRemoteVariant::Tbool: { + case Variant::Tbool: { BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant); break; } - case NPRemoteVariant::Tint: { + case Variant::Tint: { INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant); break; } - case NPRemoteVariant::Tdouble: { + case Variant::Tdouble: { DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant); break; } - case NPRemoteVariant::TnsCString: { + case Variant::TnsCString: { const nsCString& string = aRemoteVariant.get_nsCString(); NPUTF8* buffer = reinterpret_cast(strdup(string.get())); if (!buffer) { @@ -161,12 +184,19 @@ ConvertToVariant(const NPRemoteVariant& aRemoteVariant, break; } - case NPRemoteVariant::TPPluginScriptableObjectParent: { + 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; } @@ -181,7 +211,8 @@ ConvertToVariant(const NPRemoteVariant& aRemoteVariant, bool ConvertToRemoteVariant(const NPVariant& aVariant, - NPRemoteVariant& aRemoteVariant) + Variant& aRemoteVariant, + PluginInstanceParent* aInstance) { if (NPVARIANT_IS_VOID(aVariant)) { aRemoteVariant = mozilla::void_t(); @@ -205,16 +236,11 @@ ConvertToRemoteVariant(const NPVariant& aVariant, } else if (NPVARIANT_IS_OBJECT(aVariant)) { NPObject* object = NPVARIANT_TO_OBJECT(aVariant); - NS_ASSERTION(object->_class == PluginScriptableObjectParent::GetClass(), - "Don't know anything about this object!"); - - PluginScriptableObjectParent* actor = - static_cast(object)->parent; + PluginScriptableObjectParent* actor = aInstance->GetActorForNPObject(object); if (!actor) { - NS_ERROR("Failed to create actor!"); + NS_ERROR("Null actor!"); return false; } - aRemoteVariant = actor; } else { @@ -225,9 +251,12 @@ ConvertToRemoteVariant(const NPVariant& aVariant, return true; } +} // anonymous namespace + +// static NPObject* -ScriptableAllocate(NPP aInstance, - NPClass* aClass) +PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance, + NPClass* aClass) { NS_ASSERTION(aClass == PluginScriptableObjectParent::GetClass(), "Huh?! Wrong class!"); @@ -249,58 +278,65 @@ ScriptableAllocate(NPP aInstance, return object; } +// static void -ScriptableInvalidate(NPObject* aObject) +PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return; } ParentNPObject* object = reinterpret_cast(aObject); if (object->invalidated) { - NS_WARNING("Calling invalidate more than once!"); + // This can happen more than once, and is just fine. return; } - PluginInstanceParent* instance = GetInstance(aObject); - if (instance) { - if (!instance->CallPPluginScriptableObjectDestructor(object->parent)) { - NS_WARNING("Failed to send message!"); - } + PluginScriptableObjectParent* actor = object->parent; + NS_ASSERTION(actor, "Null actor?!"); + + PluginInstanceParent* instance = actor->GetInstance(); + NS_WARN_IF_FALSE(instance, "No instance?!"); + + if (!actor->CallInvalidate()) { + NS_WARNING("Failed to send message!"); } object->invalidated = true; + + if (instance && + !instance->CallPPluginScriptableObjectDestructor(actor)) { + NS_WARNING("Failed to send message!"); + } } +// static void -ScriptableDeallocate(NPObject* aObject) +PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return; } ParentNPObject* object = reinterpret_cast(aObject); if (!object->invalidated) { - NS_WARNING("Object wasn't previously invalidated!"); ScriptableInvalidate(aObject); } NS_ASSERTION(object->invalidated, "Should be invalidated!"); - const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject); - if (npn) { - npn->memfree(aObject); - } + NS_Free(aObject); } +// static bool -ScriptableHasMethod(NPObject* aObject, - NPIdentifier aName) +PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject, + NPIdentifier aName) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -326,15 +362,16 @@ ScriptableHasMethod(NPObject* aObject, return result; } +// static bool -ScriptableInvoke(NPObject* aObject, - NPIdentifier aName, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) +PluginScriptableObjectParent::ScriptableInvoke(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -351,21 +388,21 @@ ScriptableInvoke(NPObject* aObject, PluginScriptableObjectParent* actor = object->parent; NS_ASSERTION(actor, "This shouldn't ever be null!"); - nsAutoTArray args; + nsAutoTArray args; if (!args.SetLength(aArgCount)) { NS_ERROR("Out of memory?!"); return false; } for (PRUint32 index = 0; index < aArgCount; index++) { - NPRemoteVariant& arg = args[index]; - if (!ConvertToRemoteVariant(aArgs[index], arg)) { + Variant& arg = args[index]; + if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) { NS_WARNING("Failed to convert argument!"); return false; } } - NPRemoteVariant remoteResult; + Variant remoteResult; bool success; if (!actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult, &success)) { @@ -377,24 +414,22 @@ ScriptableInvoke(NPObject* aObject, return false; } - NPVariant result; - if (!ConvertToVariant(remoteResult, result)) { + if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { NS_WARNING("Failed to convert result!"); return false; } - - *aResult = result; return true; } +// static bool -ScriptableInvokeDefault(NPObject* aObject, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) +PluginScriptableObjectParent::ScriptableInvokeDefault(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -407,21 +442,21 @@ ScriptableInvokeDefault(NPObject* aObject, PluginScriptableObjectParent* actor = object->parent; NS_ASSERTION(actor, "This shouldn't ever be null!"); - nsAutoTArray args; + nsAutoTArray args; if (!args.SetLength(aArgCount)) { NS_ERROR("Out of memory?!"); return false; } for (PRUint32 index = 0; index < aArgCount; index++) { - NPRemoteVariant& arg = args[index]; - if (!ConvertToRemoteVariant(aArgs[index], arg)) { + Variant& arg = args[index]; + if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) { NS_WARNING("Failed to convert argument!"); return false; } } - NPRemoteVariant remoteResult; + Variant remoteResult; bool success; if (!actor->CallInvokeDefault(args, &remoteResult, &success)) { NS_WARNING("Failed to send message!"); @@ -432,22 +467,20 @@ ScriptableInvokeDefault(NPObject* aObject, return false; } - NPVariant result; - if (!ConvertToVariant(remoteResult, result)) { + if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { NS_WARNING("Failed to convert result!"); return false; } - - *aResult = result; return true; } +// static bool -ScriptableHasProperty(NPObject* aObject, - NPIdentifier aName) +PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject, + NPIdentifier aName) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -473,13 +506,14 @@ ScriptableHasProperty(NPObject* aObject, return result; } +// static bool -ScriptableGetProperty(NPObject* aObject, - NPIdentifier aName, - NPVariant* aResult) +PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject, + NPIdentifier aName, + NPVariant* aResult) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -496,7 +530,7 @@ ScriptableGetProperty(NPObject* aObject, PluginScriptableObjectParent* actor = object->parent; NS_ASSERTION(actor, "This shouldn't ever be null!"); - NPRemoteVariant result; + Variant result; bool success; if (!actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success)) { NS_WARNING("Failed to send message!"); @@ -507,7 +541,7 @@ ScriptableGetProperty(NPObject* aObject, return false; } - if (!ConvertToVariant(result, *aResult)) { + if (!ConvertToVariant(result, *aResult, actor->GetInstance())) { NS_WARNING("Failed to convert result!"); return false; } @@ -515,13 +549,14 @@ ScriptableGetProperty(NPObject* aObject, return true; } +// static bool -ScriptableSetProperty(NPObject* aObject, - NPIdentifier aName, - const NPVariant* aValue) +PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aValue) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -538,8 +573,8 @@ ScriptableSetProperty(NPObject* aObject, PluginScriptableObjectParent* actor = object->parent; NS_ASSERTION(actor, "This shouldn't ever be null!"); - NPRemoteVariant value; - if (!ConvertToRemoteVariant(*aValue, value)) { + Variant value; + if (!ConvertToRemoteVariant(*aValue, value, actor->GetInstance())) { NS_WARNING("Failed to convert variant!"); return false; } @@ -553,12 +588,13 @@ ScriptableSetProperty(NPObject* aObject, return success; } +// static bool -ScriptableRemoveProperty(NPObject* aObject, - NPIdentifier aName) +PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject, + NPIdentifier aName) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -584,13 +620,14 @@ ScriptableRemoveProperty(NPObject* aObject, return success; } +// static bool -ScriptableEnumerate(NPObject* aObject, - NPIdentifier** aIdentifiers, - uint32_t* aCount) +PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject, + NPIdentifier** aIdentifiers, + uint32_t* aCount) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -642,14 +679,15 @@ ScriptableEnumerate(NPObject* aObject, return true; } +// static bool -ScriptableConstruct(NPObject* aObject, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) +PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult) { if (aObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_WARNING("Don't know what kind of object this is!"); + NS_ERROR("Don't know what kind of object this is!"); return false; } @@ -662,21 +700,21 @@ ScriptableConstruct(NPObject* aObject, PluginScriptableObjectParent* actor = object->parent; NS_ASSERTION(actor, "This shouldn't ever be null!"); - nsAutoTArray args; + nsAutoTArray args; if (!args.SetLength(aArgCount)) { NS_ERROR("Out of memory?!"); return false; } for (PRUint32 index = 0; index < aArgCount; index++) { - NPRemoteVariant& arg = args[index]; - if (!ConvertToRemoteVariant(aArgs[index], arg)) { + Variant& arg = args[index]; + if (!ConvertToRemoteVariant(aArgs[index], arg, actor->GetInstance())) { NS_WARNING("Failed to convert argument!"); return false; } } - NPRemoteVariant remoteResult; + Variant remoteResult; bool success; if (!actor->CallConstruct(args, &remoteResult, &success)) { NS_WARNING("Failed to send message!"); @@ -687,32 +725,27 @@ ScriptableConstruct(NPObject* aObject, return false; } - NPVariant result; - if (!ConvertToVariant(remoteResult, result)) { + if (!ConvertToVariant(remoteResult, *aResult, actor->GetInstance())) { NS_WARNING("Failed to convert result!"); return false; } - - *aResult = result; return true; } -} // anonymous namespace - -NPClass PluginScriptableObjectParent::sNPClass = { +const NPClass PluginScriptableObjectParent::sNPClass = { NP_CLASS_STRUCT_VERSION, - ScriptableAllocate, - ScriptableDeallocate, - ScriptableInvalidate, - ScriptableHasMethod, - ScriptableInvoke, - ScriptableInvokeDefault, - ScriptableHasProperty, - ScriptableGetProperty, - ScriptableSetProperty, - ScriptableRemoveProperty, - ScriptableEnumerate, - ScriptableConstruct + PluginScriptableObjectParent::ScriptableAllocate, + PluginScriptableObjectParent::ScriptableDeallocate, + PluginScriptableObjectParent::ScriptableInvalidate, + PluginScriptableObjectParent::ScriptableHasMethod, + PluginScriptableObjectParent::ScriptableInvoke, + PluginScriptableObjectParent::ScriptableInvokeDefault, + PluginScriptableObjectParent::ScriptableHasProperty, + PluginScriptableObjectParent::ScriptableGetProperty, + PluginScriptableObjectParent::ScriptableSetProperty, + PluginScriptableObjectParent::ScriptableRemoveProperty, + PluginScriptableObjectParent::ScriptableEnumerate, + PluginScriptableObjectParent::ScriptableConstruct }; PluginScriptableObjectParent::PluginScriptableObjectParent() @@ -723,23 +756,546 @@ PluginScriptableObjectParent::PluginScriptableObjectParent() PluginScriptableObjectParent::~PluginScriptableObjectParent() { - if (mObject && !mObject->invalidated) { - ScriptableInvalidate(mObject); + if (mObject) { + if (mObject->_class == GetClass()) { + if (!static_cast(mObject)->invalidated) { + ScriptableInvalidate(mObject); + } + } + else { + mInstance->GetNPNIface()->releaseobject(mObject); + } } } void PluginScriptableObjectParent::Initialize(PluginInstanceParent* aInstance, - ParentNPObject* aObject) + NPObject* aObject) { NS_ASSERTION(aInstance && aObject, "Null pointers!"); NS_ASSERTION(!(mInstance && mObject), "Calling Initialize more than once!"); - NS_ASSERTION(aObject->_class == &sNPClass && !aObject->parent, "Bad object!"); + + if (aObject->_class == GetClass()) { + ParentNPObject* object = static_cast(aObject); + + NS_ASSERTION(!object->parent, "Bad object!"); + object->parent = const_cast(this); + + // 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; + } + else { + aInstance->GetNPNIface()->retainobject(aObject); + } mInstance = aInstance; - mObject = aObject; - mObject->parent = const_cast(this); - // XXX UGLY HACK, we let NPP_GetValue mess with the refcount, start at 0 here - mObject->referenceCount = 0; +} + +bool +PluginScriptableObjectParent::AnswerInvalidate() +{ + if (mObject) { + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + if (mObject->_class && mObject->_class->invalidate) { + mObject->_class->invalidate(mObject); + } + const NPNetscapeFuncs* npn = GetNetscapeFuncs(GetInstance()); + if (npn) { + npn->releaseobject(mObject); + } + mObject = nsnull; + } + 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!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aHasMethod = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aHasMethod = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aHasMethod = false; + return true; + } + + *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, (NPIdentifier)aId); + return true; +} + +bool +PluginScriptableObjectParent::AnswerInvoke(const NPRemoteIdentifier& aId, + const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerInvoke with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aSuccess = false; + return true; + } + + nsAutoTArray convertedArgs; + PRUint32 argCount = aArgs.Length(); + + if (!convertedArgs.SetLength(argCount)) { + *aSuccess = false; + return true; + } + + for (PRUint32 index = 0; index < argCount; index++) { + if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { + // Don't leak things we've already converted! + while (index-- > 0) { + ReleaseVariant(convertedArgs[index], instance); + } + *aSuccess = false; + return true; + } + } + + NPVariant result; + bool success = npn->invoke(instance->GetNPP(), mObject, (NPIdentifier)aId, + convertedArgs.Elements(), argCount, &result); + + for (PRUint32 index = 0; index < argCount; index++) { + ReleaseVariant(convertedArgs[index], instance); + } + + if (!success) { + *aSuccess = false; + return true; + } + + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, GetInstance()); + + ReleaseVariant(result, instance); + + if (!success) { + *aSuccess = false; + return true; + } + + *aSuccess = true; + *aResult = convertedResult; + return true; +} + +bool +PluginScriptableObjectParent::AnswerInvokeDefault(const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerInvoke with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + nsAutoTArray convertedArgs; + PRUint32 argCount = aArgs.Length(); + + if (!convertedArgs.SetLength(argCount)) { + *aSuccess = false; + return true; + } + + for (PRUint32 index = 0; index < argCount; index++) { + if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { + // Don't leak things we've already converted! + while (index-- > 0) { + ReleaseVariant(convertedArgs[index], instance); + } + *aSuccess = false; + return true; + } + } + + NPVariant result; + bool success = npn->invokeDefault(instance->GetNPP(), mObject, + convertedArgs.Elements(), argCount, + &result); + + for (PRUint32 index = 0; index < argCount; index++) { + ReleaseVariant(convertedArgs[index], instance); + } + + if (!success) { + *aSuccess = false; + return true; + } + + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, GetInstance()); + + ReleaseVariant(result, instance); + + if (!success) { + *aSuccess = false; + return true; + } + + *aSuccess = true; + *aResult = convertedResult; + return true; +} + +bool +PluginScriptableObjectParent::AnswerHasProperty(const NPRemoteIdentifier& aId, + bool* aHasProperty) +{ + if (!mObject) { + NS_WARNING("Calling AnswerHasProperty with an invalidated object!"); + *aHasProperty = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aHasProperty = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aHasProperty = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aHasProperty = false; + return true; + } + + *aHasProperty = npn->hasproperty(instance->GetNPP(), mObject, + (NPIdentifier)aId); + return true; +} + +bool +PluginScriptableObjectParent::AnswerGetProperty(const NPRemoteIdentifier& aId, + Variant* aResult, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerGetProperty with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aSuccess = false; + return true; + } + + NPVariant result; + if (!npn->getproperty(instance->GetNPP(), mObject, (NPIdentifier)aId, + &result)) { + *aSuccess = false; + return true; + } + + Variant converted; + if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) { + ReleaseVariant(result, instance); + *aResult = converted; + } + return true; +} + +bool +PluginScriptableObjectParent::AnswerSetProperty(const NPRemoteIdentifier& aId, + const Variant& aValue, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerSetProperty with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aSuccess = false; + return true; + } + + NPVariant converted; + if (!ConvertToVariant(aValue, converted, instance)) { + *aSuccess = false; + return true; + } + + if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject, + (NPIdentifier)aId, &converted))) { + ReleaseVariant(converted, instance); + } + return true; +} + +bool +PluginScriptableObjectParent::AnswerRemoveProperty(const NPRemoteIdentifier& aId, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { + NS_WARNING("Invalid NPIdentifier!"); + *aSuccess = false; + return true; + } + + *aSuccess = npn->removeproperty(instance->GetNPP(), mObject, + (NPIdentifier)aId); + return true; +} + +bool +PluginScriptableObjectParent::AnswerEnumerate(nsTArray* aProperties, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerEnumerate with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_WARNING("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + NPIdentifier* ids; + uint32_t idCount; + if (!npn->enumerate(instance->GetNPP(), mObject, &ids, &idCount)) { + *aSuccess = false; + return true; + } + + if (!aProperties->SetCapacity(idCount)) { + npn->memfree(ids); + *aSuccess = false; + return true; + } + + for (uint32_t index = 0; index < idCount; index++) { + NS_ASSERTION(EnsureValidIdentifier(instance, ids[index]), + "Identifier not yet in hashset!"); +#ifdef DEBUG + NPRemoteIdentifier* remoteId = +#endif + aProperties->AppendElement((NPRemoteIdentifier)ids[index]); + NS_ASSERTION(remoteId, "Shouldn't fail if SetCapacity above succeeded!"); + } + + npn->memfree(ids); + *aSuccess = true; + return true; +} + +bool +PluginScriptableObjectParent::AnswerConstruct(const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess) +{ + if (!mObject) { + NS_WARNING("Calling AnswerConstruct with an invalidated object!"); + *aSuccess = false; + return true; + } + + NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); + + PluginInstanceParent* instance = GetInstance(); + if (!instance) { + NS_ERROR("No instance?!"); + *aSuccess = false; + return true; + } + + const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); + if (!npn) { + NS_ERROR("No netscape funcs?!"); + *aSuccess = false; + return true; + } + + nsAutoTArray convertedArgs; + PRUint32 argCount = aArgs.Length(); + + if (!convertedArgs.SetLength(argCount)) { + *aSuccess = false; + return true; + } + + for (PRUint32 index = 0; index < argCount; index++) { + if (!ConvertToVariant(aArgs[index], convertedArgs[index], instance)) { + // Don't leak things we've already converted! + while (index-- > 0) { + ReleaseVariant(convertedArgs[index], instance); + } + *aSuccess = false; + return true; + } + } + + NPVariant result; + bool success = npn->construct(instance->GetNPP(), mObject, + convertedArgs.Elements(), argCount, &result); + + for (PRUint32 index = 0; index < argCount; index++) { + ReleaseVariant(convertedArgs[index], instance); + } + + if (!success) { + *aSuccess = false; + return true; + } + + Variant convertedResult; + success = ConvertToRemoteVariant(result, convertedResult, instance); + + ReleaseVariant(result, instance); + + if (!success) { + *aSuccess = false; + return true; + } + + *aSuccess = true; + *aResult = convertedResult; + return true; } diff --git a/dom/plugins/PluginScriptableObjectParent.h b/dom/plugins/PluginScriptableObjectParent.h index 6eab6db682dc..de3b326e6579 100644 --- a/dom/plugins/PluginScriptableObjectParent.h +++ b/dom/plugins/PluginScriptableObjectParent.h @@ -41,6 +41,7 @@ #include "mozilla/plugins/PPluginScriptableObjectParent.h" +#include "npfunctions.h" #include "npruntime.h" namespace mozilla { @@ -57,15 +58,62 @@ struct ParentNPObject : NPObject class PluginScriptableObjectParent : public PPluginScriptableObjectParent { + friend class PluginInstanceParent; + public: PluginScriptableObjectParent(); virtual ~PluginScriptableObjectParent(); + virtual bool + AnswerInvalidate(); + + virtual bool + AnswerHasMethod(const NPRemoteIdentifier& aId, + bool* aHasMethod); + + virtual bool + AnswerInvoke(const NPRemoteIdentifier& aId, + const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess); + + virtual bool + AnswerInvokeDefault(const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess); + + virtual bool + AnswerHasProperty(const NPRemoteIdentifier& aId, + bool* aHasProperty); + + virtual bool + AnswerGetProperty(const NPRemoteIdentifier& aId, + Variant* aResult, + bool* aSuccess); + + virtual bool + AnswerSetProperty(const NPRemoteIdentifier& aId, + const Variant& aValue, + bool* aSuccess); + + virtual bool + AnswerRemoveProperty(const NPRemoteIdentifier& aId, + bool* aSuccess); + + virtual bool + AnswerEnumerate(nsTArray* aProperties, + bool* aSuccess); + + virtual bool + AnswerConstruct(const nsTArray& aArgs, + Variant* aResult, + bool* aSuccess); + void Initialize(PluginInstanceParent* aInstance, - ParentNPObject* aObject); + NPObject* aObject); - static NPClass* + static const NPClass* GetClass() { return &sNPClass; @@ -84,10 +132,70 @@ public: } private: - PluginInstanceParent* mInstance; - ParentNPObject* mObject; + static NPObject* + ScriptableAllocate(NPP aInstance, + NPClass* aClass); - static NPClass sNPClass; + static void + ScriptableInvalidate(NPObject* aObject); + + static void + ScriptableDeallocate(NPObject* aObject); + + static bool + ScriptableHasMethod(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableInvoke(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + + static bool + ScriptableInvokeDefault(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + + static bool + ScriptableHasProperty(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableGetProperty(NPObject* aObject, + NPIdentifier aName, + NPVariant* aResult); + + static bool + ScriptableSetProperty(NPObject* aObject, + NPIdentifier aName, + const NPVariant* aValue); + + static bool + ScriptableRemoveProperty(NPObject* aObject, + NPIdentifier aName); + + static bool + ScriptableEnumerate(NPObject* aObject, + NPIdentifier** aIdentifiers, + uint32_t* aCount); + + static bool + ScriptableConstruct(NPObject* aObject, + const NPVariant* aArgs, + uint32_t aArgCount, + NPVariant* aResult); + +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; + + static const NPClass sNPClass; }; } /* namespace plugins */ diff --git a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp index de1ce9e429ec..fb9c2f5cf94a 100644 --- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp +++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp @@ -267,6 +267,8 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason) mInst->GetNPP(&npp); if (mStreamStarted && callbacks->destroystream) { + NPPAutoPusher nppPusher(npp); + mozilla::SharedLibrary* lib = nsnull; lib = mInst->mLibrary; NPError error; @@ -356,6 +358,8 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo) mStreamInfo = pluginInfo; + NPPAutoPusher nppPusher(npp); + NS_TRY_SAFE_CALL_RETURN(error, (*callbacks->newstream)(npp, (char*)contentType, &mNPStream, seekable, &streamType), mInst->mLibrary, mInst); NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL, @@ -595,6 +599,8 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, while (mStreamBufferByteCount > 0) { PRInt32 numtowrite; if (callbacks->writeready) { + NPPAutoPusher nppPusher(npp); + NS_TRY_SAFE_CALL_RETURN(numtowrite, (*callbacks->writeready)(npp, &mNPStream), mInst->mLibrary, mInst); NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPP WriteReady called: this=%p, npp=%p, " @@ -641,6 +647,8 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, numtowrite = mStreamBufferByteCount; } + NPPAutoPusher nppPusher(npp); + PRInt32 writeCount = 0; // bytes consumed by plugin instance NS_TRY_SAFE_CALL_RETURN(writeCount, (*callbacks->write)(npp, &mNPStream, streamPosition, numtowrite, ptrStreamBuffer), mInst->mLibrary, mInst); @@ -1191,6 +1199,10 @@ nsNPAPIPluginInstance::InitializePlugin() PRBool oldVal = mInPluginInitCall; mInPluginInitCall = PR_TRUE; + // Need this on the stack before calling NPP_New otherwise some callbacks that + // the plugin may make could fail (NPN_HasProperty, for example). + NPPAutoPusher autopush(&mNPP); + NS_TRY_SAFE_CALL_RETURN(error, (*mCallbacks->newp)((char*)mimetype, &mNPP, (PRUint16)mode, count, (char**)names, (char**)values, NULL), mLibrary,this); mInPluginInitCall = oldVal; @@ -1245,6 +1257,8 @@ NS_IMETHODIMP nsNPAPIPluginInstance::SetWindow(NPWindow* window) PRBool oldVal = mInPluginInitCall; mInPluginInitCall = PR_TRUE; + NPPAutoPusher nppPusher(&mNPP); + NPError error; NS_TRY_SAFE_CALL_RETURN(error, (*mCallbacks->setwindow)(&mNPP, (NPWindow*)window), mLibrary, this);