diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 4bbd2f72a772..c785c54daf10 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -4756,7 +4756,7 @@ nsDocShell::Destroy() { mCurrentURI = nullptr; if (mScriptGlobal) { - mScriptGlobal->DetachFromDocShell(); + mScriptGlobal->DetachFromDocShell(!mSkipBrowsingContextDetachOnDestroy); mScriptGlobal = nullptr; } diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp index f7e0533442dc..22a9d55281be 100644 --- a/dom/base/nsGlobalWindowInner.cpp +++ b/dom/base/nsGlobalWindowInner.cpp @@ -856,6 +856,7 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow, mHasGamepad(false), mHasVREvents(false), mHasVRDisplayActivateEvents(false), + mWasCurrentInnerWindow(false), mHasSeenGamepadInput(false), mSuspendDepth(0), mFreezeDepth(0), @@ -2548,19 +2549,13 @@ bool nsPIDOMWindowInner::IsCurrentInnerWindow() const { auto* bc = GetBrowsingContext(); MOZ_ASSERT(bc); - nsPIDOMWindowOuter* outer; - // When a BC is discarded, it stops returning outer windows altogether. That - // doesn't work for this check, since we still want current inner window to be - // treated as current after that point. Simply falling back to `mOuterWindow` - // here isn't ideal, since it will start returning true for inner windows - // which were current before a remoteness switch once a BrowsingContext has - // been discarded, but it's not incorrect in a way which should cause - // significant issues. - if (!bc->IsDiscarded()) { - outer = bc->GetDOMWindow(); - } else { - outer = mOuterWindow; + if (bc->IsDiscarded()) { + // If our BrowsingContext has been discarded, we consider ourselves + // still-current if we were current at the time it was discarded. + return WasCurrentInnerWindow(); } + + nsPIDOMWindowOuter* outer = bc->GetDOMWindow(); return outer && outer->GetCurrentInnerWindow() == this; } diff --git a/dom/base/nsGlobalWindowInner.h b/dom/base/nsGlobalWindowInner.h index d1c9793d886e..e0c345b2271e 100644 --- a/dom/base/nsGlobalWindowInner.h +++ b/dom/base/nsGlobalWindowInner.h @@ -1295,9 +1295,17 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget, // Indicates whether this window wants VRDisplayActivate events bool mHasVRDisplayActivateEvents : 1; + + // True if this was the currently-active inner window for a BrowsingContext at + // the time it was discarded. + bool mWasCurrentInnerWindow : 1; + void SetWasCurrentInnerWindow() { mWasCurrentInnerWindow = true; } + bool WasCurrentInnerWindow() const override { return mWasCurrentInnerWindow; } + + bool mHasSeenGamepadInput : 1; + nsCheapSet mGamepadIndexSet; nsRefPtrHashtable mGamepads; - bool mHasSeenGamepadInput; RefPtr mScreen; diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index b4ee8518a012..c0eb6867c678 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -2458,7 +2458,7 @@ void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) { SetIsBackgroundInternal(!docShellActive); } -void nsGlobalWindowOuter::DetachFromDocShell() { +void nsGlobalWindowOuter::DetachFromDocShell(bool aIsBeingDiscarded) { // DetachFromDocShell means the window is being torn down. Drop our // reference to the script context, allowing it to be deleted // later. Meanwhile, keep our weak reference to the script object @@ -2520,6 +2520,14 @@ void nsGlobalWindowOuter::DetachFromDocShell() { mContext = nullptr; } + if (aIsBeingDiscarded) { + // If our BrowsingContext is being discarded, make a note that our current + // inner window was active at the time it went away. + if (GetCurrentInnerWindow()) { + GetCurrentInnerWindowInternal()->SetWasCurrentInnerWindow(); + } + } + mDocShell = nullptr; mBrowsingContext->ClearDocShell(); diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h index f7b7e176d127..b3852630f740 100644 --- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h @@ -311,7 +311,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, // Outer windows only. bool WouldReuseInnerWindow(Document* aNewDocument); - void DetachFromDocShell(); + void DetachFromDocShell(bool aIsBeingDiscarded); virtual nsresult SetNewDocument( Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow, diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index e6b6ef86264c..cbe61f3a007b 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -170,6 +170,10 @@ class nsPIDOMWindowInner : public mozIDOMWindow { // Returns true if this window is the same as mTopInnerWindow inline bool IsTopInnerWindow() const; + // Returns true if this was the current window for its BrowsingContext when it + // was discarded. + virtual bool WasCurrentInnerWindow() const = 0; + // Check whether a document is currently loading (really checks if the // load event has completed). May not be reset to false on errors. inline bool IsLoading() const; diff --git a/dom/base/test/file_current_inner_window.html b/dom/base/test/file_current_inner_window.html new file mode 100644 index 000000000000..8156e290005d --- /dev/null +++ b/dom/base/test/file_current_inner_window.html @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index d2e47507898d..13bd17211448 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -131,6 +131,7 @@ support-files = file_bug945152.jar file_bug1274806.html file_bug1453693.html + file_current_inner_window.html file_domwindowutils_animation.html file_general_document.html file_history_document_open.html @@ -653,6 +654,7 @@ skip-if = verify [test_document_importNode_document.html] [test_custom_element.html] [test_custom_element_reflector.html] +[test_current_inner_window.html] [test_domparser_null_char.html] [test_domparsing.html] [test_domrequest.html] diff --git a/dom/base/test/test_current_inner_window.html b/dom/base/test/test_current_inner_window.html new file mode 100644 index 000000000000..3e7a700e635c --- /dev/null +++ b/dom/base/test/test_current_inner_window.html @@ -0,0 +1,61 @@ + + + + + Test that current inner window checks are correct after navigations/discards + + + + + + + + + +