eafe1a2078e5fb260041778adc3ef9ef67b0c0d8
[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 "ContainerNode.h"
30 #include "EventContext.h"
31 #include "FocusEvent.h"
32 #include "FrameView.h"
33 #include "HTMLInputElement.h"
34 #include "HTMLMediaElement.h"
35 #include "InsertionPoint.h"
36 #include "InspectorInstrumentation.h"
37 #include "MouseEvent.h"
38 #include "PseudoElement.h"
39 #include "ScopedEventQueue.h"
40 #include "ShadowRoot.h"
41 #include "TouchEvent.h"
42 #include <wtf/RefPtr.h>
43
44 #if ENABLE(SVG)
45 #include "SVGElementInstance.h"
46 #include "SVGNames.h"
47 #include "SVGUseElement.h"
48 #endif
49
50 namespace WebCore {
51
52 class WindowEventContext {
53 public:
54     WindowEventContext(PassRefPtr<Node>, const EventContext*);
55
56     DOMWindow* window() const { return m_window.get(); }
57     EventTarget* target() const { return m_target.get(); }
58     bool handleLocalEvents(Event&);
59
60 private:
61     RefPtr<DOMWindow> m_window;
62     RefPtr<EventTarget> m_target;
63 };
64
65 WindowEventContext::WindowEventContext(PassRefPtr<Node> node, const EventContext* topEventContext)
66 {
67     Node* topLevelContainer = topEventContext ? topEventContext->node() : node.get();
68     if (!topLevelContainer->isDocumentNode())
69         return;
70
71     m_window = toDocument(topLevelContainer)->domWindow();
72     m_target = topEventContext ? topEventContext->target() : node.get();
73 }
74
75 bool WindowEventContext::handleLocalEvents(Event& event)
76 {
77     if (!m_window)
78         return false;
79
80     event.setTarget(m_target.get());
81     event.setCurrentTarget(m_window.get());
82     m_window->fireEventListeners(&event);
83     return true;
84 }
85
86 class EventPath {
87 public:
88     EventPath(Node& origin, Event&);
89
90     bool isEmpty() const { return m_path.isEmpty(); }
91     size_t size() const { return m_path.size(); }
92     const EventContext& contextAt(size_t i) const { return *m_path[i]; }
93     EventContext& contextAt(size_t i) { return *m_path[i]; }
94
95 #if ENABLE(TOUCH_EVENTS)
96     void updateTouchLists(const TouchEvent&);
97 #endif
98     void setRelatedTarget(EventTarget&);
99
100     bool hasEventListeners(const AtomicString& eventType) const;
101
102     EventContext* lastContextIfExists() { return m_path.isEmpty() ? 0 : m_path.last().get(); }
103
104 private:
105 #if ENABLE(TOUCH_EVENTS)
106     void updateTouchListsInEventPath(const TouchList*, TouchEventContext::TouchListType);
107 #endif
108
109     Vector<std::unique_ptr<EventContext>, 32> m_path;
110 };
111
112 class EventRelatedNodeResolver {
113 public:
114     EventRelatedNodeResolver(Node& relatedNode)
115         : m_relatedNode(relatedNode)
116         , m_relatedNodeTreeScope(relatedNode.treeScope())
117         , m_relatedNodeInCurrentTreeScope(nullptr)
118         , m_currentTreeScope(nullptr)
119 #if ENABLE(TOUCH_EVENTS)
120         , m_touch(0)
121         , m_touchListType(TouchEventContext::NotTouchList)
122 #endif
123     {
124     }
125
126 #if ENABLE(TOUCH_EVENTS)
127     EventRelatedNodeResolver(Touch& touch, TouchEventContext::TouchListType touchListType)
128         : m_relatedNode(*touch.target()->toNode())
129         , m_relatedNodeTreeScope(m_relatedNode.treeScope())
130         , m_relatedNodeInCurrentTreeScope(nullptr)
131         , m_currentTreeScope(nullptr)
132         , m_touch(&touch)
133         , m_touchListType(touchListType)
134     {
135         ASSERT(touch.target()->toNode());
136     }
137 #endif
138
139 #if ENABLE(TOUCH_EVENTS)
140     Touch* touch() const { return m_touch; }
141     TouchEventContext::TouchListType touchListType() const { return m_touchListType; }
142 #endif
143
144     Node* moveToParentOrShadowHost(Node& newTarget)
145     {
146         TreeScope& newTreeScope = newTarget.treeScope();
147         if (&newTreeScope == m_currentTreeScope)
148             return m_relatedNodeInCurrentTreeScope;
149
150         if (m_currentTreeScope) {
151             ASSERT(m_currentTreeScope->rootNode()->isShadowRoot());
152             ASSERT(&newTarget == toShadowRoot(m_currentTreeScope->rootNode())->hostElement());
153             ASSERT(m_currentTreeScope->parentTreeScope() == &newTreeScope);
154         }
155
156         if (m_relatedNodeInCurrentTreeScope) { // relatedNode is under the current tree scope
157             ASSERT(m_currentTreeScope);
158             m_relatedNodeInCurrentTreeScope = &newTarget;
159         } else if (&newTreeScope == &m_relatedNodeTreeScope) // relatedNode is in the current tree scope;
160             m_relatedNodeInCurrentTreeScope = &m_relatedNode;
161         // Otherwise, we haven't reached the tree scope that contains relatedNode yet.
162
163         m_currentTreeScope = &newTreeScope;
164
165         return m_relatedNodeInCurrentTreeScope;
166     }
167
168 private:
169     Node& m_relatedNode;
170     const TreeScope& m_relatedNodeTreeScope;
171     Node* m_relatedNodeInCurrentTreeScope;
172     TreeScope* m_currentTreeScope;
173 #if ENABLE(TOUCH_EVENTS)
174     Touch* m_touch;
175     TouchEventContext::TouchListType m_touchListType;
176 #endif
177 };
178
179 inline EventTarget& eventTargetRespectingTargetRules(Node& referenceNode)
180 {
181     if (referenceNode.isPseudoElement()) {
182         EventTarget* hostElement = toPseudoElement(referenceNode).hostElement();
183         ASSERT(hostElement);
184         return *hostElement;
185     }
186
187 #if ENABLE(SVG)
188     if (!referenceNode.isSVGElement() || !referenceNode.isInShadowTree())
189         return referenceNode;
190
191     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
192     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
193     Node* rootNode = referenceNode.treeScope().rootNode();
194     Element* shadowHostElement = rootNode->isShadowRoot() ? toShadowRoot(rootNode)->hostElement() : 0;
195     // At this time, SVG nodes are not supported in non-<use> shadow trees.
196     if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag))
197         return referenceNode;
198     SVGUseElement* useElement = toSVGUseElement(shadowHostElement);
199     if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(&referenceNode))
200         return *instance;
201 #endif
202
203     return referenceNode;
204 }
205
206 void EventDispatcher::dispatchScopedEvent(Node& node, PassRefPtr<Event> event)
207 {
208     // We need to set the target here because it can go away by the time we actually fire the event.
209     event->setTarget(&eventTargetRespectingTargetRules(node));
210     ScopedEventQueue::instance()->enqueueEvent(event);
211 }
212
213 void EventDispatcher::dispatchSimulatedClick(Element* element, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions, SimulatedClickVisualOptions visualOptions)
214 {
215     if (element->isDisabledFormControl())
216         return;
217
218     DEFINE_STATIC_LOCAL(HashSet<Element*>, elementsDispatchingSimulatedClicks, ());
219     if (!elementsDispatchingSimulatedClicks.add(element).isNewEntry)
220         return;
221
222     if (mouseEventOptions == SendMouseOverUpDownEvents)
223         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mouseoverEvent, element->document().defaultView(), underlyingEvent));
224
225     if (mouseEventOptions != SendNoEvents)
226         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mousedownEvent, element->document().defaultView(), underlyingEvent));
227     element->setActive(true, visualOptions == ShowPressedLook);
228     if (mouseEventOptions != SendNoEvents)
229         dispatchEvent(element, SimulatedMouseEvent::create(eventNames().mouseupEvent, element->document().defaultView(), underlyingEvent));
230     element->setActive(false);
231
232     // always send click
233     dispatchEvent(element, SimulatedMouseEvent::create(eventNames().clickEvent, element->document().defaultView(), underlyingEvent));
234
235     elementsDispatchingSimulatedClicks.remove(element);
236 }
237
238 static void callDefaultEventHandlersInTheBubblingOrder(Event& event, const EventPath& path)
239 {
240     // Non-bubbling events call only one default event handler, the one for the target.
241     path.contextAt(0).node()->defaultEventHandler(&event);
242     ASSERT(!event.defaultPrevented());
243
244     if (event.defaultHandled() || !event.bubbles())
245         return;
246
247     size_t size = path.size();
248     for (size_t i = 1; i < size; ++i) {
249         path.contextAt(i).node()->defaultEventHandler(&event);
250         ASSERT(!event.defaultPrevented());
251         if (event.defaultHandled())
252             return;
253     }
254 }
255
256 static void dispatchEventInDOM(Event& event, const EventPath& path, WindowEventContext& windowEventContext)
257 {
258     // Trigger capturing event handlers, starting at the top and working our way down.
259     event.setEventPhase(Event::CAPTURING_PHASE);
260
261     // We don't dispatch load events to the window. This quirk was originally
262     // added because Mozilla doesn't propagate load events to the window object.
263     bool shouldFireEventAtWindow = event.type() != eventNames().loadEvent;
264     if (shouldFireEventAtWindow && windowEventContext.handleLocalEvents(event) && event.propagationStopped())
265         return;
266
267     for (size_t i = path.size() - 1; i > 0; --i) {
268         const EventContext& eventContext = path.contextAt(i);
269         if (eventContext.currentTargetSameAsTarget())
270             continue;
271         eventContext.handleLocalEvents(event);
272         if (event.propagationStopped())
273             return;
274     }
275
276     event.setEventPhase(Event::AT_TARGET);
277     path.contextAt(0).handleLocalEvents(event);
278     if (event.propagationStopped())
279         return;
280
281     // Trigger bubbling event handlers, starting at the bottom and working our way up.
282     size_t size = path.size();
283     for (size_t i = 1; i < size; ++i) {
284         const EventContext& eventContext = path.contextAt(i);
285         if (eventContext.currentTargetSameAsTarget())
286             event.setEventPhase(Event::AT_TARGET);
287         else if (event.bubbles() && !event.cancelBubble())
288             event.setEventPhase(Event::BUBBLING_PHASE);
289         else
290             continue;
291         eventContext.handleLocalEvents(event);
292         if (event.propagationStopped())
293             return;
294     }
295     if (event.bubbles() && !event.cancelBubble()) {
296         event.setEventPhase(Event::BUBBLING_PHASE);
297         if (shouldFireEventAtWindow)
298             windowEventContext.handleLocalEvents(event);
299     }
300 }
301
302 bool EventDispatcher::dispatchEvent(Node* origin, PassRefPtr<Event> prpEvent)
303 {
304     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
305     if (!prpEvent)
306         return true;
307
308     ASSERT(origin);
309     RefPtr<Node> node(origin);
310     RefPtr<Event> event(prpEvent);
311     RefPtr<FrameView> view = node->document().view();
312     EventPath eventPath(*node, *event);
313
314     if (EventTarget* relatedTarget = event->relatedTarget())
315         eventPath.setRelatedTarget(*relatedTarget);
316 #if ENABLE(TOUCH_EVENTS)
317     if (event->isTouchEvent())
318         eventPath.updateTouchLists(*toTouchEvent(event.get()));
319 #endif
320
321     ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
322
323     event->setTarget(&eventTargetRespectingTargetRules(*node));
324     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
325     ASSERT(event->target());
326     WindowEventContext windowEventContext(node.get(), eventPath.lastContextIfExists());
327
328     InputElementClickState clickHandlingState;
329     if (isHTMLInputElement(node.get()))
330         toHTMLInputElement(*node).willDispatchEvent(*event, clickHandlingState);
331
332     if (!event->propagationStopped() && !eventPath.isEmpty())
333         dispatchEventInDOM(*event, eventPath, windowEventContext);
334
335     event->setTarget(&eventTargetRespectingTargetRules(*node));
336     event->setCurrentTarget(0);
337     event->setEventPhase(0);
338
339     if (clickHandlingState.stateful)
340         toHTMLInputElement(*node).didDispatchClickEvent(*event, clickHandlingState);
341
342     // Call default event handlers. While the DOM does have a concept of preventing
343     // default handling, the detail of which handlers are called is an internal
344     // implementation detail and not part of the DOM.
345     if (!event->defaultPrevented() && !event->defaultHandled())
346         callDefaultEventHandlersInTheBubblingOrder(*event, eventPath);
347
348     // Ensure that after event dispatch, the event's target object is the
349     // outermost shadow DOM boundary.
350     event->setTarget(windowEventContext.target());
351     event->setCurrentTarget(0);
352
353     return !event->defaultPrevented();
354 }
355
356 static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
357 {
358     Node* targetNode = target.toNode();
359 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
360     // Video-only full screen is a mode where we use the shadow DOM as an implementation
361     // detail that should not be detectable by the web content.
362     if (targetNode) {
363         if (Element* element = targetNode->document().webkitCurrentFullScreenElement()) {
364             // FIXME: We assume that if the full screen element is a media element that it's
365             // the video-only full screen. Both here and elsewhere. But that is probably wrong.
366             if (element->isMediaElement() && shadowRoot.hostElement() == element)
367                 return false;
368         }
369     }
370 #endif
371
372     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
373     // Changing this breaks existing sites.
374     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
375     const AtomicString& eventType = event.type();
376     bool targetIsInShadowRoot = targetNode && targetNode->treeScope().rootNode() == &shadowRoot;
377     return !targetIsInShadowRoot
378         || !(eventType == eventNames().abortEvent
379             || eventType == eventNames().changeEvent
380             || eventType == eventNames().errorEvent
381             || eventType == eventNames().loadEvent
382             || eventType == eventNames().resetEvent
383             || eventType == eventNames().resizeEvent
384             || eventType == eventNames().scrollEvent
385             || eventType == eventNames().selectEvent
386             || eventType == eventNames().selectstartEvent);
387 }
388
389 static Node* nodeOrHostIfPseudoElement(Node* node)
390 {
391     return node->isPseudoElement() ? toPseudoElement(node)->hostElement() : node;
392 }
393
394 EventPath::EventPath(Node& targetNode, Event& event)
395 {
396     bool inDocument = targetNode.inDocument();
397     bool isSVGElement = targetNode.isSVGElement();
398     bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
399 #if ENABLE(TOUCH_EVENTS)
400     bool isTouchEvent = event.isTouchEvent();
401 #endif
402     EventTarget* target = 0;
403
404     Node* node = nodeOrHostIfPseudoElement(&targetNode);
405     while (node) {
406         if (!target || !isSVGElement) // FIXME: This code doesn't make sense once we've climbed out of the SVG subtree in a HTML document.
407             target = &eventTargetRespectingTargetRules(*node);
408         for (; node; node = node->parentNode()) {
409             EventTarget& currentTarget = eventTargetRespectingTargetRules(*node);
410             if (isMouseOrFocusEvent)
411                 m_path.append(std::make_unique<MouseOrFocusEventContext>(node, &currentTarget, target));
412 #if ENABLE(TOUCH_EVENTS)
413             else if (isTouchEvent)
414                 m_path.append(std::make_unique<TouchEventContext>(node, &currentTarget, target));
415 #endif
416             else
417                 m_path.append(std::make_unique<EventContext>(node, &currentTarget, target));
418             if (!inDocument)
419                 return;
420             if (node->isShadowRoot())
421                 break;
422         }
423         if (!node || !shouldEventCrossShadowBoundary(event, *toShadowRoot(node), *target))
424             return;
425         node = toShadowRoot(node)->hostElement();
426     }
427 }
428
429 #if ENABLE(TOUCH_EVENTS)
430 static void addRelatedNodeResolversForTouchList(Vector<EventRelatedNodeResolver, 16>& touchTargetResolvers, TouchList* touchList, TouchEventContext::TouchListType type)
431 {
432     const size_t touchListSize = touchList->length();
433     for (size_t i = 0; i < touchListSize; ++i)
434         touchTargetResolvers.append(EventRelatedNodeResolver(*touchList->item(i), type));
435 }
436
437 void EventPath::updateTouchLists(const TouchEvent& touchEvent)
438 {
439     Vector<EventRelatedNodeResolver, 16> touchTargetResolvers;
440     const size_t touchNodeCount = touchEvent.touches()->length() + touchEvent.targetTouches()->length() + touchEvent.changedTouches()->length();
441     touchTargetResolvers.reserveInitialCapacity(touchNodeCount);
442
443     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.touches(), TouchEventContext::Touches);
444     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.targetTouches(), TouchEventContext::TargetTouches);
445     addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.changedTouches(), TouchEventContext::ChangedTouches);
446
447     ASSERT(touchTargetResolvers.size() == touchNodeCount);
448     size_t eventPathSize = m_path.size();
449     for (size_t i = 0; i < eventPathSize; ++i) {
450         TouchEventContext& context = toTouchEventContext(*m_path[i]);
451         Node& nodeToMoveTo = *context.node();
452         for (size_t resolverIndex = 0; resolverIndex < touchNodeCount; ++resolverIndex) {
453             EventRelatedNodeResolver& currentResolver = touchTargetResolvers[resolverIndex];
454             Node* nodeInCurrentTreeScope = currentResolver.moveToParentOrShadowHost(nodeToMoveTo);
455             ASSERT(currentResolver.touch());
456             context.touchList(currentResolver.touchListType())->append(currentResolver.touch()->cloneWithNewTarget(nodeInCurrentTreeScope));
457         }
458     }
459 }
460 #endif
461
462 void EventPath::setRelatedTarget(EventTarget& relatedTarget)
463 {
464     Node* relatedNode = relatedTarget.toNode();
465     if (!relatedNode)
466         return;
467
468     EventRelatedNodeResolver resolver(*relatedNode);
469
470     size_t eventPathSize = m_path.size();
471     for (size_t i = 0; i < eventPathSize; i++)
472         toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(resolver.moveToParentOrShadowHost(*m_path[i]->node()));
473 }
474
475 bool EventPath::hasEventListeners(const AtomicString& eventType) const
476 {
477     for (size_t i = 0; i < m_path.size(); i++) {
478         if (m_path[i]->node()->hasEventListeners(eventType))
479             return true;
480     }
481
482     return false;
483 }
484
485 }