Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<html>
<head>
<title>Test for race conditions of Fullscreen API</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script>
function Deferred() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
function checkIsChromeFullscreen(win, inFullscreen) {
return SimpleTest.promiseWaitForCondition(
() => win.fullScreen == inFullscreen,
"The window should exit fullscreen state");
}
SimpleTest.waitForExplicitFinish();
// XXX This actually exposes a true race condition, but it could rarely
// happen in real world, because it only happens when requestFullscreen
// is called immediately after exiting fullscreen in certain condition,
// and in real life, requestFullscreen can only be called inside a user
// event handler. But we want to fix this race condition at some point,
// via queuing all exiting request as well as entering request together
// which we may eventually need to do for bug 1188256.
SimpleTest.requestFlakyTimeout(
"Need to wait for potential fullscreen transition");
addLoadEvent(function () {
SpecialPowers.pushPrefEnv({
"set": [
["full-screen-api.allow-trusted-requests-only", false],
]
}, next);
});
const OPEN_WINDOW_FUNCS = [
function openNewTab() {
return new Promise(resolve => {
var win = window.open("about:blank");
win.addEventListener("load", () => {
resolve(win);
}, { once: true });
});
},
function openNewWindow() {
return new Promise(resolve => {
var win = window.open("about:blank", "", "width=300,height=200");
win.addEventListener("load", () => {
resolve(win);
}, { once: true });
});
}
];
const ACTION_FUNCS = [
function navigate(win) {
info("About to navigate to another page");
var promise = new Promise(resolve => {
window.addEventListener("message", () => {
SimpleTest.waitForFocus(() => {
checkIsChromeFullscreen(win, false).then(() => {
win.close();
resolve();
});
}, win);
}, { once: true });
});
win.location = "file_fullscreen-api-race.html";
return promise;
},
function closeWindow(win) {
info("About to close the window");
win.close();
return Promise.resolve();
},
function exitFullscreen(win) {
info("About to cancel fullscreen");
var deferred = new Deferred();
function listener() {
win.removeEventListener("fullscreenchange", listener);
ok(!win.document.fullscreenElement, "Should exit fullscreen");
checkIsChromeFullscreen(win, false).then(() => {
win.close();
deferred.resolve();
});
}
win.addEventListener("fullscreenchange", listener);
win.document.exitFullscreen();
return deferred.promise;
},
function exitAndClose(win) {
info("About to cancel fullscreen and close the window");
win.document.exitFullscreen();
win.close();
return Promise.resolve();
}
];
function* testGenerator() {
for (var openWinFunc of OPEN_WINDOW_FUNCS) {
for (var actionFunc of ACTION_FUNCS) {
info(`Testing ${openWinFunc.name}, ${actionFunc.name}`);
yield { openWinFunc, actionFunc };
}
}
}
function runTest(test) {
var winPromise = test.openWinFunc();
return winPromise.then((win) => {
return new Promise(resolve => {
SimpleTest.waitForFocus(() => resolve(win), win, true);
});
}).then((win) => {
return new Promise((resolve, reject) => {
var retried = false;
function listener(evt) {
if (!retried && evt.type == "fullscreenerror") {
todo(false, "Failed to enter fullscreen, but try again");
retried = true;
SimpleTest.waitForFocus(() => {
win.document.documentElement.requestFullscreen();
}, win, true);
return;
}
win.removeEventListener("fullscreenchange", listener);
win.removeEventListener("fullscreenerror", listener);
is(evt.type, "fullscreenchange", "Should get fullscreenchange");
ok(win.document.fullscreenElement, "Should have entered fullscreen");
ok(win.fullScreen, "The window should be in fullscreen");
test.actionFunc(win).then(() => resolve(win));
}
if (win.fullScreen) {
todo(false, "Should not open in fullscreen mode");
win.close();
reject();
return;
}
info("About to enter fullscreen");
win.addEventListener("fullscreenchange", listener);
win.addEventListener("fullscreenerror", listener);
win.document.documentElement.requestFullscreen();
});
}).then((win) => {
ok(win.closed, "The window should have been closed");
});
}
var tests = testGenerator();
function next() {
var test = tests.next().value;
if (test) {
runTest(test).catch(() => {
return new Promise(resolve => {
SimpleTest.waitForFocus(resolve);
}).then(() => runTest(test));
}).catch(() => {
ok(false, "Fail to run test " +
`${test.openWinFunc.name}, ${test.actionFunc.name}`);
}).then(() => {
setTimeout(() => SimpleTest.waitForFocus(next), 1000);
});
} else {
SimpleTest.finish();
}
}
</script>
</body>
</html>