Home | History | Annotate | Download | only in events
      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