requestLongerTimeout(2); add_task(async function () { function pushPrefs(prefs) { return SpecialPowers.pushPrefEnv({ set: prefs }); } await pushPrefs([ ["general.autoScroll", true], ["test.events.async.enabled", true], ]); const expectScrollNone = 0; const expectScrollVert = 1; const expectScrollHori = 2; const expectScrollBoth = 3; var allTests = [ { dataUri: 'data:text/html,\
\
\
\
\ \ \
\
\ \ ', }, { elem: "a", expected: expectScrollNone }, { elem: "b", expected: expectScrollBoth }, { elem: "c", expected: expectScrollHori }, { elem: "d", expected: expectScrollVert }, { elem: "e", expected: expectScrollVert }, { elem: "f", expected: expectScrollNone }, { elem: "g", expected: expectScrollBoth }, { elem: "h", expected: expectScrollNone }, { dataUri: 'data:text/html,
\ \ ', }, { elem: "i", expected: expectScrollVert }, // bug 695121 { dataUri: 'data:text/html,\
\ \ ', }, { elem: "j", expected: expectScrollVert }, // bug 914251 { dataUri: 'data:text/html,\ \
', }, { elem: "t", expected: expectScrollBoth }, // bug 1308775 { dataUri: 'data:text/html,\
\ \
\
\ \
\ \
filler to make document overflow: scroll;
\ ', }, { elem: "k", expected: expectScrollBoth }, { elem: "k", expected: expectScrollNone, testwindow: true }, { elem: "l", expected: expectScrollNone }, { elem: "m", expected: expectScrollVert, testwindow: true }, { dataUri: 'data:text/html,\ image map\ \ \ \ link\ \ \
\ ', }, { elem: "n", expected: expectScrollNone, testwindow: true }, { elem: "o", expected: expectScrollNone, testwindow: true }, { elem: "p", expected: expectScrollVert, testwindow: true, middlemousepastepref: false, }, { elem: "q", expected: expectScrollVert, testwindow: true, middlemousepastepref: false, }, { dataUri: 'data:text/html,\ \ \
\ ', }, { elem: "r", expected: expectScrollNone, testwindow: true, middlemousepastepref: true, }, { elem: "s", expected: expectScrollNone, testwindow: true, middlemousepastepref: true, }, { dataUri: "data:text/html," + encodeURIComponent(`
`), }, { elem: "i", // We expect the outer window to scroll vertically, not the iframe's window. expected: expectScrollVert, testwindow: true, }, { dataUri: "data:text/html," + encodeURIComponent(`
`), }, { elem: "i", // We expect the iframe's window to scroll vertically, so the outer window should not scroll. expected: expectScrollNone, testwindow: true, }, { // Test: scroll is initiated in out of process iframe having no scrollable area dataUri: "data:text/html," + encodeURIComponent(`
`), }, { elem: "noscroll-outofprocess-iframe", // We expect the div to scroll vertically, not the iframe's window. expected: expectScrollVert, scrollable: "scroller", }, ]; for (let test of allTests) { if (test.dataUri) { let loadedPromise = BrowserTestUtils.browserLoaded( gBrowser.selectedBrowser ); BrowserTestUtils.loadURIString(gBrowser, test.dataUri); await loadedPromise; await ContentTask.spawn(gBrowser.selectedBrowser, {}, async () => { // Wait for a paint so that hit-testing works correctly. await new Promise(resolve => content.requestAnimationFrame(() => content.requestAnimationFrame(resolve) ) ); }); continue; } let prefsChanged = "middlemousepastepref" in test; if (prefsChanged) { await pushPrefs([["middlemouse.paste", test.middlemousepastepref]]); } await BrowserTestUtils.synthesizeMouse( "#" + test.elem, 50, 80, { button: 1 }, gBrowser.selectedBrowser ); // This ensures bug 605127 is fixed: pagehide in an unrelated document // should not cancel the autoscroll. await ContentTask.spawn( gBrowser.selectedBrowser, { waitForAutoScrollStart: test.expected != expectScrollNone }, async ({ waitForAutoScrollStart }) => { var iframe = content.document.getElementById("iframe"); if (iframe) { var e = new iframe.contentWindow.PageTransitionEvent("pagehide", { bubbles: true, cancelable: true, persisted: false, }); iframe.contentDocument.dispatchEvent(e); iframe.contentDocument.documentElement.dispatchEvent(e); } if (waitForAutoScrollStart) { await new Promise(resolve => Services.obs.addObserver(resolve, "autoscroll-start") ); } } ); is( document.activeElement, gBrowser.selectedBrowser, "Browser still focused after autoscroll started" ); await BrowserTestUtils.synthesizeMouse( "#" + test.elem, 100, 100, { type: "mousemove", clickCount: "0" }, gBrowser.selectedBrowser ); if (prefsChanged) { await SpecialPowers.popPrefEnv(); } // Start checking for the scroll. let firstTimestamp = undefined; let timeCompensation; do { let timestamp = await new Promise(resolve => window.requestAnimationFrame(resolve) ); if (firstTimestamp === undefined) { firstTimestamp = timestamp; } // This value is calculated similarly to the value of the same name in // ClickEventHandler.autoscrollLoop, except here it's cumulative across // all frames after the first one instead of being based only on the // current frame. timeCompensation = (timestamp - firstTimestamp) / 20; info( "timestamp=" + timestamp + " firstTimestamp=" + firstTimestamp + " timeCompensation=" + timeCompensation ); // Try to wait until enough time has passed to allow the scroll to happen. // autoscrollLoop incrementally scrolls during each animation frame, but // due to how its calculations work, when a frame is very close to the // previous frame, no scrolling may actually occur during that frame. // After 100ms's worth of frames, timeCompensation will be 1, making it // more likely that the accumulated scroll in autoscrollLoop will be >= 1, // although it also depends on acceleration, which here in this test // should be > 1 due to how it synthesizes mouse events below. } while (timeCompensation < 5); // Close the autoscroll popup by synthesizing Esc. EventUtils.synthesizeKey("KEY_Escape"); let scrollVert = test.expected & expectScrollVert; let scrollHori = test.expected & expectScrollHori; await SpecialPowers.spawn( gBrowser.selectedBrowser, [ { scrollVert, scrollHori, elemid: test.scrollable || test.elem, checkWindow: test.testwindow, }, ], async function (args) { let msg = ""; if (args.checkWindow) { if ( !( (args.scrollVert && content.scrollY > 0) || (!args.scrollVert && content.scrollY == 0) ) ) { msg += "Failed: "; } msg += "Window for " + args.elemid + " should" + (args.scrollVert ? "" : " not") + " have scrolled vertically\n"; if ( !( (args.scrollHori && content.scrollX > 0) || (!args.scrollHori && content.scrollX == 0) ) ) { msg += "Failed: "; } msg += " Window for " + args.elemid + " should" + (args.scrollHori ? "" : " not") + " have scrolled horizontally\n"; } else { let elem = content.document.getElementById(args.elemid); if ( !( (args.scrollVert && elem.scrollTop > 0) || (!args.scrollVert && elem.scrollTop == 0) ) ) { msg += "Failed: "; } msg += " " + args.elemid + " should" + (args.scrollVert ? "" : " not") + " have scrolled vertically\n"; if ( !( (args.scrollHori && elem.scrollLeft > 0) || (!args.scrollHori && elem.scrollLeft == 0) ) ) { msg += "Failed: "; } msg += args.elemid + " should" + (args.scrollHori ? "" : " not") + " have scrolled horizontally"; } Assert.ok(!msg.includes("Failed"), msg); } ); // Before continuing the test, we need to ensure that the IPC // message that stops autoscrolling has had time to arrive. await new Promise(resolve => executeSoon(resolve)); } // remove 2 tabs that were opened by middle-click on links while (gBrowser.visibleTabs.length > 1) { gBrowser.removeTab(gBrowser.visibleTabs[gBrowser.visibleTabs.length - 1]); } // wait for focus to fix a failure in the next test if the latter runs too soon. await SimpleTest.promiseFocus(); });