96 lines
3 KiB
JavaScript
96 lines
3 KiB
JavaScript
/**
|
|
* 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 hitTestOOPIF(point, iframeElement) {
|
|
let getIframeCompositorTestData = async iframe => {
|
|
let data = await SpecialPowers.spawn(iframe, [], () => {
|
|
let utils = SpecialPowers.getDOMWindowUtils(content.window);
|
|
return JSON.stringify(utils.getCompositorAPZTestData());
|
|
});
|
|
|
|
return JSON.parse(data);
|
|
};
|
|
|
|
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 = await getIframeCompositorTestData(iframeElement);
|
|
|
|
let hittestPromise = SpecialPowers.spawnChrome([], () => {
|
|
return new Promise(resolve => {
|
|
browsingContext.topChromeWindow.addEventListener(
|
|
"MozMouseHittest",
|
|
() => {
|
|
resolve();
|
|
},
|
|
{ once: true }
|
|
);
|
|
});
|
|
});
|
|
await SpecialPowers.executeAfterFlushingMessageQueue();
|
|
|
|
// 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,
|
|
false /* aIsWidgetEventSynthesized */
|
|
);
|
|
|
|
await hittestPromise;
|
|
|
|
// Collect the new test data
|
|
let newParentTestData = utils.getCompositorAPZTestData();
|
|
let newIframeTestData = await getIframeCompositorTestData(iframeElement);
|
|
|
|
// See which test data has new hit results
|
|
let hitResultCount = 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 = 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!"
|
|
);
|
|
}
|
|
}
|