1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) 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 "core/events/EventDispatcher.h" 28 29 #include "core/dom/ContainerNode.h" 30 #include "core/events/EventDispatchMediator.h" 31 #include "core/events/MouseEvent.h" 32 #include "core/events/ScopedEventQueue.h" 33 #include "core/events/WindowEventContext.h" 34 #include "core/frame/FrameView.h" 35 #include "core/inspector/InspectorInstrumentation.h" 36 #include "core/inspector/InspectorTraceEvents.h" 37 #include "platform/EventDispatchForbiddenScope.h" 38 #include "platform/TraceEvent.h" 39 #include "wtf/RefPtr.h" 40 41 namespace blink { 42 43 bool EventDispatcher::dispatchEvent(Node* node, PassRefPtrWillBeRawPtr<EventDispatchMediator> mediator) 44 { 45 TRACE_EVENT0("blink", "EventDispatcher::dispatchEvent"); 46 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); 47 if (!mediator->event()) 48 return true; 49 EventDispatcher dispatcher(node, mediator->event()); 50 return mediator->dispatchEvent(&dispatcher); 51 } 52 53 EventDispatcher::EventDispatcher(Node* node, PassRefPtrWillBeRawPtr<Event> event) 54 : m_node(node) 55 , m_event(event) 56 #if ENABLE(ASSERT) 57 , m_eventDispatched(false) 58 #endif 59 { 60 ASSERT(node); 61 ASSERT(m_event.get()); 62 ASSERT(!m_event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. 63 m_view = node->document().view(); 64 m_event->ensureEventPath().resetWith(m_node.get()); 65 } 66 67 void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtrWillBeRawPtr<EventDispatchMediator> mediator) 68 { 69 // We need to set the target here because it can go away by the time we actually fire the event. 70 mediator->event()->setTarget(EventPath::eventTargetRespectingTargetRules(node)); 71 ScopedEventQueue::instance()->enqueueEventDispatchMediator(mediator); 72 } 73 74 void EventDispatcher::dispatchSimulatedClick(Node* node, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions) 75 { 76 // This persistent vector doesn't cause leaks, because added Nodes are removed 77 // before dispatchSimulatedClick() returns. This vector is here just to prevent 78 // the code from running into an infinite recursion of dispatchSimulatedClick(). 79 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WillBeHeapHashSet<RawPtrWillBeMember<Node> > >, nodesDispatchingSimulatedClicks, (adoptPtrWillBeNoop(new WillBeHeapHashSet<RawPtrWillBeMember<Node> >()))); 80 81 if (isDisabledFormControl(node)) 82 return; 83 84 if (nodesDispatchingSimulatedClicks->contains(node)) 85 return; 86 87 nodesDispatchingSimulatedClicks->add(node); 88 89 if (mouseEventOptions == SendMouseOverUpDownEvents) 90 EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mouseover, node->document().domWindow(), underlyingEvent)).dispatch(); 91 92 if (mouseEventOptions != SendNoEvents) { 93 EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mousedown, node->document().domWindow(), underlyingEvent)).dispatch(); 94 node->setActive(true); 95 EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::mouseup, node->document().domWindow(), underlyingEvent)).dispatch(); 96 } 97 // Some elements (e.g. the color picker) may set active state to true before 98 // calling this method and expect the state to be reset during the call. 99 node->setActive(false); 100 101 // always send click 102 EventDispatcher(node, SimulatedMouseEvent::create(EventTypeNames::click, node->document().domWindow(), underlyingEvent)).dispatch(); 103 104 nodesDispatchingSimulatedClicks->remove(node); 105 } 106 107 bool EventDispatcher::dispatch() 108 { 109 TRACE_EVENT0("blink", "EventDispatcher::dispatch"); 110 111 #if ENABLE(ASSERT) 112 ASSERT(!m_eventDispatched); 113 m_eventDispatched = true; 114 #endif 115 116 m_event->setTarget(EventPath::eventTargetRespectingTargetRules(m_node.get())); 117 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); 118 ASSERT(m_event->target()); 119 WindowEventContext windowEventContext(m_event.get(), m_node.get(), topNodeEventContext()); 120 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch", "data", InspectorEventDispatchEvent::data(*m_event)); 121 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 122 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(&m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_event->eventPath()); 123 124 void* preDispatchEventHandlerResult; 125 if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching) 126 if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching) 127 if (dispatchEventAtTarget() == ContinueDispatching) 128 dispatchEventAtBubbling(windowEventContext); 129 dispatchEventPostProcess(preDispatchEventHandlerResult); 130 131 // Ensure that after event dispatch, the event's target object is the 132 // outermost shadow DOM boundary. 133 m_event->setTarget(windowEventContext.target()); 134 m_event->setCurrentTarget(0); 135 InspectorInstrumentation::didDispatchEvent(cookie); 136 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); 137 138 return !m_event->defaultPrevented(); 139 } 140 141 inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult) 142 { 143 // Give the target node a chance to do some work before DOM event handlers get a crack. 144 preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get()); 145 return (m_event->eventPath().isEmpty() || m_event->propagationStopped()) ? DoneDispatching : ContinueDispatching; 146 } 147 148 inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(WindowEventContext& windowEventContext) 149 { 150 // Trigger capturing event handlers, starting at the top and working our way down. 151 m_event->setEventPhase(Event::CAPTURING_PHASE); 152 153 if (windowEventContext.handleLocalEvents(m_event.get()) && m_event->propagationStopped()) 154 return DoneDispatching; 155 156 for (size_t i = m_event->eventPath().size() - 1; i > 0; --i) { 157 const NodeEventContext& eventContext = m_event->eventPath()[i]; 158 if (eventContext.currentTargetSameAsTarget()) 159 continue; 160 eventContext.handleLocalEvents(m_event.get()); 161 if (m_event->propagationStopped()) 162 return DoneDispatching; 163 } 164 165 return ContinueDispatching; 166 } 167 168 inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget() 169 { 170 m_event->setEventPhase(Event::AT_TARGET); 171 m_event->eventPath()[0].handleLocalEvents(m_event.get()); 172 return m_event->propagationStopped() ? DoneDispatching : ContinueDispatching; 173 } 174 175 inline void EventDispatcher::dispatchEventAtBubbling(WindowEventContext& windowContext) 176 { 177 // Trigger bubbling event handlers, starting at the bottom and working our way up. 178 size_t size = m_event->eventPath().size(); 179 for (size_t i = 1; i < size; ++i) { 180 const NodeEventContext& eventContext = m_event->eventPath()[i]; 181 if (eventContext.currentTargetSameAsTarget()) 182 m_event->setEventPhase(Event::AT_TARGET); 183 else if (m_event->bubbles() && !m_event->cancelBubble()) 184 m_event->setEventPhase(Event::BUBBLING_PHASE); 185 else 186 continue; 187 eventContext.handleLocalEvents(m_event.get()); 188 if (m_event->propagationStopped()) 189 return; 190 } 191 if (m_event->bubbles() && !m_event->cancelBubble()) { 192 m_event->setEventPhase(Event::BUBBLING_PHASE); 193 windowContext.handleLocalEvents(m_event.get()); 194 } 195 } 196 197 inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult) 198 { 199 m_event->setTarget(EventPath::eventTargetRespectingTargetRules(m_node.get())); 200 m_event->setCurrentTarget(0); 201 m_event->setEventPhase(0); 202 203 // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler. 204 m_node->postDispatchEventHandler(m_event.get(), preDispatchEventHandlerResult); 205 206 // Call default event handlers. While the DOM does have a concept of preventing 207 // default handling, the detail of which handlers are called is an internal 208 // implementation detail and not part of the DOM. 209 if (!m_event->defaultPrevented() && !m_event->defaultHandled()) { 210 // Non-bubbling events call only one default event handler, the one for the target. 211 m_node->willCallDefaultEventHandler(*m_event); 212 m_node->defaultEventHandler(m_event.get()); 213 ASSERT(!m_event->defaultPrevented()); 214 if (m_event->defaultHandled()) 215 return; 216 // For bubbling events, call default event handlers on the same targets in the 217 // same order as the bubbling phase. 218 if (m_event->bubbles()) { 219 size_t size = m_event->eventPath().size(); 220 for (size_t i = 1; i < size; ++i) { 221 m_event->eventPath()[i].node()->willCallDefaultEventHandler(*m_event); 222 m_event->eventPath()[i].node()->defaultEventHandler(m_event.get()); 223 ASSERT(!m_event->defaultPrevented()); 224 if (m_event->defaultHandled()) 225 return; 226 } 227 } 228 } 229 } 230 231 const NodeEventContext* EventDispatcher::topNodeEventContext() 232 { 233 return m_event->eventPath().isEmpty() ? 0 : &m_event->eventPath().last(); 234 } 235 236 } 237