bc1de960c53612cf97fd5d7caa753f5b775c8360
[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 "ComposedShadowTreeWalker.h"
30 #include "ContainerNode.h"
31 #include "ElementShadow.h"
32 #include "EventContext.h"
33 #include "EventDispatchMediator.h"
34 #include "FrameView.h"
35 #include "HTMLMediaElement.h"
36 #include "InsertionPoint.h"
37 #include "InspectorInstrumentation.h"
38 #include "MouseEvent.h"
39 #include "ScopedEventQueue.h"
40 #include "ShadowRoot.h"
41 #include "WindowEventContext.h"
42 #include <wtf/RefPtr.h>
43 #include <wtf/UnusedParam.h>
44
45 #if ENABLE(SVG)
46 #include "SVGElementInstance.h"
47 #include "SVGNames.h"
48 #include "SVGUseElement.h"
49 #endif
50
51 namespace WebCore {
52
53 static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
54
55 EventRelatedTargetAdjuster::EventRelatedTargetAdjuster(PassRefPtr<Node> node, PassRefPtr<Node> relatedTarget)
56     : m_node(node)
57     , m_relatedTarget(relatedTarget)
58 {
59     ASSERT(m_node);
60     ASSERT(m_relatedTarget);
61 }
62
63 void EventRelatedTargetAdjuster::adjust(Vector<EventContext>& ancestors)
64 {
65     Vector<EventTarget*> relatedTargetStack;
66     TreeScope* lastTreeScope = 0;
67     Node* lastNode = 0;
68     for (ComposedShadowTreeParentWalker walker(m_relatedTarget.get()); walker.get(); walker.parentIncludingInsertionPointAndShadowRoot()) {
69         Node* node = walker.get();
70         if (relatedTargetStack.isEmpty())
71             relatedTargetStack.append(node);
72         else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(lastNode))
73             relatedTargetStack.append(relatedTargetStack.last());
74         TreeScope* scope = node->treeScope();
75         // Skips adding a node to the map if treeScope does not change. Just for the performance optimization.
76         if (scope != lastTreeScope)
77             m_relatedTargetMap.add(scope, relatedTargetStack.last());
78         lastTreeScope = scope;
79         lastNode = node;
80         if (node->isShadowRoot()) {
81             ASSERT(!relatedTargetStack.isEmpty());
82             relatedTargetStack.removeLast();
83         }
84     }
85
86     lastTreeScope = 0;
87     EventTarget* adjustedRelatedTarget = 0;
88     for (Vector<EventContext>::iterator iter = ancestors.begin(); iter < ancestors.end(); ++iter) {
89         TreeScope* scope = iter->node()->treeScope();
90         if (scope == lastTreeScope) {
91             // Re-use the previous adjustedRelatedTarget if treeScope does not change. Just for the performance optimization.
92             iter->setRelatedTarget(adjustedRelatedTarget);
93         } else {
94             adjustedRelatedTarget = findRelatedTarget(scope);
95             iter->setRelatedTarget(adjustedRelatedTarget);
96         }
97         lastTreeScope = scope;
98         if (iter->target() == adjustedRelatedTarget) {
99             // Event dispatching should be stopped here.
100             ancestors.shrink(iter - ancestors.begin());
101             break;
102         }
103     }
104 }
105
106 EventTarget* EventRelatedTargetAdjuster::findRelatedTarget(TreeScope* scope)
107 {
108     Vector<TreeScope*> parentTreeScopes;
109     EventTarget* relatedTarget = 0;
110     while (scope) {
111         parentTreeScopes.append(scope);
112         RelatedTargetMap::const_iterator found = m_relatedTargetMap.find(scope);
113         if (found != m_relatedTargetMap.end()) {
114             relatedTarget = found->second;
115             break;
116         }
117         scope = scope->parentTreeScope();
118     }
119     for (Vector<TreeScope*>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
120       m_relatedTargetMap.add(*iter, relatedTarget);
121     return relatedTarget;
122 }
123
124 bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
125 {
126     ASSERT(!eventDispatchForbidden());
127
128     EventDispatcher dispatcher(node);
129     return mediator->dispatchEvent(&dispatcher);
130 }
131
132 inline static EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
133 {
134     ASSERT(referenceNode);
135
136 #if ENABLE(SVG)
137     if (!referenceNode->isSVGElement() || !referenceNode->isInShadowTree())
138         return referenceNode;
139
140     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
141     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
142     Element* shadowHostElement = toShadowRoot(referenceNode->treeScope()->rootNode())->host();
143     // At this time, SVG nodes are not supported in non-<use> shadow trees.
144     if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag))
145         return referenceNode;
146     SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowHostElement);
147     if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(referenceNode))
148         return instance;
149 #endif
150
151     return referenceNode;
152 }
153
154 void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
155 {
156     // We need to set the target here because it can go away by the time we actually fire the event.
157     mediator->event()->setTarget(eventTargetRespectingSVGTargetRules(node));
158     ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator);
159 }
160
161 void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook)
162 {
163     if (node->disabled())
164         return;
165
166     EventDispatcher dispatcher(node);
167
168     if (!gNodesDispatchingSimulatedClicks)
169         gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
170     else if (gNodesDispatchingSimulatedClicks->contains(node))
171         return;
172
173     gNodesDispatchingSimulatedClicks->add(node);
174
175     // send mousedown and mouseup before the click, if requested
176     if (sendMouseEvents)
177         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));
178     node->setActive(true, showPressedLook);
179     if (sendMouseEvents)
180         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));
181     node->setActive(false);
182
183     // always send click
184     dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));
185
186     gNodesDispatchingSimulatedClicks->remove(node);
187 }
188
189 void EventDispatcher::adjustRelatedTarget(Event* event, PassRefPtr<EventTarget> prpRelatedTarget)
190 {
191     if (!prpRelatedTarget)
192         return;
193     RefPtr<Node> relatedTarget = prpRelatedTarget->toNode();
194     if (!relatedTarget)
195         return;
196     if (!m_node.get())
197         return;
198     ensureEventAncestors(event);
199     EventRelatedTargetAdjuster(m_node, relatedTarget.release()).adjust(m_ancestors);
200 }
201
202 EventDispatcher::EventDispatcher(Node* node)
203     : m_node(node)
204     , m_ancestorsInitialized(false)
205 #ifndef NDEBUG
206     , m_eventDispatched(false)
207 #endif
208 {
209     ASSERT(node);
210     m_view = node->document()->view();
211 }
212
213 void EventDispatcher::ensureEventAncestors(Event* event)
214 {
215     if (m_ancestorsInitialized)
216         return;
217     m_ancestorsInitialized = true;
218     bool inDocument = m_node->inDocument();
219     bool isSVGElement = m_node->isSVGElement();
220     Vector<EventTarget*> targetStack;
221     Node* last = 0;
222     for (ComposedShadowTreeParentWalker walker(m_node.get()); walker.get(); walker.parentIncludingInsertionPointAndShadowRoot()) {
223         Node* node = walker.get();
224         if (targetStack.isEmpty())
225             targetStack.append(eventTargetRespectingSVGTargetRules(node));
226         else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(last))
227             targetStack.append(targetStack.last());
228         m_ancestors.append(EventContext(node, eventTargetRespectingSVGTargetRules(node), targetStack.last()));
229         if (!inDocument)
230             return;
231         last = node;
232         if (!node->isShadowRoot())
233             continue;
234         if (determineDispatchBehavior(event, toShadowRoot(node), targetStack.last()) == StayInsideShadowDOM)
235             return;
236         if (!isSVGElement) {
237             ASSERT(!targetStack.isEmpty());
238             targetStack.removeLast();
239         }
240     }
241 }
242
243 bool EventDispatcher::dispatchEvent(PassRefPtr<Event> prpEvent)
244 {
245 #ifndef NDEBUG
246     ASSERT(!m_eventDispatched);
247     m_eventDispatched = true;
248 #endif
249     RefPtr<Event> event = prpEvent;
250     ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
251
252     event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
253     ASSERT(!eventDispatchForbidden());
254     ASSERT(event->target());
255     ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
256     ensureEventAncestors(event.get());
257     WindowEventContext windowEventContext(event.get(), m_node.get(), topEventContext());
258     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowEventContext.window(), m_node.get(), m_ancestors);
259
260     void* preDispatchEventHandlerResult;
261     if (dispatchEventPreProcess(event, preDispatchEventHandlerResult) == ContinueDispatching)
262         if (dispatchEventAtCapturing(event, windowEventContext) == ContinueDispatching)
263             if (dispatchEventAtTarget(event) == ContinueDispatching)
264                 dispatchEventAtBubbling(event, windowEventContext);
265     dispatchEventPostProcess(event, preDispatchEventHandlerResult);
266
267     // Ensure that after event dispatch, the event's target object is the
268     // outermost shadow DOM boundary.
269     event->setTarget(windowEventContext.target());
270     event->setCurrentTarget(0);
271     InspectorInstrumentation::didDispatchEvent(cookie);
272
273     return !event->defaultPrevented();
274 }
275
276 inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(PassRefPtr<Event> event, void*& preDispatchEventHandlerResult)
277 {
278     // Give the target node a chance to do some work before DOM event handlers get a crack.
279     preDispatchEventHandlerResult = m_node->preDispatchEventHandler(event.get());
280     return (m_ancestors.isEmpty() || event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
281 }
282
283 inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(PassRefPtr<Event> event, WindowEventContext& windowEventContext)
284 {
285     // Trigger capturing event handlers, starting at the top and working our way down.
286     event->setEventPhase(Event::CAPTURING_PHASE);
287
288     if (windowEventContext.handleLocalEvents(event.get()) && event->propagationStopped())
289         return DoneDispatching;
290
291     for (size_t i = m_ancestors.size() - 1; i > 0; --i) {
292         const EventContext& eventContext = m_ancestors[i];
293         if (eventContext.currentTargetSameAsTarget()) {
294             if (event->bubbles())
295                 continue;
296             event->setEventPhase(Event::AT_TARGET);
297         } else
298             event->setEventPhase(Event::CAPTURING_PHASE);
299         eventContext.handleLocalEvents(event.get());
300         if (event->propagationStopped())
301             return DoneDispatching;
302     }
303
304     return ContinueDispatching;
305 }
306
307 inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget(PassRefPtr<Event> event)
308 {
309     event->setEventPhase(Event::AT_TARGET);
310     m_ancestors[0].handleLocalEvents(event.get());
311     return event->propagationStopped() ? DoneDispatching : ContinueDispatching;
312 }
313
314 inline EventDispatchContinuation EventDispatcher::dispatchEventAtBubbling(PassRefPtr<Event> event, WindowEventContext& windowContext)
315 {
316     if (event->bubbles() && !event->cancelBubble()) {
317         // Trigger bubbling event handlers, starting at the bottom and working our way up.
318         event->setEventPhase(Event::BUBBLING_PHASE);
319
320         size_t size = m_ancestors.size();
321         for (size_t i = 1; i < size; ++i) {
322             const EventContext& eventContext = m_ancestors[i];
323             if (eventContext.currentTargetSameAsTarget())
324                 event->setEventPhase(Event::AT_TARGET);
325             else
326                 event->setEventPhase(Event::BUBBLING_PHASE);
327             eventContext.handleLocalEvents(event.get());
328             if (event->propagationStopped() || event->cancelBubble())
329                 return DoneDispatching;
330         }
331         windowContext.handleLocalEvents(event.get());
332     }
333     return ContinueDispatching;
334 }
335
336 inline void EventDispatcher::dispatchEventPostProcess(PassRefPtr<Event> event, void* preDispatchEventHandlerResult)
337 {
338     event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
339     event->setCurrentTarget(0);
340     event->setEventPhase(0);
341
342     // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
343     m_node->postDispatchEventHandler(event.get(), preDispatchEventHandlerResult);
344
345     // Call default event handlers. While the DOM does have a concept of preventing
346     // default handling, the detail of which handlers are called is an internal
347     // implementation detail and not part of the DOM.
348     if (!event->defaultPrevented() && !event->defaultHandled()) {
349         // Non-bubbling events call only one default event handler, the one for the target.
350         m_node->defaultEventHandler(event.get());
351         ASSERT(!event->defaultPrevented());
352         if (event->defaultHandled())
353             return;
354         // For bubbling events, call default event handlers on the same targets in the
355         // same order as the bubbling phase.
356         if (event->bubbles()) {
357             size_t size = m_ancestors.size();
358             for (size_t i = 1; i < size; ++i) {
359                 m_ancestors[i].node()->defaultEventHandler(event.get());
360                 ASSERT(!event->defaultPrevented());
361                 if (event->defaultHandled())
362                     return;
363             }
364         }
365     }
366 }
367
368 const EventContext* EventDispatcher::topEventContext()
369 {
370     return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
371 }
372
373 static inline bool inTheSameScope(ShadowRoot* shadowRoot, EventTarget* target)
374 {
375     return target->toNode() && target->toNode()->treeScope()->rootNode() == shadowRoot;
376 }
377
378 EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event, ShadowRoot* shadowRoot, EventTarget* target)
379 {
380 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
381     // Video-only full screen is a mode where we use the shadow DOM as an implementation
382     // detail that should not be detectable by the web content.
383     if (Element* element = m_node->document()->webkitCurrentFullScreenElement()) {
384         // FIXME: We assume that if the full screen element is a media element that it's
385         // the video-only full screen. Both here and elsewhere. But that is probably wrong.
386         if (element->isMediaElement() && shadowRoot && shadowRoot->host() == element)
387             return StayInsideShadowDOM;
388     }
389 #else
390     UNUSED_PARAM(shadowRoot);
391 #endif
392
393     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
394     // Changing this breaks existing sites.
395     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
396     const AtomicString eventType = event->type();
397     if (inTheSameScope(shadowRoot, target)
398         && (eventType == eventNames().abortEvent
399             || eventType == eventNames().changeEvent
400             || eventType == eventNames().resetEvent
401             || eventType == eventNames().resizeEvent
402             || eventType == eventNames().scrollEvent
403             || eventType == eventNames().selectEvent
404             || eventType == eventNames().selectstartEvent))
405         return StayInsideShadowDOM;
406
407     return RetargetEvent;
408 }
409
410 }