Commit 2cb0f893 authored by Damien Fouilleul's avatar Damien Fouilleul

- mozilla: I finally figured out why firefox was corrupting memory after...

 - mozilla: I finally figured out why firefox was corrupting memory after destroying plugin (so much fore reference counted objects !)
parent d9372ba6
...@@ -38,23 +38,22 @@ ...@@ -38,23 +38,22 @@
** implementation of libvlc root object ** implementation of libvlc root object
*/ */
LibvlcRootNPObject::LibvlcRootNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass)
{
audioObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcAudioNPObject>::getClass());
inputObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcInputNPObject>::getClass());
logObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcLogNPObject>::getClass());
playlistObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());
videoObj = NPN_CreateObject(instance,RuntimeNPClass<LibvlcVideoNPObject>::getClass());
}
LibvlcRootNPObject::~LibvlcRootNPObject() LibvlcRootNPObject::~LibvlcRootNPObject()
{ {
NPN_ReleaseObject(audioObj); /*
NPN_ReleaseObject(inputObj); ** when plugin is destroyed, firefox takes upon itself to destroy all 'live' script objects
NPN_ReleaseObject(logObj); ** and ignores refcounting. Therefore we cannot safely assume that refcounting will control
NPN_ReleaseObject(playlistObj); ** lifespan of objects. Hence they are only lazily created on request, so that firefox can
NPN_ReleaseObject(videoObj); ** 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[] = const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
...@@ -87,19 +86,44 @@ RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVaria ...@@ -87,19 +86,44 @@ RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVaria
switch( index ) switch( index )
{ {
case ID_root_audio: 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<LibvlcAudioNPObject>::getClass());
OBJECT_TO_NPVARIANT(audioObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
case ID_root_input: 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<LibvlcInputNPObject>::getClass());
OBJECT_TO_NPVARIANT(inputObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
case ID_root_log: 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<LibvlcLogNPObject>::getClass());
OBJECT_TO_NPVARIANT(logObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
case ID_root_playlist: 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<LibvlcPlaylistNPObject>::getClass());
OBJECT_TO_NPVARIANT(playlistObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
case ID_root_video: 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<LibvlcVideoNPObject>::getClass());
OBJECT_TO_NPVARIANT(videoObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
case ID_root_VersionInfo: case ID_root_VersionInfo:
{ {
...@@ -1029,15 +1053,12 @@ RuntimeNPObject::InvokeResult LibvlcMessagesNPObject::invoke(int index, const NP ...@@ -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<LibvlcMessagesNPObject>::getClass());
};
LibvlcLogNPObject::~LibvlcLogNPObject() LibvlcLogNPObject::~LibvlcLogNPObject()
{ {
NPN_ReleaseObject(_p_vlcmessages); if( isValid() )
{
if( messagesObj ) NPN_ReleaseObject(messagesObj);
}
}; };
const NPUTF8 * const LibvlcLogNPObject::propertyNames[] = const NPUTF8 * const LibvlcLogNPObject::propertyNames[] =
...@@ -1067,7 +1088,12 @@ RuntimeNPObject::InvokeResult LibvlcLogNPObject::getProperty(int index, NPVarian ...@@ -1067,7 +1088,12 @@ RuntimeNPObject::InvokeResult LibvlcLogNPObject::getProperty(int index, NPVarian
{ {
case ID_log_messages: 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<LibvlcMessagesNPObject>::getClass());
OBJECT_TO_NPVARIANT(messagesObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
} }
case ID_log_verbosity: case ID_log_verbosity:
...@@ -1281,15 +1307,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistItemsNPObject::invoke(int index, con ...@@ -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<LibvlcPlaylistItemsNPObject>::getClass());
};
LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject() LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
{ {
NPN_ReleaseObject(_p_vlcplaylistitems); if( isValid() )
{
if( playlistItemsObj ) NPN_ReleaseObject(playlistItemsObj);
}
}; };
const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] = const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
...@@ -1345,7 +1368,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::getProperty(int index, NPV ...@@ -1345,7 +1368,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::getProperty(int index, NPV
} }
case ID_playlist_items: 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<LibvlcPlaylistItemsNPObject>::getClass());
OBJECT_TO_NPVARIANT(playlistItemsObj, result);
return INVOKERESULT_NO_ERROR; return INVOKERESULT_NO_ERROR;
} }
default: default:
......
...@@ -32,7 +32,14 @@ class LibvlcRootNPObject: public RuntimeNPObject ...@@ -32,7 +32,14 @@ class LibvlcRootNPObject: public RuntimeNPObject
protected: protected:
friend class RuntimeNPClass<LibvlcRootNPObject>; friend class RuntimeNPClass<LibvlcRootNPObject>;
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(); virtual ~LibvlcRootNPObject();
static const int propertyCount; static const int propertyCount;
...@@ -172,7 +179,10 @@ class LibvlcLogNPObject: public RuntimeNPObject ...@@ -172,7 +179,10 @@ class LibvlcLogNPObject: public RuntimeNPObject
protected: protected:
friend class RuntimeNPClass<LibvlcLogNPObject>; friend class RuntimeNPClass<LibvlcLogNPObject>;
LibvlcLogNPObject(NPP instance, const NPClass *aClass); LibvlcLogNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass),
messagesObj(NULL) {};
virtual ~LibvlcLogNPObject(); virtual ~LibvlcLogNPObject();
static const int propertyCount; static const int propertyCount;
...@@ -185,7 +195,7 @@ protected: ...@@ -185,7 +195,7 @@ protected:
static const NPUTF8 * const methodNames[]; static const NPUTF8 * const methodNames[];
private: private:
NPObject* _p_vlcmessages; NPObject* messagesObj;
}; };
class LibvlcPlaylistItemsNPObject: public RuntimeNPObject class LibvlcPlaylistItemsNPObject: public RuntimeNPObject
...@@ -213,7 +223,10 @@ class LibvlcPlaylistNPObject: public RuntimeNPObject ...@@ -213,7 +223,10 @@ class LibvlcPlaylistNPObject: public RuntimeNPObject
protected: protected:
friend class RuntimeNPClass<LibvlcPlaylistNPObject>; friend class RuntimeNPClass<LibvlcPlaylistNPObject>;
LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass); LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass),
playlistItemsObj(NULL) {};
virtual ~LibvlcPlaylistNPObject(); virtual ~LibvlcPlaylistNPObject();
static const int propertyCount; static const int propertyCount;
...@@ -230,7 +243,7 @@ protected: ...@@ -230,7 +243,7 @@ protected:
void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options); void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options);
private: private:
NPObject* _p_vlcplaylistitems; NPObject* playlistItemsObj;
}; };
class LibvlcVideoNPObject: public RuntimeNPObject class LibvlcVideoNPObject: public RuntimeNPObject
......
...@@ -71,17 +71,21 @@ public: ...@@ -71,17 +71,21 @@ public:
protected: protected:
void *operator new(size_t n) 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); return NPN_MemAlloc(n);
}; };
void operator delete(void *p) void operator delete(void *p)
{ {
/* NPN_MemFree(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. bool isValid()
*/ {
//NPN_MemFree(p); return _instance != NULL;
}; };
RuntimeNPObject(NPP instance, const NPClass *aClass) : RuntimeNPObject(NPP instance, const NPClass *aClass) :
...@@ -197,7 +201,7 @@ template<class T> ...@@ -197,7 +201,7 @@ template<class T>
static bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) static bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
{ {
RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj); RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
if( vObj->_instance ) if( vObj->isValid() )
{ {
const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class); const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
int index = vClass->indexOfProperty(name); int index = vClass->indexOfProperty(name);
...@@ -213,7 +217,7 @@ template<class T> ...@@ -213,7 +217,7 @@ template<class T>
static bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) static bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
{ {
RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj); RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
if( vObj->_instance ) if( vObj->isValid() )
{ {
const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class); const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
int index = vClass->indexOfProperty(name); int index = vClass->indexOfProperty(name);
...@@ -229,7 +233,7 @@ template<class T> ...@@ -229,7 +233,7 @@ template<class T>
static bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name) static bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name)
{ {
RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj); RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
if( vObj->_instance ) if( vObj->isValid() )
{ {
const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class); const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
int index = vClass->indexOfProperty(name); int index = vClass->indexOfProperty(name);
...@@ -247,7 +251,7 @@ static bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name, ...@@ -247,7 +251,7 @@ static bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name,
NPVariant *result) NPVariant *result)
{ {
RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj); RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
if( vObj->_instance ) if( vObj->isValid() )
{ {
const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class); const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
int index = vClass->indexOfMethod(name); int index = vClass->indexOfMethod(name);
...@@ -266,7 +270,7 @@ static bool RuntimeNPClassInvokeDefault(NPObject *npobj, ...@@ -266,7 +270,7 @@ static bool RuntimeNPClassInvokeDefault(NPObject *npobj,
NPVariant *result) NPVariant *result)
{ {
RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj); RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
if( vObj->_instance ) if( vObj->isValid() )
{ {
return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, *result)); return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, *result));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment