[tbb-commits] [tor-browser] 42/76: Bug 1736570 - Avoid DocumentChannel for nsParser-created initial about:blank replacement. r=smaug, a=RyanVM

gitolite role git at cupani.torproject.org
Wed Mar 30 20:40:10 UTC 2022


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 at 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::UniquePtr<mozilla::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::UniquePtr<mozilla::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;
   })();
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the tbb-commits mailing list