Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!doctype html>
<meta name="timeout" content="long">
<title>AudioContext.suspend() with navigation</title>
<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>
'use strict';
runBfcacheTest({
funcBeforeNavigation: async () => {
window.promise_event = (target, name) => {
return new Promise(resolve => target[`on${name}`] = resolve);
};
window.promise_source_ended = (audioCtx) => {
const source = new ConstantSourceNode(audioCtx);
source.start(0);
source.stop(audioCtx.currentTime + 1/audioCtx.sampleRate);
return promise_event(source, "ended");
};
window.suspended_ctx = new AudioContext();
// Perform the equivalent of test_driver.bless() to request a user gesture
// for when the test is run from a browser. test_driver would need to be
// able to postMessage() to the test context, which is not available due
// to window.open() being called with noopener (for back/forward cache).
// Audio autoplay is expected to be allowed when run through webdriver
// from `wpt run`.
let button = document.createElement('button');
button.innerHTML = 'This test requires user interaction.<br />' +
'Please click here to allow AudioContext.';
document.body.appendChild(button);
button.addEventListener('click', () => {
document.body.removeChild(button);
suspended_ctx.resume();
}, {once: true});
// Wait for user gesture, if required.
await suspended_ctx.resume();
await suspended_ctx.suspend();
window.ended_promise = promise_source_ended(suspended_ctx);
},
funcAfterAssertion: async (pageA) => {
const state = await pageA.execute_script(() => suspended_ctx.state);
assert_equals(state, 'suspended', 'state after back()');
const first_ended = await pageA.execute_script(async () => {
// Wait for an ended event from a running AudioContext to provide enough
// time to check that the ended event has not yet been dispatched from
// the suspended ctx.
const running_ctx = new AudioContext();
await running_ctx.resume();
return Promise.race([
ended_promise.then(() => 'suspended_ctx'),
promise_source_ended(running_ctx).then(() => 'running_ctx'),
]);
});
assert_equals(first_ended, 'running_ctx',
'AudioContext of first ended event');
await pageA.execute_script(() => {
window.suspended_ctx.resume();
return ended_promise;
});
},
}, 'suspend() with navigation');
</script>