From 2cb0f8937bdf6e15aafbc5689f7a1272d5fdfb3f Mon Sep 17 00:00:00 2001 From: Damien Fouilleul Date: Tue, 20 Mar 2007 22:15:07 +0000 Subject: [PATCH] - mozilla: I finally figured out why firefox was corrupting memory after destroying plugin (so much fore reference counted objects !) --- mozilla/control/npolibvlc.cpp | 100 ++++++++++++++++++++++------------ mozilla/control/npolibvlc.h | 23 ++++++-- mozilla/control/nporuntime.h | 26 +++++---- 3 files changed, 97 insertions(+), 52 deletions(-) diff --git a/mozilla/control/npolibvlc.cpp b/mozilla/control/npolibvlc.cpp index f0971020de..f7d7d8e8e1 100755 --- a/mozilla/control/npolibvlc.cpp +++ b/mozilla/control/npolibvlc.cpp @@ -38,23 +38,22 @@ ** implementation of libvlc root object */ -LibvlcRootNPObject::LibvlcRootNPObject(NPP instance, const NPClass *aClass) : - RuntimeNPObject(instance, aClass) -{ - audioObj = NPN_CreateObject(instance, RuntimeNPClass::getClass()); - inputObj = NPN_CreateObject(instance, RuntimeNPClass::getClass()); - logObj = NPN_CreateObject(instance, RuntimeNPClass::getClass()); - playlistObj = NPN_CreateObject(instance, RuntimeNPClass::getClass()); - videoObj = NPN_CreateObject(instance,RuntimeNPClass::getClass()); -} - LibvlcRootNPObject::~LibvlcRootNPObject() { - NPN_ReleaseObject(audioObj); - NPN_ReleaseObject(inputObj); - NPN_ReleaseObject(logObj); - NPN_ReleaseObject(playlistObj); - NPN_ReleaseObject(videoObj); + /* + ** when plugin is destroyed, firefox takes upon itself to destroy all 'live' script objects + ** and ignores refcounting. Therefore we cannot safely assume that refcounting will control + ** lifespan of objects. Hence they are only lazily created on request, so that firefox can + ** take ownership, and are not released when plugin is being destroyed. + */ + if( isValid() ) + { + if( audioObj ) NPN_ReleaseObject(audioObj); + if( inputObj ) NPN_ReleaseObject(inputObj); + if( logObj ) NPN_ReleaseObject(logObj); + if( playlistObj ) NPN_ReleaseObject(playlistObj); + if( videoObj ) NPN_ReleaseObject(videoObj); + } } const NPUTF8 * const LibvlcRootNPObject::propertyNames[] = @@ -87,19 +86,44 @@ RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVaria switch( index ) { case ID_root_audio: - OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( audioObj ) + NPN_RetainObject(audioObj); + else + audioObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(audioObj, result); return INVOKERESULT_NO_ERROR; case ID_root_input: - OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( inputObj ) + NPN_RetainObject(inputObj); + else + inputObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(inputObj, result); return INVOKERESULT_NO_ERROR; case ID_root_log: - OBJECT_TO_NPVARIANT(NPN_RetainObject(logObj), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( logObj ) + NPN_RetainObject(logObj); + else + logObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(logObj, result); return INVOKERESULT_NO_ERROR; case ID_root_playlist: - OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( playlistObj ) + NPN_RetainObject(playlistObj); + else + playlistObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(playlistObj, result); return INVOKERESULT_NO_ERROR; case ID_root_video: - OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( videoObj ) + NPN_RetainObject(videoObj); + else + videoObj = NPN_CreateObject(_instance,RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(videoObj, result); return INVOKERESULT_NO_ERROR; case ID_root_VersionInfo: { @@ -1029,15 +1053,12 @@ RuntimeNPObject::InvokeResult LibvlcMessagesNPObject::invoke(int index, const NP */ -LibvlcLogNPObject::LibvlcLogNPObject(NPP instance, const NPClass *aClass) : - RuntimeNPObject(instance, aClass) -{ - _p_vlcmessages = NPN_CreateObject(instance, RuntimeNPClass::getClass()); -}; - LibvlcLogNPObject::~LibvlcLogNPObject() { - NPN_ReleaseObject(_p_vlcmessages); + if( isValid() ) + { + if( messagesObj ) NPN_ReleaseObject(messagesObj); + } }; const NPUTF8 * const LibvlcLogNPObject::propertyNames[] = @@ -1067,7 +1088,12 @@ RuntimeNPObject::InvokeResult LibvlcLogNPObject::getProperty(int index, NPVarian { case ID_log_messages: { - OBJECT_TO_NPVARIANT(NPN_RetainObject(_p_vlcmessages), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( messagesObj ) + NPN_RetainObject(messagesObj); + else + messagesObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(messagesObj, result); return INVOKERESULT_NO_ERROR; } case ID_log_verbosity: @@ -1281,15 +1307,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistItemsNPObject::invoke(int index, con */ -LibvlcPlaylistNPObject::LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass) : - RuntimeNPObject(instance, aClass) -{ - _p_vlcplaylistitems = NPN_CreateObject(instance, RuntimeNPClass::getClass()); -}; - LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject() { - NPN_ReleaseObject(_p_vlcplaylistitems); + if( isValid() ) + { + if( playlistItemsObj ) NPN_ReleaseObject(playlistItemsObj); + } }; const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] = @@ -1345,7 +1368,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::getProperty(int index, NPV } case ID_playlist_items: { - OBJECT_TO_NPVARIANT(NPN_RetainObject(_p_vlcplaylistitems), result); + // create child object in lazyman fashion to avoid ownership problem with firefox + if( playlistItemsObj ) + NPN_RetainObject(playlistItemsObj); + else + playlistItemsObj = NPN_CreateObject(_instance, RuntimeNPClass::getClass()); + OBJECT_TO_NPVARIANT(playlistItemsObj, result); return INVOKERESULT_NO_ERROR; } default: diff --git a/mozilla/control/npolibvlc.h b/mozilla/control/npolibvlc.h index c018c0c732..7683917398 100755 --- a/mozilla/control/npolibvlc.h +++ b/mozilla/control/npolibvlc.h @@ -32,7 +32,14 @@ class LibvlcRootNPObject: public RuntimeNPObject protected: friend class RuntimeNPClass; - LibvlcRootNPObject(NPP instance, const NPClass *aClass); + LibvlcRootNPObject(NPP instance, const NPClass *aClass) : + RuntimeNPObject(instance, aClass), + audioObj(NULL), + inputObj(NULL), + logObj(NULL), + playlistObj(NULL), + videoObj(NULL) {}; + virtual ~LibvlcRootNPObject(); static const int propertyCount; @@ -172,7 +179,10 @@ class LibvlcLogNPObject: public RuntimeNPObject protected: friend class RuntimeNPClass; - LibvlcLogNPObject(NPP instance, const NPClass *aClass); + LibvlcLogNPObject(NPP instance, const NPClass *aClass) : + RuntimeNPObject(instance, aClass), + messagesObj(NULL) {}; + virtual ~LibvlcLogNPObject(); static const int propertyCount; @@ -185,7 +195,7 @@ protected: static const NPUTF8 * const methodNames[]; private: - NPObject* _p_vlcmessages; + NPObject* messagesObj; }; class LibvlcPlaylistItemsNPObject: public RuntimeNPObject @@ -213,7 +223,10 @@ class LibvlcPlaylistNPObject: public RuntimeNPObject protected: friend class RuntimeNPClass; - LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass); + LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass) : + RuntimeNPObject(instance, aClass), + playlistItemsObj(NULL) {}; + virtual ~LibvlcPlaylistNPObject(); static const int propertyCount; @@ -230,7 +243,7 @@ protected: void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options); private: - NPObject* _p_vlcplaylistitems; + NPObject* playlistItemsObj; }; class LibvlcVideoNPObject: public RuntimeNPObject diff --git a/mozilla/control/nporuntime.h b/mozilla/control/nporuntime.h index f2f7fc2b8d..8182fef004 100755 --- a/mozilla/control/nporuntime.h +++ b/mozilla/control/nporuntime.h @@ -71,17 +71,21 @@ public: protected: void *operator new(size_t n) { + /* + ** Assume that browser has a smarter memory allocator + ** than plain old malloc() and use it instead. + */ return NPN_MemAlloc(n); }; void operator delete(void *p) { - /* - ** Some memory scribble happens occasionally on freed object - ** when used on Firefox (MacOS X) and may cause crash, a leak - ** sounds like the better option. - */ - //NPN_MemFree(p); + NPN_MemFree(p); + }; + + bool isValid() + { + return _instance != NULL; }; RuntimeNPObject(NPP instance, const NPClass *aClass) : @@ -197,7 +201,7 @@ template static bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) { RuntimeNPObject *vObj = static_cast(npobj); - if( vObj->_instance ) + if( vObj->isValid() ) { const RuntimeNPClass *vClass = static_cast *>(npobj->_class); int index = vClass->indexOfProperty(name); @@ -213,7 +217,7 @@ template static bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) { RuntimeNPObject *vObj = static_cast(npobj); - if( vObj->_instance ) + if( vObj->isValid() ) { const RuntimeNPClass *vClass = static_cast *>(npobj->_class); int index = vClass->indexOfProperty(name); @@ -229,7 +233,7 @@ template static bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name) { RuntimeNPObject *vObj = static_cast(npobj); - if( vObj->_instance ) + if( vObj->isValid() ) { const RuntimeNPClass *vClass = static_cast *>(npobj->_class); int index = vClass->indexOfProperty(name); @@ -247,7 +251,7 @@ static bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name, NPVariant *result) { RuntimeNPObject *vObj = static_cast(npobj); - if( vObj->_instance ) + if( vObj->isValid() ) { const RuntimeNPClass *vClass = static_cast *>(npobj->_class); int index = vClass->indexOfMethod(name); @@ -266,7 +270,7 @@ static bool RuntimeNPClassInvokeDefault(NPObject *npobj, NPVariant *result) { RuntimeNPObject *vObj = static_cast(npobj); - if( vObj->_instance ) + if( vObj->isValid() ) { return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, *result)); } -- 2.39.2