Bug 1648630 - Part 3: Propagate layers id to touch event properly for Fission; r=kats

Differential Revision: https://phabricator.services.mozilla.com/D81869
This commit is contained in:
Edgar Chen 2020-07-03 07:45:35 +00:00
parent 71ad0b0850
commit dc0bf3f975
5 changed files with 117 additions and 0 deletions

View File

@ -45,6 +45,7 @@ add_task(async function test_main() {
},
{ url: httpURL("helper_fission_animation_styling_in_oopif.html") },
{ url: httpURL("helper_fission_force_empty_hit_region.html") },
{ url: httpURL("helper_fission_touch.html") },
// add additional tests here
];
if (isWebRender) {

View File

@ -0,0 +1,99 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test to ensure touch events for OOP iframes</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="helper_fission_utils.js"></script>
<script src="apz_test_utils.js"></script>
<script src="apz_test_native_event_utils.js"></script>
<script>
fission_subtest_init();
FissionTestHelper.startTestPromise
.then(waitUntilApzStable)
.then(loadOOPIFrame("testframe", "helper_fission_empty.html"))
.then(waitUntilApzStable)
.then(runAsyncContinuation(test))
.then(FissionTestHelper.subtestDone, FissionTestHelper.subtestDone);
let code_for_oopif_to_run = function() {
let listener = function(e) {
let result = { type: e.type, touches: [] };
dump(`OOPIF got ${e.type}\n`);
for (let touch of e.touches) {
result.touches.push({
identifier: touch.identifier,
clientX: touch.clientX,
clientY: touch.clientY
});
dump(` identifier ${touch.identifier} at ${touch.clientX},${touch.clientY}\n`);
}
FissionTestHelper.fireEventInEmbedder("OOPIF:TouchEvent", result);
};
document.addEventListener("touchstart", listener, {once: true});
document.addEventListener("touchmove", listener, {once: true});
document.addEventListener("touchend", listener, {once: true});
dump("OOPIF registered touch listener\n");
return true;
};
function failsafe() {
let failListener = function(e) {
dump(`${location.href} got ${e.type}\n`);
ok(false, `The OOPIF hosting page should not have gotten the ${e.type}`);
setTimeout(FissionTestHelper.subtestDone, 0);
};
// Catch and fail faster on the case where the touch event ends up not going
// to the iframe like it should. Otherwise the test hangs until timeout which
// is more painful.
document.addEventListener("touchstart", failListener, {once: true});
document.addEventListener("touchmove", failListener, {once: true});
document.addEventListener("touchend", failListener, {once: true});
}
function waitForTouchEvent(aType) {
return promiseOneEvent(window, "OOPIF:TouchEvent", function(e) {
return e.data.type === aType;
});
}
async function* test() {
let iframeElement = document.getElementById("testframe");
let iframeResponse = await FissionTestHelper.sendToOopif(iframeElement, `(${code_for_oopif_to_run})()`);
dump("OOPIF response: " + JSON.stringify(iframeResponse) + "\n");
ok(iframeResponse, "code_for_oopif_to_run successfully installed");
iframePromise = Promise.all([waitForTouchEvent("touchstart"),
waitForTouchEvent("touchmove"),
waitForTouchEvent("touchend")]);
yield* synthesizeNativeTouchSequences(document.body,
[[{x: 100, y: 100}], [{x: 150, y: 150}], [{x: 150, y: 150}]], function() {
dump("Finished synthesizing touch tap, waiting for OOPIF message...\n");
});
await iframePromise;
}
</script>
<style>
body, html {
margin: 0;
}
div {
width: 500px;
}
iframe {
width: 400px;
height: 300px;
border: solid 1px black;
}
</style>
</head>
<body onload="failsafe()">
<div><iframe id="testframe"></iframe></div>
</body>
</html>

View File

@ -19,12 +19,14 @@ namespace mozilla {
nsDataHashtable<nsUint32HashKey, TouchManager::TouchInfo>*
TouchManager::sCaptureTouchList;
layers::LayersId TouchManager::sCaptureTouchLayersId;
/*static*/
void TouchManager::InitializeStatics() {
NS_ASSERTION(!sCaptureTouchList, "InitializeStatics called multiple times!");
sCaptureTouchList =
new nsDataHashtable<nsUint32HashKey, TouchManager::TouchInfo>;
sCaptureTouchLayersId = layers::LayersId{0};
}
/*static*/
@ -98,6 +100,7 @@ void TouchManager::EvictTouches(Document* aLimitToDocument) {
for (uint32_t i = 0; i < touches.Length(); ++i) {
EvictTouchPoint(touches[i], aLimitToDocument);
}
sCaptureTouchLayersId = layers::LayersId{0};
}
/* static */
@ -225,6 +228,14 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
// queue
if (touchEvent->mTouches.Length() == 1) {
EvictTouches();
// Per
// https://w3c.github.io/touch-events/#touchevent-implementer-s-note,
// all touch event should be dispatched to the same document that first
// touch event associated to. We cache layers id of the first touchstart
// event, all subsequent touch events will use the same layers id.
sCaptureTouchLayersId = aEvent->mLayersId;
} else {
touchEvent->mLayersId = sCaptureTouchLayersId;
}
// Add any new touches to the queue
WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
@ -253,6 +264,7 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
// Check for touches that changed. Mark them add to queue
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
touchEvent->mLayersId = sCaptureTouchLayersId;
bool haveChanged = false;
for (int32_t i = touches.Length(); i;) {
--i;
@ -326,6 +338,7 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
// need to make sure we only remove touches that are ending here
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
touchEvent->mLayersId = sCaptureTouchLayersId;
for (int32_t i = touches.Length(); i;) {
--i;
Touch* touch = touches[i];
@ -363,6 +376,7 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
// is received.
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
touchEvent->mLayersId = sCaptureTouchLayersId;
for (uint32_t i = 0; i < touches.Length(); ++i) {
Touch* touch = touches[i];
if (!touch) {

View File

@ -72,7 +72,9 @@ class TouchManager {
nsCOMPtr<nsIContent> mNonAnonymousTarget;
bool mConvertToPointer;
};
static nsDataHashtable<nsUint32HashKey, TouchInfo>* sCaptureTouchList;
static layers::LayersId sCaptureTouchLayersId;
};
} // namespace mozilla

View File

@ -185,6 +185,7 @@ WidgetTouchEvent MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const {
event.mTimeStamp = this->mTimeStamp;
event.mFlags.mHandledByAPZ = mHandledByAPZ;
event.mFocusSequenceNumber = mFocusSequenceNumber;
event.mLayersId = mLayersId;
for (size_t i = 0; i < mTouches.Length(); i++) {
*event.mTouches.AppendElement() = mTouches[i].ToNewDOMTouch();