Bug 1916141 - Make AutoPointerEventTargetUpdater guarantee that the target is an element if the event target should be so r=smaug

According to test result on tryserver, the constructor may receive text frame,
although I couldn't reproduce it with writing tests.  Then, it'll return
the text node as the mouse event target after dispatching a pointer event.
However, mouse events need to be targeted to element node.  Therefore, it's
wrong to use the frame when `aTargetContent` is specified.

Additionally, for the last resort, it should refer an inclusive ancestor element
of the target frame content if `aTargetContent` is not specified and the event
should be targeted to an element.

Finally, there is another path to set non-element node in
`PresShell::EventHandler::DispatchEventToDOM`.  The path is not the cause of
the reported case, but we should fix it too.

Differential Revision: https://phabricator.services.mozilla.com/D222091
This commit is contained in:
Masayuki Nakano
2024-09-15 21:57:51 +00:00
parent b13159498a
commit 136939d338

View File

@@ -574,8 +574,23 @@ class MOZ_STACK_CLASS AutoPointerEventTargetUpdater final {
mFromTouch = aEvent->AsPointerEvent()->mFromTouchEvent;
// Touch event target may have no frame, e.g., removed from the DOM
MOZ_ASSERT_IF(!mFromTouch, aFrame);
mOriginalPointerEventTarget = aShell->mPointerEventTarget =
aFrame ? aFrame->GetContent() : aTargetContent;
// The frame may be a text frame, but the event target should be an element
// node. Therefore, refer aTargetContent first, then, if we have only a
// frame, we should use inclusive ancestor of the content.
mOriginalPointerEventTarget =
aShell->mPointerEventTarget = [&]() -> nsIContent* {
nsIContent* const target =
aTargetContent ? aTargetContent
: (aFrame ? aFrame->GetContent() : nullptr);
if (MOZ_UNLIKELY(!target)) {
return nullptr;
}
if (target->IsElement() ||
!IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) {
return target;
}
return target->GetInclusiveFlattenedTreeAncestorElement();
}();
}
~AutoPointerEventTargetUpdater() {
@@ -8948,6 +8963,11 @@ nsresult PresShell::EventHandler::DispatchEventToDOM(
if (mPresShell->mCurrentEventTarget.mFrame) {
rv = mPresShell->mCurrentEventTarget.mFrame->GetContentForEvent(
aEvent, getter_AddRefs(targetContent));
if (targetContent && !targetContent->IsElement() &&
IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) {
targetContent =
targetContent->GetInclusiveFlattenedTreeAncestorElement();
}
}
if (NS_SUCCEEDED(rv) && targetContent) {
eventTarget = targetContent;