Make EventDispatchMediator RefCounted.
[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 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) 2011 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 "FrameView.h"
31 #include "HTMLMediaElement.h"
32 #include "InspectorInstrumentation.h"
33 #include "MouseEvent.h"
34 #include "ScopedEventQueue.h"
35 #include "WindowEventContext.h"
36 #include <wtf/RefPtr.h>
37 #include <wtf/UnusedParam.h>
38
39 #if ENABLE(SVG)
40 #include "SVGElementInstance.h"
41 #include "SVGNames.h"
42 #include "SVGUseElement.h"
43 #endif
44
45 namespace WebCore {
46
47 static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
48
49 bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
50 {
51     ASSERT(!eventDispatchForbidden());
52
53     EventDispatcher dispatcher(node);
54     return mediator->dispatchEvent(&dispatcher);
55 }
56
57 static EventTarget* findElementInstance(Node* referenceNode)
58 {
59 #if ENABLE(SVG)
60     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
61     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
62     for (Node* n = referenceNode; n; n = n->parentNode()) {
63         if (!n->isSVGShadowRoot() || !n->isSVGElement())
64             continue;
65
66         Element* shadowTreeParentElement = n->svgShadowHost();
67         ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
68
69         if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
70             return instance;
71     }
72 #else
73     // SVG elements with SVG disabled should not be possible.
74     ASSERT_NOT_REACHED();
75 #endif
76
77     return referenceNode;
78 }
79
80 inline static EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
81 {
82     ASSERT(referenceNode);
83
84     return referenceNode->isSVGElement() ? findElementInstance(referenceNode) : referenceNode;
85 }
86
87 void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<Event> event)
88 {
89     // We need to set the target here because it can go away by the time we actually fire the event.
90     event->setTarget(eventTargetRespectingSVGTargetRules(node));
91
92     ScopedEventQueue::instance()->enqueueEvent(event);
93 }
94
95 void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook)
96 {
97     if (node->disabled())
98         return;
99
100     EventDispatcher dispatcher(node);
101
102     if (!gNodesDispatchingSimulatedClicks)
103         gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
104     else if (gNodesDispatchingSimulatedClicks->contains(node))
105         return;
106
107     gNodesDispatchingSimulatedClicks->add(node);
108
109     // send mousedown and mouseup before the click, if requested
110     if (sendMouseEvents)
111         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));
112     node->setActive(true, showPressedLook);
113     if (sendMouseEvents)
114         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));
115     node->setActive(false);
116
117     // always send click
118     dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));
119
120     gNodesDispatchingSimulatedClicks->remove(node);
121 }
122
123 static inline bool isShadowRootOrSVGShadowRoot(const Node* node)
124 {
125     return node->isShadowRoot() || node->isSVGShadowRoot();
126 }
127
128 static inline bool isShadowHost(Node* node)
129 {
130     return node->isElementNode() && toElement(node)->shadowRoot();
131 }
132
133 PassRefPtr<EventTarget> EventDispatcher::adjustToShadowBoundaries(PassRefPtr<Node> relatedTarget, const Vector<Node*> relatedTargetAncestors)
134 {
135     Vector<EventContext>::const_iterator lowestCommonBoundary = m_ancestors.end();
136     // Assume divergent boundary is the relatedTarget itself (in other words, related target ancestor chain does not cross any shadow DOM boundaries).
137     Vector<Node*>::const_iterator firstDivergentBoundary = relatedTargetAncestors.begin();
138
139     Vector<EventContext>::const_iterator targetAncestor = m_ancestors.end();
140     // Walk down from the top, looking for lowest common ancestor, also monitoring shadow DOM boundaries.
141     bool diverged = false;
142     for (Vector<Node*>::const_iterator i = relatedTargetAncestors.end() - 1; i >= relatedTargetAncestors.begin(); --i) {
143         if (diverged) {
144             if (isShadowRootOrSVGShadowRoot(*i)) {
145                 firstDivergentBoundary = i + 1;
146                 break;
147             }
148             continue;
149         }
150
151         if (targetAncestor == m_ancestors.begin()) {
152             diverged = true;
153             continue;
154         }
155
156         targetAncestor--;
157
158         if (isShadowRootOrSVGShadowRoot(*i))
159             lowestCommonBoundary = targetAncestor;
160
161         if ((*i) != (*targetAncestor).node())
162             diverged = true;
163     }
164
165     if (!diverged) {
166         // The relatedTarget is an ancestor or shadowHost of the target.
167         // FIXME: Remove the first check once conversion to new shadow DOM is complete <http://webkit.org/b/48698>
168         if (m_node->shadowHost() == relatedTarget.get() || isShadowHost(relatedTarget.get()))
169             lowestCommonBoundary = m_ancestors.begin();
170     } else if ((*firstDivergentBoundary) == m_node.get()) {
171         // Since ancestors does not contain target itself, we must account
172         // for the possibility that target is a shadowHost of relatedTarget
173         // and thus serves as the lowestCommonBoundary.
174         // Luckily, in this case the firstDivergentBoundary is target.
175         lowestCommonBoundary = m_ancestors.begin();
176     }
177
178     if (lowestCommonBoundary != m_ancestors.end()) {
179         // Trim ancestors to lowestCommonBoundary to keep events inside of the common shadow DOM subtree.
180         m_ancestors.shrink(lowestCommonBoundary - m_ancestors.begin());
181         m_shouldPreventDispatch = !m_ancestors.size();
182     }
183     // Set event's related target to the first encountered shadow DOM boundary in the divergent subtree.
184     return firstDivergentBoundary != relatedTargetAncestors.begin() ? *firstDivergentBoundary : relatedTarget;
185 }
186
187 inline static bool ancestorsCrossShadowBoundaries(const Vector<EventContext>& ancestors)
188 {
189     return ancestors.isEmpty() || ancestors.first().node() == ancestors.last().node();
190 }
191
192 // FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
193 // be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
194 PassRefPtr<EventTarget> EventDispatcher::adjustRelatedTarget(Event* event, PassRefPtr<EventTarget> prpRelatedTarget)
195 {
196     if (!prpRelatedTarget)
197         return 0;
198
199     RefPtr<Node> relatedTarget = prpRelatedTarget->toNode();
200     if (!relatedTarget)
201         return 0;
202
203     Node* target = m_node.get();
204     if (!target)
205         return prpRelatedTarget;
206
207     ensureEventAncestors(event);
208
209     // Calculate early if the common boundary is even possible by looking at
210     // ancestors size and if the retargeting has occured (indicating the presence of shadow DOM boundaries).
211     // If there are no boundaries detected, the target and related target can't have a common boundary.
212     bool noCommonBoundary = ancestorsCrossShadowBoundaries(m_ancestors);
213
214     Vector<Node*> relatedTargetAncestors;
215     Node* outermostShadowBoundary = relatedTarget.get();
216     for (Node* n = outermostShadowBoundary; n; n = n->parentOrHostNode()) {
217         if (isShadowRootOrSVGShadowRoot(n))
218             outermostShadowBoundary = n->parentOrHostNode();
219         if (!noCommonBoundary)
220             relatedTargetAncestors.append(n);
221     }
222
223     // Short-circuit the fast case when we know there is no need to calculate a common boundary.
224     if (noCommonBoundary)
225         return outermostShadowBoundary;
226
227     return adjustToShadowBoundaries(relatedTarget.release(), relatedTargetAncestors);
228 }
229
230 EventDispatcher::EventDispatcher(Node* node)
231     : m_node(node)
232     , m_ancestorsInitialized(false)
233     , m_shouldPreventDispatch(false)
234 {
235     ASSERT(node);
236     m_view = node->document()->view();
237 }
238
239 void EventDispatcher::ensureEventAncestors(Event* event)
240 {
241     if (!m_node->inDocument())
242         return;
243
244     if (m_ancestorsInitialized)
245         return;
246
247     m_ancestorsInitialized = true;
248
249     Node* ancestor = m_node.get();
250     EventTarget* target = eventTargetRespectingSVGTargetRules(ancestor);
251     bool shouldSkipNextAncestor = false;
252     while (true) {
253         bool isSVGShadowRoot = ancestor->isSVGShadowRoot();
254         if (isSVGShadowRoot || ancestor->isShadowRoot()) {
255             if (determineDispatchBehavior(event, ancestor) == StayInsideShadowDOM)
256                 return;
257 #if ENABLE(SVG)
258             ancestor = isSVGShadowRoot ? ancestor->svgShadowHost() : ancestor->shadowHost();
259 #else
260             ancestor = ancestor->shadowHost();
261 #endif
262             if (!shouldSkipNextAncestor)
263                 target = ancestor;
264         } else
265             ancestor = ancestor->parentNodeGuaranteedHostFree();
266
267         if (!ancestor)
268             return;
269
270 #if ENABLE(SVG)
271         // Skip SVGShadowTreeRootElement.
272         shouldSkipNextAncestor = ancestor->isSVGShadowRoot();
273         if (shouldSkipNextAncestor)
274             continue;
275 #endif
276         // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
277         m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
278     }
279 }
280
281 bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
282 {
283     event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
284
285     ASSERT(!eventDispatchForbidden());
286     ASSERT(event->target());
287     ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
288
289     RefPtr<EventTarget> originalTarget = event->target();
290     ensureEventAncestors(event.get());
291
292     WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
293
294     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
295
296     // Give the target node a chance to do some work before DOM event handlers get a crack.
297     void* data = m_node->preDispatchEventHandler(event.get());
298     if (m_shouldPreventDispatch || event->propagationStopped())
299         goto doneDispatching;
300
301     // Trigger capturing event handlers, starting at the top and working our way down.
302     event->setEventPhase(Event::CAPTURING_PHASE);
303
304     if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
305         goto doneDispatching;
306
307     for (size_t i = m_ancestors.size(); i; --i) {
308         m_ancestors[i - 1].handleLocalEvents(event.get());
309         if (event->propagationStopped())
310             goto doneDispatching;
311     }
312
313     event->setEventPhase(Event::AT_TARGET);
314     event->setTarget(originalTarget.get());
315     event->setCurrentTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
316     m_node->handleLocalEvents(event.get());
317     if (event->propagationStopped())
318         goto doneDispatching;
319
320     if (event->bubbles() && !event->cancelBubble()) {
321         // Trigger bubbling event handlers, starting at the bottom and working our way up.
322         event->setEventPhase(Event::BUBBLING_PHASE);
323
324         size_t size = m_ancestors.size();
325         for (size_t i = 0; i < size; ++i) {
326             m_ancestors[i].handleLocalEvents(event.get());
327             if (event->propagationStopped() || event->cancelBubble())
328                 goto doneDispatching;
329         }
330         windowContext.handleLocalEvents(event.get());
331     }
332
333 doneDispatching:
334     event->setTarget(originalTarget.get());
335     event->setCurrentTarget(0);
336     event->setEventPhase(0);
337
338     // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
339     m_node->postDispatchEventHandler(event.get(), data);
340
341     // Call default event handlers. While the DOM does have a concept of preventing
342     // default handling, the detail of which handlers are called is an internal
343     // implementation detail and not part of the DOM.
344     if (!event->defaultPrevented() && !event->defaultHandled()) {
345         // Non-bubbling events call only one default event handler, the one for the target.
346         m_node->defaultEventHandler(event.get());
347         ASSERT(!event->defaultPrevented());
348         if (event->defaultHandled())
349             goto doneWithDefault;
350         // For bubbling events, call default event handlers on the same targets in the
351         // same order as the bubbling phase.
352         if (event->bubbles()) {
353             size_t size = m_ancestors.size();
354             for (size_t i = 0; i < size; ++i) {
355                 m_ancestors[i].node()->defaultEventHandler(event.get());
356                 ASSERT(!event->defaultPrevented());
357                 if (event->defaultHandled())
358                     goto doneWithDefault;
359             }
360         }
361     }
362
363 doneWithDefault:
364
365     // Ensure that after event dispatch, the event's target object is the
366     // outermost shadow DOM boundary.
367     event->setTarget(windowContext.target());
368     event->setCurrentTarget(0);
369     InspectorInstrumentation::didDispatchEvent(cookie);
370
371     return !event->defaultPrevented();
372 }
373
374 const EventContext* EventDispatcher::topEventContext()
375 {
376     return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
377 }
378
379 EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event, Node* shadowRoot)
380 {
381 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
382     // Video-only full screen is a mode where we use the shadow DOM as an implementation
383     // detail that should not be detectable by the web content.
384     if (Element* element = m_node->document()->webkitCurrentFullScreenElement()) {
385         // FIXME: We assume that if the full screen element is a media element that it's
386         // the video-only full screen. Both here and elsewhere. But that is probably wrong.
387         if (element->isMediaElement() && shadowRoot && shadowRoot->shadowHost() == element)
388             return StayInsideShadowDOM;
389     }
390 #else
391     UNUSED_PARAM(shadowRoot);
392 #endif
393
394     // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
395     // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
396     if (event->isMutationEvent())
397         return StayInsideShadowDOM;
398
399     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
400     // Changing this breaks existing sites.
401     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
402     if (event->type() == eventNames().selectstartEvent)
403         return StayInsideShadowDOM;
404
405     return RetargetEvent;
406 }
407
408 }