mobile/android/tests/browser/chrome/test_session_scroll_position.html
author Jan Henning <jh+bugzilla@buttercookie.de>
Tue, 16 Oct 2018 20:12:20 +0000
changeset 489885 de6fb9a3d7a5dcf98798c833994c68f2ac83526c
parent 489694 8e482a5a51ad99eb7173e1bf1a2410c1a70d6825
permissions -rw-r--r--
Bug 1499239 - Use a smaller scroll range for the frameset. r=gbrown The size of the frameset on the emulator is smaller than I expected, so we can't scroll the full range of SCROLL_Y even when we've zoomed in somewhat. Because SCROLL_Y has a maximum of 400 and the scroll got truncated to 292, we divide the number in half. So we don't have to generate yet another hard-coded scroll string for this case, we switch to generating them on the fly from the test data for the respective sub test. Differential Revision: https://phabricator.services.mozilla.com/D8894

<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=810981
https://bugzilla.mozilla.org/show_bug.cgi?id=1282902
https://bugzilla.mozilla.org/show_bug.cgi?id=1301016
https://bugzilla.mozilla.org/show_bug.cgi?id=1265818
https://bugzilla.mozilla.org/show_bug.cgi?id=1498892
-->
<head>
  <meta charset="utf-8">
  <title>Various scroll position/zoom level tests for the mobile session store</title>
  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
  <link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
  <script type="application/javascript" src="head.js"></script>
  <script type="application/javascript">

  /** Tests for Bug 810981, 1282902, 1301016, 1265818, 1498892 **/

  "use strict";

  ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
  ChromeUtils.import("resource://gre/modules/Services.jsm");
  ChromeUtils.import("resource://gre/modules/Messaging.jsm");
  ChromeUtils.import("resource://gre/modules/Task.jsm");

  // The chrome window and friends.
  let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
  let BrowserApp = chromeWin.BrowserApp;

  const BASE = "http://example.org/chrome/mobile/android/tests/browser/chrome/";
  // Use something with ample space for scrolling and zooming.
  const URL = BASE + "browser_scrollPositions_sample.html";
  // Same content but under a different URL, so we have something to navigate to and from.
  const URL2 = BASE + "browser_scrollPositions_sample2.html";
  // Test nested scrolling with frames.
  const URL_FRAMESET = BASE + "browser_scrollPositions_sample_frameset.html";
  // Reader mode URL
  const URL_reader = "about:reader?url=http%3A%2F%2Fexample.org%2Fchrome%2Fmobile%2Fandroid%2Ftests%2Fbrowser%2Fchrome%2Fbasic_article_mobile.html";

  // Randomized set of scroll positions and zoom factors we will use in this test.
  const SCROLL_X = Math.round(100 * (1 + Math.random()));
  const SCROLL_Y = Math.round(200 * (1 + Math.random()));
  const ZOOM = 1 + 0.5 * Math.random();

  const SCROLL2_X = Math.round(300 * (1 + Math.random()));
  const SCROLL2_Y = Math.round(400 * (1 + Math.random()));
  const ZOOM2 = 1.5 + 0.5 * Math.random();

  function getFrame(browser, data) {
    let frame = browser.contentWindow;
    if (data.hasOwnProperty("frame")) {
      frame = browser.contentWindow.frames[data.frame];
    }
    return frame;
  }

  function setScrollPosition(browser, data) {
    let {x, y, zoom} = data;
    x = x || 0;
    y = y || 0;
    let frame = getFrame(browser, data);
    if (data.hasOwnProperty("zoom")) {
      browser.contentWindow.windowUtils.setResolutionAndScaleTo(zoom);
    }
    frame.scrollTo(x, y);
  }

  function checkScroll(browser, data) {
    let {x, y, zoom} = data;
    let utils = getFrame(browser, data).windowUtils;

    let actualX = {}, actualY = {}, actualZoom = {};
    utils.getResolution(actualZoom);
    utils.getScrollXY(false, actualX, actualY);

    if (data.hasOwnProperty("x")) {
      is(actualX.value, x, "scrollX set correctly");
    }
    if (data.hasOwnProperty("y")) {
      is(actualY.value, y, "scrollY set correctly");
    }
    if (data.hasOwnProperty("zoom")) {
      ok(fuzzyEquals(actualZoom.value, zoom), "zoom set correctly");
    }
  }

  function getScrollString(data) {
    let {x, y} = data;
    x = x || 0;
    y = y || 0;
    return x + "," + y;
  }

  // Track the tabs where the tests are happening.
  let tabScroll;

  function cleanupTabs() {
    if (tabScroll) {
      BrowserApp.closeTab(tabScroll);
      tabScroll = null;
    }
  }

  SimpleTest.registerCleanupFunction(function() {
    cleanupTabs();
  });

  let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);

  add_task(async function test_sessionStoreScrollPositionReaderMode() {
    let testData = {x: 0, y: SCROLL_Y};
    // Creates a tab, sets a scroll position and closes the tab.
    function createAndRemoveReaderTab() {
      return Task.spawn(function* () {
        // Create a new tab.
        tabScroll = BrowserApp.addTab(URL_reader);
        let browser = tabScroll.browser;
        yield promiseBrowserEvent(browser, "AboutReaderContentReady");

        // Modify scroll position.
        setScrollPosition(browser, testData);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");

        // Check that we've actually scrolled.
        checkScroll(browser, testData);

        // Remove the tab.
        BrowserApp.closeTab(tabScroll);
        yield promiseTabEvent(browser, "SSTabCloseProcessed");
      });
    }

    await createAndRemoveReaderTab();
    let state = ss.getClosedTabs(chromeWin);
    let [{scrolldata}] = state;
    is(scrolldata.scroll, getScrollString(testData), "stored scroll position is correct");

    // Restore the closed tab.
    let closedTabData = ss.getClosedTabs(chromeWin)[0];
    let browser = ss.undoCloseTab(chromeWin, closedTabData);
    await promiseBrowserEvent(browser, "AboutReaderContentReady");

    // Check the scroll position.
    checkScroll(browser, testData);

    // Remove the tab.
    BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
  });

  add_task(async function test_sessionStoreScrollPositionAndZoomLevel() {
    let testData1 = {x: SCROLL_X, y: SCROLL_Y, zoom: ZOOM};
    let testData2 = {x: SCROLL2_X, y: SCROLL2_Y, zoom: ZOOM2};
    // Creates a tab, sets a scroll position and zoom level and closes the tab.
    function createAndRemoveTab() {
      return Task.spawn(function* () {
        // Create a new tab.
        tabScroll = BrowserApp.addTab(URL);
        let browser = tabScroll.browser;
        yield promiseBrowserEvent(browser, "pageshow");

        // Modify scroll position and zoom level.
        setScrollPosition(browser, testData1);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");

        // Check that we've actually scrolled and zoomed.
        checkScroll(browser, testData1);

        // Navigate to a different page and scroll/zoom there as well.
        browser.loadURI(URL2);
        yield promiseBrowserEvent(browser, "pageshow");

        setScrollPosition(browser, testData2);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");

        checkScroll(browser, testData2);

        // Remove the tab.
        BrowserApp.closeTab(tabScroll);
        yield promiseTabEvent(browser, "SSTabCloseProcessed");
      });
    }

    await createAndRemoveTab();
    let state = ss.getClosedTabs(chromeWin);
    let [{scrolldata}] = state;
    is(scrolldata.scroll, getScrollString(testData2), "stored scroll position is correct");
    ok(fuzzyEquals(scrolldata.zoom.resolution, ZOOM2), "stored zoom level is correct");

    // Restore the closed tab.
    let closedTabData = ss.getClosedTabs(chromeWin)[0];
    let browser = ss.undoCloseTab(chromeWin, closedTabData);
    let pageshow = promiseBrowserEvent(browser, "pageshow");
    let scroll = promiseBrowserEvent(browser, "scroll");
    await pageshow;
    await scroll;

    // Check the scroll position and zoom level.
    checkScroll(browser, testData2);

    // Now go back in history and check that the scroll position
    // is restored there as well.
    is(browser.canGoBack, true, "can go back");
    pageshow = promiseBrowserEvent(browser, "pageshow");
    scroll = promiseBrowserEvent(browser, "scroll");
    browser.goBack();
    await pageshow;
    await scroll;

    checkScroll(browser, testData1);

    // Remove the tab.
    BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
  });

  add_task(async function test_sessionStoreZoomLevelRecalc() {
    let testData = {x: SCROLL_X, y: SCROLL_Y, zoom: ZOOM};
    // Creates a tab, sets a scroll position and zoom level and closes the tab.
    function createAndRemoveTab() {
      return Task.spawn(function* () {
        // Create a new tab.
        tabScroll = BrowserApp.addTab(URL);
        let browser = tabScroll.browser;
        yield promiseBrowserEvent(browser, "pageshow");

        // Modify scroll position and zoom level.
        setScrollPosition(browser, testData);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");

        // Check that we've actually scrolled and zoomed.
        checkScroll(browser, testData);

        // Remove the tab.
        BrowserApp.closeTab(tabScroll);
        yield promiseTabEvent(browser, "SSTabCloseProcessed");
      });
    }

    await createAndRemoveTab();
    let state = ss.getClosedTabs(chromeWin);
    let [{scrolldata}] = state;
    is(scrolldata.scroll, getScrollString(testData), "stored scroll position is correct");
    ok(fuzzyEquals(scrolldata.zoom.resolution, ZOOM), "stored zoom level is correct");

    // Pretend the zoom level was originally saved on a rotated device.
    let closedTabData = ss.getClosedTabs(chromeWin)[0];
    let displayWidth = scrolldata.zoom.displaySize.width;
    let displayHeight = scrolldata.zoom.displaySize.height;
    closedTabData.scrolldata.zoom.displaySize.width = displayHeight;
    closedTabData.scrolldata.zoom.displaySize.height = displayWidth;

    // Restore the closed tab.
    let browser = ss.undoCloseTab(chromeWin, closedTabData);
    await promiseBrowserEvent(browser, "pageshow");

    // Check the scroll position and zoom level.
    testData.zoom = ZOOM * displayWidth / displayHeight;
    checkScroll(browser, testData);

    // Remove the tab.
    BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
  });

  add_task(async function test_sessionStoreScrollPositionForFrames() {
    let testDataParent = {x: 0, y: Math.round(SCROLL_Y / 2), zoom: 2.0};
    let testData1 = {x: SCROLL_X, y: SCROLL_Y, frame: 0};
    let testData2 = {x: SCROLL2_X, y: SCROLL2_Y, frame: 1};
    // Creates a tab, sets a scroll position and zoom level and closes the tab.
    function createAndRemoveTab() {
      return Task.spawn(function* () {
        // Create a new tab.
        tabScroll = BrowserApp.addTab(URL_FRAMESET);
        let browser = tabScroll.browser;
        yield promiseBrowserEvent(browser, "pageshow");

        // Move the frameset itself.
        setScrollPosition(browser, testDataParent);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");
        checkScroll(browser, testDataParent);

        // Modify scroll position and zoom level for one frame...
        setScrollPosition(browser, testData1);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");
        checkScroll(browser, testData1);

        // ... and the other.
        setScrollPosition(browser, testData2);
        yield promiseTabEvent(browser, "SSTabScrollCaptured");
        checkScroll(browser, testData2);

        // Remove the tab.
        BrowserApp.closeTab(tabScroll);
        yield promiseTabEvent(browser, "SSTabCloseProcessed");
      });
    }

    await createAndRemoveTab();
    let state = ss.getClosedTabs(chromeWin);
    let [{scrolldata}] = state;
    is(scrolldata.scroll, getScrollString(testDataParent), "stored scroll position for frameset is correct");
    is(scrolldata.children[0].scroll, getScrollString(testData1), "stored scroll position for frame 1 is correct");
    is(scrolldata.children[1].scroll, getScrollString(testData2), "stored scroll position for frame 2 is correct");

    // Restore the closed tab.
    let closedTabData = ss.getClosedTabs(chromeWin)[0];
    let browser = ss.undoCloseTab(chromeWin, closedTabData);
    let pageshow = promiseBrowserEvent(browser, "pageshow");
    // We can't add event listeners for the frames until we're sure that they've actually loaded.
    let load = promiseBrowserEvent(browser, "load");
    await load;
    let scrollParent = promiseBrowserEvent(getFrame(browser, testDataParent), "scroll");
    let scroll1 = promiseBrowserEvent(getFrame(browser, testData1), "scroll");
    let scroll2 = promiseBrowserEvent(getFrame(browser, testData2), "scroll");
    await pageshow;
    await scrollParent;
    await scroll1;
    await scroll2;

    // Check the scroll position and zoom level.
    checkScroll(browser, testDataParent);
    checkScroll(browser, testData1);
    checkScroll(browser, testData2);

    // Remove the tab.
    BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
  });

  </script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=810981">Mozilla Bug 810981</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1282902">Mozilla Bug 1282902</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301016">Mozilla Bug 1301016</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265818">Mozilla Bug 1265818</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1498892">Mozilla Bug 1498892</a>
<p id="display"></p>
<div id="content" style="display: none">

</div>
<pre id="test">
</pre>
</body>
</html>