Bug 1405176 - Bail out DoURILoad if the docshell is being async destructed
MozReview-Commit-ID: KjUdCn6KkOu
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -814,16 +814,17 @@ nsDocShell::nsDocShell()
, mWindowDraggingAllowed(false)
, mInFrameSwap(false)
, mInheritPrivateBrowsingId(true)
, mCanExecuteScripts(false)
, mFiredUnloadEvent(false)
, mEODForCurrentDocument(false)
, mURIResultedInDocument(false)
, mIsBeingDestroyed(false)
+ , mInAsyncDestroy(false)
, mIsExecutingOnLoadHandler(false)
, mIsPrintingOrPP(false)
, mSavingOldViewer(false)
, mDynamicallyCreated(false)
, mAffectPrivateSessionLifetime(true)
, mInvisible(false)
, mHasLoadedNonBlankURI(false)
, mBlankTiming(false)
@@ -11024,17 +11025,17 @@ nsDocShell::DoURILoad(nsIURI* aURI,
bool aIsNewWindowTarget,
bool aBypassClassifier,
bool aForceAllowCookies,
const nsAString& aSrcdoc,
nsIURI* aBaseURI,
nsContentPolicyType aContentPolicyType)
{
// Double-check that we're still around to load this URI.
- if (mIsBeingDestroyed) {
+ if (mIsBeingDestroyed || mInAsyncDestroy) {
// Return NS_OK despite not doing anything to avoid throwing exceptions from
// nsLocation::SetHref if the unload handler of the existing page tears us
// down.
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsIURILoader> uriLoader = do_GetService(NS_URI_LOADER_CONTRACTID, &rv);
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -346,16 +346,21 @@ public:
*
* This method steals the data from the passed-in array.
*/
void SetAncestorOuterWindowIDs(nsTArray<uint64_t>&& aAncestorOuterWindowIDs)
{
mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs);
}
+ void SetInAsyncDestroy(bool aInAsyncDestroy)
+ {
+ mInAsyncDestroy = aInAsyncDestroy;
+ }
+
private:
bool CanSetOriginAttributes();
public:
const mozilla::OriginAttributes&
GetOriginAttributes()
{
return mOriginAttributes;
@@ -1068,16 +1073,17 @@ protected:
// this flag is for bug #21358. a docshell may load many urls
// which don't result in new documents being created (i.e. a new
// content viewer) we want to make sure we don't call a on load
// event more than once for a given content viewer.
bool mEODForCurrentDocument : 1;
bool mURIResultedInDocument : 1;
bool mIsBeingDestroyed : 1;
+ bool mInAsyncDestroy : 1;
bool mIsExecutingOnLoadHandler : 1;
// Indicates that a DocShell in this "docshell tree" is printing
bool mIsPrintingOrPP : 1;
// Indicates to CreateContentViewer() that it is safe to cache the old
// presentation of the page, and to SetupNewViewer() that the old viewer
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2232,16 +2232,24 @@ nsFrameLoader::StartDestroy()
groupedSHistory->CloseInactiveFrameLoaderOwners();
}));
}
}
nsCOMPtr<nsIRunnable> destroyRunnable = new nsFrameLoaderDestroyRunnable(this);
if (mNeedsAsyncDestroy || !doc ||
NS_FAILED(doc->FinalizeFrameLoader(this, destroyRunnable))) {
+ // We are going to defer destroying the docshell until we return to the
+ // event loop. Let docShell knows about that to bail out loading if we are in
+ // the middle of a load.
+ RefPtr<nsDocShell> docshell = static_cast<nsDocShell*>(GetExistingDocShell());
+ if (docshell) {
+ docshell->SetInAsyncDestroy(true);
+ }
+
NS_DispatchToCurrentThread(destroyRunnable);
}
}
nsresult
nsFrameLoaderDestroyRunnable::Run()
{
switch (mPhase) {