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) 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 "ContainerNode.h"
30#include "ElementShadow.h"
31#include "EventContext.h"
32#include "EventDispatchMediator.h"
33#include "EventPathWalker.h"
34#include "EventRetargeter.h"
35#include "FrameView.h"
36#include "HTMLMediaElement.h"
37#include "InsertionPoint.h"
38#include "InspectorInstrumentation.h"
39#include "MouseEvent.h"
40#include "ScopedEventQueue.h"
41#include "ShadowRoot.h"
42#include "WindowEventContext.h"
43#include <wtf/RefPtr.h>
44
45namespace WebCore {
46
47bool EventDispatcher::dispatchEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
48{
49    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
50    if (!mediator->event())
51        return true;
52    EventDispatcher dispatcher(node, mediator->event());
53    return mediator->dispatchEvent(&dispatcher);
54}
55
56EventDispatcher::EventDispatcher(Node* node, PassRefPtr<Event> event)
57    : m_node(node)
58    , m_event(event)
59#ifndef NDEBUG
60    , m_eventDispatched(false)
61#endif
62{
63    ASSERT(node);
64    ASSERT(m_event.get());
65    ASSERT(!m_event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
66    m_view = node->document()->view();
67    EventRetargeter::calculateEventPath(m_node.get(), m_event.get(), m_eventPath);
68}
69
70void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<EventDispatchMediator> mediator)
71{
72    // We need to set the target here because it can go away by the time we actually fire the event.
73    mediator->event()->setTarget(EventRetargeter::eventTargetRespectingTargetRules(node));
74    ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator);
75}
76
77void EventDispatcher::dispatchSimulatedClick(Element* element, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions, SimulatedClickVisualOptions visualOptions)
78{
79    if (element->isDisabledFormControl())
80        return;
81
82    DEFINE_STATIC_LOCAL(HashSet<Element*>, elementsDispatchingSimulatedClicks, ());
83    if (!elementsDispatchingSimulatedClicks.add(element).isNewEntry)
84        return;
85
86    if (mouseEventOptions == SendMouseOverUpDownEvents)
87        EventDispatcher(element, SimulatedMouseEvent::create(eventNames().mouseoverEvent, element->document()->defaultView(), underlyingEvent)).dispatch();
88
89    if (mouseEventOptions != SendNoEvents)
90        EventDispatcher(element, SimulatedMouseEvent::create(eventNames().mousedownEvent, element->document()->defaultView(), underlyingEvent)).dispatch();
91    element->setActive(true, visualOptions == ShowPressedLook);
92    if (mouseEventOptions != SendNoEvents)
93        EventDispatcher(element, SimulatedMouseEvent::create(eventNames().mouseupEvent, element->document()->defaultView(), underlyingEvent)).dispatch();
94    element->setActive(false);
95
96    // always send click
97    EventDispatcher(element, SimulatedMouseEvent::create(eventNames().clickEvent, element->document()->defaultView(), underlyingEvent)).dispatch();
98
99    elementsDispatchingSimulatedClicks.remove(element);
100}
101
102bool EventDispatcher::dispatch()
103{
104#ifndef NDEBUG
105    ASSERT(!m_eventDispatched);
106    m_eventDispatched = true;
107#endif
108    ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
109
110    m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));
111    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
112    ASSERT(m_event->target());
113    WindowEventContext windowEventContext(m_event.get(), m_node.get(), topEventContext());
114    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_eventPath);
115
116    void* preDispatchEventHandlerResult;
117    if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching)
118        if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching)
119            if (dispatchEventAtTarget() == ContinueDispatching)
120                dispatchEventAtBubbling(windowEventContext);
121    dispatchEventPostProcess(preDispatchEventHandlerResult);
122
123    // Ensure that after event dispatch, the event's target object is the
124    // outermost shadow DOM boundary.
125    m_event->setTarget(windowEventContext.target());
126    m_event->setCurrentTarget(0);
127    InspectorInstrumentation::didDispatchEvent(cookie);
128
129    return !m_event->defaultPrevented();
130}
131
132inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult)
133{
134    // Give the target node a chance to do some work before DOM event handlers get a crack.
135    preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get());
136    return (m_eventPath.isEmpty() || m_event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
137}
138
139inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(WindowEventContext& windowEventContext)
140{
141    // Trigger capturing event handlers, starting at the top and working our way down.
142    m_event->setEventPhase(Event::CAPTURING_PHASE);
143
144    if (windowEventContext.handleLocalEvents(m_event.get()) && m_event->propagationStopped())
145        return DoneDispatching;
146
147    for (size_t i = m_eventPath.size() - 1; i > 0; --i) {
148        const EventContext& eventContext = *m_eventPath[i];
149        if (eventContext.currentTargetSameAsTarget())
150            continue;
151        eventContext.handleLocalEvents(m_event.get());
152        if (m_event->propagationStopped())
153            return DoneDispatching;
154    }
155
156    return ContinueDispatching;
157}
158
159inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget()
160{
161    m_event->setEventPhase(Event::AT_TARGET);
162    m_eventPath[0]->handleLocalEvents(m_event.get());
163    return m_event->propagationStopped() ? DoneDispatching : ContinueDispatching;
164}
165
166inline void EventDispatcher::dispatchEventAtBubbling(WindowEventContext& windowContext)
167{
168    // Trigger bubbling event handlers, starting at the bottom and working our way up.
169    size_t size = m_eventPath.size();
170    for (size_t i = 1; i < size; ++i) {
171        const EventContext& eventContext = *m_eventPath[i];
172        if (eventContext.currentTargetSameAsTarget())
173            m_event->setEventPhase(Event::AT_TARGET);
174        else if (m_event->bubbles() && !m_event->cancelBubble())
175            m_event->setEventPhase(Event::BUBBLING_PHASE);
176        else
177            continue;
178        eventContext.handleLocalEvents(m_event.get());
179        if (m_event->propagationStopped())
180            return;
181    }
182    if (m_event->bubbles() && !m_event->cancelBubble()) {
183        m_event->setEventPhase(Event::BUBBLING_PHASE);
184        windowContext.handleLocalEvents(m_event.get());
185    }
186}
187
188inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult)
189{
190    m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));
191    m_event->setCurrentTarget(0);
192    m_event->setEventPhase(0);
193
194    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
195    m_node->postDispatchEventHandler(m_event.get(), preDispatchEventHandlerResult);
196
197    // Call default event handlers. While the DOM does have a concept of preventing
198    // default handling, the detail of which handlers are called is an internal
199    // implementation detail and not part of the DOM.
200    if (!m_event->defaultPrevented() && !m_event->defaultHandled()) {
201        // Non-bubbling events call only one default event handler, the one for the target.
202        m_node->defaultEventHandler(m_event.get());
203        ASSERT(!m_event->defaultPrevented());
204        if (m_event->defaultHandled())
205            return;
206        // For bubbling events, call default event handlers on the same targets in the
207        // same order as the bubbling phase.
208        if (m_event->bubbles()) {
209            size_t size = m_eventPath.size();
210            for (size_t i = 1; i < size; ++i) {
211                m_eventPath[i]->node()->defaultEventHandler(m_event.get());
212                ASSERT(!m_event->defaultPrevented());
213                if (m_event->defaultHandled())
214                    return;
215            }
216        }
217    }
218}
219
220const EventContext* EventDispatcher::topEventContext()
221{
222    return m_eventPath.isEmpty() ? 0 : m_eventPath.last().get();
223}
224
225}
226