blob: 77602b2d4258c87a7ac055475986d691da8dad90 [file] [log] [blame]
<!doctype html>
<title>Verify history.back() on a persisted page resumes timers</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
function make_post_back_url(name) {
return new URL('resources/post_name_on_load.html?name=' + name,
window.location).href;
}
function wait_for_message(name) {
return new Promise(resolve => {
addEventListener('message', function onMsg(evt) {
if (evt.data !== name) {
return;
}
removeEventListener('message', onMsg);
resolve();
});
});
}
function with_window_by_name(name) {
let win = window.open(make_post_back_url(name));
return wait_for_message(name).then(_ => {
return win;
});
}
function with_nested_frame(win, url) {
return new Promise(resolve => {
let frame = win.document.createElement('iframe');
frame.addEventListener('load', function onLoad(evt) {
removeEventListener('load', onLoad);
resolve(frame);
});
frame.src = url;
win.document.body.appendChild(frame);
});
}
function delay(win, delay) {
return new Promise(resolve => {
win.setTimeout(_ => {
resolve(win);
}, delay);
});
}
function navigate_by_name(win, name) {
win.location = make_post_back_url(name);
return wait_for_message(name).then(_ => {
return win;
});
}
function go_back(win) {
return new Promise(resolve => {
win.onpagehide = e => resolve(win);
win.history.back();
});
}
let DELAY = 500;
promise_test(t => {
// Create a new window so we can navigate it later.
return with_window_by_name('foo').then(win => {
// Schedule a timer within the new window. Our intent is
// to navigate the window before the timer fires.
let delayFired = false;
let innerDelay = delay(win, DELAY);
innerDelay.then(_ => {
delayFired = true;
});
return navigate_by_name(win, 'bar').then(_ => {
// Since the window has navigated the timer should not
// fire. We set a timer on our current test window
// to verify the other timer is not received.
assert_false(delayFired);
return delay(window, DELAY * 2);
}).then(_ => {
// The navigated window's timer should not have fired.
assert_false(delayFired);
// Now go back to the document that set the timer.
return go_back(win);
}).then(_ => {
// We wait for one of two conditions here. For browsers
// with a bfcache the original suspended timer will fire.
// Alternatively, if the browser reloads the page the original
// message will be sent again. Wait for either of these
// two events.
return Promise.race([wait_for_message('foo'), innerDelay]);
}).then(_ => {
win.close();
});
});
}, 'history.back() handles top level page timer correctly');
promise_test(t => {
let win;
// Create a new window so we can navigate it later.
return with_window_by_name('foo').then(w => {
win = w;
// Create a nested frame so we check if navigation and history.back()
// properly handle child window state.
return with_nested_frame(win, 'about:blank');
}).then(frame => {
// Schedule a timer within the nested frame contained by the new window.
// Our intent is to navigate the window before the timer fires.
let delayFired = false;
let innerDelay = delay(frame.contentWindow, DELAY);
innerDelay.then(_ => {
delayFired = true;
});
return navigate_by_name(win, 'bar').then(_ => {
// Since the window has navigated the timer should not
// fire. We set a timer on our current test window
// to verify the other timer is not received.
assert_false(delayFired);
return delay(window, DELAY * 2);
}).then(_ => {
// The navigated window's timer should not have fired.
assert_false(delayFired);
// Now go back to the document containing the frame that set the timer.
return go_back(win);
}).then(_ => {
// We wait for one of two conditions here. For browsers
// with a bfcache the original suspended timer will fire.
// Alternatively, if the browser reloads the page the original
// message will be sent again. Wait for either of these
// two events.
return Promise.race([wait_for_message('foo'), innerDelay]);
}).then(_ => {
win.close();
});
});
}, 'history.back() handles nested iframe timer correctly');
</script>