mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1449560 - clear event.target and .relatedTarget in case they would otherwise reveal targets in shadow DOM, r=bz
This commit is contained in:
parent
7d559398bd
commit
96c6253308
@ -1091,7 +1091,11 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
// point to a node in Shadow DOM.
|
||||
aVisitor.mEvent->mTarget = aVisitor.mTargetInKnownToBeHandledScope;
|
||||
return;
|
||||
} else {
|
||||
} else if (targetInKnownToBeHandledScope) {
|
||||
// Note, if targetInKnownToBeHandledScope is null,
|
||||
// mTargetInKnownToBeHandledScope could be Window object in content
|
||||
// page and we're in chrome document in the same process.
|
||||
|
||||
// Step 11.6
|
||||
aVisitor.mRetargetedRelatedTarget = retargetedRelatedTarget;
|
||||
}
|
||||
|
@ -656,6 +656,26 @@ MayRetargetToChromeIfCanNotHandleEvent(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldClearTargets(WidgetEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIContent> finalTarget;
|
||||
nsCOMPtr<nsIContent> finalRelatedTarget;
|
||||
if ((finalTarget = do_QueryInterface(aEvent->mTarget)) &&
|
||||
finalTarget->SubtreeRoot()->IsShadowRoot()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((finalRelatedTarget =
|
||||
do_QueryInterface(aEvent->mRelatedTarget)) &&
|
||||
finalRelatedTarget->SubtreeRoot()->IsShadowRoot()) {
|
||||
return true;
|
||||
}
|
||||
//XXXsmaug Check also all the touch objects.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
nsPresContext* aPresContext,
|
||||
@ -836,6 +856,8 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
|
||||
aEvent->mOriginalRelatedTarget = aEvent->mRelatedTarget;
|
||||
|
||||
bool clearTargets = false;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aEvent->mOriginalTarget);
|
||||
bool isInAnon = content && content->IsInAnonymousSubtree();
|
||||
|
||||
@ -859,6 +881,8 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
for (uint32_t i = 0; i < chain.Length(); ++i) {
|
||||
chain[i].PreHandleEvent(preVisitor);
|
||||
}
|
||||
|
||||
clearTargets = ShouldClearTargets(aEvent);
|
||||
} else {
|
||||
// At least the original target can handle the event.
|
||||
// Setting the retarget to the |target| simplifies retargeting code.
|
||||
@ -927,6 +951,9 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
for (uint32_t i = 0; i < chain.Length(); ++i) {
|
||||
chain[i].PreHandleEvent(preVisitor);
|
||||
}
|
||||
|
||||
clearTargets = ShouldClearTargets(aEvent);
|
||||
|
||||
// Handle the chain.
|
||||
EventChainPostVisitor postVisitor(preVisitor);
|
||||
MOZ_RELEASE_ASSERT(!aEvent->mPath);
|
||||
@ -951,15 +978,16 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
aEvent->mFlags.mDispatchedAtLeastOnce = true;
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-dispatch
|
||||
// Step 18
|
||||
// "If target's root is a shadow root, then set event's target attribute and
|
||||
// event's relatedTarget to null."
|
||||
nsCOMPtr<nsIContent> finalTarget = do_QueryInterface(aEvent->mTarget);
|
||||
if (finalTarget && finalTarget->SubtreeRoot()->IsShadowRoot()) {
|
||||
// step 10. If clearTargets, then:
|
||||
// 1. Set event's target to null.
|
||||
// 2. Set event's relatedTarget to null.
|
||||
// 3. Set event's touch target list to the empty list.
|
||||
if (clearTargets) {
|
||||
aEvent->mTarget = nullptr;
|
||||
aEvent->mOriginalTarget = nullptr;
|
||||
aEvent->mRelatedTarget = nullptr;
|
||||
aEvent->mOriginalRelatedTarget = nullptr;
|
||||
//XXXsmaug Check also all the touch objects.
|
||||
}
|
||||
|
||||
if (!externalDOMEvent && preVisitor.mDOMEvent) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
[relatedTarget.window.html]
|
||||
[Untitled]
|
||||
prefs: [dom.webcomponents.shadowdom.enabled:true]
|
||||
[Reset targets before activation behavior]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -41,13 +41,15 @@ async_test(t => {
|
||||
|
||||
async_test(t => {
|
||||
const shadowChild = shadow.appendChild(document.createElement("div"));
|
||||
shadowChild.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild)));
|
||||
const shadowChild2 = shadow.appendChild(document.createElement("div"));
|
||||
shadowChild2.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild)));
|
||||
const event = new FocusEvent("demo", { relatedTarget: shadowChild });
|
||||
document.body.dispatchEvent(event);
|
||||
shadowChild2.dispatchEvent(event);
|
||||
assert_equals(shadowChild.parentNode, document.body);
|
||||
assert_equals(event.target, null);
|
||||
assert_equals(event.relatedTarget, null);
|
||||
shadowChild.remove();
|
||||
shadowChild2.remove();
|
||||
t.done();
|
||||
}, "Reset if relatedTarget pointed to a shadow tree pre-dispatch");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user