]> git.sesse.net Git - vlc/commitdiff
- mozilla: I finally figured out why firefox was corrupting memory after destroying...
authorDamien Fouilleul <damienf@videolan.org>
Tue, 20 Mar 2007 22:15:07 +0000 (22:15 +0000)
committerDamien Fouilleul <damienf@videolan.org>
Tue, 20 Mar 2007 22:15:07 +0000 (22:15 +0000)
mozilla/control/npolibvlc.cpp
mozilla/control/npolibvlc.h
mozilla/control/nporuntime.h

index f0971020dec090696ed2902e4172b358ddbfa2b0..f7d7d8e8e1722709dfff6a67c1f1eb3e9be59f48 100755 (executable)
 ** implementation of libvlc root object\r
 */\r
 \r
-LibvlcRootNPObject::LibvlcRootNPObject(NPP instance, const NPClass *aClass) :\r
-        RuntimeNPObject(instance, aClass)\r
-{\r
-    audioObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcAudioNPObject>::getClass());\r
-    inputObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcInputNPObject>::getClass());\r
-    logObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcLogNPObject>::getClass());\r
-    playlistObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());\r
-    videoObj = NPN_CreateObject(instance,RuntimeNPClass<LibvlcVideoNPObject>::getClass());\r
-}\r
-\r
 LibvlcRootNPObject::~LibvlcRootNPObject()\r
 {\r
-    NPN_ReleaseObject(audioObj);\r
-    NPN_ReleaseObject(inputObj);\r
-    NPN_ReleaseObject(logObj);\r
-    NPN_ReleaseObject(playlistObj);\r
-    NPN_ReleaseObject(videoObj);\r
+    /*\r
+    ** when plugin is destroyed, firefox takes upon itself to destroy all 'live' script objects\r
+    ** and ignores refcounting. Therefore we cannot safely assume  that refcounting will control\r
+    ** lifespan of objects. Hence they are only lazily created on request, so that firefox can\r
+    ** take ownership, and are not released when plugin is being destroyed.\r
+    */\r
+    if( isValid() )\r
+    {\r
+       if( audioObj    ) NPN_ReleaseObject(audioObj);\r
+       if( inputObj    ) NPN_ReleaseObject(inputObj);\r
+       if( logObj      ) NPN_ReleaseObject(logObj);\r
+       if( playlistObj ) NPN_ReleaseObject(playlistObj);\r
+       if( videoObj    ) NPN_ReleaseObject(videoObj);\r
+    }\r
 }\r
 \r
 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] = \r
@@ -87,19 +86,44 @@ RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVaria
         switch( index )\r
         {\r
             case ID_root_audio:\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( audioObj )\r
+                   NPN_RetainObject(audioObj);\r
+               else\r
+                   audioObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcAudioNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(audioObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             case ID_root_input:\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( inputObj )\r
+                   NPN_RetainObject(inputObj);\r
+               else\r
+                   inputObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcInputNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(inputObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             case ID_root_log:\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(logObj), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( logObj )\r
+                   NPN_RetainObject(logObj);\r
+               else\r
+                   logObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcLogNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(logObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             case ID_root_playlist:\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( playlistObj )\r
+                   NPN_RetainObject(playlistObj);\r
+               else\r
+                   playlistObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(playlistObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             case ID_root_video:\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( videoObj )\r
+                   NPN_RetainObject(videoObj);\r
+               else\r
+                   videoObj = NPN_CreateObject(_instance,RuntimeNPClass<LibvlcVideoNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(videoObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             case ID_root_VersionInfo:\r
             {\r
@@ -1029,15 +1053,12 @@ RuntimeNPObject::InvokeResult LibvlcMessagesNPObject::invoke(int index, const NP
 */\r
 \r
 \r
-LibvlcLogNPObject::LibvlcLogNPObject(NPP instance, const NPClass *aClass) :\r
-    RuntimeNPObject(instance, aClass)\r
-{\r
-    _p_vlcmessages = NPN_CreateObject(instance, RuntimeNPClass<LibvlcMessagesNPObject>::getClass());\r
-};\r
-    \r
 LibvlcLogNPObject::~LibvlcLogNPObject()\r
 {\r
-    NPN_ReleaseObject(_p_vlcmessages);\r
+    if( isValid() )\r
+    {\r
+       if( messagesObj ) NPN_ReleaseObject(messagesObj);\r
+    }\r
 };\r
 \r
 const NPUTF8 * const LibvlcLogNPObject::propertyNames[] = \r
@@ -1067,7 +1088,12 @@ RuntimeNPObject::InvokeResult LibvlcLogNPObject::getProperty(int index, NPVarian
         {\r
             case ID_log_messages:\r
             {\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(_p_vlcmessages), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( messagesObj )\r
+                   NPN_RetainObject(messagesObj);\r
+               else\r
+                   messagesObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcMessagesNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(messagesObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             }\r
             case ID_log_verbosity:\r
@@ -1281,15 +1307,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistItemsNPObject::invoke(int index, con
 */\r
 \r
 \r
-LibvlcPlaylistNPObject::LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass) :\r
-    RuntimeNPObject(instance, aClass)\r
-{\r
-    _p_vlcplaylistitems = NPN_CreateObject(instance, RuntimeNPClass<LibvlcPlaylistItemsNPObject>::getClass());\r
-};\r
-    \r
 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()\r
 {\r
-    NPN_ReleaseObject(_p_vlcplaylistitems);\r
+    if( isValid() )\r
+    {\r
+       if( playlistItemsObj ) NPN_ReleaseObject(playlistItemsObj);\r
+    }\r
 };\r
 \r
 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] = \r
@@ -1345,7 +1368,12 @@ RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::getProperty(int index, NPV
             }\r
             case ID_playlist_items:\r
             {\r
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(_p_vlcplaylistitems), result);\r
+               // create child object in lazyman fashion to avoid ownership problem with firefox\r
+               if( playlistItemsObj )\r
+                   NPN_RetainObject(playlistItemsObj);\r
+               else\r
+                   playlistItemsObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcPlaylistItemsNPObject>::getClass());\r
+                OBJECT_TO_NPVARIANT(playlistItemsObj, result);\r
                 return INVOKERESULT_NO_ERROR;\r
             }\r
             default:\r
index c018c0c7321dac642126d37e0f2b9cd70f1bf45b..76839173988f6583f8a840e0edccd2c4798608ee 100755 (executable)
@@ -32,7 +32,14 @@ class LibvlcRootNPObject: public RuntimeNPObject
 protected:\r
     friend class RuntimeNPClass<LibvlcRootNPObject>;\r
 \r
-    LibvlcRootNPObject(NPP instance, const NPClass *aClass);\r
+    LibvlcRootNPObject(NPP instance, const NPClass *aClass) :\r
+        RuntimeNPObject(instance, aClass),\r
+       audioObj(NULL),\r
+       inputObj(NULL),\r
+       logObj(NULL),\r
+       playlistObj(NULL),\r
+       videoObj(NULL) {};\r
+\r
     virtual ~LibvlcRootNPObject();\r
 \r
     static const int propertyCount;\r
@@ -172,7 +179,10 @@ class LibvlcLogNPObject: public RuntimeNPObject
 protected:\r
     friend class RuntimeNPClass<LibvlcLogNPObject>;\r
 \r
-    LibvlcLogNPObject(NPP instance, const NPClass *aClass);\r
+    LibvlcLogNPObject(NPP instance, const NPClass *aClass) :\r
+       RuntimeNPObject(instance, aClass),\r
+       messagesObj(NULL) {};\r
+\r
     virtual ~LibvlcLogNPObject();\r
 \r
     static const int propertyCount;\r
@@ -185,7 +195,7 @@ protected:
     static const NPUTF8 * const methodNames[];\r
 \r
 private:\r
-    NPObject* _p_vlcmessages;\r
+    NPObject* messagesObj;\r
 };\r
 \r
 class LibvlcPlaylistItemsNPObject: public RuntimeNPObject\r
@@ -213,7 +223,10 @@ class LibvlcPlaylistNPObject: public RuntimeNPObject
 protected:\r
     friend class RuntimeNPClass<LibvlcPlaylistNPObject>;\r
 \r
-    LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass);\r
+    LibvlcPlaylistNPObject(NPP instance, const NPClass *aClass) :\r
+       RuntimeNPObject(instance, aClass),\r
+       playlistItemsObj(NULL) {};\r
+       \r
     virtual ~LibvlcPlaylistNPObject();\r
 \r
     static const int propertyCount;\r
@@ -230,7 +243,7 @@ protected:
     void parseOptions(NPObject *obj, int *i_options, char*** ppsz_options);\r
 \r
 private:\r
-    NPObject*  _p_vlcplaylistitems;\r
+    NPObject*  playlistItemsObj;\r
 };\r
 \r
 class LibvlcVideoNPObject: public RuntimeNPObject\r
index f2f7fc2b8d529af6aa13edb916c0eb74ad21be89..8182fef004bf13423b3adfdacd11c5536412b473 100755 (executable)
@@ -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<class T>
 static bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
 {
     RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
-    if( vObj->_instance )
+    if( vObj->isValid() )
     {
         const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
         int index = vClass->indexOfProperty(name);
@@ -213,7 +217,7 @@ template<class T>
 static bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
 {
     RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
-    if( vObj->_instance )
+    if( vObj->isValid() )
     {
         const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
         int index = vClass->indexOfProperty(name);
@@ -229,7 +233,7 @@ template<class T>
 static bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name)
 {
     RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
-    if( vObj->_instance )
+    if( vObj->isValid() )
     {
         const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
         int index = vClass->indexOfProperty(name);
@@ -247,7 +251,7 @@ static bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name,
                                     NPVariant *result)
 {
     RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
-    if( vObj->_instance )
+    if( vObj->isValid() )
     {
         const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
         int index = vClass->indexOfMethod(name);
@@ -266,7 +270,7 @@ static bool RuntimeNPClassInvokeDefault(NPObject *npobj,
                                            NPVariant *result)
 {
     RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
-    if( vObj->_instance )
+    if( vObj->isValid() )
     {
         return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, *result));
     }