From dc79137dfcf8a8664939690dc0be210c0016488f Mon Sep 17 00:00:00 2001 From: "Olli.Pettay%helsinki.fi" Date: Tue, 26 Feb 2008 14:47:52 +0000 Subject: [PATCH] Bug 402982, r=jst, sr=sicking git-svn-id: svn://10.0.0.236/trunk@246529 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsIDocument.h | 6 ++- mozilla/content/base/src/nsDocument.cpp | 28 +++++++++++ mozilla/content/base/src/nsDocument.h | 4 ++ mozilla/content/base/src/nsFrameLoader.cpp | 57 +++++++++++++++++++--- mozilla/content/base/src/nsFrameLoader.h | 12 ++++- 5 files changed, 97 insertions(+), 10 deletions(-) diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index 9410e61ac1e..8cf14313e91 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -93,11 +93,12 @@ class nsBindingManager; class nsIDOMNodeList; class mozAutoSubtreeModified; struct JSObject; +class nsFrameLoader; // IID for the nsIDocument interface #define NS_IDOCUMENT_IID \ -{ 0x626d86d2, 0x615f, 0x4a12, \ - { 0x94, 0xd8, 0xe3, 0xdb, 0x3a, 0x29, 0x83, 0x72 } } +{ 0x3c441ae9, 0xaa82, 0x4102, \ + { 0xa3, 0x16, 0x3b, 0x97, 0x2b, 0x60, 0x2b, 0x05 } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -951,6 +952,7 @@ public: // Do nothing. } + virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0; protected: ~nsIDocument() { diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 1f63bceae90..d710dd0f6d2 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -158,6 +158,8 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID); #include "nsCCUncollectableMarker.h" #include "nsIContentPolicy.h" +#include "nsFrameLoader.h" + #ifdef MOZ_LOGGING // so we can get logging even in release builds #define FORCE_PR_LOG 1 @@ -2719,6 +2721,17 @@ nsDocument::EndUpdate(nsUpdateType aUpdateType) if (mScriptLoader) { mScriptLoader->RemoveExecuteBlocker(); } + + if (mUpdateNestLevel == 0) { + PRUint32 length = mFinalizableFrameLoaders.Length(); + if (length > 0) { + nsTArray > loaders; + mFinalizableFrameLoaders.SwapElements(loaders); + for (PRInt32 i = 0; i < length; ++i) { + loaders[i]->Finalize(); + } + } + } } void @@ -3825,6 +3838,21 @@ nsDocument::FlushSkinBindings() mBindingManager->FlushSkinBindings(); } +nsresult +nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader) +{ + if (mInDestructor) { + return NS_ERROR_FAILURE; + } + if (mUpdateNestLevel == 0) { + nsRefPtr loader = aLoader; + loader->Finalize(); + } else { + mFinalizableFrameLoaders.AppendElement(aLoader); + } + return NS_OK; +} + struct DirTable { const char* mName; PRUint8 mValue; diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index ef06d1db7e2..46e35d52451 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -647,6 +647,8 @@ public: virtual NS_HIDDEN_(nsresult) GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult); virtual NS_HIDDEN_(void) FlushSkinBindings(); + + virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader); NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument) @@ -839,6 +841,8 @@ private: // Member to store out last-selected stylesheet set. nsString mLastStyleSheetSet; + + nsTArray > mFinalizableFrameLoaders; }; diff --git a/mozilla/content/base/src/nsFrameLoader.cpp b/mozilla/content/base/src/nsFrameLoader.cpp index 298b649d4aa..9275189bdae 100644 --- a/mozilla/content/base/src/nsFrameLoader.cpp +++ b/mozilla/content/base/src/nsFrameLoader.cpp @@ -73,6 +73,26 @@ #include "nsGkAtoms.h" #include "nsINameSpaceManager.h" +#include "nsThreadUtils.h" + +class nsAsyncDocShellDestroyer : public nsRunnable +{ +public: + nsAsyncDocShellDestroyer(nsIDocShell* aDocShell) + : mDocShell(aDocShell) + { + } + + NS_IMETHOD Run() + { + nsCOMPtr base_win(do_QueryInterface(mDocShell)); + if (base_win) { + base_win->Destroy(); + } + } + nsRefPtr mDocShell; +}; + // Bug 136580: Limit to the number of nested content frames that can have the // same URL. This is to stop content that is recursively loading // itself. Note that "#foo" on the end of URL doesn't affect @@ -140,6 +160,7 @@ NS_IMETHODIMP nsFrameLoader::LoadURI(nsIURI* aURI) { NS_PRECONDITION(aURI, "Null URI?"); + NS_ENSURE_STATE(!mDestroyCalled); if (!aURI) return NS_ERROR_INVALID_POINTER; @@ -227,11 +248,27 @@ nsFrameLoader::GetDocShell(nsIDocShell **aDocShell) return NS_OK; } +void +nsFrameLoader::Finalize() +{ + nsCOMPtr base_win(do_QueryInterface(mDocShell)); + if (base_win) { + base_win->Destroy(); + } + mDocShell = nsnull; +} + NS_IMETHODIMP nsFrameLoader::Destroy() { + if (mDestroyCalled) { + return NS_OK; + } + mDestroyCalled = PR_TRUE; + + nsCOMPtr doc; if (mOwnerContent) { - nsCOMPtr doc = mOwnerContent->GetDocument(); + doc = mOwnerContent->GetOwnerDoc(); if (doc) { doc->SetSubDocumentFor(mOwnerContent, nsnull); @@ -258,14 +295,21 @@ nsFrameLoader::Destroy() if (win_private) { win_private->SetFrameElementInternal(nsnull); } - - nsCOMPtr base_win(do_QueryInterface(mDocShell)); - if (base_win) { - base_win->Destroy(); + if ((mInDestructor || !doc || + NS_FAILED(doc->FinalizeFrameLoader(this))) && mDocShell) { + nsCOMPtr event = new nsAsyncDocShellDestroyer(mDocShell); + NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY); + NS_DispatchToCurrentThread(event); + + // Let go of our docshell now that the async destroyer holds on to + // the docshell. + + mDocShell = nsnull; } - mDocShell = nsnull; + // NOTE: 'this' may very well be gone by now. + return NS_OK; } @@ -282,6 +326,7 @@ nsFrameLoader::EnsureDocShell() if (mDocShell) { return NS_OK; } + NS_ENSURE_STATE(!mDestroyCalled); // Get our parent docshell off the document of mOwnerContent // XXXbz this is such a total hack.... We really need to have a diff --git a/mozilla/content/base/src/nsFrameLoader.h b/mozilla/content/base/src/nsFrameLoader.h index dbad685f3ff..beb522f3c41 100755 --- a/mozilla/content/base/src/nsFrameLoader.h +++ b/mozilla/content/base/src/nsFrameLoader.h @@ -57,15 +57,21 @@ public: nsFrameLoader(nsIContent *aOwner) : mOwnerContent(aOwner), mDepthTooGreat(PR_FALSE), - mIsTopLevelContent(PR_FALSE) + mIsTopLevelContent(PR_FALSE), + mDestroyCalled(PR_FALSE), + mInDestructor(PR_FALSE) {} NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader) NS_DECL_NSIFRAMELOADER NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); + void Finalize(); private: - ~nsFrameLoader() { nsFrameLoader::Destroy(); } + ~nsFrameLoader() { + mInDestructor = PR_TRUE; + nsFrameLoader::Destroy(); + } NS_HIDDEN_(nsresult) EnsureDocShell(); NS_HIDDEN_(void) GetURL(nsString& aURL); @@ -75,6 +81,8 @@ private: nsIContent *mOwnerContent; // WEAK PRPackedBool mDepthTooGreat; PRPackedBool mIsTopLevelContent; + PRPackedBool mDestroyCalled; + PRPackedBool mInDestructor; }; #endif