test_fullscreen-api-race.html (5346B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Test for race conditions of Fullscreen API</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script src="/tests/SimpleTest/EventUtils.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 8 </head> 9 <body> 10 <script> 11 12 function Deferred() { 13 this.promise = new Promise(resolve => { 14 this.resolve = resolve; 15 }); 16 } 17 18 function checkIsChromeFullscreen(win, inFullscreen) { 19 return SimpleTest.promiseWaitForCondition( 20 () => win.fullScreen == inFullscreen, 21 "The window should exit fullscreen state"); 22 } 23 24 SimpleTest.waitForExplicitFinish(); 25 // XXX This actually exposes a true race condition, but it could rarely 26 // happen in real world, because it only happens when requestFullscreen 27 // is called immediately after exiting fullscreen in certain condition, 28 // and in real life, requestFullscreen can only be called inside a user 29 // event handler. But we want to fix this race condition at some point, 30 // via queuing all exiting request as well as entering request together 31 // which we may eventually need to do for bug 1188256. 32 SimpleTest.requestFlakyTimeout( 33 "Need to wait for potential fullscreen transition"); 34 addLoadEvent(function () { 35 SpecialPowers.pushPrefEnv({ 36 "set": [ 37 ["full-screen-api.allow-trusted-requests-only", false], 38 ] 39 }, next); 40 }); 41 42 const OPEN_WINDOW_FUNCS = [ 43 function openNewTab() { 44 return new Promise(resolve => { 45 var win = window.open("about:blank"); 46 setTimeout(function() { 47 resolve(win); 48 }, 0); 49 }); 50 }, 51 function openNewWindow() { 52 return new Promise(resolve => { 53 var win = window.open("about:blank", "", "width=300,height=200"); 54 setTimeout(function() { 55 resolve(win); 56 }, 0); 57 }); 58 } 59 ]; 60 61 const ACTION_FUNCS = [ 62 function navigate(win) { 63 info("About to navigate to another page"); 64 var promise = new Promise(resolve => { 65 window.addEventListener("message", () => { 66 SimpleTest.waitForFocus(() => { 67 checkIsChromeFullscreen(win, false).then(() => { 68 win.close(); 69 resolve(); 70 }); 71 }, win); 72 }, { once: true }); 73 }); 74 win.location = "file_fullscreen-api-race.html"; 75 return promise; 76 }, 77 function closeWindow(win) { 78 info("About to close the window"); 79 win.close(); 80 return Promise.resolve(); 81 }, 82 function exitFullscreen(win) { 83 info("About to cancel fullscreen"); 84 var deferred = new Deferred(); 85 function listener() { 86 win.removeEventListener("fullscreenchange", listener); 87 ok(!win.document.fullscreenElement, "Should exit fullscreen"); 88 checkIsChromeFullscreen(win, false).then(() => { 89 win.close(); 90 deferred.resolve(); 91 }); 92 } 93 win.addEventListener("fullscreenchange", listener); 94 win.document.exitFullscreen(); 95 return deferred.promise; 96 }, 97 function exitAndClose(win) { 98 info("About to cancel fullscreen and close the window"); 99 win.document.exitFullscreen(); 100 win.close(); 101 return Promise.resolve(); 102 } 103 ]; 104 105 function* testGenerator() { 106 for (var openWinFunc of OPEN_WINDOW_FUNCS) { 107 for (var actionFunc of ACTION_FUNCS) { 108 info(`Testing ${openWinFunc.name}, ${actionFunc.name}`); 109 yield { openWinFunc, actionFunc }; 110 } 111 } 112 } 113 114 function runTest(test) { 115 var winPromise = test.openWinFunc(); 116 return winPromise.then((win) => { 117 return new Promise(resolve => { 118 SimpleTest.waitForFocus(() => resolve(win), win, true); 119 }); 120 }).then((win) => { 121 return new Promise((resolve, reject) => { 122 var retried = false; 123 function listener(evt) { 124 if (!retried && evt.type == "fullscreenerror") { 125 todo(false, "Failed to enter fullscreen, but try again"); 126 retried = true; 127 SimpleTest.waitForFocus(() => { 128 win.document.documentElement.requestFullscreen(); 129 }, win, true); 130 return; 131 } 132 win.removeEventListener("fullscreenchange", listener); 133 win.removeEventListener("fullscreenerror", listener); 134 is(evt.type, "fullscreenchange", "Should get fullscreenchange"); 135 ok(win.document.fullscreenElement, "Should have entered fullscreen"); 136 ok(win.fullScreen, "The window should be in fullscreen"); 137 test.actionFunc(win).then(() => resolve(win)); 138 } 139 if (win.fullScreen) { 140 todo(false, "Should not open in fullscreen mode"); 141 win.close(); 142 reject(); 143 return; 144 } 145 info("About to enter fullscreen"); 146 win.addEventListener("fullscreenchange", listener); 147 win.addEventListener("fullscreenerror", listener); 148 win.document.documentElement.requestFullscreen(); 149 }); 150 }).then((win) => { 151 ok(win.closed, "The window should have been closed"); 152 }); 153 } 154 155 var tests = testGenerator(); 156 157 function next() { 158 var test = tests.next().value; 159 if (test) { 160 runTest(test).catch(() => { 161 return new Promise(resolve => { 162 SimpleTest.waitForFocus(resolve); 163 }).then(() => runTest(test)); 164 }).catch(() => { 165 ok(false, "Fail to run test " + 166 `${test.openWinFunc.name}, ${test.actionFunc.name}`); 167 }).then(() => { 168 setTimeout(() => SimpleTest.waitForFocus(next), 1000); 169 }); 170 } else { 171 SimpleTest.finish(); 172 } 173 } 174 175 </script> 176 </body> 177 </html>