diff --git a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html
index b89d3bb54b8ebe..6b30f2aba13909 100644
--- a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html
+++ b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html
@@ -175,4 +175,39 @@
assert_equals(history.length, startingHistoryLength + 1,
"history.length increases after normal navigation from non-initial empty document");
}, "form submission");
+
+// This test is very similar to the `location.href` test a few cases above, but
+// the difference is that instead of navigating from:
+// initial about:blank Document => HTTP => HTTP
+// ... we navigate from:
+// initial about:blank Document => (non-initial) about:blank Document => HTTP
+//
+// We do this to ensure/assert that an explicit navigation to about:blank
+// *after* the iframe has finished initializing, is counted as a normal
+// navigation away from the initial about:blank Document, and the "initial-ness"
+// of the initial about:blank Document is not carried over to the next
+// about:blank Document.
+promise_test(async t => {
+ const startingHistoryLength = history.length;
+ // Create an iframe with src not set, which will stay on the initial empty
+ // document.
+ const iframe = insertIframe(t);
+ assert_equals(history.length, startingHistoryLength,
+ "Inserting iframe with no src must not change history.length");
+
+ // Navigate away from the initial empty document through setting location.href
+ // to `about:blank`. This should do a replacement TO ANOTHER about:blank
+ // Document, which is not the initial about:blank Document.
+ iframe.contentWindow.location.href = 'about:blank';
+ await waitForLoad(t, iframe, 'about:blank');
+ assert_equals(history.length, startingHistoryLength,
+ "history.length must not change after normal navigation on document loaded by iframe with no src");
+
+ // Navigate again using the same method, but this time it shouldn't do a
+ // replacement since it's no longer on the initial empty document.
+ iframe.contentWindow.location.href = url2;
+ await waitForLoad(t, iframe, url2);
+ assert_equals(history.length, startingHistoryLength + 1,
+ "history.length increases after normal navigation from non-initial empty document");
+}, "initial about:blank => non-initial about:blank (via location.href) => normal HTTP navigation");
diff --git a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html
index a75257d91cf6c5..626588f335093b 100644
--- a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html
+++ b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html
@@ -16,32 +16,42 @@
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank. This would trigger a
- // navigation to a non-initial about:blank document.
+ // Create an iframe with src set to about:blank. Per the HTML Standard, this
+ // stays on the "initial about:blank Document" [1], because the "process the
+ // iframe attributes" algorithm [2] catches the "about:blank" navigation and
+ // fires a special synchronous `load` event at the initial about:blank
+ // Document, instead of replacing it with a non-initial, second about:blank
+ // Document. This is documented in the note at the end of [3].
+ //
+ // [1]: https://html.spec.whatwg.org/#is-initial-about:blank.
+ // [2]: https://html.spec.whatwg.org/#process-the-iframe-attributes
+ // [3]: https://html.spec.whatwg.org/#completely-finish-loading
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Trigger a navigation to url1 through the iframe's src attribute.
- // The iframe should still be on the initial empty document, and the
- // navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // the iframe's src attribute. Because we're navigating from the initial
+ // about:blank Document, the navigation should be a replacement.
iframe.src = url1;
+
// Wait for the latest navigation to finish.
await waitForLoad(t, iframe, url1);
assert_equals(history.length, startingHistoryLength,
- "history.length must not change after normal navigation on initial empty document");
-}, "Navigating to a different document with src");
+ "history.length must not change after normal navigation from initial " +
+ "about:blank Document");
+}, "Navigating away from the initial about:blank Document to a different " +
+ "one, with src");
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank but navigate away from it immediately below.
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Navigate away from the initial empty document through setting
- // location.href. The iframe should still be on the initial empty document,
- // and the navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // location.href. Because we're navigating from the initial about:blank
+ // Document, the navigation should be a replacement.
iframe.contentWindow.location.href = url1;
await waitForLoad(t, iframe, url1);
assert_equals(history.length, startingHistoryLength,
@@ -50,14 +60,13 @@
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank but navigate away from it immediately below.
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Navigate away from the initial empty document through location.assign().
- // The iframe should still be on the initial empty document, and the
- // navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // location.assign(). Because we're navigating from the initial about:blank
+ // Document, the navigation should be a replacement.
iframe.contentWindow.location.assign(url1);
await waitForLoad(t, iframe, url1);
assert_equals(history.length, startingHistoryLength,
@@ -66,14 +75,13 @@
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank but navigate away from it immediately below.
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Navigate away from the initial empty document through window.open().
- // The iframe should still be on the initial empty document, and the
- // navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // window.open(). Because we're navigating from the initial about:blank
+ // Document, the navigation should be a replacement.
iframe.contentWindow.open(url1, "_self");
await waitForLoad(t, iframe, url1);
assert_equals(history.length, startingHistoryLength,
@@ -82,14 +90,13 @@
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank but navigate away from it immediately below.
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Navigate away from the initial empty document through clicking an
- // element. The iframe should still be on the initial empty document, and the
- // navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // clicking an `` element. Because we're navigating from the initial
+ // about:blank Document, the navigation should be a replacement.
const a = iframe.contentDocument.createElement("a");
a.href = url1;
iframe.contentDocument.body.appendChild(a);
@@ -101,14 +108,13 @@
promise_test(async t => {
const startingHistoryLength = history.length;
- // Create an iframe with src set to about:blank but navigate away from it immediately below.
const iframe = insertIframeWithAboutBlankSrc(t);
assert_equals(history.length, startingHistoryLength,
"Inserting iframe with src='about:blank' must not change history.length");
- // Navigate away from the initial empty document through form submission.
- // The iframe should still be on the initial empty document, and the
- // navigation should do replacement.
+ // Trigger a navigation from the initial about:blank Document, to url1 through
+ // a form submission. Because we're navigating from the initial about:blank
+ // Document, the navigation should be a replacement.
const form = iframe.contentDocument.createElement("form");
form.action = "/common/blank.html";
iframe.contentDocument.body.appendChild(form);
diff --git a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/resources/helpers.js b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/resources/helpers.js
index 8d9473a9497d74..8866f7750627db 100644
--- a/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/resources/helpers.js
+++ b/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/resources/helpers.js
@@ -37,7 +37,16 @@ window.insertIframeWith204Src = (t) => {
return iframe;
};
-// Creates an iframe with src="about:blank" and appends it to the document.
+// Creates an iframe with src="about:blank" and appends it to the document. The
+// resulting document in the iframe is the initial about:blank Document [1],
+// because during the "process the iframe attributes" algorithm [2], `src`
+// navigations to `about:blank` are caught and result in a synchronous load
+// event; not a SEPARATE navigation to a non-initial `about:blank` Document. See
+// the documentation in [3] as well.
+//
+// [1]: https://html.spec.whatwg.org/#is-initial-about:blank
+// [2]: https://html.spec.whatwg.org/#process-the-iframe-attributes
+// [3]: https://html.spec.whatwg.org/#completely-finish-loading
window.insertIframeWithAboutBlankSrc = (t) => {
const iframe = document.createElement("iframe");
t.add_cleanup(() => iframe.remove());
@@ -47,12 +56,14 @@ window.insertIframeWithAboutBlankSrc = (t) => {
};
// Creates an iframe with src="about:blank", appends it to the document, and
-// waits for the non-initial about:blank document finished loading.
+// waits for initial about:blank Document to finish loading.
window.insertIframeWithAboutBlankSrcWaitForLoad = async (t) => {
const iframe = insertIframeWithAboutBlankSrc(t);
const aboutBlankLoad = new Promise(resolve => {
- // In some browsers, the non-initial about:blank navigation commits
+ // In some browsers, when the initial about:blank Document is influenced by
+ // a `src=about:blank` attribute, the about:blank navigation commits
// asynchronously, while in other browsers, it would commit synchronously.
+ //
// This means we can't wait for the "load" event as it might have already
// ran. Instead, just wait for 100ms before resolving, as the non-initial
// about:blank navigation will most likely take less than 100 ms to commit.