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