Bug 587222 - Script caching in messageManager leaks; r=Olli.Pettay a=blocking-because-550936-is-a-blocker
authorAlon Zakai <azakai@mozilla.com>
Mon, 16 Aug 2010 16:40:04 -0400
changeset 50684 8541ae9ea9b3102d068981b3d4c232e54d2959c8
parent 50683 d773ca26da83c85fc4a1097d6f2cc43cd209308a
child 50685 c8dc4dd369ee9b8668685d3a2011473cde7390f1
push idunknown
push userunknown
push dateunknown
reviewersOlli.Pettay, blocking-because-550936-is-a-blocker
bugs587222, 550936
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 587222 - Script caching in messageManager leaks; r=Olli.Pettay a=blocking-because-550936-is-a-blocker
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -505,25 +505,28 @@ NS_NewGlobalMessageManager(nsIChromeFram
                                                         nsnull,
                                                         PR_TRUE);
   NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
   return CallQueryInterface(mm, aResult);
 }
 
 nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>*
   nsFrameScriptExecutor::sCachedScripts = nsnull;
+nsRefPtr<nsScriptCacheCleaner> nsFrameScriptExecutor::sScriptCacheCleaner;
 
 void
 nsFrameScriptExecutor::DidCreateCx()
 {
   NS_ASSERTION(mCx, "Should have mCx!");
   if (!sCachedScripts) {
     sCachedScripts =
       new nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>;
     sCachedScripts->Init();
+
+    sScriptCacheCleaner = new nsScriptCacheCleaner();
   }
 }
 
 void
 nsFrameScriptExecutor::DestroyCx()
 {
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   if (xpc) {
@@ -559,16 +562,18 @@ nsFrameScriptExecutor::Shutdown()
       NS_ASSERTION(sCachedScripts != nsnull, "Need cached scripts");
       sCachedScripts->Enumerate(CachedScriptUnrooter, cx);
     } else {
       NS_WARNING("No context available. Leaking cached scripts!\n");
     }
 
     delete sCachedScripts;
     sCachedScripts = nsnull;
+
+    sScriptCacheCleaner = nsnull;
   }
 }
 
 void
 nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
 {
   if (!mGlobal || !mCx) {
     return;
@@ -667,8 +672,11 @@ nsFrameScriptExecutor::LoadFrameScriptIn
         //XXX Argh, JSPrincipals are manually refcounted!
         JSPRINCIPALS_DROP(mCx, jsprin);
       }
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
 }
+
+NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver);
+
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -33,26 +33,29 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsFrameMessageManager_h__
 #define nsFrameMessageManager_h__
 
 #include "nsIFrameMessageManager.h"
+#include "nsIObserver.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsIAtom.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsDataHashtable.h"
+#include "mozilla/Services.h"
+#include "nsIObserverService.h"
 
 class nsAXPCNativeCallContext;
 struct JSContext;
 struct JSObject;
 
 struct nsMessageListenerInfo
 {
   nsCOMPtr<nsIFrameMessageListener> mListener;
@@ -148,16 +151,18 @@ protected:
   nsSyncMessageCallback mSyncCallback;
   nsAsyncMessageCallback mAsyncCallback;
   nsLoadScriptCallback mLoadScriptCallback;
   void* mCallbackData;
   JSContext* mContext;
   nsTArray<nsString> mPendingScripts;
 };
 
+class nsScriptCacheCleaner;
+
 struct nsFrameScriptExecutorJSObjectHolder
 {
   nsFrameScriptExecutorJSObjectHolder(JSObject* aObject) : mObject(aObject) {}
   JSObject* mObject;
 };
 
 class nsFrameScriptExecutor
 {
@@ -168,11 +173,32 @@ protected:
   void DidCreateCx();
   // Call this when you want to destroy mCx.
   void DestroyCx();
   void LoadFrameScriptInternal(const nsAString& aURL);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   JSContext* mCx;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   static nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>* sCachedScripts;
+  static nsRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
+};
+
+class nsScriptCacheCleaner : public nsIObserver
+{
+  NS_DECL_ISUPPORTS
+
+  nsScriptCacheCleaner()
+  {
+    nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
+    if (obsSvc)
+      obsSvc->AddObserver(this, "xpcom-shutdown", PR_FALSE);
+  }
+
+  NS_IMETHODIMP Observe(nsISupports *aSubject,
+                        const char *aTopic,
+                        const PRUnichar *aData)
+  {
+    nsFrameScriptExecutor::Shutdown();
+    return NS_OK;
+  }
 };
 
 #endif