Skip to content

Commit

Permalink
NavigationActivation prototype
Browse files Browse the repository at this point in the history
Initial discussion: whatwg/html#9760
Draft spec PR: whatwg/html#9856

Bug: 1492932
Change-Id: I2e090a8366906e4cb6778893ad9ffdca18d6ec37
  • Loading branch information
natechapin authored and chromium-wpt-export-bot committed Oct 31, 2023
1 parent 89e44c7 commit 40131e8
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
<script src="resources/is_uuid.js"></script>

<script>
// This test ensures that navigation.activation is properly updated when a page
// is restored from bfcache.
runBfcacheTest({
targetOrigin: originSameSite,
async funcAfterAssertion(pageA, pageB) {
const activationData = await pageA.execute_script(() => {
return { entryURL : navigation.activation.entry.url,
fromIsNull : navigation.activation.from == null,
navigationType : navigation.activation.navigationType }
});

// activation.entry should be the currently activated page, and
// activation.from should be omitted because it is a different origin.
assert_equals(activationData.entryURL, pageA.url);
assert_true(activationData.fromIsNull);
assert_equals(activationData.navigationType, "traverse");
}
}, "navigation.activation must be updated when restored from bfcache");
</script>
28 changes: 28 additions & 0 deletions navigation-api/navigation-activation/activation-after-bfcache.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
<script src="resources/is_uuid.js"></script>

<script>
// This test ensures that navigation.activation is properly updated when a page
// is restored from bfcache.
runBfcacheTest({
targetOrigin: originSameOrigin,
async funcAfterAssertion(pageA, pageB) {
const activationData = await pageA.execute_script(() => {
return { entryURL : navigation.activation.entry.url,
fromURL : navigation.activation.from.url,
navigationType : navigation.activation.navigationType }
});

// activation.entry should be the currently activated page, and
// activation.from should be the page before restored from bfcache.
assert_equals(activationData.entryURL, pageA.url);
assert_equals(activationData.fromURL, pageB.url);
assert_equals(activationData.navigationType, "traverse");
}
}, "navigation.activation must be updated when restored from bfcache");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

assert_equals(navigation.activation.entry, navigation.currentEntry);
let activationEntry = navigation.activation.entry;
let entryIndexBeforePush = activationEntry.index;
history.pushState("#fragment", "", "");
assert_not_equals(navigation.activation.entry, navigation.currentEntry);
assert_equals(navigation.activation.entry, activationEntry);
assert_equals(navigation.activation.entry.index, entryIndexBeforePush);
}, "navigation.activation.entry should not change due to history.pushState()");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

assert_equals(navigation.activation.entry, navigation.currentEntry);
let activationEntry = navigation.activation.entry;
history.replaceState("#fragment", "", "");
assert_not_equals(navigation.activation.entry, navigation.currentEntry);
assert_equals(navigation.activation.entry, activationEntry);
assert_equals(navigation.activation.entry.index, -1);
}, "navigation.activation.entry should be orphaned by history.replaceState()");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

let i = document.createElement("iframe");
i.src = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + "/common/blank.html";
document.body.appendChild(i);
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.location = "/common/blank.html";
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;

assert_equals(i.contentWindow.navigation.entries().length, 1);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.from, null);
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
}, "navigation.activation after push cross-origin");
</script>
30 changes: 30 additions & 0 deletions navigation-api/navigation-activation/activation-push.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.navigation.navigate("/common/blank.html?a");
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;

assert_equals(i.contentWindow.navigation.entries().length, 2);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[0]);
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");

// Same-document navigation doesn't change navigation.activation.
await i.contentWindow.navigation.navigate("/common/blank.html?a#fragment").finished;

assert_equals(i.contentWindow.navigation.entries().length, 3);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[0]);
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
}, "navigation.activation after push");
</script>
21 changes: 21 additions & 0 deletions navigation-api/navigation-activation/activation-reload.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.navigation.reload();
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

// activation.entry and activation.from are equal after reload
assert_equals(i.contentWindow.navigation.entries().length, 1);
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
assert_equals(i.contentWindow.navigation.activation.entry,
i.contentWindow.navigation.activation.from);
assert_equals(i.contentWindow.navigation.activation.navigationType, "reload");
}, "navigation.activation after reload");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

let i = document.createElement("iframe");
i.src = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + "/common/blank.html";
document.body.appendChild(i);
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.location.replace("/common/blank.html");
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;

assert_equals(i.contentWindow.navigation.entries().length, 1);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.from, null);
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
}, "navigation.activation after replace cross-origin");
</script>
44 changes: 44 additions & 0 deletions navigation-api/navigation-activation/activation-replace.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

let before_key = i.contentWindow.navigation.currentEntry.key;
let before_id = i.contentWindow.navigation.currentEntry.id;
let before_url = i.contentWindow.navigation.currentEntry.url;
i.contentWindow.navigation.navigate("/common/blank.html?a", { history: "replace" });
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
let current_entry_after_nav = i.contentWindow.navigation.currentEntry;
let from_entry_after_nav = i.contentWindow.navigation.activation.from;

// activation.entry is the current entry. activation.from is a new
// NavigationHistoryEntry object (because there is a new window), with the
// same key/id/url as before the navigation, and an index of -1 because it is
// not present in the entries array.
assert_equals(i.contentWindow.navigation.entries().length, 1);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
assert_equals(from_entry_after_nav.key, before_key);
assert_equals(from_entry_after_nav.id, before_id);
assert_equals(from_entry_after_nav.url, before_url);
assert_equals(from_entry_after_nav.index, -1);
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");

await i.contentWindow.navigation.navigate("/common/blank.html?a#fragment", { history: "replace" }).finished;

// activation.entry is no longer navigation.currentEntry and is disposed.
// activation.from has not changed.
assert_equals(i.contentWindow.navigation.entries().length, 1);
assert_equals(i.contentWindow.navigation.activation.entry, current_entry_after_nav);
assert_not_equals(i.contentWindow.navigation.activation.entry,
i.contentWindow.navigation.currentEntry);
assert_equals(i.contentWindow.navigation.activation.entry.index, -1);
assert_equals(i.contentWindow.navigation.activation.from, from_entry_after_nav);
assert_equals(i.contentWindow.navigation.activation.navigationType, "replace");
}, "navigation.activation after replace");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));
await i.contentWindow.navigation.navigate("/common/blank.html#fragment").finished;
assert_equals(i.contentWindow.navigation.entries().length, 2);

let urlAfterSameDoc = i.contentWindow.location.href;

i.contentWindow.navigation.navigate("/common/blank.html?a");
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));
assert_equals(i.contentWindow.navigation.entries().length, 3);

assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[1]);
assert_equals(i.contentWindow.navigation.activation.from.url, urlAfterSameDoc);
assert_equals(i.contentWindow.navigation.activation.navigationType, "push");
}, "navigation.activation same-document then cross-document");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.navigation.navigate("/common/blank.html?a");
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

assert_equals(i.contentWindow.navigation.entries().length, 2);

i.contentWindow.navigation.back();
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

// activation.entry is the current entry. activation.from is the entry the
// traverse came from.
assert_equals(i.contentWindow.navigation.entries().length, 2);
assert_equals(i.contentWindow.navigation.activation.entry, i.contentWindow.navigation.currentEntry);
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[1]);
assert_equals(i.contentWindow.navigation.activation.navigationType, "traverse");

let from_key_before_push = i.contentWindow.navigation.activation.from.key;
let from_id_before_push = i.contentWindow.navigation.activation.from.id;
let from_url_before_push = i.contentWindow.navigation.activation.from.url;
await i.contentWindow.navigation.navigate("/common/blank.html#fragment").finished;

// pushing same document will not change activation.entry, but it will cut
// activation.from out of the entries array. Its parameters should not change
//except for its index, which becomes -1.
assert_equals(i.contentWindow.navigation.entries().length, 2);
assert_equals(i.contentWindow.navigation.activation.entry, i.contentWindow.navigation.entries()[0]);
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
assert_not_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[1]);
assert_equals(i.contentWindow.navigation.activation.from.key, from_key_before_push);
assert_equals(i.contentWindow.navigation.activation.from.id, from_id_before_push);
assert_equals(i.contentWindow.navigation.activation.from.url, from_url_before_push);
assert_equals(i.contentWindow.navigation.activation.from.index, -1);
assert_equals(i.contentWindow.navigation.activation.navigationType, "traverse");
}, "navigation.activation - traverse, then push same-document");
</script>
38 changes: 38 additions & 0 deletions navigation-api/navigation-activation/activation-traverse.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="i" src="/common/blank.html"></iframe>
<script>
promise_test(async t => {
// Wait for after the load event so that the navigation doesn't get converted
// into a replace navigation.
await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0));

i.contentWindow.navigation.navigate("/common/blank.html?a");
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

assert_equals(i.contentWindow.navigation.entries().length, 2);

i.contentWindow.navigation.back();
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

// activation.entry is the current entry. activation.from is the entry the
// traverse came from.
assert_equals(i.contentWindow.navigation.entries().length, 2);
assert_equals(i.contentWindow.navigation.activation.entry, i.contentWindow.navigation.currentEntry);
assert_equals(i.contentWindow.navigation.activation.entry.index, 0);
assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[1]);
assert_equals(i.contentWindow.navigation.activation.navigationType, "traverse");

i.contentWindow.navigation.forward();
await new Promise(resolve => i.onload = () => t.step_timeout(resolve, 0));

assert_equals(i.contentWindow.navigation.entries().length, 2);
assert_equals(i.contentWindow.navigation.activation.entry, i.contentWindow.navigation.currentEntry);
assert_equals(i.contentWindow.navigation.activation.entry.index, 1);
assert_equals(i.contentWindow.navigation.activation.from,
i.contentWindow.navigation.entries()[0]);
assert_equals(i.contentWindow.navigation.activation.navigationType, "traverse");
}, "navigation.activation after traverse");
</script>

0 comments on commit 40131e8

Please sign in to comment.