element-request-fullscreen-cross-origin-multi-steps.sub.html (5771B)
1 <!DOCTYPE html> 2 <title> 3 Element#requestFullscreen() works properly with a tree of cross-origin iframes, with multiple requests 4 </title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 10 <body> 11 <script> 12 let childFrame = null; 13 function waitFor(action, frameName) { 14 return new Promise((resolve) => { 15 window.addEventListener("message", function listener(e) { 16 if (e.data.action === action && e.data.name === frameName) { 17 window.removeEventListener("message", listener); 18 resolve(event.data); 19 } 20 }); 21 }); 22 } 23 24 function compare_report(report, frame, expectedIndex) { 25 assert_array_equals(report.events, frame.expectedEvents[expectedIndex], `compare events for ${frame.name}`); 26 assert_equals(report.fullscreenElementIsNull, frame.expectedNullFullscreenElement[expectedIndex], `frame ${frame.name} has expected fullscreen element`); 27 } 28 29 const iframes = [ 30 { 31 name: "A", 32 src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?a", 33 allow_fullscreen: true, 34 expectedEvents: [["fullscreenchange"], []], 35 expectedNullFullscreenElement: [false, false] 36 }, 37 { // first check should see its body go fs, 2nd should see it's <iframe> go fs 38 name: "B", 39 src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?b", 40 allow_fullscreen: true, 41 expectedEvents: [["fullscreenchange"], ["fullscreenchange"]], 42 expectedNullFullscreenElement: [false, false] 43 }, 44 { 45 name: "C", 46 src: "http://{{hosts[][www]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?c", 47 allow_fullscreen: true, 48 expectedEvents: [[], ["fullscreenchange"]], 49 expectedNullFullscreenElement: [true, false] 50 }, 51 { 52 name: "D", 53 src: "http://{{hosts[][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?d", 54 allow_fullscreen: true, 55 expectedEvents: [[],["fullscreenchange"]], 56 expectedNullFullscreenElement: [true, false] 57 }, 58 { 59 name: "E", 60 src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?e", 61 allow_fullscreen: true, 62 expectedEvents: [[],[]], 63 expectedNullFullscreenElement: [true, true] 64 }, 65 ]; 66 67 promise_setup(async () => { 68 // Add the first iframe. 69 const iframeDetails = iframes[0]; 70 childFrame = document.createElement("iframe"); 71 childFrame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : ""; 72 childFrame.name = iframeDetails.name; 73 childFrame.style.width = "100%"; 74 childFrame.style.height = "100%"; 75 childFrame.src = iframeDetails.src; 76 await new Promise((resolve) => { 77 childFrame.onload = resolve; 78 document.body.appendChild(childFrame); 79 }); 80 81 // Create the nested iframes. 82 for (let i = 1; i < iframes.length; i++) { 83 const parentName = iframes[i - 1].name; 84 const details = iframes[i]; 85 childFrame.contentWindow.postMessage( 86 { action: "addIframe", iframe: details, name: parentName }, 87 "*" 88 ); 89 await waitFor("load", details.name); 90 } 91 }); 92 93 promise_test(async (t) => { 94 t.add_cleanup(async () => { 95 if (document.fullscreenElement) { 96 await new Promise((resolve) => { 97 document.addEventListener("fullscreenchange", resolve, { once: true }); 98 document.exitFullscreen(); 99 }); 100 } 101 if (childFrame) { 102 childFrame.remove(); 103 } 104 }); 105 document.onfullscreenerror = t.unreached_func( 106 "fullscreenerror event fired" 107 ); 108 109 const childFrame = document.querySelector("iframe[name=A]"); 110 111 // request fullscreen by trusted click in `name` 112 // and wait until we've seen fullscreen events from 113 // `expectedFrames`. This is to handle intermittent failures 114 // where we check results before the request has completed entirely. 115 const requestFullscreenIn = (name, expectedFrames) => { 116 return new Promise((resolve) => { 117 const pending = new Set(expectedFrames); 118 119 function listener(e) { 120 if (e.data.action === "fsEvent" && pending.has(e.data.name)) { 121 pending.delete(e.data.name); 122 123 if (pending.size === 0) { 124 window.removeEventListener("message", listener); 125 resolve(); 126 } 127 } 128 } 129 130 window.addEventListener("message", listener); 131 childFrame.contentWindow.postMessage( 132 { action: "requestFullscreen", name }, 133 "*" 134 ); 135 }); 136 }; 137 138 const verifyResult = async (expectedResultIndex) => { 139 for (const frame of iframes) { 140 const data = { 141 action: "requestReport", 142 name: frame.name, 143 }; 144 childFrame.contentWindow.postMessage(data, "*"); 145 const { report } = await waitFor("report", frame.name); 146 compare_report(report, frame, expectedResultIndex); 147 } 148 } 149 150 await requestFullscreenIn("B", ["A", "B"]); 151 await verifyResult(0); 152 153 await requestFullscreenIn("D", ["B", "C", "D"]); 154 await verifyResult(1); 155 }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes"); 156 </script> 157 </body>