From d9f6ce40c4ae63c4244c7759378a4facda26fc9b Mon Sep 17 00:00:00 2001 From: "Olli.Pettay%helsinki.fi" Date: Thu, 24 Apr 2008 10:33:24 +0000 Subject: [PATCH] Bug 430050, cancel frameloader initialization when docshell starts to load a page, r=sicking, sr=jst, a=dsicore git-svn-id: svn://10.0.0.236/trunk@250752 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsIDocument.h | 8 +-- mozilla/content/base/src/nsDocument.cpp | 29 ++++++++--- mozilla/content/base/src/nsDocument.h | 1 + mozilla/content/base/src/nsFrameLoader.h | 1 + mozilla/content/base/test/chrome/Makefile.in | 1 + .../base/test/chrome/test_bug430050.xul | 52 +++++++++++++++++++ mozilla/docshell/base/nsDocShell.cpp | 12 +++++ 7 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 mozilla/content/base/test/chrome/test_bug430050.xul diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index 89e0c37085c..289466a9425 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -56,7 +56,7 @@ class nsIContent; class nsPresContext; class nsIPresShell; - +class nsIDocShell; class nsIStreamListener; class nsIStreamObserver; class nsStyleSet; @@ -97,8 +97,8 @@ class nsFrameLoader; // IID for the nsIDocument interface #define NS_IDOCUMENT_IID \ -{ 0x680f5dac, 0x8863, 0x4c80, \ - { 0xbb, 0xe4, 0x21, 0x35, 0xbd, 0x8f, 0x83, 0x9a } } +{ 0xdd40333d, 0x913c, 0x4909, \ + { 0xb9, 0xe8, 0xf5, 0x45, 0x56, 0x5c, 0xe5, 0x4e } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -964,6 +964,8 @@ public: // In case of failure, the caller must handle the error, for example by // finalizing frame loader asynchronously. virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0; + + virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0; protected: ~nsIDocument() { diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 78ee34ec4d0..ea351f5119f 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -3892,16 +3892,17 @@ nsDocument::InitializeFinalizeFrameLoaders() { NS_ASSERTION(mUpdateNestLevel == 0 && !mDelayFrameLoaderInitialization, "Wrong time to call InitializeFinalizeFrameLoaders!"); - PRUint32 length = mInitializableFrameLoaders.Length(); - if (length > 0) { - nsTArray > loaders; - mInitializableFrameLoaders.SwapElements(loaders); - for (PRUint32 i = 0; i < length; ++i) { - loaders[i]->ReallyStartLoading(); - } + // Don't use a temporary array for mInitializableFrameLoaders, because + // loading a frame may cause some other frameloader to be removed from the + // array. But be careful to keep the loader alive when starting the load! + while (mInitializableFrameLoaders.Length()) { + nsRefPtr loader = mInitializableFrameLoaders[0]; + mInitializableFrameLoaders.RemoveElementAt(0); + NS_ASSERTION(loader, "null frameloader in the array?"); + loader->ReallyStartLoading(); } - length = mFinalizableFrameLoaders.Length(); + PRUint32 length = mFinalizableFrameLoaders.Length(); if (length > 0) { nsTArray > loaders; mFinalizableFrameLoaders.SwapElements(loaders); @@ -3911,6 +3912,18 @@ nsDocument::InitializeFinalizeFrameLoaders() } } +void +nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell) +{ + PRUint32 length = mInitializableFrameLoaders.Length(); + for (PRUint32 i = 0; i < length; ++i) { + if (mInitializableFrameLoaders[i]->GetExistingDocShell() == aShell) { + mInitializableFrameLoaders.RemoveElementAt(i); + return; + } + } +} + struct DirTable { const char* mName; PRUint8 mValue; diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index 733108960e1..230eb03c574 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -651,6 +651,7 @@ public: virtual NS_HIDDEN_(nsresult) InitializeFrameLoader(nsFrameLoader* aLoader); virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader); + virtual NS_HIDDEN_(void) TryCancelFrameLoaderInitialization(nsIDocShell* aShell); NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument) diff --git a/mozilla/content/base/src/nsFrameLoader.h b/mozilla/content/base/src/nsFrameLoader.h index 58a50b5494d..efaead1e52d 100755 --- a/mozilla/content/base/src/nsFrameLoader.h +++ b/mozilla/content/base/src/nsFrameLoader.h @@ -74,6 +74,7 @@ public: NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI); nsresult ReallyStartLoading(); void Finalize(); + nsIDocShell* GetExistingDocShell() { return mDocShell; } private: NS_HIDDEN_(nsresult) EnsureDocShell(); diff --git a/mozilla/content/base/test/chrome/Makefile.in b/mozilla/content/base/test/chrome/Makefile.in index c485ebfe427..8efa5baff0d 100644 --- a/mozilla/content/base/test/chrome/Makefile.in +++ b/mozilla/content/base/test/chrome/Makefile.in @@ -49,6 +49,7 @@ _TEST_FILES = \ _CHROME_FILES = \ test_bug421622.xul \ + test_bug430050.xul \ $(NULL) libs:: $(_TEST_FILES) diff --git a/mozilla/content/base/test/chrome/test_bug430050.xul b/mozilla/content/base/test/chrome/test_bug430050.xul new file mode 100644 index 00000000000..9616fe8631c --- /dev/null +++ b/mozilla/content/base/test/chrome/test_bug430050.xul @@ -0,0 +1,52 @@ + + + + + + + + + + + Mozilla Bug 430050 + + + + + + diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 78db0a9a6e5..e8cb7ce98ea 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -6884,6 +6884,18 @@ nsDocShell::InternalLoad(nsIURI * aURI, return rv; } + // If this docshell is owned by a frameloader, make sure to cancel + // possible frameloader initialization before loading a new page. + nsCOMPtr parent; + GetParent(getter_AddRefs(parent)); + if (parent) { + nsCOMPtr domDoc = do_GetInterface(parent); + nsCOMPtr doc = do_QueryInterface(domDoc); + if (doc) { + doc->TryCancelFrameLoaderInitialization(this); + } + } + if (mFiredUnloadEvent) { if (IsOKToLoadURI(aURI)) { NS_PRECONDITION(!aWindowTarget || !*aWindowTarget,