Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf-8>
<title>PerformanceNavigationTiming timing remains after iframe removed</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
const start_page = "/navigation-timing/resources/blank_page_green.html";
const end_page = "/navigation-timing/resources/blank_page_yellow.html";
const host_info = get_host_info();
const same_origin_redirect_chain = () => {
let url = host_info["ORIGIN"];
url += "/common/redirect.py";
url += "?location=";
url += host_info["ORIGIN"];
url += end_page;
return url;
};
const timingAttributes = [
'domComplete',
'domContentLoadedEventEnd',
'domContentLoadedEventStart',
'domInteractive',
//'criticalCHRestart' is not supported in iframe.
'unloadEventStart',
'unloadEventEnd',
'loadEventStart',
'loadEventEnd',
'redirectCount',
'redirectStart',
'redirectEnd',
'fetchStart',
'responseEnd',
];
function verify_timing(pnt, description) {
for (const att of timingAttributes) {
assert_greater_than(pnt[att], 0, `${description} ${att}`);
}
}
promise_test(async function (t) {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
// Navigate from one location to another, then redirect. As a result, the tested fields contain non-zero values.
await new Promise(resolve => {
iframe.onload = function () {
step_timeout(() => { iframe.contentWindow.location.href = same_origin_redirect_chain(); }, 10);
iframe.onload = resolve;
}
iframe.src = start_page;
});
await new Promise(resolve => {
const entries = iframe.contentWindow.performance.getEntriesByType("navigation");
assert_equals(entries.length, 1, "Only one navigation time entry");
const pnt = entries[0];
assert_equals(pnt.name, iframe.contentWindow.location.toString(), "navigation name matches the window.location");
assert_true(pnt.name.endsWith("blank_page_yellow.html"), "navigation name is blank_page_yellow.html");
verify_timing(pnt, "timing values should be positive numbers:")
iframe.remove();
verify_timing(pnt, "timing values should remain positive numbers after iframe is removed:")
resolve();
})
}, "iframe navigation times are persistent after the iframe is removed. Part 1.");
function getOutOfLoadEventHandler(t) {
return new Promise(resolve => t.step_timeout(resolve, 0));
}
function waitForLoad(obj) {
return new Promise(resolve => {
obj.addEventListener("load", resolve, { once: true });
});
}
// 'type' entry should be persistent.
promise_test(async function (t) {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.src = start_page;
await waitForLoad(iframe);
await getOutOfLoadEventHandler(t);
iframe.contentWindow.location.href = end_page;
await waitForLoad(iframe);
iframe.contentWindow.history.back();
await waitForLoad(iframe);
await new Promise(resolve => {
const entries = iframe.contentWindow.performance.getEntriesByType("navigation");
assert_equals(entries.length, 1, "Only one navigation time entry");
const pnt = entries[0];
assert_equals(pnt.name, iframe.contentWindow.location.toString(), "navigation name matches the window.location");
assert_true(pnt.name.endsWith("blank_page_green.html"), "navigation name is blank_page_green.html");
assert_equals(pnt.type, "back_forward", "type should be back_forward after going back to history");
iframe.remove();
assert_equals(pnt.type, "back_forward", "type should remain back_forward after iframe is removed");
resolve();
})
}, "iframe navigation times are persistent after the iframe is removed Part 2.");
</script>
</body>
</html>