1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim: set sts=2 sw=2 et tw=80: */
6 Services.scriptloader.loadSubScript(
7 "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_utils.js",
11 Services.scriptloader.loadSubScript(
12 "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js",
16 async function waitForWhile() {
17 await new Promise(resolve => {
18 requestIdleCallback(resolve, { timeout: 300 });
20 await new Promise(r => requestAnimationFrame(r));
23 requestLongerTimeout(2);
25 add_task(async () => {
26 // Set the default values for an OS that supports swipe to nav, except for
27 // pixel-size which varies by OS, we vary it in differente tests in this file.
28 await SpecialPowers.pushPrefEnv({
30 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
31 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
32 ["widget.disable-swipe-tracker", false],
33 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
34 // Set the velocity-contribution to 0 so we can exactly control the
35 // values in the swipe tracker via the delta in the events that we send.
36 ["widget.swipe.success-velocity-contribution", 0.0],
37 ["widget.swipe.pixel-size", 550.0],
41 const firstPage = "about:about";
42 const secondPage = "about:mozilla";
43 const tab = await BrowserTestUtils.openNewForegroundTab(
46 true /* waitForLoad */
49 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
50 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
52 // Make sure we can go back to the previous page.
53 ok(gBrowser.webNavigation.canGoBack);
54 // and we cannot go forward to the next page.
55 ok(!gBrowser.webNavigation.canGoForward);
57 let wheelEventCount = 0;
58 tab.linkedBrowser.addEventListener("wheel", () => {
62 // Send a pan that starts a navigate back but doesn't have enough delta to do
63 // anything. Don't send the pan end because we want to check the opacity
64 // before the MSD animation in SwipeTracker starts which can temporarily put
66 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 0.9);
67 await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 0.9);
69 // Check both getComputedStyle instead of element.style.opacity because we use a transition on the opacity.
70 let computedOpacity = window
71 .getComputedStyle(gHistorySwipeAnimation._prevBox)
72 .getPropertyValue("opacity");
73 is(computedOpacity, "1", "opacity of prevbox is 1");
74 let opacity = gHistorySwipeAnimation._prevBox.style.opacity;
75 is(opacity, "", "opacity style isn't explicitly set");
77 const isTranslatingIcon =
78 Services.prefs.getIntPref(
79 "browser.swipe.navigation-icon-start-position",
82 Services.prefs.getIntPref(
83 "browser.swipe.navigation-icon-end-position",
86 if (isTranslatingIcon != 0) {
89 .getComputedStyle(gHistorySwipeAnimation._prevBox)
90 .getPropertyValue("translate"),
92 "translate of prevbox is not `none` during gestures"
96 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0.9);
98 // NOTE: We only get a wheel event for the beginPhase, rest of events have
99 // been captured by the swipe gesture module.
100 is(wheelEventCount, 1, "Received a wheel event");
102 await waitForWhile();
103 // Make sure any navigation didn't happen.
104 is(tab.linkedBrowser.currentURI.spec, secondPage);
106 // Try to navigate backward.
108 let startLoadingPromise = BrowserTestUtils.browserStarted(
112 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
116 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
117 // NOTE: We only get a wheel event for the beginPhase, rest of events have
118 // been captured by the swipe gesture module.
119 is(wheelEventCount, 1, "Received a wheel event");
121 // The element.style opacity will be 0 because we set it to 0 on successful navigation, however
122 // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet.
123 computedOpacity = window
124 .getComputedStyle(gHistorySwipeAnimation._prevBox)
125 .getPropertyValue("opacity");
126 Assert.equal(computedOpacity, 1, "computed opacity of prevbox is 1");
127 opacity = gHistorySwipeAnimation._prevBox.style.opacity;
128 Assert.equal(opacity, 0, "element.style opacity of prevbox 0");
130 if (isTranslatingIcon) {
131 // We don't have a transition for translate property so that we still have
132 // some amount of translate.
135 .getComputedStyle(gHistorySwipeAnimation._prevBox)
136 .getPropertyValue("translate"),
138 "translate of prevbox is not `none` during the opacity transition"
142 // Make sure the gesture triggered going back to the previous page.
143 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
145 ok(gBrowser.webNavigation.canGoForward);
147 BrowserTestUtils.removeTab(tab);
148 await SpecialPowers.popPrefEnv();
151 // Same test as above but pixel-size is increased and the multipliers passed to panLeftToRight correspondingly increased.
152 add_task(async () => {
153 // Set the default values for an OS that supports swipe to nav, except for
154 // pixel-size which varies by OS, we vary it in differente tests
156 await SpecialPowers.pushPrefEnv({
158 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
159 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
160 ["widget.disable-swipe-tracker", false],
161 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
162 // Set the velocity-contribution to 0 so we can exactly control the
163 // values in the swipe tracker via the delta in the events that we send.
164 ["widget.swipe.success-velocity-contribution", 0.0],
165 ["widget.swipe.pixel-size", 1100.0],
169 const firstPage = "about:about";
170 const secondPage = "about:mozilla";
171 const tab = await BrowserTestUtils.openNewForegroundTab(
174 true /* waitForLoad */
177 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
178 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
180 // Make sure we can go back to the previous page.
181 ok(gBrowser.webNavigation.canGoBack);
182 // and we cannot go forward to the next page.
183 ok(!gBrowser.webNavigation.canGoForward);
185 let wheelEventCount = 0;
186 tab.linkedBrowser.addEventListener("wheel", () => {
190 // Send a pan that starts a navigate back but doesn't have enough delta to do
191 // anything. Don't send the pan end because we want to check the opacity
192 // before the MSD animation in SwipeTracker starts which can temporarily put
194 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 1.8);
195 await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 1.8);
197 // Check both getComputedStyle instead of element.style.opacity because we use a transition on the opacity.
198 let computedOpacity = window
199 .getComputedStyle(gHistorySwipeAnimation._prevBox)
200 .getPropertyValue("opacity");
201 is(computedOpacity, "1", "opacity of prevbox is 1");
202 let opacity = gHistorySwipeAnimation._prevBox.style.opacity;
203 is(opacity, "", "opacity style isn't explicitly set");
205 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 1.8);
207 // NOTE: We only get a wheel event for the beginPhase, rest of events have
208 // been captured by the swipe gesture module.
209 is(wheelEventCount, 1, "Received a wheel event");
211 await waitForWhile();
212 // Make sure any navigation didn't happen.
213 is(tab.linkedBrowser.currentURI.spec, secondPage);
215 // Try to navigate backward.
217 let startLoadingPromise = BrowserTestUtils.browserStarted(
221 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
225 await panLeftToRight(tab.linkedBrowser, 100, 100, 2);
226 // NOTE: We only get a wheel event for the beginPhase, rest of events have
227 // been captured by the swipe gesture module.
228 is(wheelEventCount, 1, "Received a wheel event");
230 // The element.style opacity will be 0 because we set it to 0 on successful navigation, however
231 // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet.
232 computedOpacity = window
233 .getComputedStyle(gHistorySwipeAnimation._prevBox)
234 .getPropertyValue("opacity");
235 Assert.equal(computedOpacity, 1, "computed opacity of prevbox is 1");
236 opacity = gHistorySwipeAnimation._prevBox.style.opacity;
237 Assert.equal(opacity, 0, "element.style opacity of prevbox 0");
239 // Make sure the gesture triggered going back to the previous page.
240 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
242 ok(gBrowser.webNavigation.canGoForward);
244 BrowserTestUtils.removeTab(tab);
245 await SpecialPowers.popPrefEnv();
248 add_task(async () => {
249 // Set the default values for an OS that supports swipe to nav, except for
250 // pixel-size which varies by OS, we vary it in different tests
252 await SpecialPowers.pushPrefEnv({
254 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
255 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
256 ["widget.disable-swipe-tracker", false],
257 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
258 // Set the velocity-contribution to 1 (default 0.05f) so velocity is a
259 // large contribution to the success value in SwipeTracker.cpp so it
260 // pushes us into success territory without going into success territory
261 // purely from th deltas.
262 ["widget.swipe.success-velocity-contribution", 2.0],
263 ["widget.swipe.pixel-size", 550.0],
267 async function runTest() {
268 const firstPage = "about:about";
269 const secondPage = "about:mozilla";
270 const tab = await BrowserTestUtils.openNewForegroundTab(
273 true /* waitForLoad */
276 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
277 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
279 // Make sure we can go back to the previous page.
280 ok(gBrowser.webNavigation.canGoBack);
281 // and we cannot go forward to the next page.
282 ok(!gBrowser.webNavigation.canGoForward);
284 let wheelEventCount = 0;
285 tab.linkedBrowser.addEventListener("wheel", () => {
289 let startLoadingPromise = BrowserTestUtils.browserStarted(
293 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
297 let startTime = performance.now();
298 await panLeftToRight(tab.linkedBrowser, 100, 100, 0.2);
299 let endTime = performance.now();
301 // If sending the events took too long then we might not have been able
302 // to generate enough velocity.
303 // The value 230 was picked based on try runs, in particular test verify
304 // runs on mac were the long pole, and when we get times near this we can
305 // still achieve the required velocity.
306 if (endTime - startTime > 230) {
307 BrowserTestUtils.removeTab(tab);
311 // NOTE: We only get a wheel event for the beginPhase, rest of events have
312 // been captured by the swipe gesture module.
313 is(wheelEventCount, 1, "Received a wheel event");
315 // The element.style opacity will be 0 because we set it to 0 on successful navigation, however
316 // we have a tranisition on it so the computed style opacity will still be 1 because the transition hasn't started yet.
317 let computedOpacity = window
318 .getComputedStyle(gHistorySwipeAnimation._prevBox)
319 .getPropertyValue("opacity");
320 Assert.equal(computedOpacity, 1, "computed opacity of prevbox is 1");
321 let opacity = gHistorySwipeAnimation._prevBox.style.opacity;
322 Assert.equal(opacity, 0, "element.style opacity of prevbox 0");
324 // Make sure the gesture triggered going back to the previous page.
325 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
327 ok(gBrowser.webNavigation.canGoForward);
329 BrowserTestUtils.removeTab(tab);
335 while (numTries > 0) {
336 await new Promise(r => requestAnimationFrame(r));
337 await new Promise(resolve => requestIdleCallback(resolve));
338 await new Promise(r => requestAnimationFrame(r));
340 // runTest return value indicates if test was able to run to the end.
341 if (await runTest()) {
346 Assert.greater(numTries, 0, "never ran the test");
347 await SpecialPowers.popPrefEnv();
350 add_task(async () => {
351 // Set the default values for an OS that supports swipe to nav, except for
352 // pixel-size which varies by OS, we vary it in differente tests
354 await SpecialPowers.pushPrefEnv({
356 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
357 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
358 ["widget.disable-swipe-tracker", false],
359 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
360 // Set the velocity-contribution to 0 so we can exactly control the
361 // values in the swipe tracker via the delta in the events that we send.
362 ["widget.swipe.success-velocity-contribution", 0.0],
363 ["widget.swipe.pixel-size", 550.0],
367 const firstPage = "about:about";
368 const secondPage = "about:mozilla";
369 const tab = await BrowserTestUtils.openNewForegroundTab(
372 true /* waitForLoad */
375 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
376 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
378 // Make sure we can go back to the previous page.
379 ok(gBrowser.webNavigation.canGoBack);
380 // and we cannot go forward to the next page.
381 ok(!gBrowser.webNavigation.canGoForward);
383 let startLoadingPromise = BrowserTestUtils.browserStarted(
387 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
391 await panLeftToRight(tab.linkedBrowser, 100, 100, 2);
393 // Make sure the gesture triggered going back to the previous page.
394 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
396 ok(gBrowser.webNavigation.canGoForward);
399 gHistorySwipeAnimation._prevBox != null ||
400 gHistorySwipeAnimation._nextBox != null
402 await new Promise(r => requestAnimationFrame(r));
406 gHistorySwipeAnimation._prevBox == null &&
407 gHistorySwipeAnimation._nextBox == null
410 BrowserTestUtils.removeTab(tab);
411 await SpecialPowers.popPrefEnv();
414 add_task(async () => {
415 await SpecialPowers.pushPrefEnv({
417 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
418 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
419 ["widget.disable-swipe-tracker", false],
420 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
421 // Set the velocity-contribution to 0 so we can exactly control the
422 // values in the swipe tracker via the delta in the events that we send.
423 ["widget.swipe.success-velocity-contribution", 0.0],
424 ["widget.swipe.pixel-size", 550.0],
428 function swipeGestureEndPromise() {
429 return new Promise(resolve => {
430 let promiseObserver = {
431 handleEvent(aEvent) {
432 switch (aEvent.type) {
433 case "MozSwipeGestureEnd":
434 gBrowser.tabbox.removeEventListener(
435 "MozSwipeGestureEnd",
444 gBrowser.tabbox.addEventListener(
445 "MozSwipeGestureEnd",
452 const firstPage = "about:about";
453 const secondPage = "about:mozilla";
454 const tab = await BrowserTestUtils.openNewForegroundTab(
457 true /* waitForLoad */
460 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
461 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
463 // Make sure we can go back to the previous page.
464 ok(gBrowser.webNavigation.canGoBack);
465 // and we cannot go forward to the next page.
466 ok(!gBrowser.webNavigation.canGoForward);
468 let numSwipeGestureEndEvents = 0;
470 handleEvent(aEvent) {
471 switch (aEvent.type) {
472 case "MozSwipeGestureEnd":
473 numSwipeGestureEndEvents++;
479 gBrowser.tabbox.addEventListener("MozSwipeGestureEnd", anObserver, true);
481 let gestureEndPromise = swipeGestureEndPromise();
484 numSwipeGestureEndEvents,
486 "expected no MozSwipeGestureEnd got " + numSwipeGestureEndEvents
489 // Send a pan that starts a navigate back but doesn't have enough delta to do
491 await panLeftToRight(tab.linkedBrowser, 100, 100, 0.9);
493 await waitForWhile();
494 // Make sure any navigation didn't happen.
495 is(tab.linkedBrowser.currentURI.spec, secondPage);
496 // end event comes after a swipe that does not navigate
497 await gestureEndPromise;
499 numSwipeGestureEndEvents,
501 "expected one MozSwipeGestureEnd got " + numSwipeGestureEndEvents
504 // Try to navigate backward.
505 let startLoadingPromise = BrowserTestUtils.browserStarted(
509 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
514 gestureEndPromise = swipeGestureEndPromise();
516 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
518 // Make sure the gesture triggered going back to the previous page.
519 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
521 ok(gBrowser.webNavigation.canGoForward);
523 await gestureEndPromise;
526 numSwipeGestureEndEvents,
528 "expected one MozSwipeGestureEnd got " + (numSwipeGestureEndEvents - 1)
531 gBrowser.tabbox.removeEventListener("MozSwipeGestureEnd", anObserver, true);
533 BrowserTestUtils.removeTab(tab);
534 await SpecialPowers.popPrefEnv();
537 add_task(async () => {
538 // success-velocity-contribution is very high and pixel-size is
539 // very low so that one swipe goes over the threshold asap.
540 await SpecialPowers.pushPrefEnv({
542 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
543 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
544 ["widget.disable-swipe-tracker", false],
545 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
546 ["widget.swipe.success-velocity-contribution", 999999.0],
547 ["widget.swipe.pixel-size", 1.0],
551 const firstPage = "about:about";
552 const secondPage = "about:mozilla";
553 const tab = await BrowserTestUtils.openNewForegroundTab(
556 true /* waitForLoad */
559 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
560 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
562 // Make sure we can go back to the previous page.
563 ok(gBrowser.webNavigation.canGoBack);
564 // and we cannot go forward to the next page.
565 ok(!gBrowser.webNavigation.canGoForward);
567 // Navigate backward.
568 let startLoadingPromise = BrowserTestUtils.browserStarted(
572 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
577 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 100);
579 Assert.notEqual(gHistorySwipeAnimation._prevBox, null, "should have prevbox");
580 let transitionCancelPromise = new Promise(resolve => {
581 gHistorySwipeAnimation._prevBox.addEventListener(
585 event.propertyName == "opacity" &&
586 event.target == gHistorySwipeAnimation._prevBox
594 let transitionStartPromise = new Promise(resolve => {
595 gHistorySwipeAnimation._prevBox.addEventListener(
599 event.propertyName == "opacity" &&
600 event.target == gHistorySwipeAnimation._prevBox
609 await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 100);
610 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 100);
612 // Make sure the gesture triggered going back to the previous page.
613 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
615 ok(gBrowser.webNavigation.canGoForward);
617 await Promise.any([transitionStartPromise, transitionCancelPromise]);
619 await TestUtils.waitForCondition(() => {
621 gHistorySwipeAnimation._prevBox == null &&
622 gHistorySwipeAnimation._nextBox == null
626 // Navigate forward and check the forward navigation icon box state.
627 startLoadingPromise = BrowserTestUtils.browserStarted(
631 stoppedLoadingPromise = BrowserTestUtils.browserStopped(
636 await panRightToLeftBegin(tab.linkedBrowser, 100, 100, 100);
638 Assert.notEqual(gHistorySwipeAnimation._nextBox, null, "should have nextbox");
639 transitionCancelPromise = new Promise(resolve => {
640 gHistorySwipeAnimation._nextBox.addEventListener(
644 event.propertyName == "opacity" &&
645 event.target == gHistorySwipeAnimation._nextBox
652 transitionStartPromise = new Promise(resolve => {
653 gHistorySwipeAnimation._nextBox.addEventListener(
657 event.propertyName == "opacity" &&
658 event.target == gHistorySwipeAnimation._nextBox
666 await panRightToLeftUpdate(tab.linkedBrowser, 100, 100, 100);
667 await panRightToLeftEnd(tab.linkedBrowser, 100, 100, 100);
669 // Make sure the gesture triggered going forward to the next page.
670 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
672 ok(gBrowser.webNavigation.canGoBack);
674 await Promise.any([transitionStartPromise, transitionCancelPromise]);
676 await TestUtils.waitForCondition(() => {
678 gHistorySwipeAnimation._nextBox == null &&
679 gHistorySwipeAnimation._prevBox == null
683 BrowserTestUtils.removeTab(tab);
684 await SpecialPowers.popPrefEnv();
687 // A simple test case on RTL.
688 add_task(async () => {
689 await SpecialPowers.pushPrefEnv({
691 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
692 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
693 ["widget.disable-swipe-tracker", false],
694 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
695 ["widget.swipe.success-velocity-contribution", 0.5],
696 ["intl.l10n.pseudo", "bidi"],
700 const newWin = await BrowserTestUtils.openNewBrowserWindow();
702 const firstPage = "about:about";
703 const secondPage = "about:mozilla";
704 const tab = await BrowserTestUtils.openNewForegroundTab(
707 true /* waitForLoad */
710 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
711 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
713 // Make sure we can go back to the previous page.
714 ok(newWin.gBrowser.webNavigation.canGoBack);
715 // and we cannot go forward to the next page.
716 ok(!newWin.gBrowser.webNavigation.canGoForward);
718 // Make sure that our gesture support stuff has been initialized in the new
720 await TestUtils.waitForCondition(() => {
721 return newWin.gHistorySwipeAnimation.active;
724 // Try to navigate backward.
725 let startLoadingPromise = BrowserTestUtils.browserStarted(
729 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
733 await panRightToLeft(tab.linkedBrowser, 100, 100, 1);
734 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
736 ok(newWin.gBrowser.webNavigation.canGoForward);
738 // Now try to navigate forward again.
739 startLoadingPromise = BrowserTestUtils.browserStarted(
743 stoppedLoadingPromise = BrowserTestUtils.browserStopped(
747 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
748 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
750 ok(newWin.gBrowser.webNavigation.canGoBack);
752 await BrowserTestUtils.closeWindow(newWin);
753 await SpecialPowers.popPrefEnv();
756 add_task(async () => {
757 await SpecialPowers.pushPrefEnv({
759 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
760 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
761 ["widget.disable-swipe-tracker", false],
762 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
763 ["widget.swipe.success-velocity-contribution", 0.5],
764 ["apz.overscroll.enabled", true],
765 ["apz.test.logging_enabled", true],
769 const tab = await BrowserTestUtils.openNewForegroundTab(
772 true /* waitForLoad */
775 const URL_ROOT = getRootDirectory(gTestPath).replace(
776 "chrome://mochitests/content/",
777 "http://mochi.test:8888/"
779 BrowserTestUtils.startLoadingURIString(
781 URL_ROOT + "helper_swipe_gesture.html"
783 await BrowserTestUtils.browserLoaded(
785 false /* includeSubFrames */,
786 URL_ROOT + "helper_swipe_gesture.html"
789 // Make sure we can go back to the previous page.
790 ok(gBrowser.webNavigation.canGoBack);
792 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
793 // Set `overscroll-behavior-x: contain` and flush it.
794 content.document.documentElement.style.overscrollBehaviorX = "contain";
795 content.document.documentElement.getBoundingClientRect();
796 await content.wrappedJSObject.promiseApzFlushedRepaints();
799 // Start a pan gesture but keep touching.
800 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2);
802 // Flush APZ pending requests to make sure the pan gesture has been processed.
803 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
804 await content.wrappedJSObject.promiseApzFlushedRepaints();
807 const isOverscrolled = await SpecialPowers.spawn(
811 const scrollId = SpecialPowers.DOMWindowUtils.getViewId(
812 content.document.scrollingElement
814 const data = SpecialPowers.DOMWindowUtils.getCompositorAPZTestData();
815 return data.additionalData.some(entry => {
817 entry.key == scrollId &&
818 entry.value.split(",").includes("overscrolled")
824 ok(isOverscrolled, "The root scroller should have overscrolled");
826 // Finish the pan gesture.
827 await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 2);
828 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 2);
830 // And wait a while to give a chance to navigate.
831 await waitForWhile();
833 // Make sure any navigation didn't happen.
834 is(tab.linkedBrowser.currentURI.spec, URL_ROOT + "helper_swipe_gesture.html");
836 BrowserTestUtils.removeTab(tab);
837 await SpecialPowers.popPrefEnv();
840 // A test case to make sure the short circuit path for swipe-to-navigations in
841 // APZ works, i.e. cases where we know for sure that the target APZC for a given
842 // pan-start event isn't scrollable in the pan-start event direction.
843 add_task(async () => {
844 await SpecialPowers.pushPrefEnv({
846 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
847 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
848 ["widget.disable-swipe-tracker", false],
849 ["apz.overscroll.enabled", true],
853 const tab = await BrowserTestUtils.openNewForegroundTab(
856 true /* waitForLoad */
859 const URL_ROOT = getRootDirectory(gTestPath).replace(
860 "chrome://mochitests/content/",
861 "http://mochi.test:8888/"
863 BrowserTestUtils.startLoadingURIString(
865 URL_ROOT + "helper_swipe_gesture.html"
867 await BrowserTestUtils.browserLoaded(
869 false /* includeSubFrames */,
870 URL_ROOT + "helper_swipe_gesture.html"
873 // Make sure the content can allow both of overscrolling and
874 // swipe-to-navigations.
875 const overscrollBehaviorX = await SpecialPowers.spawn(
879 return content.window.getComputedStyle(content.document.documentElement)
880 .overscrollBehaviorX;
883 is(overscrollBehaviorX, "auto");
885 // Make sure we can go back to the previous page.
886 ok(gBrowser.webNavigation.canGoBack);
888 // Start a pan gesture but keep touching.
889 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2);
891 // The above pan event should invoke a SwipeGestureStart event immediately so
892 // that the swipe-to-navigation icon box should be uncollapsed to show it.
893 ok(!gHistorySwipeAnimation._prevBox.collapsed);
895 // Finish the pan gesture, i.e. sending a pan-end event, otherwise a new
896 // pan-start event in the next will also generate a pan-interrupt event which
897 // will break the test.
898 await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 2);
899 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 2);
901 BrowserTestUtils.removeTab(tab);
902 await SpecialPowers.popPrefEnv();
905 add_task(async () => {
906 await SpecialPowers.pushPrefEnv({
908 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
909 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
910 ["widget.disable-swipe-tracker", false],
911 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
912 ["widget.swipe.success-velocity-contribution", 0.5],
913 ["apz.overscroll.enabled", true],
914 ["apz.test.logging_enabled", true],
918 const tab = await BrowserTestUtils.openNewForegroundTab(
921 true /* waitForLoad */
924 const URL_ROOT = getRootDirectory(gTestPath).replace(
925 "chrome://mochitests/content/",
926 "http://mochi.test:8888/"
928 BrowserTestUtils.startLoadingURIString(
930 URL_ROOT + "helper_swipe_gesture.html"
932 await BrowserTestUtils.browserLoaded(
934 false /* includeSubFrames */,
935 URL_ROOT + "helper_swipe_gesture.html"
938 // Make sure we can go back to the previous page.
939 ok(gBrowser.webNavigation.canGoBack);
941 // Start a pan gesture but keep touching.
942 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 2);
944 // Flush APZ pending requests to make sure the pan gesture has been processed.
945 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
946 await content.wrappedJSObject.promiseApzFlushedRepaints();
949 const isOverscrolled = await SpecialPowers.spawn(
953 const scrollId = SpecialPowers.DOMWindowUtils.getViewId(
954 content.document.scrollingElement
956 const data = SpecialPowers.DOMWindowUtils.getCompositorAPZTestData();
957 return data.additionalData.some(entry => {
958 return entry.key == scrollId && entry.value.includes("overscrolled");
963 ok(!isOverscrolled, "The root scroller should not have overscrolled");
965 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0);
967 BrowserTestUtils.removeTab(tab);
968 await SpecialPowers.popPrefEnv();
971 add_task(async () => {
972 await SpecialPowers.pushPrefEnv({
974 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
975 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
976 ["widget.disable-swipe-tracker", false],
977 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
978 ["widget.swipe.success-velocity-contribution", 0.5],
982 // Load three pages and go to the second page so that it can be navigated
983 // to both back and forward.
984 const tab = await BrowserTestUtils.openNewForegroundTab(
987 true /* waitForLoad */
990 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:mozilla");
991 await BrowserTestUtils.browserLoaded(
993 false /* includeSubFrames */,
997 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:home");
998 await BrowserTestUtils.browserLoaded(
1000 false /* includeSubFrames */,
1005 await BrowserTestUtils.browserLoaded(
1007 false /* includeSubFrames */,
1011 // Make sure we can go back and go forward.
1012 ok(gBrowser.webNavigation.canGoBack);
1013 ok(gBrowser.webNavigation.canGoForward);
1015 // Start a history back pan gesture but keep touching.
1016 await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 1);
1019 !gHistorySwipeAnimation._prevBox.collapsed,
1020 "The icon box for the previous navigation should NOT be collapsed"
1023 gHistorySwipeAnimation._nextBox.collapsed,
1024 "The icon box for the next navigation should be collapsed"
1027 // Pan back to the opposite direction so that the gesture should be cancelled.
1028 // eslint-disable-next-line no-undef
1029 await NativePanHandler.promiseNativePanEvent(
1033 // eslint-disable-next-line no-undef
1034 NativePanHandler.delta,
1036 // eslint-disable-next-line no-undef
1037 NativePanHandler.updatePhase
1041 gHistorySwipeAnimation._prevBox.collapsed,
1042 "The icon box for the previous navigation should be collapsed"
1045 gHistorySwipeAnimation._nextBox.collapsed,
1046 "The icon box for the next navigation should be collapsed"
1049 await panLeftToRightEnd(tab.linkedBrowser, 100, 100, 0);
1051 BrowserTestUtils.removeTab(tab);
1052 await SpecialPowers.popPrefEnv();
1055 add_task(async () => {
1056 await SpecialPowers.pushPrefEnv({
1058 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
1059 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
1060 ["widget.disable-swipe-tracker", false],
1061 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
1062 ["widget.swipe.success-velocity-contribution", 0.5],
1063 ["apz.overscroll.enabled", true],
1064 ["apz.overscroll.damping", 5.0],
1065 ["apz.content_response_timeout", 0],
1069 const tab = await BrowserTestUtils.openNewForegroundTab(
1072 true /* waitForLoad */
1075 const URL_ROOT = getRootDirectory(gTestPath).replace(
1076 "chrome://mochitests/content/",
1077 "http://mochi.test:8888/"
1080 // Load a horizontal scrollable content.
1081 BrowserTestUtils.startLoadingURIString(
1083 URL_ROOT + "helper_swipe_gesture.html"
1085 await BrowserTestUtils.browserLoaded(
1087 false /* includeSubFrames */,
1088 URL_ROOT + "helper_swipe_gesture.html"
1091 // Make sure we can go back to the previous page.
1092 ok(gBrowser.webNavigation.canGoBack);
1094 // Shift the horizontal scroll position slightly to make the content
1096 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
1097 content.document.documentElement.scrollLeft = 1;
1098 content.document.documentElement.getBoundingClientRect();
1099 await content.wrappedJSObject.promiseApzFlushedRepaints();
1102 // Swipe horizontally to overscroll.
1103 await panLeftToRight(tab.linkedBrowser, 1, 100, 1);
1105 // Swipe again over the overscroll gutter.
1106 await panLeftToRight(tab.linkedBrowser, 1, 100, 1);
1108 // Wait the overscroll gutter is restored.
1109 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
1110 // For some reasons using functions in apz_test_native_event_utils.js
1111 // sometimes causes "TypeError content.wrappedJSObject.XXXX is not a
1112 // function" error, so we observe "APZ:TransformEnd" instead of using
1113 // promiseTransformEnd().
1114 await new Promise((resolve, reject) => {
1115 SpecialPowers.Services.obs.addObserver(function observer(
1121 SpecialPowers.Services.obs.removeObserver(observer, topic);
1122 resolve([subject, data]);
1124 SpecialPowers.Services.obs.removeObserver(observer, topic);
1128 "APZ:TransformEnd");
1132 // Set up an APZ aware event listener and...
1133 await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
1134 content.document.documentElement.addEventListener("wheel", () => {}, {
1137 await content.wrappedJSObject.promiseApzFlushedRepaints();
1140 // Try to swipe back again without overscrolling to make sure swipe-navigation
1141 // works with the APZ aware event listener.
1142 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
1144 let startLoadingPromise = BrowserTestUtils.browserStarted(
1148 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
1153 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
1155 ok(gBrowser.webNavigation.canGoForward);
1157 BrowserTestUtils.removeTab(tab);
1158 await SpecialPowers.popPrefEnv();
1161 // NOTE: This test listens wheel events so that it causes an overscroll issue
1162 // (bug 1800022). To avoid the bug, we need to run this test case at the end
1164 add_task(async () => {
1165 await SpecialPowers.pushPrefEnv({
1167 ["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
1168 ["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
1169 ["widget.disable-swipe-tracker", false],
1170 ["widget.swipe.velocity-twitch-tolerance", 0.0000001],
1171 ["widget.swipe.success-velocity-contribution", 0.5],
1175 const firstPage = "about:about";
1176 const secondPage = "about:mozilla";
1177 const tab = await BrowserTestUtils.openNewForegroundTab(
1180 true /* waitForLoad */
1183 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
1184 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
1186 // Make sure we can go back to the previous page.
1187 ok(gBrowser.webNavigation.canGoBack);
1188 // and we cannot go forward to the next page.
1189 ok(!gBrowser.webNavigation.canGoForward);
1191 let wheelEventCount = 0;
1192 tab.linkedBrowser.addEventListener("wheel", () => {
1196 // Try to navigate forward.
1197 await panRightToLeft(tab.linkedBrowser, 100, 100, 1);
1198 // NOTE: The last endPhase shouldn't fire a wheel event since
1199 // its delta is zero.
1200 is(wheelEventCount, 2, "Received 2 wheel events");
1202 await waitForWhile();
1203 // Make sure any navigation didn't happen.
1204 is(tab.linkedBrowser.currentURI.spec, secondPage);
1206 // Try to navigate backward.
1207 wheelEventCount = 0;
1208 let startLoadingPromise = BrowserTestUtils.browserStarted(
1212 let stoppedLoadingPromise = BrowserTestUtils.browserStopped(
1216 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
1217 // NOTE: We only get a wheel event for the beginPhase, rest of events have
1218 // been captured by the swipe gesture module.
1219 is(wheelEventCount, 1, "Received a wheel event");
1221 // Make sure the gesture triggered going back to the previous page.
1222 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
1224 ok(gBrowser.webNavigation.canGoForward);
1226 // Now try to navigate forward again.
1227 wheelEventCount = 0;
1228 startLoadingPromise = BrowserTestUtils.browserStarted(
1232 stoppedLoadingPromise = BrowserTestUtils.browserStopped(
1236 await panRightToLeft(tab.linkedBrowser, 100, 100, 1);
1237 is(wheelEventCount, 1, "Received a wheel event");
1239 await Promise.all([startLoadingPromise, stoppedLoadingPromise]);
1241 ok(gBrowser.webNavigation.canGoBack);
1243 // Now try to navigate backward again but with preventDefault-ed event
1245 wheelEventCount = 0;
1246 let wheelEventListener = event => {
1247 event.preventDefault();
1249 tab.linkedBrowser.addEventListener("wheel", wheelEventListener);
1250 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
1251 is(wheelEventCount, 3, "Received all wheel events");
1253 await waitForWhile();
1254 // Make sure any navigation didn't happen.
1255 is(tab.linkedBrowser.currentURI.spec, secondPage);
1257 // Now drop the event handler and disable the swipe tracker and try to swipe
1259 wheelEventCount = 0;
1260 tab.linkedBrowser.removeEventListener("wheel", wheelEventListener);
1261 await SpecialPowers.pushPrefEnv({
1262 set: [["widget.disable-swipe-tracker", true]],
1265 await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
1266 is(wheelEventCount, 3, "Received all wheel events");
1268 await waitForWhile();
1269 // Make sure any navigation didn't happen.
1270 is(tab.linkedBrowser.currentURI.spec, secondPage);
1272 BrowserTestUtils.removeTab(tab);
1273 await SpecialPowers.popPrefEnv();