helper_scroll_over_subframe.html (4825B)
1 <!DOCTYPE html> 2 <html> 3 <title>A scroll over an iframe should not terminate the wheel transaction</title> 4 <script type="application/javascript" src="apz_test_utils.js"></script> 5 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 6 <script src="/tests/SimpleTest/paint_listener.js"></script> 7 <head> 8 <style> 9 body { 10 height: 250vh; 11 width: 100%; 12 margin: 0; 13 padding: 0; 14 } 15 16 #spacer { 17 height: 150px; 18 width: 100vw; 19 background: yellow; 20 } 21 22 #subframe { 23 width: 80vw; 24 height: 100vh; 25 } 26 </style> 27 </head> 28 <body> 29 <div id="spacer"></div> 30 <iframe id="subframe"> 31 </iframe> 32 </body> 33 <script> 34 const searchParams = new URLSearchParams(location.search); 35 36 const GESTURE_Y = 120; 37 38 async function scrollWithPan() { 39 let transformEndPromise = promiseTransformEnd(); 40 41 await NativePanHandler.promiseNativePanEvent( 42 window, 43 150, 44 GESTURE_Y, 45 0, 46 NativePanHandler.delta * 0.5, 47 NativePanHandler.beginPhase, 48 ); 49 50 // The iframe we need to scroll over is 30 CSS pixels lower than the original 51 // gesture location. We need to perform at least one pan gesture update after 52 // we have scrolled at least 30 CSS pixels. 53 await SimpleTest.promiseWaitForCondition(async () => { 54 let scrollOffset = window.scrollY; 55 56 await NativePanHandler.promiseNativePanEvent( 57 window, 58 150, 59 GESTURE_Y, 60 0, 61 NativePanHandler.delta * 0.5, 62 NativePanHandler.updatePhase, 63 ); 64 65 await promiseFrame(); 66 await promiseApzFlushedRepaints(); 67 68 return scrollOffset > 50; 69 }, "Scroll at least once over the iframe"); 70 71 await NativePanHandler.promiseNativePanEvent( 72 window, 73 150, 74 GESTURE_Y, 75 0, 76 NativePanHandler.delta, 77 NativePanHandler.endPhase, 78 ); 79 80 await transformEndPromise; 81 } 82 83 async function scrollWithWheel() { 84 let transformEndPromise = promiseTransformEnd(); 85 86 await promiseMoveMouseAndScrollWheelOver(window, 150, GESTURE_Y, false, 20); 87 88 // The iframe we need to scroll over is 30 CSS pixels lower than the original 89 // gesture location. We need to perform at least one mousewheel scroll after 90 // we have scrolled at least 30 CSS pixels. 91 await SimpleTest.promiseWaitForCondition(async () => { 92 let scrollOffset = window.scrollY; 93 94 // While promiseMoveMouseAndScrollWheelOver uses a positive value to scroll 95 // down, synthesizeNativeWheel uses a negative value to scroll down. 96 await synthesizeNativeWheel(window, 150, GESTURE_Y, 0, -20, null); 97 98 await promiseFrame(); 99 await promiseApzFlushedRepaints(); 100 101 return scrollOffset > 50; 102 }, "Scroll at least once over the iframe"); 103 104 await transformEndPromise; 105 } 106 107 async function test() { 108 let iframeURL = 109 SimpleTest.getTestFileURL("helper_scroll_over_subframe_child.html"); 110 111 switch (searchParams.get("oop")) { 112 case "true": 113 iframeURL = iframeURL.replace(window.location.origin, "https://example.com/"); 114 break; 115 default: 116 break; 117 } 118 119 const iframeLoadPromise = promiseOneEvent(subframe, "load", null); 120 subframe.src = iframeURL; 121 await iframeLoadPromise; 122 123 await SpecialPowers.spawn(subframe, [], async () => { 124 await content.wrappedJSObject.waitUntilApzStable(); 125 await SpecialPowers.contentTransformsReceived(content); 126 }); 127 128 let childWindowReceivedWheelEvent = false; 129 130 window.addEventListener("message", e => { 131 if (e.data == "child-received-wheel-event") { 132 childWindowReceivedWheelEvent = true; 133 } 134 }); 135 136 await SpecialPowers.spawn(subframe, [], () => { 137 let target = content.document.getElementById("target") 138 target.style.backgroundColor = "green"; 139 content.getComputedStyle(target).backgroundColor; 140 target.addEventListener("wheel", () => { 141 target.style.backgroundColor = "red"; 142 content.getComputedStyle(target).backgroundColor; 143 }); 144 return new Promise(resolve => resolve()); 145 }); 146 147 await promiseFrame(); 148 149 // Scroll over the iframe 150 switch (searchParams.get("scroll")) { 151 case "wheel": 152 await scrollWithWheel(); 153 break; 154 case "pan": 155 await scrollWithPan(); 156 break; 157 default: 158 ok(false, "Unsupported scroll value: " + searchParams.get("scroll")); 159 break; 160 } 161 162 // Wait an extra frame to ensure any message from the child has 163 // extra time to be sent to the parent. 164 await promiseFrame(); 165 166 let res = await SpecialPowers.spawn(subframe, [], () => { 167 let target = content.document.getElementById("target") 168 return target.style.backgroundColor; 169 }); 170 171 await promiseFrame(); 172 173 // We should not have fired a wheel event to the element in the iframe 174 ok(!childWindowReceivedWheelEvent, "Child window should not receive wheel events"); 175 is(res, "green", "OOP iframe does not halt user scroll of parent"); 176 } 177 waitUntilApzStable().then(test).then(subtestDone, subtestFailed); 178 </script> 179 </html>