f7798d30a40729f02ce1fadbcd86b0714108c1a2
[WebKit-https.git] / Source / WebCore / dom / EventDispatcher.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  * Copyright (C) 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "EventDispatcher.h"
28
29 #include "EventContext.h"
30 #include "FocusEvent.h"
31 #include "FrameView.h"
32 #include "HTMLInputElement.h"
33 #include "HTMLMediaElement.h"
34 #include "InsertionPoint.h"
35 #include "InspectorInstrumentation.h"
36 #include "MouseEvent.h"
37 #include "PseudoElement.h"
38 #include "ScopedEventQueue.h"
39 #include "ShadowRoot.h"
40 #include "SVGElementInstance.h"
41 #include "SVGNames.h"
42 #include "SVGUseElement.h"
43 #include "TouchEvent.h"
44
45 namespace WebCore {
46
47 class WindowEventContext {
48 public:
49     WindowEventContext(PassRefPtr<Node>, const EventContext*);
50
51     DOMWindow* window() const { return m_window.get(); }
52     EventTarget* target() const { return m_target.get(); }
53     bool handleLocalEvents(Event&);
54
55 private:
56     RefPtr<DOMWindow> m_window;
57     RefPtr<EventTarget> m_target;
58 };
59
60 WindowEventContext::WindowEventContext(PassRefPtr<Node> node, const EventContext* topEventContext)
61 {
62     Node* topLevelContainer = topEventContext ? topEventContext->node() : node.get();
63     if (!is<Document>(topLevelContainer))
64         return;
65
66     m_window = downcast<Document>(*topLevelContainer).domWindow();
67     m_target = topEventContext ? topEventContext->target() : node.get();
68 }
69
70 bool WindowEventContext::handleLocalEvents(Event& event)
71 {
72     if (!m_window)
73         return false;
74
75     event.setTarget(m_target.get());
76     event.setCurrentTarget(m_window.get());
77     m_window->fireEventListeners(&event);
78     return true;
79 }
80
81 class EventPath {
82 public:
83     EventPath(Node& origin, Event&);
84
85     bool isEmpty() const { return m_path.isEmpty(); }
86     size_t size() const { return m_path.size(); }
87     const EventContext& contextAt(size_t i) const { return *m_path[i]; }
88     EventContext& contextAt(size_t i) { return *m_path[i]; }
89
90 #if ENABLE(TOUCH_EVENTS)
91     bool updateTouchLists(const TouchEvent&);
92 #endif
93     void setRelatedTarget(Node& origin, EventTarget&);
94
95     bool hasEventListeners(const AtomicString& eventType) const;
96
97     EventContext* lastContextIfExists() { return m_path.isEmpty() ? 0 : m_path.last().get(); }
98
99 private:
100 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
101     void updateTouchListsInEventPath(const TouchList*, TouchEventContext::TouchListType);
102 #endif
103
104     Vector<std::unique_ptr<EventContext>, 32> m_path;
105 };
106
107 class EventRelatedNodeResolver {
108 public:
109     EventRelatedNodeResolver(Node& relatedNode)
110         : m_relatedNode(relatedNode)
111         , m_relatedNodeTreeScope(relatedNode.treeScope())
112         , m_relatedNodeInCurrentTreeScope(nullptr)
113         , m_currentTreeScope(nullptr)
114 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
115         , m_touch(0)
116         , m_touchListType(TouchEventContext::NotTouchList)
117 #endif
118     {
119     }
120
121 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
122     EventRelatedNodeResolver(Touch& touch, TouchEventContext::TouchListType touchListType)
123         : m_relatedNode(*touch.target()->toNode())
124         , m_relatedNodeTreeScope(m_relatedNode.treeScope())
125         , m_relatedNodeInCurrentTreeScope(nullptr)
126         , m_currentTreeScope(nullptr)
127         , m_touch(&touch)
128         , m_touchListType(touchListType)
129     {
130         ASSERT(touch.target()->toNode());
131     }
132 #endif
133
134 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
135     Touch* touch() const { return m_touch; }
136     TouchEventContext::TouchListType touchListType() const { return m_touchListType; }
137 #endif
138
139     Node* moveToParentOrShadowHost(Node& newTarget)
140     {
141         TreeScope& newTreeScope = newTarget.treeScope();
142         if (&newTreeScope == m_currentTreeScope)
143             return m_relatedNodeInCurrentTreeScope;
144
145         if (m_currentTreeScope) {
146             ASSERT(is<ShadowRoot>(m_currentTreeScope->rootNode()));
147             ASSERT(&newTarget == downcast<ShadowRoot>(m_currentTreeScope->rootNode()).hostElement());
148             ASSERT(m_currentTreeScope->parentTreeScope() == &newTreeScope);
149         }
150
151         if (&newTreeScope == &m_relatedNodeTreeScope)
152             m_relatedNodeInCurrentTreeScope = &m_relatedNode;
153         else if (m_relatedNodeInCurrentTreeScope) {
154             ASSERT(m_currentTreeScope);
155             m_relatedNodeInCurrentTreeScope = &newTarget;
156         } else {
157             if (!m_currentTreeScope) {
158                 TreeScope* newTreeScopeAncestor = &newTreeScope;
159                 do {
160                     m_relatedNodeInCurrentTreeScope = findHostOfTreeScopeInTargetTreeScope(m_relatedNodeTreeScope, *newTreeScopeAncestor);
161                     newTreeScopeAncestor = newTreeScopeAncestor->parentTreeScope();
162                     if (newTreeScopeAncestor == &m_relatedNodeTreeScope) {
163                         m_relatedNodeInCurrentTreeScope = &m_relatedNode;
164                         break;
165                     }
166                 } while (newTreeScopeAncestor && !m_relatedNodeInCurrentTreeScope);
167             }
168             ASSERT(m_relatedNodeInCurrentTreeScope || findHostOfTreeScopeInTargetTreeScope(newTreeScope, m_relatedNodeTreeScope)
169                 || &newTreeScope.documentScope() != &m_relatedNodeTreeScope.documentScope());
170         }
171
172         m_currentTreeScope = &newTreeScope;
173
174         return m_relatedNodeInCurrentTreeScope;
175     }
176
177     static Node* findHostOfTreeScopeInTargetTreeScope(const TreeScope& startingTreeScope, const TreeScope& targetScope)
178     {
179         ASSERT(&targetScope != &startingTreeScope);
180         Node* previousHost = nullptr;
181         for (const TreeScope* scope = &startingTreeScope; scope; scope = scope->parentTreeScope()) {
182             if (scope == &targetScope) {
183                 ASSERT(previousHost);
184                 ASSERT_WITH_SECURITY_IMPLICATION(&previousHost->treeScope() == &targetScope);
185                 return previousHost;
186             }
187             if (is<ShadowRoot>(scope->rootNode()))
188                 previousHost = downcast<ShadowRoot>(scope->rootNode()).hostElement();
189             else
190                 ASSERT_WITH_SECURITY_IMPLICATION(!scope->parentTreeScope());
191         }
192         return nullptr;
193     }
194
195 private:
196     Node& m_relatedNode;
197     const TreeScope& m_relatedNodeTreeScope;
198     Node* m_relatedNodeInCurrentTreeScope;
199     TreeScope* m_currentTreeScope;
200 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
201     Touch* m_touch;
202     TouchEventContext::TouchListType m_touchListType;
203 #endif
204 };
205
206 inline EventTarget& eventTargetRespectingTargetRules(Node& referenceNode)
207 {
208     if (is<PseudoElement>(referenceNode)) {
209         EventTarget* hostElement = downcast<PseudoElement>(referenceNode).hostElement();
210         ASSERT(hostElement);
211         return *hostElement;
212     }
213
214     if (!referenceNode.isSVGElement() || !referenceNode.isInShadowTree())
215         return referenceNode;
216
217     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
218     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
219     auto& rootNode = referenceNode.treeScope().rootNode();
220     Element* shadowHostElement = is<ShadowRoot>(rootNode) ? downcast<ShadowRoot>(rootNode).hostElement() : nullptr;
221     // At this time, SVG nodes are not supported in non-<use> shadow trees.
222     if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag))
223         return referenceNode;
224     SVGUseElement& useElement = downcast<SVGUseElement>(*shadowHostElement);
225     if (SVGElementInstance* instance = useElement.instanceForShadowTreeElement(&referenceNode))
226         return *instance;
227
228     return referenceNode;
229 }
230
231 void EventDispatcher::dispatchScopedEvent(Node& node, PassRefPtr<Event> event)
232 {
233     // We need to set the target here because it can go away by the time we actually fire the event.
234     event->setTarget(&eventTargetRespectingTargetRules(node));
235     ScopedEventQueue::instance().enqueueEvent(event);
236 }
237
238 void EventDispatcher::dispatchSimulatedClick(Element* element, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions, SimulatedClickVisualOptions visualOptions)
239 {
240     if (element->isDisabledFormControl())
241         return;
242
243     DEPRECATED_DEFINE_STATIC_LOCAL(HashSet<Element*>, elementsDispatchingSimulatedClicks, ());
244     if (!elementsDispatchingSimulatedClicks.add(element).isNewEntry)
245         return;
246
247     if (mouseEventOptions == SendMouseOverUpDownEvents)
248         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mouseoverEvent, element->document().defaultView(), underlyingEvent, element));
249
250     if (mouseEventOptions != SendNoEvents)
251         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mousedownEvent, element->document().defaultView(), underlyingEvent, element));
252     element->setActive(true, visualOptions == ShowPressedLook);
253     if (mouseEventOptions != SendNoEvents)
254         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mouseupEvent, element->document().defaultView(), underlyingEvent, element));
255     element->setActive(false);
256
257     // always send click
258     dispatchEvent(element, SimulatedMouseEvent::create(eventNames().clickEvent, element->document().defaultView(), underlyingEvent, element));
259
260     elementsDispatchingSimulatedClicks.remove(element);
261 }
262
263 static void callDefaultEventHandlersInTheBubblingOrder(Event& event, const EventPath& path)
264 {
265     if (path.isEmpty())
266         return;
267
268     // Non-bubbling events call only one default event handler, the one for the target.
269     path.contextAt(0).node()->defaultEventHandler(&event);
270     ASSERT(!event.defaultPrevented());
271
272     if (event.defaultHandled() || !event.bubbles())
273         return;
274
275     size_t size = path.size();
276     for (size_t i = 1; i < size; ++i) {
277         path.contextAt(i).node()->defaultEventHandler(&event);
278         ASSERT(!event.defaultPrevented());
279         if (event.defaultHandled())
280             return;
281     }
282 }
283
284 static void dispatchEventInDOM(Event& event, const EventPath& path, WindowEventContext& windowEventContext)
285 {
286     // Trigger capturing event handlers, starting at the top and working our way down.
287     event.setEventPhase(Event::CAPTURING_PHASE);
288
289     // We don't dispatch load events to the window. This quirk was originally
290     // added because Mozilla doesn't propagate load events to the window object.
291     bool shouldFireEventAtWindow = event.type() != eventNames().loadEvent;
292     if (shouldFireEventAtWindow && windowEventContext.handleLocalEvents(event) && event.propagationStopped())
293         return;
294
295     for (size_t i = path.size() - 1; i > 0; --i) {
296         const EventContext& eventContext = path.contextAt(i);
297         if (eventContext.currentTargetSameAsTarget())
298             continue;
299         eventContext.handleLocalEvents(event);
300         if (event.propagationStopped())
301             return;
302     }
303
304     event.setEventPhase(Event::AT_TARGET);
305     path.contextAt(0).handleLocalEvents(event);
306     if (event.propagationStopped())
307         return;
308
309     // Trigger bubbling event handlers, starting at the bottom and working our way up.
310     size_t size = path.size();
311     for (size_t i = 1; i < size; ++i) {
312         const EventContext& eventContext = path.contextAt(i);
313         if (eventContext.currentTargetSameAsTarget())
314             event.setEventPhase(Event::AT_TARGET);
315         else if (event.bubbles() && !event.cancelBubble())
316             event.setEventPhase(Event::BUBBLING_PHASE);
317         else
318             continue;
319         eventContext.handleLocalEvents(event);
320         if (event.propagationStopped())
321             return;
322     }
323     if (event.bubbles() && !event.cancelBubble()) {
324         event.setEventPhase(Event::BUBBLING_PHASE);
325         if (shouldFireEventAtWindow)
326             windowEventContext.handleLocalEvents(event);
327     }
328 }
329
330 bool EventDispatcher::dispatchEvent(Node* origin, PassRefPtr<Event> prpEvent)
331 {
332     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
333     if (!prpEvent)
334         return true;
335
336     ASSERT(origin);
337     RefPtr<Node> node(origin);
338     RefPtr<Event> event(prpEvent);
339     RefPtr<FrameView> view = node->document().view();
340     EventPath eventPath(*node, *event);
341
342     if (EventTarget* relatedTarget = event->relatedTarget())
343         eventPath.setRelatedTarget(*node, *relatedTarget);
344 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
345     if (is<TouchEvent>(*event)) {
346         if (!eventPath.updateTouchLists(downcast<TouchEvent>(*event)))
347             return true;
348     }
349 #endif
350
351     ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
352
353     event->setTarget(&eventTargetRespectingTargetRules(*node));
354     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
355     ASSERT(event->target());
356     WindowEventContext windowEventContext(node.get(), eventPath.lastContextIfExists());
357
358     InputElementClickState clickHandlingState;
359     if (is<HTMLInputElement>(node.get()))
360         downcast<HTMLInputElement>(*node).willDispatchEvent(*event, clickHandlingState);
361
362     if (!event->propagationStopped() && !eventPath.isEmpty())
363         dispatchEventInDOM(*event, eventPath, windowEventContext);
364
365     event->setTarget(&eventTargetRespectingTargetRules(*node));
366     event->setCurrentTarget(nullptr);
367     event->setEventPhase(0);
368
369     if (clickHandlingState.stateful)
370         downcast<HTMLInputElement>(*node).didDispatchClickEvent(*event, clickHandlingState);
371
372     // Call default event handlers. While the DOM does have a concept of preventing
373     // default handling, the detail of which handlers are called is an internal
374     // implementation detail and not part of the DOM.
375     if (!event->defaultPrevented() && !event->defaultHandled())
376         callDefaultEventHandlersInTheBubblingOrder(*event, eventPath);
377
378     // Ensure that after event dispatch, the event's target object is the
379     // outermost shadow DOM boundary.
380     event->setTarget(windowEventContext.target());
381     event->setCurrentTarget(0);
382
383     return !event->defaultPrevented();
384 }
385
386 static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
387 {
388     Node* targetNode = target.toNode();
389 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
390     // Video-only full screen is a mode where we use the shadow DOM as an implementation
391     // detail that should not be detectable by the web content.
392     if (targetNode) {
393         if (Element* element = targetNode->document().webkitCurrentFullScreenElement()) {
394             // FIXME: We assume that if the full screen element is a media element that it's
395             // the video-only full screen. Both here and elsewhere. But that is probably wrong.
396             if (element->isMediaElement() && shadowRoot.hostElement() == element)
397                 return false;
398         }
399     }
400 #endif
401
402     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
403     // Changing this breaks existing sites.
404     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
405     const AtomicString& eventType = event.type();
406     bool targetIsInShadowRoot = targetNode && &targetNode->treeScope().rootNode() == &shadowRoot;
407     return !targetIsInShadowRoot
408         || !(eventType == eventNames().abortEvent
409             || eventType == eventNames().changeEvent
410             || eventType == eventNames().errorEvent
411             || eventType == eventNames().loadEvent
412             || eventType == eventNames().resetEvent
413             || eventType == eventNames().resizeEvent
414             || eventType == eventNames().scrollEvent
415             || eventType == eventNames().selectEvent
416             || eventType == eventNames().selectstartEvent);
417 }
418
419 static Node* nodeOrHostIfPseudoElement(Node* node)
420 {
421     return is<PseudoElement>(node) ? downcast<PseudoElement>(*node).hostElement() : node;
422 }
423
424 EventPath::EventPath(Node& targetNode, Event& event)
425 {
426     bool inDocument = targetNode.inDocument();
427     bool isSVGElement = targetNode.isSVGElement();
428     bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
429 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
430     bool isTouchEvent = event.isTouchEvent();
431 #endif
432     EventTarget* target = 0;
433
434     Node* node = nodeOrHostIfPseudoElement(&targetNode);
435     while (node) {
436         if (!target || !isSVGElement) // FIXME: This code doesn't make sense once we've climbed out of the SVG subtree in a HTML document.
437             target = &eventTargetRespectingTargetRules(*node);
438         for (; node; node = node->parentNode()) {
439             EventTarget& currentTarget = eventTargetRespectingTargetRules(*node);
440             if (isMouseOrFocusEvent)
441                 m_path.append(std::make_unique<MouseOrFocusEventContext>(node, &currentTarget, target));
442 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
443             else if (isTouchEvent)
444                 m_path.append(std::make_unique<TouchEventContext>(node, &currentTarget, target));
445 #endif
446             else
447                 m_path.append(std::make_unique<EventContext>(node, &currentTarget, target));
448             if (!inDocument)
449                 return;
450             if (is<ShadowRoot>(node))
451                 break;
452         }
453         if (!node || !shouldEventCrossShadowBoundary(event, downcast<ShadowRoot>(*node), *target))
454             return;
455         node = downcast<ShadowRoot>(*node).hostElement();
456     }
457 }
458
459 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
460 static void addRelatedNodeResolversForTouchList(Vector<EventRelatedNodeResolver, 16>& touchTargetResolvers, TouchList* touchList, TouchEventContext::TouchListType type)
461 {
462     const size_t touchListSize = touchList->length();
463     for (size_t i = 0; i < touchListSize; ++i)
464         touchTargetResolvers.append(EventRelatedNodeResolver(*touchList->item(i), type));
465 }
466
467 bool EventPath::updateTouchLists(const TouchEvent& touchEvent)
468 {
469     if (!touchEvent.touches() || !touchEvent.targetTouches() || !touchEvent.changedTouches())
470         return false;
471     
472     Vector<EventRelatedNodeResolver, 16> touchTargetResolvers;
473     const size_t touchNodeCount = touchEvent.touches()->length() + touchEvent.targetTouches()->length() + touchEvent.changedTouches()->length();
474     touchTargetResolvers.reserveInitialCapacity(touchNodeCount);
475
476     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.touches(), TouchEventContext::Touches);
477     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.targetTouches(), TouchEventContext::TargetTouches);
478     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.changedTouches(), TouchEventContext::ChangedTouches);
479
480     ASSERT(touchTargetResolvers.size() == touchNodeCount);
481     size_t eventPathSize = m_path.size();
482     for (size_t i = 0; i < eventPathSize; ++i) {
483         TouchEventContext& context = toTouchEventContext(*m_path[i]);
484         Node& nodeToMoveTo = *context.node();
485         for (size_t resolverIndex = 0; resolverIndex < touchNodeCount; ++resolverIndex) {
486             EventRelatedNodeResolver& currentResolver = touchTargetResolvers[resolverIndex];
487             Node* nodeInCurrentTreeScope = currentResolver.moveToParentOrShadowHost(nodeToMoveTo);
488             ASSERT(currentResolver.touch());
489             context.touchList(currentResolver.touchListType())->append(currentResolver.touch()->cloneWithNewTarget(nodeInCurrentTreeScope));
490         }
491     }
492     return true;
493 }
494 #endif
495
496 void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
497 {
498     Node* relatedNode = relatedTarget.toNode();
499     if (!relatedNode)
500         return;
501
502     EventRelatedNodeResolver resolver(*relatedNode);
503
504     bool originIsRelatedTarget = &origin == relatedNode;
505     Node& rootNodeInOriginTreeScope = origin.treeScope().rootNode();
506
507     size_t eventPathSize = m_path.size();
508     size_t i = 0;
509     while (i < eventPathSize) {
510         Node* contextNode = m_path[i]->node();
511         Node* currentRelatedNode = resolver.moveToParentOrShadowHost(*contextNode);
512         if (!originIsRelatedTarget && m_path[i]->target() == currentRelatedNode)
513             break;
514         toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(currentRelatedNode);
515         i++;
516         if (originIsRelatedTarget && &rootNodeInOriginTreeScope == contextNode)
517             break;
518     }
519     m_path.shrink(i);
520 }
521
522 bool EventPath::hasEventListeners(const AtomicString& eventType) const
523 {
524     for (size_t i = 0; i < m_path.size(); i++) {
525         if (m_path[i]->node()->hasEventListeners(eventType))
526             return true;
527     }
528
529     return false;
530 }
531
532 }