tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_test_APZ.js (9202B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 Services.scriptloader.loadSubScript(
      8  "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js",
      9  this
     10 );
     11 
     12 add_setup(async function () {
     13  await SpecialPowers.pushPrefEnv({
     14    set: [["test.wait300msAfterTabSwitch", true]],
     15  });
     16 });
     17 
     18 /**
     19 * Test accessible is hittestable before and after APZ. Also verify
     20 * bounds change in the direction we expect.
     21 *
     22 * Note: the `display:inline-block` styling ensures elements that would
     23 * otherwise span the entire page in width do not extend beyond their
     24 * visual boundaries. Without it, we'd still "hit" items in the reduced
     25 * visual viewport even though their content doesn't appear on screen.
     26 */
     27 addAccessibleTask(
     28  `
     29  <div id="test" role="button" style="background:green; min-height: 10vh; max-width: 10vh; display:inline-block;">I am square</div><br>
     30  <div style="height: 70vh;">hello world I am large</div><br>
     31  <h1 id="heading" style="display:inline-block;">I am a heading</h1>
     32  `,
     33  async function (browser, accDoc) {
     34    const test = findAccessibleChildByID(accDoc, "test");
     35 
     36    info("Hittesting pre-APZ");
     37    let dpr = await getContentDPR(browser);
     38    let [targetX, targetY, targetW, targetH] = Layout.getBounds(test, dpr);
     39    let [x, y] = Layout.getBounds(accDoc, dpr);
     40    await testChildAtPoint(
     41      dpr,
     42      targetX - x + targetW / 2,
     43      targetY - y + targetH / 2,
     44      accDoc,
     45      test, // Direct Child
     46      test // Deepest Child
     47    );
     48 
     49    info("Pinch zooming...");
     50    await SpecialPowers.spawn(browser, [], async () => {
     51      const visualScrollPromise = new Promise(resolve => {
     52        content.window.visualViewport.addEventListener("scroll", resolve, {
     53          once: true,
     54        });
     55      });
     56      const utils = SpecialPowers.getDOMWindowUtils(content.window);
     57      utils.setResolutionAndScaleTo(2);
     58      utils.scrollToVisual(
     59        200,
     60        200,
     61        utils.UPDATE_TYPE_MAIN_THREAD,
     62        utils.SCROLL_MODE_INSTANT
     63      );
     64      await visualScrollPromise;
     65    });
     66    info("Hittesting post-APZ");
     67    dpr = await getContentDPR(browser);
     68    let [newX, newY, newW, newH] = Layout.getBounds(test, dpr);
     69    [x, y] = Layout.getBounds(accDoc, dpr);
     70    // This shouldn't be in the viewport cache, because it is out of the
     71    // visual viewport
     72    await testChildAtPoint(
     73      dpr,
     74      newX - x + newW / 2,
     75      newY - y + newH / 2,
     76      accDoc,
     77      null, // Direct Child
     78      null // Deepest Child
     79    );
     80 
     81    // We pinch zoom to the right of the square,
     82    // which means its coords become off-screen
     83    // (negative).
     84    info("Verifying scaled bounds");
     85    Assert.less(newX, 0, "X coord should be smaller than 0");
     86    Assert.less(newY, 0, "Y coord should be smaller than 0");
     87    // Because we zoomed in, width and height should
     88    // be larger than they were before.
     89    Assert.greater(newW, targetW, "Width should be larger than old width");
     90    Assert.greater(newH, targetH, "Height should be larger than old height");
     91  },
     92  // APZ only happens on the top-level document, which means iframe tests
     93  // will assert differently than classic remote doc tests.
     94  { iframe: false, remoteIframe: false }
     95 );
     96 
     97 /**
     98 * Test accessible is hittestable before and after APZ with scroll. Also verify
     99 * the viewport cache is cleared of "old" information.
    100 */
    101 addAccessibleTask(
    102  `
    103  <div id="test" role="button" style="background:green; min-height: 10vh; max-width: 10vh; display:inline-block;">I am square</div><br>
    104  <div id="spacer" style="min-height: 70vh; display:inline-block;">hello world I am large</div><br>
    105  <h1 id="heading" style="display:inline-block;">I am a heading</h1>
    106  `,
    107  async function (browser, accDoc) {
    108    const test = findAccessibleChildByID(accDoc, "test");
    109    const heading = findAccessibleChildByID(accDoc, "heading");
    110 
    111    info("Hittesting pre-APZ");
    112    let dpr = await getContentDPR(browser);
    113    let [targetX, targetY, targetW, targetH] = Layout.getBounds(test, dpr);
    114    let [x, y] = Layout.getBounds(accDoc, dpr);
    115    // Save these values for later, we'll need them to compare.
    116    const origTestX = targetX - x + targetW / 2;
    117    const origTestY = targetY - y + targetH / 2;
    118    // Try hittesting the test node, which should succeed.
    119    await testChildAtPoint(
    120      dpr,
    121      origTestX,
    122      origTestY,
    123      accDoc,
    124      test, // Direct Child
    125      test // Deepest Child
    126    );
    127 
    128    // Now try hittesting the heading, we should get the heading and its internal
    129    // text node.
    130    [targetX, targetY, targetW, targetH] = Layout.getBounds(heading, dpr);
    131    const origHeadingX = targetX - x + targetW / 2;
    132    const origHeadingY = targetY - y + targetH / 2;
    133    await testChildAtPoint(
    134      dpr,
    135      origHeadingX,
    136      origHeadingY,
    137      accDoc,
    138      heading, // Direct Child
    139      heading.firstChild // Deepest Child
    140    );
    141 
    142    info("Pinch zooming...");
    143    await SpecialPowers.spawn(browser, [], async () => {
    144      const visualScrollPromise = new Promise(resolve => {
    145        content.window.visualViewport.addEventListener("scroll", resolve, {
    146          once: true,
    147        });
    148      });
    149      const utils = SpecialPowers.getDOMWindowUtils(content.window);
    150      utils.setResolutionAndScaleTo(2);
    151      utils.scrollToVisual(
    152        200,
    153        200,
    154        utils.UPDATE_TYPE_MAIN_THREAD,
    155        utils.SCROLL_MODE_INSTANT
    156      );
    157      await visualScrollPromise;
    158    });
    159 
    160    info("Hittesting post-APZ, pre-scroll");
    161    dpr = await getContentDPR(browser);
    162    let [newX, newY, newW, newH] = Layout.getBounds(heading, dpr);
    163    [x, y] = Layout.getBounds(accDoc, dpr);
    164    // Try hittesting the heading, which should be outside
    165    // the visual viewport.
    166    info("Testing heading at new point");
    167    await testChildAtPoint(
    168      dpr,
    169      newX - x + newW / 2,
    170      newY - y + newH / 2,
    171      accDoc,
    172      null, // Direct Child
    173      null // Deepest Child
    174    );
    175 
    176    info("Testing heading at old point");
    177    // To ensure the viewport cache has updated, and that the heading isn't
    178    // stuck in its old location, test there too. If this fails, we know we're
    179    // missing a viewport update.
    180    await testChildAtPoint(
    181      dpr,
    182      origHeadingX,
    183      origHeadingY,
    184      accDoc,
    185      accDoc, // Direct Child
    186      accDoc // Deepest Child
    187    );
    188 
    189    // Then try hittesting the original div, which should
    190    // also be outside the visual viewport
    191    [newX, newY, newW, newH] = Layout.getBounds(test, dpr);
    192    info("testing test at new point");
    193    await testChildAtPoint(
    194      dpr,
    195      newX - x + newW / 2,
    196      newY - y + newH / 2,
    197      accDoc,
    198      null, // Direct Child
    199      null // Deepest Child
    200    );
    201    info("testing test at old point");
    202    // If we still get the test div, the viewport cache is
    203    // stale.
    204    await testChildAtPoint(
    205      dpr,
    206      origTestX,
    207      origTestY,
    208      accDoc,
    209      accDoc, // Direct Child
    210      accDoc // Deepest Child
    211    );
    212 
    213    info("Scrolling to bottom of page...");
    214    await SpecialPowers.spawn(browser, [], async () => {
    215      const visualScrollPromise = new Promise(resolve => {
    216        content.window.visualViewport.addEventListener("scroll", resolve, {
    217          once: true,
    218        });
    219      });
    220      const utils = SpecialPowers.getDOMWindowUtils(content.window);
    221      utils.scrollToVisual(
    222        0,
    223        content.visualViewport.height,
    224        utils.UPDATE_TYPE_MAIN_THREAD,
    225        utils.SCROLL_MODE_INSTANT
    226      );
    227      await visualScrollPromise;
    228    });
    229 
    230    info("Hittesting post-APZ, post-scroll");
    231    dpr = await getContentDPR(browser);
    232    [newX, newY, newW, newH] = Layout.getBounds(test, dpr);
    233    [x, y] = Layout.getBounds(accDoc, dpr);
    234    // We shouldn't get anything in the spot that the test acc
    235    // previously occupied, it should be offscreen.
    236    info("testing test at new point");
    237    await testChildAtPoint(
    238      dpr,
    239      newX - x + newW / 2,
    240      newY - y + newH / 2,
    241      accDoc,
    242      null, // Direct Child
    243      null // Deepest Child
    244    );
    245    info("Testing test at old point");
    246    const spacer = findAccessibleChildByID(accDoc, "spacer");
    247    // "Spacer" takes up all the space above the heading, which means
    248    // it occupies the region our test div originally did. We
    249    // should find it here, if the viewport cache isn't stale.
    250    await testChildAtPoint(
    251      dpr,
    252      origTestX,
    253      origTestY,
    254      accDoc,
    255      spacer, // Direct Child
    256      spacer // Deepest Child
    257    );
    258 
    259    // We should be able to hittest the heading at the
    260    // bottom of the page.
    261    [newX, newY, newW, newH] = Layout.getBounds(heading, dpr);
    262    info("Testing heading at new point");
    263    await testChildAtPoint(
    264      dpr,
    265      newX - x + newW / 2,
    266      newY - y + newH / 2,
    267      accDoc,
    268      heading, // Direct Child
    269      heading.firstChild // Deepest Child
    270    );
    271  },
    272  // APZ only happens on the top-level document, which means iframe tests
    273  // will assert differently than classic remote doc tests.
    274  { iframe: false, remoteIframe: false }
    275 );