Skip to content

Commit

Permalink
Navigation API: ensure that 204/205/downloads never settle
Browse files Browse the repository at this point in the history
See WICG/navigation-api#137.

Bug: 1183545
Change-Id: I6f8f1771816ddf454d651f7147d3179fba88979b
  • Loading branch information
domenic authored and chromium-wpt-export-bot committed Mar 21, 2022
1 parent 0e9eddc commit 5a7d12a
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/helpers.js"></script>
<script src="/common/utils.js"></script>

<body>
<script>
const tests = [
["204s", "204"],
["205s", "205"],
["Content-Disposition: attachment responses", "download"]
];

for (const [description, action] of tests) {
promise_test(async t => {
const id = token();

const i = document.createElement("iframe");
i.src = `resources/204-205-download-on-second-visit.py?id=${id}`;
document.body.append(i);
await new Promise(r => i.onload = r);

// Configure it to return a 204 on the next visit
await fetch(i.src + `&action=${action}`, { method: "POST" });

// Now navigate elsewhere
i.contentWindow.location.href = "/common/blank.html";
await new Promise(r => i.onload = r);

// Now try going back. It should do nothing (and not tell us about the result).

const indexBefore = i.contentWindow.navigation.currentEntry.index;

// One might be surprised that navigate does not fire. (It does fire for the
// corresponding tests of navigation.navigate(), i.e., this is
// traversal-specific behavior.) See https://github.com/WICG/navigation-api/issues/207
// for some discussion.
i.contentWindow.navigation.onnavigate = t.unreached_func("onnavigate should not be called");
i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called");
i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called");

const result = i.contentWindow.navigation.back();

assertNeverSettles(t, result, i.contentWindow);

await new Promise(resolve => t.step_timeout(resolve, 50));
assert_equals(i.contentWindow.navigation.currentEntry.index, indexBefore);
}, `back() promises to ${description} never settle`);
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/helpers.js"></script>

<body>
<script>
const tests = [
["204s", "/common/blank.html?pipe=status(204)"],
["205s", "/common/blank.html?pipe=status(205)"],
["Content-Disposition: attachment responses", "/common/blank.html?pipe=header(Content-Disposition,attachment)"]
];

for (const [description, url] of tests) {
promise_test(async t => {
const i = document.createElement("iframe");
i.src = "/common/blank.html";
document.body.append(i);
await new Promise(resolve => i.onload = resolve);

// This seems to be important? Without it the (outer) window load event
// doesn't fire, and the test harness hangs forever. This is probably a
// Chromium bug, but maybe a testharness bug, especially since explicit_done
// doesn't seem to help?
t.add_cleanup(() => i.remove());

let navigateCount = 0;
i.contentWindow.navigation.onnavigate = () => { ++navigateCount; };
i.contentWindow.navigation.onnavigatesuccess = t.unreached_func("onnavigatesuccess should not be called");
i.contentWindow.navigation.onnavigateerror = t.unreached_func("onnavigateerror should not be called");

const result = i.contentWindow.navigation.navigate(url);

assert_equals(navigateCount, 1);
assertNeverSettles(t, result, i.contentWindow);

await new Promise(resolve => t.step_timeout(resolve, 50));
assert_equals(i.contentWindow.location.href, i.src);
}, `navigate() promises to ${description} never settle`);
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def main(request, response):
key = request.GET[b"id"]

# If hit with a POST with ?action=X, store X in the stash
if request.method == "POST":
action = request.GET[b"action"]
request.server.stash.put(key, action)

return (204, [], "")

# If hit with a GET, either return a normal initial page, or the abnormal requested response
elif request.method == "GET":
action = request.server.stash.take(key)

if action is None:
return (200, [("Content-Type", "text/html"), ("Cache-Control", "no-store")], "initial page")
if action == b"204":
return (204, [], "")
if action == b"205":
return (205, [], "")
if action == b"download":
return (200, [("Content-Type", "text/plain"), ("Content-Disposition", "attachment")], "some text to download")

return (400, [], "")

0 comments on commit 5a7d12a

Please sign in to comment.