summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_fission_utils.js
blob: ddcab62253184d7be0a79d25ec1f0470b33d5e56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// loadOOPIFrame expects apz_test_utils.js to be loaded as well, for promiseOneEvent.
/* import-globals-from apz_test_utils.js */

function fission_subtest_init() {
  // Silence SimpleTest warning about missing assertions by having it wait
  // indefinitely. We don't need to give it an explicit finish because the
  // entire window this test runs in will be closed after subtestDone is called.
  SimpleTest.waitForExplicitFinish();

  // This is the point at which we inject the ok, is, subtestDone, etc. functions
  // into this window. In particular this function should run after SimpleTest.js
  // is imported, otherwise SimpleTest.js will clobber the functions with its
  // own versions. This is implicitly enforced because if we call this function
  // before SimpleTest.js is imported, the above line will throw an exception.
  window.dispatchEvent(new Event("FissionTestHelper:Init"));
}

/**
 * Starts loading the given `iframePage` in the iframe element with the given
 * id, and waits for it to load.
 * Note that calling this function doesn't do the load directly; instead it
 * returns an async function which can be added to a thenable chain.
 */
function loadOOPIFrame(iframeElementId, iframePage) {
  return async function () {
    if (window.location.href.startsWith("https://example.com/")) {
      dump(
        `WARNING: Calling loadOOPIFrame from ${window.location.href} so the iframe may not be OOP\n`
      );
      ok(false, "Current origin is not example.com:443");
    }

    let url =
      "https://example.com/browser/gfx/layers/apz/test/mochitest/" + iframePage;
    let loadPromise = promiseOneEvent(window, "OOPIF:Load", function (e) {
      return typeof e.data.content == "string" && e.data.content == url;
    });
    let elem = document.getElementById(iframeElementId);
    elem.src = url;
    await loadPromise;
  };
}

/**
 * This is similar to the hitTest function in apz_test_utils.js, in that it
 * does a hit-test for a point and returns the result. The difference is that
 * in the fission world, the hit-test may land on an OOPIF, which means the
 * result information will be in the APZ test data for the OOPIF process. This
 * function checks both the current process and OOPIF process to see which one
 * got a hit result, and returns the result regardless of which process got it.
 * The caller is expected to check the layers id which will allow distinguishing
 * the two cases.
 */
async function fissionHitTest(point, iframeElement) {
  let get_iframe_compositor_test_data = function () {
    let utils = SpecialPowers.getDOMWindowUtils(window);
    return JSON.stringify(utils.getCompositorAPZTestData());
  };

  let utils = SpecialPowers.getDOMWindowUtils(window);

  // Get the test data before doing the actual hit-test, to get a baseline
  // of what we can ignore.
  let oldParentTestData = utils.getCompositorAPZTestData();
  let oldIframeTestData = JSON.parse(
    await FissionTestHelper.sendToOopif(
      iframeElement,
      `(${get_iframe_compositor_test_data})()`
    )
  );

  // Now do the hit-test
  dump(`Hit-testing point (${point.x}, ${point.y}) in fission context\n`);
  utils.sendMouseEvent(
    "MozMouseHittest",
    point.x,
    point.y,
    0,
    0,
    0,
    true,
    0,
    0,
    true,
    true
  );

  // Collect the new test data
  let newParentTestData = utils.getCompositorAPZTestData();
  let newIframeTestData = JSON.parse(
    await FissionTestHelper.sendToOopif(
      iframeElement,
      `(${get_iframe_compositor_test_data})()`
    )
  );

  // See which test data has new hit results
  let hitResultCount = function (testData) {
    return Object.keys(testData.hitResults).length;
  };

  let hitIframe =
    hitResultCount(newIframeTestData) > hitResultCount(oldIframeTestData);
  let hitParent =
    hitResultCount(newParentTestData) > hitResultCount(oldParentTestData);

  // Extract the results from the appropriate test data
  let lastHitResult = function (testData) {
    let lastHit =
      testData.hitResults[Object.keys(testData.hitResults).length - 1];
    return {
      hitInfo: lastHit.hitResult,
      scrollId: lastHit.scrollId,
      layersId: lastHit.layersId,
    };
  };
  if (hitIframe && hitParent) {
    throw new Error(
      "Both iframe and parent got hit-results, that is unexpected!"
    );
  } else if (hitIframe) {
    return lastHitResult(newIframeTestData);
  } else if (hitParent) {
    return lastHitResult(newParentTestData);
  } else {
    throw new Error(
      "Neither iframe nor parent got the hit-result, that is unexpected!"
    );
  }
}