Home | History | Annotate | Download | only in dom
      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 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 "Event.h"
     30 #include "EventContext.h"
     31 #include "EventTarget.h"
     32 #include "FrameView.h"
     33 #include "InspectorInstrumentation.h"
     34 #include "MouseEvent.h"
     35 #include "Node.h"
     36 #include "ScopedEventQueue.h"
     37 
     38 #if ENABLE(SVG)
     39 #include "SVGElementInstance.h"
     40 #include "SVGNames.h"
     41 #include "SVGUseElement.h"
     42 #endif
     43 
     44 #include "UIEvent.h"
     45 #include "UIEventWithKeyState.h"
     46 #include "WindowEventContext.h"
     47 
     48 #include <wtf/RefPtr.h>
     49 
     50 namespace WebCore {
     51 
     52 static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
     53 
     54 bool EventDispatcher::dispatchEvent(Node* node, const EventDispatchMediator& mediator)
     55 {
     56     ASSERT(!eventDispatchForbidden());
     57 
     58     EventDispatcher dispatcher(node);
     59     return mediator.dispatchEvent(&dispatcher);
     60 }
     61 
     62 static EventTarget* findElementInstance(Node* referenceNode)
     63 {
     64 #if ENABLE(SVG)
     65     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
     66     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
     67     for (Node* n = referenceNode; n; n = n->parentNode()) {
     68         if (!n->isSVGShadowRoot() || !n->isSVGElement())
     69             continue;
     70 
     71         Element* shadowTreeParentElement = n->svgShadowHost();
     72         ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));
     73 
     74         if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
     75             return instance;
     76     }
     77 #else
     78     // SVG elements with SVG disabled should not be possible.
     79     ASSERT_NOT_REACHED();
     80 #endif
     81 
     82     return referenceNode;
     83 }
     84 
     85 inline static EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
     86 {
     87     ASSERT(referenceNode);
     88 
     89     return referenceNode->isSVGElement() ? findElementInstance(referenceNode) : referenceNode;
     90 }
     91 
     92 void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<Event> event)
     93 {
     94     // We need to set the target here because it can go away by the time we actually fire the event.
     95     event->setTarget(eventTargetRespectingSVGTargetRules(node));
     96 
     97     ScopedEventQueue::instance()->enqueueEvent(event);
     98 }
     99 
    100 void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook)
    101 {
    102     if (node->disabled())
    103         return;
    104 
    105     EventDispatcher dispatcher(node);
    106 
    107     if (!gNodesDispatchingSimulatedClicks)
    108         gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
    109     else if (gNodesDispatchingSimulatedClicks->contains(node))
    110         return;
    111 
    112     gNodesDispatchingSimulatedClicks->add(node);
    113 
    114     // send mousedown and mouseup before the click, if requested
    115     if (sendMouseEvents)
    116         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));
    117     node->setActive(true, showPressedLook);
    118     if (sendMouseEvents)
    119         dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));
    120     node->setActive(false);
    121 
    122     // always send click
    123     dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));
    124 
    125     gNodesDispatchingSimulatedClicks->remove(node);
    126 }
    127 
    128 static inline bool isShadowRootOrSVGShadowRoot(const Node* node)
    129 {
    130     return node->isShadowRoot() || node->isSVGShadowRoot();
    131 }
    132 
    133 PassRefPtr<EventTarget> EventDispatcher::adjustToShadowBoundaries(PassRefPtr<Node> relatedTarget, const Vector<Node*> relatedTargetAncestors)
    134 {
    135     Vector<EventContext>::const_iterator lowestCommonBoundary = m_ancestors.end();
    136     // Assume divergent boundary is the relatedTarget itself (in other words, related target ancestor chain does not cross any shadow DOM boundaries).
    137     Vector<Node*>::const_iterator firstDivergentBoundary = relatedTargetAncestors.begin();
    138 
    139     Vector<EventContext>::const_iterator targetAncestor = m_ancestors.end();
    140     // Walk down from the top, looking for lowest common ancestor, also monitoring shadow DOM boundaries.
    141     bool diverged = false;
    142     for (Vector<Node*>::const_iterator i = relatedTargetAncestors.end() - 1; i >= relatedTargetAncestors.begin(); --i) {
    143         if (diverged) {
    144             if (isShadowRootOrSVGShadowRoot(*i)) {
    145                 firstDivergentBoundary = i + 1;
    146                 break;
    147             }
    148             continue;
    149         }
    150 
    151         if (targetAncestor == m_ancestors.begin()) {
    152             diverged = true;
    153             continue;
    154         }
    155 
    156         targetAncestor--;
    157 
    158         if (isShadowRootOrSVGShadowRoot(*i))
    159             lowestCommonBoundary = targetAncestor;
    160 
    161         if ((*i) != (*targetAncestor).node())
    162             diverged = true;
    163     }
    164 
    165     if (!diverged) {
    166         // The relatedTarget is an ancestor or shadowHost of the target.
    167         if (m_node->shadowHost() == relatedTarget.get())
    168             lowestCommonBoundary = m_ancestors.begin();
    169     } else if ((*firstDivergentBoundary) == m_node.get()) {
    170         // Since ancestors does not contain target itself, we must account
    171         // for the possibility that target is a shadowHost of relatedTarget
    172         // and thus serves as the lowestCommonBoundary.
    173         // Luckily, in this case the firstDivergentBoundary is target.
    174         lowestCommonBoundary = m_ancestors.begin();
    175     }
    176 
    177     // Trim ancestors to lowestCommonBoundary to keep events inside of the common shadow DOM subtree.
    178     if (lowestCommonBoundary != m_ancestors.end())
    179         m_ancestors.shrink(lowestCommonBoundary - m_ancestors.begin());
    180     // Set event's related target to the first encountered shadow DOM boundary in the divergent subtree.
    181     return firstDivergentBoundary != relatedTargetAncestors.begin() ? *firstDivergentBoundary : relatedTarget;
    182 }
    183 
    184 inline static bool ancestorsCrossShadowBoundaries(const Vector<EventContext>& ancestors)
    185 {
    186     return ancestors.isEmpty() || ancestors.first().node() == ancestors.last().node();
    187 }
    188 
    189 // FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
    190 // be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
    191 PassRefPtr<EventTarget> EventDispatcher::adjustRelatedTarget(Event* event, PassRefPtr<EventTarget> prpRelatedTarget)
    192 {
    193     if (!prpRelatedTarget)
    194         return 0;
    195 
    196     RefPtr<Node> relatedTarget = prpRelatedTarget->toNode();
    197     if (!relatedTarget)
    198         return 0;
    199 
    200     Node* target = m_node.get();
    201     if (!target)
    202         return prpRelatedTarget;
    203 
    204     ensureEventAncestors(event);
    205 
    206     // Calculate early if the common boundary is even possible by looking at
    207     // ancestors size and if the retargeting has occured (indicating the presence of shadow DOM boundaries).
    208     // If there are no boundaries detected, the target and related target can't have a common boundary.
    209     bool noCommonBoundary = ancestorsCrossShadowBoundaries(m_ancestors);
    210 
    211     Vector<Node*> relatedTargetAncestors;
    212     Node* outermostShadowBoundary = relatedTarget.get();
    213     for (Node* n = outermostShadowBoundary; n; n = n->parentOrHostNode()) {
    214         if (isShadowRootOrSVGShadowRoot(n))
    215             outermostShadowBoundary = n->parentOrHostNode();
    216         if (!noCommonBoundary)
    217             relatedTargetAncestors.append(n);
    218     }
    219 
    220     // Short-circuit the fast case when we know there is no need to calculate a common boundary.
    221     if (noCommonBoundary)
    222         return outermostShadowBoundary;
    223 
    224     return adjustToShadowBoundaries(relatedTarget.release(), relatedTargetAncestors);
    225 }
    226 
    227 EventDispatcher::EventDispatcher(Node* node)
    228     : m_node(node)
    229     , m_ancestorsInitialized(false)
    230 {
    231     ASSERT(node);
    232     m_view = node->document()->view();
    233 }
    234 
    235 void EventDispatcher::ensureEventAncestors(Event* event)
    236 {
    237     EventDispatchBehavior behavior = determineDispatchBehavior(event);
    238 
    239     if (!m_node->inDocument())
    240         return;
    241 
    242     if (m_ancestorsInitialized)
    243         return;
    244 
    245     m_ancestorsInitialized = true;
    246 
    247     Node* ancestor = m_node.get();
    248     EventTarget* target = eventTargetRespectingSVGTargetRules(ancestor);
    249     bool shouldSkipNextAncestor = false;
    250     while (true) {
    251         bool isSVGShadowRoot = ancestor->isSVGShadowRoot();
    252         if (isSVGShadowRoot || ancestor->isShadowRoot()) {
    253             if (behavior == StayInsideShadowDOM)
    254                 return;
    255 #if ENABLE(SVG)
    256             ancestor = isSVGShadowRoot ? ancestor->svgShadowHost() : ancestor->shadowHost();
    257 #else
    258             ancestor = ancestor->shadowHost();
    259 #endif
    260             if (!shouldSkipNextAncestor)
    261                 target = ancestor;
    262         } else
    263             ancestor = ancestor->parentNodeGuaranteedHostFree();
    264 
    265         if (!ancestor)
    266             return;
    267 
    268 #if ENABLE(SVG)
    269         // Skip SVGShadowTreeRootElement.
    270         shouldSkipNextAncestor = ancestor->isSVGShadowRoot();
    271         if (shouldSkipNextAncestor)
    272             continue;
    273 #endif
    274         // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
    275         m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
    276     }
    277 }
    278 
    279 bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
    280 {
    281     event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    282 
    283     ASSERT(!eventDispatchForbidden());
    284     ASSERT(event->target());
    285     ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
    286 
    287     RefPtr<EventTarget> originalTarget = event->target();
    288     ensureEventAncestors(event.get());
    289 
    290     WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
    291 
    292     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
    293 
    294     // Give the target node a chance to do some work before DOM event handlers get a crack.
    295     void* data = m_node->preDispatchEventHandler(event.get());
    296     if (event->propagationStopped())
    297         goto doneDispatching;
    298 
    299     // Trigger capturing event handlers, starting at the top and working our way down.
    300     event->setEventPhase(Event::CAPTURING_PHASE);
    301 
    302     if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
    303         goto doneDispatching;
    304 
    305     for (size_t i = m_ancestors.size(); i; --i) {
    306         m_ancestors[i - 1].handleLocalEvents(event.get());
    307         if (event->propagationStopped())
    308             goto doneDispatching;
    309     }
    310 
    311     event->setEventPhase(Event::AT_TARGET);
    312     event->setTarget(originalTarget.get());
    313     event->setCurrentTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    314     m_node->handleLocalEvents(event.get());
    315     if (event->propagationStopped())
    316         goto doneDispatching;
    317 
    318     if (event->bubbles() && !event->cancelBubble()) {
    319         // Trigger bubbling event handlers, starting at the bottom and working our way up.
    320         event->setEventPhase(Event::BUBBLING_PHASE);
    321 
    322         size_t size = m_ancestors.size();
    323         for (size_t i = 0; i < size; ++i) {
    324             m_ancestors[i].handleLocalEvents(event.get());
    325             if (event->propagationStopped() || event->cancelBubble())
    326                 goto doneDispatching;
    327         }
    328         windowContext.handleLocalEvents(event.get());
    329     }
    330 
    331 doneDispatching:
    332     event->setTarget(originalTarget.get());
    333     event->setCurrentTarget(0);
    334     event->setEventPhase(0);
    335 
    336     // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
    337     m_node->postDispatchEventHandler(event.get(), data);
    338 
    339     // Call default event handlers. While the DOM does have a concept of preventing
    340     // default handling, the detail of which handlers are called is an internal
    341     // implementation detail and not part of the DOM.
    342     if (!event->defaultPrevented() && !event->defaultHandled()) {
    343         // Non-bubbling events call only one default event handler, the one for the target.
    344         m_node->defaultEventHandler(event.get());
    345         ASSERT(!event->defaultPrevented());
    346         if (event->defaultHandled())
    347             goto doneWithDefault;
    348         // For bubbling events, call default event handlers on the same targets in the
    349         // same order as the bubbling phase.
    350         if (event->bubbles()) {
    351             size_t size = m_ancestors.size();
    352             for (size_t i = 0; i < size; ++i) {
    353                 m_ancestors[i].node()->defaultEventHandler(event.get());
    354                 ASSERT(!event->defaultPrevented());
    355                 if (event->defaultHandled())
    356                     goto doneWithDefault;
    357             }
    358         }
    359     }
    360 
    361 doneWithDefault:
    362 
    363     // Ensure that after event dispatch, the event's target object is the
    364     // outermost shadow DOM boundary.
    365     event->setTarget(windowContext.target());
    366     event->setCurrentTarget(0);
    367     InspectorInstrumentation::didDispatchEvent(cookie);
    368 
    369     return !event->defaultPrevented();
    370 }
    371 
    372 const EventContext* EventDispatcher::topEventContext()
    373 {
    374     return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
    375 }
    376 
    377 EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event)
    378 {
    379     // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
    380     // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
    381     if (event->isMutationEvent())
    382         return StayInsideShadowDOM;
    383 
    384     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
    385     // Changing this breaks existing sites.
    386     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
    387     if (event->type() == eventNames().selectstartEvent)
    388         return StayInsideShadowDOM;
    389 
    390     return RetargetEvent;
    391 }
    392 
    393 }
    394 
    395