This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch tor-browser-91.8.0esr-11.0-1 in repository tor-browser.
commit c58a1ce7837ea9c17d4ad9ae9f91419512087a8d Author: Henri Sivonen hsivonen@hsivonen.fi AuthorDate: Mon Feb 21 10:59:02 2022 +0000
Bug 1736570 - Avoid DocumentChannel for nsParser-created initial about:blank replacement. r=smaug, a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D139272 --- docshell/base/BrowsingContext.cpp | 10 +- docshell/base/BrowsingContext.h | 3 +- docshell/base/CanonicalBrowsingContext.cpp | 2 + docshell/base/nsDocShell.cpp | 108 ++++++++++++++++----- docshell/base/nsDocShell.h | 19 +++- docshell/shistory/SessionHistoryEntry.cpp | 6 +- docshell/shistory/SessionHistoryEntry.h | 3 + dom/base/nsObjectLoadingContent.cpp | 13 ++- dom/base/nsObjectLoadingContent.h | 6 ++ netwerk/ipc/DocumentChannel.cpp | 2 - ...versal-navigate-parent-while-child-loading.html | 4 +- .../empty-iframe-load-event.html | 39 ++++++++ .../aboutprocesses/tests/browser/head.js | 9 +- 13 files changed, 185 insertions(+), 39 deletions(-)
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp index 37e526d848e4d..e43c87642bb77 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -3424,7 +3424,7 @@ void BrowsingContext::SessionHistoryCommit(
void BrowsingContext::SetActiveSessionHistoryEntry( const Maybe<nsPoint>& aPreviousScrollPos, SessionHistoryInfo* aInfo, - uint32_t aLoadType, uint32_t aUpdatedCacheKey) { + uint32_t aLoadType, uint32_t aUpdatedCacheKey, bool aUpdateLength) { if (XRE_IsContentProcess()) { // XXX Why we update cache key only in content process case? if (aUpdatedCacheKey != 0) { @@ -3432,9 +3432,11 @@ void BrowsingContext::SetActiveSessionHistoryEntry( }
nsID changeID = {}; - RefPtr<ChildSHistory> shistory = Top()->GetChildSessionHistory(); - if (shistory) { - changeID = shistory->AddPendingHistoryChange(); + if (aUpdateLength) { + RefPtr<ChildSHistory> shistory = Top()->GetChildSessionHistory(); + if (shistory) { + changeID = shistory->AddPendingHistoryChange(); + } } ContentChild::GetSingleton()->SendSetActiveSessionHistoryEntry( this, aPreviousScrollPos, *aInfo, aLoadType, aUpdatedCacheKey, diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h index 0033bf7e65750..1306f715a5002 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h @@ -793,7 +793,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { void SetActiveSessionHistoryEntry(const Maybe<nsPoint>& aPreviousScrollPos, SessionHistoryInfo* aInfo, uint32_t aLoadType, - uint32_t aUpdatedCacheKey); + uint32_t aUpdatedCacheKey, + bool aUpdateLength = true);
// Replace the active entry for this browsing context. This is used for // implementing history.replaceState and same document navigations. diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp index f51e668d0e47d..749591918f8cd 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp @@ -750,6 +750,8 @@ void CanonicalBrowsingContext::SessionHistoryCommit(uint64_t aLoadId, MOZ_LOG(gSHLog, LogLevel::Verbose, ("CanonicalBrowsingContext::SessionHistoryCommit %p %" PRIu64, this, aLoadId)); + MOZ_ASSERT(aLoadId != UINT64_MAX, + "Must not send special about:blank loadinfo to parent."); for (size_t i = 0; i < mLoadingEntries.Length(); ++i) { if (mLoadingEntries[i].mLoadId == aLoadId) { nsSHistory* shistory = static_cast<nsSHistory*>(GetSessionHistory()); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index c04a496bdf07c..67732b7cad675 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -230,6 +230,7 @@ #include "nsWidgetsCID.h" #include "nsXULAppAPI.h"
+#include "ThirdPartyUtil.h" #include "BRNameMatchingPolicy.h" #include "GeckoProfiler.h" #include "mozilla/NullPrincipal.h" @@ -388,7 +389,8 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, mWillChangeProcess(false), mIsNavigating(false), mSuspendMediaWhenInactive(false), - mForcedAutodetection(false) { + mForcedAutodetection(false), + mNeedToReportActiveAfterLoadingBecomesActive(false) { // If no outer window ID was provided, generate a new one. if (aContentWindowID == 0) { mContentWindowID = nsContentUtils::GenerateWindowId(); @@ -8687,6 +8689,7 @@ nsresult nsDocShell::HandleSameDocumentNavigation( if (aLoadState->GetLoadingSessionHistoryInfo()) { mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>( *aLoadState->GetLoadingSessionHistoryInfo()); + mNeedToReportActiveAfterLoadingBecomesActive = false; }
// Set the doc's URI according to the new history entry's URI. @@ -9899,6 +9902,14 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal( return true; }
+bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank( + nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { + return NS_IsAboutBlank(aURI) && aInheritPrincipal && + (aPrincipalToInherit == GetInheritedPrincipal(false)) && + (!mContentViewer || !mContentViewer->GetDocument() || + mContentViewer->GetDocument()->IsInitialDocument()); +} + nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, Maybe<uint32_t> aCacheKey, nsIRequest** aRequest) { @@ -10040,11 +10051,44 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, "DoURILoad thinks this is a document and InternalLoad does not"); }
+ // We want to inherit aLoadState->PrincipalToInherit() when: + // 1. ChannelShouldInheritPrincipal returns true. + // 2. aLoadState->URI() is not data: URI, or data: URI is not + // configured as unique opaque origin. + bool inheritPrincipal = false; + + if (aLoadState->PrincipalToInherit()) { + bool isSrcdoc = + aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); + bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( + aLoadState->PrincipalToInherit(), aLoadState->URI(), + true, // aInheritForAboutBlank + isSrcdoc); + + inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); + } + + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570 + const bool isAboutBlankLoadOntoInitialAboutBlank = + IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal, + aLoadState->PrincipalToInherit()); + // FIXME We still have a ton of codepaths that don't pass through // DocumentLoadListener, so probably need to create session history info // in more places. if (aLoadState->GetLoadingSessionHistoryInfo()) { SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo()); + } else if (isAboutBlankLoadOntoInitialAboutBlank && + mozilla::SessionHistoryInParent()) { + // Materialize LoadingSessionHistoryInfo here, because DocumentChannel + // loads have it, and later history behavior depends on it existing. + UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>( + aLoadState->URI(), aLoadState->TriggeringPrincipal(), + aLoadState->PrincipalToInherit(), + aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(), + mContentTypeHint); + mozilla::dom::LoadingSessionHistoryInfo info(*entry); + SetLoadingSessionHistoryInfo(info, true); }
// open a channel for the url @@ -10128,23 +10172,6 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, return NS_ERROR_FAILURE; }
- // We want to inherit aLoadState->PrincipalToInherit() when: - // 1. ChannelShouldInheritPrincipal returns true. - // 2. aLoadState->URI() is not data: URI, or data: URI is not - // configured as unique opaque origin. - bool inheritPrincipal = false; - - if (aLoadState->PrincipalToInherit()) { - bool isSrcdoc = - aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC); - bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal( - aLoadState->PrincipalToInherit(), aLoadState->URI(), - true, // aInheritForAboutBlank - isSrcdoc); - - inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI()); - } - uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags(); nsSecurityFlags securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; @@ -10177,6 +10204,30 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, sandboxFlags); RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
+ if (isAboutBlankLoadOntoInitialAboutBlank) { + // Match the DocumentChannel case where the default for third-partiness + // differs from the default in LoadInfo construction here. + // toolkit/components/antitracking/test/browser/browser_aboutblank.js + // fails without this. + BrowsingContext* top = mBrowsingContext->Top(); + if (top == mBrowsingContext) { + // If we're at the top, this must be a window.open()ed + // window, and we can't be third-party relative to ourselves. + loadInfo->SetIsThirdPartyContextToTopWindow(false); + } else { + if (Document* topDoc = top->GetDocument()) { + bool thirdParty = false; + mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal( + aLoadState->PrincipalToInherit(), &thirdParty); + loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty); + } else { + // If top is in a different process, we have to be third-party relative + // to it. + loadInfo->SetIsThirdPartyContextToTopWindow(true); + } + } + } + if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess() && context->HasValidTransientUserGestureActivation()) { aLoadState->SetHasValidUserGestureActivation(true); @@ -10244,7 +10295,8 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, currentUnstrippedURI);
nsCOMPtr<nsIChannel> channel; - if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI())) { + if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) && + !isAboutBlankLoadOntoInitialAboutBlank) { channel = DocumentChannel::CreateForDocument(aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified, isXFOError); @@ -13308,13 +13360,16 @@ bool nsDocShell::GetIsAttemptingToNavigate() { }
void nsDocShell::SetLoadingSessionHistoryInfo( - const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo) { + const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, + bool aNeedToReportActiveAfterLoadingBecomesActive) { // FIXME Would like to assert this, but can't yet. // MOZ_ASSERT(!mLoadingEntry); MOZ_LOG(gSHLog, LogLevel::Debug, ("Setting the loading entry on nsDocShell %p to %s", this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get())); mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo); + mNeedToReportActiveAfterLoadingBecomesActive = + aNeedToReportActiveAfterLoadingBecomesActive; }
void nsDocShell::MoveLoadingToActiveEntry(bool aPersist) { @@ -13336,16 +13391,25 @@ void nsDocShell::MoveLoadingToActiveEntry(bool aPersist) { mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo); mLoadingEntry.swap(loadingEntry); if (!mActiveEntryIsLoadingFromSessionHistory) { + if (mNeedToReportActiveAfterLoadingBecomesActive) { + // Needed to pass various history length WPTs. + mBrowsingContext->SetActiveSessionHistoryEntry( + mozilla::Nothing(), mActiveEntry.get(), mLoadType, + /* aUpdatedCacheKey = */ 0, false); + } mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext(); } } + mNeedToReportActiveAfterLoadingBecomesActive = false;
if (mActiveEntry) { MOZ_ASSERT(loadingEntry); uint32_t loadType = mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType; - mBrowsingContext->SessionHistoryCommit(*loadingEntry, loadType, - hadActiveEntry, aPersist, false); + if (loadingEntry->mLoadId != UINT64_MAX) { + mBrowsingContext->SessionHistoryCommit(*loadingEntry, loadType, + hadActiveEntry, aPersist, false); + } } }
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 19b09f3bd470f..1b06af5c84e5c 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -493,7 +493,8 @@ class nsDocShell final : public nsDocLoader, mozilla::dom::BrowsingContext* aBrowsingContext, uint32_t aLoadType);
void SetLoadingSessionHistoryInfo( - const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo); + const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo, + bool aNeedToReportActiveAfterLoadingBecomesActive = false); const mozilla::dom::LoadingSessionHistoryInfo* GetLoadingSessionHistoryInfo() { return mLoadingEntry.get(); @@ -666,6 +667,12 @@ class nsDocShell final : public nsDocLoader, nsIURI* aCurrentURI, nsIReferrerInfo* aReferrerInfo, bool aNotifiedBeforeUnloadListeners = false);
+ public: + bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI, + bool aInheritPrincipal, + nsIPrincipal* aPrincipalToInherit); + + private: // // URI Load // @@ -1167,7 +1174,9 @@ class nsDocShell final : public nsDocLoader, // These are only set when fission.sessionHistoryInParent is set. mozilla::UniquePtrmozilla::dom::SessionHistoryInfo mActiveEntry; bool mActiveEntryIsLoadingFromSessionHistory = false; - // mLoadingEntry is set when we're about to start loading. + // mLoadingEntry is set when we're about to start loading. Whenever + // setting mLoadingEntry, be sure to also set + // mNeedToReportActiveAfterLoadingBecomesActive. mozilla::UniquePtrmozilla::dom::LoadingSessionHistoryInfo mLoadingEntry;
// Holds a weak pointer to a RestorePresentationEvent object if any that @@ -1309,6 +1318,12 @@ class nsDocShell final : public nsDocLoader, // Whether we have a pending encoding autodetection request from the // menu for all encodings. bool mForcedAutodetection : 1; + + // Whether mBrowsingContext->SetActiveSessionHistoryEntry() needs to be called + // when the loading entry becomes the active entry. This is used for the + // initial about:blank-replacing about:blank in order to make the history + // length WPTs pass. + bool mNeedToReportActiveAfterLoadingBecomesActive : 1; };
#endif /* nsDocShell_h__ */ diff --git a/docshell/shistory/SessionHistoryEntry.cpp b/docshell/shistory/SessionHistoryEntry.cpp index 0361fb0c28c58..509955485108e 100644 --- a/docshell/shistory/SessionHistoryEntry.cpp +++ b/docshell/shistory/SessionHistoryEntry.cpp @@ -355,6 +355,10 @@ LoadingSessionHistoryInfo::LoadingSessionHistoryInfo( SessionHistoryEntry::sLoadIdToEntry->Get(mLoadId) == aEntry); }
+LoadingSessionHistoryInfo::LoadingSessionHistoryInfo( + const SessionHistoryInfo& aInfo) + : mInfo(aInfo), mLoadId(UINT64_MAX) {} + already_AddRefed<nsDocShellLoadState> LoadingSessionHistoryInfo::CreateLoadInfo() const { RefPtr<nsDocShellLoadState> loadState( @@ -1195,7 +1199,7 @@ void SessionHistoryEntry::AddChild(SessionHistoryEntry* aChild, int32_t aOffset, // This should ideally stop being an issue once the Fission-aware // session history rewrite is complete. NS_ASSERTION( - aUseRemoteSubframes, + aUseRemoteSubframes || NS_IsAboutBlank(oldChild->Info().GetURI()), "Adding a child where we already have a child? This may misbehave"); oldChild->SetParent(nullptr); } diff --git a/docshell/shistory/SessionHistoryEntry.h b/docshell/shistory/SessionHistoryEntry.h index a05fa42a2a94a..2fa195cf3b8f0 100644 --- a/docshell/shistory/SessionHistoryEntry.h +++ b/docshell/shistory/SessionHistoryEntry.h @@ -217,6 +217,9 @@ struct LoadingSessionHistoryInfo { LoadingSessionHistoryInfo(SessionHistoryEntry* aEntry, LoadingSessionHistoryInfo* aInfo);
+ // For about:blank only. + explicit LoadingSessionHistoryInfo(const SessionHistoryInfo& aInfo); + already_AddRefed<nsDocShellLoadState> CreateLoadInfo() const;
SessionHistoryInfo mInfo; diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 788663016e918..db3297eb69e76 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1758,6 +1758,15 @@ nsresult nsObjectLoadingContent::CloseChannel() { return NS_OK; }
+bool nsObjectLoadingContent::IsAboutBlankLoadOntoInitialAboutBlank( + nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) { + return NS_IsAboutBlank(aURI) && aInheritPrincipal && + (!mFrameLoader || !mFrameLoader->GetExistingDocShell() || + mFrameLoader->GetExistingDocShell() + ->IsAboutBlankLoadOntoInitialAboutBlank(aURI, aInheritPrincipal, + aPrincipalToInherit)); +} + nsresult nsObjectLoadingContent::OpenChannel() { nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); @@ -1830,7 +1839,9 @@ nsresult nsObjectLoadingContent::OpenChannel() { loadInfo->SetCSPToInherit(cspToInherit); }
- if (DocumentChannel::CanUseDocumentChannel(mURI)) { + if (DocumentChannel::CanUseDocumentChannel(mURI) && + !IsAboutBlankLoadOntoInitialAboutBlank(mURI, inheritPrincipal, + thisContent->NodePrincipal())) { // --- Create LoadState RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(mURI); loadState->SetPrincipalToInherit(thisContent->NodePrincipal()); diff --git a/dom/base/nsObjectLoadingContent.h b/dom/base/nsObjectLoadingContent.h index 37bfd96ae0cf2..efe0b610be427 100644 --- a/dom/base/nsObjectLoadingContent.h +++ b/dom/base/nsObjectLoadingContent.h @@ -371,6 +371,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent, */ void QueueCheckPluginStopEvent();
+ public: + bool IsAboutBlankLoadOntoInitialAboutBlank(nsIURI* aURI, + bool aInheritPrincipal, + nsIPrincipal* aPrincipalToInherit); + + private: /** * Opens the channel pointed to by mURI into mChannel. */ diff --git a/netwerk/ipc/DocumentChannel.cpp b/netwerk/ipc/DocumentChannel.cpp index 4dfa0eddf8ca7..2d566c6451986 100644 --- a/netwerk/ipc/DocumentChannel.cpp +++ b/netwerk/ipc/DocumentChannel.cpp @@ -154,8 +154,6 @@ nsDocShell* DocumentChannel::GetDocShell() { return nsDocShell::Cast(docshell); }
-// Changes here should also be made in -// E10SUtils.documentChannelPermittedForURI(). static bool URIUsesDocChannel(nsIURI* aURI) { if (SchemeIsJavascript(aURI)) { return false; diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html index 44ba631cf0028..2b70375a14358 100644 --- a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html @@ -10,10 +10,10 @@ async_test(t => { i.src = iframe_url;
history.pushState("a", "", "#a"); - assert_equals(starting_history_length + 1, history.length); + assert_equals(history.length, starting_history_length + 1, "First history length");
i.onload = t.step_func(() => { - assert_equals(starting_history_length + 1, history.length); + assert_equals(history.length, starting_history_length + 1, "Second history length"); assert_equals(i.contentWindow.location.href, iframe_url); assert_equals(location.hash, "#a"); history.back(); diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/empty-iframe-load-event.html b/testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/empty-iframe-load-event.html new file mode 100644 index 0000000000000..b9108f9937701 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/navigating-across-documents/empty-iframe-load-event.html @@ -0,0 +1,39 @@ +<!doctype html> +<title>load event for empty iframe in relation to the event loop</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +setup({explicit_done:true}); +let ran = false; + +onload = function() { + let iframe = document.createElement("iframe"); + iframe.onload = function() { + test(function() { + assert_equals(ran, false, 'Expected onload to run first'); + }, "Check execution order on load handler"); + if (ran) { + done(); + } else { + ran = true; + } + }; + document.body.appendChild(iframe); + + // Nested timeout to accommodate Gecko, because the it seems + // the outer setTimeout takes its slot in the event queue right away + // but the load event task takes its slot only at the end of this script. + setTimeout(function() { + setTimeout(function() { + test(function() { + assert_equals(ran, true, 'Expected nested setTimeout to run second'); + }, "Check execution order from nested timeout"); + if (ran) { + done(); + } else { + ran = true; + } + }); + }); +}; +</script> diff --git a/toolkit/components/aboutprocesses/tests/browser/head.js b/toolkit/components/aboutprocesses/tests/browser/head.js index 9e98a404bc0e8..a8f1b82ae2f97 100644 --- a/toolkit/components/aboutprocesses/tests/browser/head.js +++ b/toolkit/components/aboutprocesses/tests/browser/head.js @@ -415,15 +415,16 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) { skipAnimation: true, }); await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + let p = BrowserTestUtils.browserLoaded( + tab.linkedBrowser, + true /* includeSubFrames */ + ); await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { // Open an in-process iframe to test toolkit.aboutProcesses.showAllSubframes let frame = content.document.createElement("iframe"); content.document.body.appendChild(frame); }); - await BrowserTestUtils.browserLoaded( - tab.linkedBrowser, - true /* includeSubFrames */ - ); + await p; return tab; })();