Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / events / EventPath.cpp
index 7799a86..b976427 100644 (file)
 #include "config.h"
 #include "core/events/EventPath.h"
 
-#include "EventNames.h"
-#include "RuntimeEnabledFeatures.h"
-#include "SVGNames.h"
-#include "core/dom/FullscreenElementStack.h"
+#include "core/EventNames.h"
+#include "core/dom/Document.h"
 #include "core/dom/Touch.h"
 #include "core/dom/TouchList.h"
 #include "core/dom/shadow/InsertionPoint.h"
 #include "core/dom/shadow/ShadowRoot.h"
-#include "core/events/FocusEvent.h"
-#include "core/events/MouseEvent.h"
 #include "core/events/TouchEvent.h"
 #include "core/events/TouchEventContext.h"
-#include "core/svg/SVGElementInstance.h"
-#include "core/svg/SVGUseElement.h"
 
-namespace WebCore {
-
-Node* EventPath::parent(Node* node)
-{
-    EventPath eventPath(node);
-    return eventPath.size() > 1 ? eventPath[1].node() : 0;
-}
+namespace blink {
 
 EventTarget* EventPath::eventTargetRespectingTargetRules(Node* referenceNode)
 {
@@ -57,44 +45,16 @@ EventTarget* EventPath::eventTargetRespectingTargetRules(Node* referenceNode)
     if (referenceNode->isPseudoElement())
         return referenceNode->parentNode();
 
-    if (!referenceNode->isSVGElement() || !referenceNode->isInShadowTree())
-        return referenceNode;
-
-    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
-    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects.
-    Node& rootNode = referenceNode->treeScope().rootNode();
-    Element* shadowHostElement = rootNode.isShadowRoot() ? toShadowRoot(rootNode).host() : 0;
-    // At this time, SVG nodes are not supported in non-<use> shadow trees.
-    if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag))
-        return referenceNode;
-    SVGUseElement* useElement = toSVGUseElement(shadowHostElement);
-    if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(referenceNode))
-        return instance;
-
     return referenceNode;
 }
 
-static inline bool inTheSameScope(ShadowRoot* shadowRoot, EventTarget* target)
-{
-    return target->toNode() && target->toNode()->treeScope().rootNode() == shadowRoot;
-}
-
-static inline EventDispatchBehavior determineDispatchBehavior(Event* event, ShadowRoot* shadowRoot, EventTarget* target)
+static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
 {
-    // Video-only full screen is a mode where we use the shadow DOM as an implementation
-    // detail that should not be detectable by the web content.
-    if (Element* element = FullscreenElementStack::currentFullScreenElementFrom(&target->toNode()->document())) {
-        // FIXME: We assume that if the full screen element is a media element that it's
-        // the video-only full screen. Both here and elsewhere. But that is probably wrong.
-        if (element->isMediaElement() && shadowRoot && shadowRoot->host() == element)
-            return StayInsideShadowDOM;
-    }
-
     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
     // Changing this breaks existing sites.
     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
-    const AtomicString eventType = event->type();
-    if (inTheSameScope(shadowRoot, target)
+    const AtomicString eventType = event.type();
+    return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host()
         && (eventType == EventTypeNames::abort
             || eventType == EventTypeNames::change
             || eventType == EventTypeNames::error
@@ -103,21 +63,18 @@ static inline EventDispatchBehavior determineDispatchBehavior(Event* event, Shad
             || eventType == EventTypeNames::resize
             || eventType == EventTypeNames::scroll
             || eventType == EventTypeNames::select
-            || eventType == EventTypeNames::selectstart))
-        return StayInsideShadowDOM;
-
-    return RetargetEvent;
+            || eventType == EventTypeNames::selectstart);
 }
 
 EventPath::EventPath(Event* event)
-    : m_node(0)
+    : m_node(nullptr)
     , m_event(event)
 {
 }
 
 EventPath::EventPath(Node* node)
     : m_node(node)
-    , m_event(0)
+    , m_event(nullptr)
 {
     resetWith(node);
 }
@@ -130,7 +87,7 @@ void EventPath::resetWith(Node* node)
     m_treeScopeEventContexts.clear();
     calculatePath();
     calculateAdjustedTargets();
-    calculateAdjustedEventPath();
+    calculateTreeScopePrePostOrderNumbers();
 }
 
 void EventPath::addNodeEventContext(Node* node)
@@ -142,20 +99,19 @@ void EventPath::calculatePath()
 {
     ASSERT(m_node);
     ASSERT(m_nodeEventContexts.isEmpty());
-    m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node));
+    m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node.get()));
 
     Node* current = m_node;
     addNodeEventContext(current);
     if (!m_node->inDocument())
         return;
     while (current) {
-        if (current->isShadowRoot() && m_event && determineDispatchBehavior(m_event, toShadowRoot(current), m_node) == StayInsideShadowDOM)
+        if (m_event && current->keepEventInNode(m_event))
             break;
-        Vector<InsertionPoint*, 8> insertionPoints;
+        WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
         collectDestinationInsertionPoints(*current, insertionPoints);
         if (!insertionPoints.isEmpty()) {
-            for (size_t i = 0; i < insertionPoints.size(); ++i) {
-                InsertionPoint* insertionPoint = insertionPoints[i];
+            for (const auto& insertionPoint : insertionPoints) {
                 if (insertionPoint->isShadowInsertionPoint()) {
                     ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
                     ASSERT(containingShadowRoot);
@@ -168,6 +124,8 @@ void EventPath::calculatePath()
             continue;
         }
         if (current->isShadowRoot()) {
+            if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(current), *m_node))
+                break;
             current = current->shadowHost();
             addNodeEventContext(current);
         } else {
@@ -178,29 +136,45 @@ void EventPath::calculatePath()
     }
 }
 
-void EventPath::calculateAdjustedEventPath()
+void EventPath::calculateTreeScopePrePostOrderNumbers()
 {
-    if (!RuntimeEnabledFeatures::shadowDOMEnabled())
-        return;
-    for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
-        TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get();
-        Vector<RefPtr<Node> > nodes;
-        nodes.reserveInitialCapacity(size());
-        for (size_t i = 0; i < size(); ++i) {
-            if (at(i).node()->treeScope().isInclusiveAncestorOf(treeScopeEventContext->treeScope()))
-                nodes.append(at(i).node());
+    // Precondition:
+    //   - TreeScopes in m_treeScopeEventContexts must be *connected* in the same tree of trees.
+    //   - The root tree must be included.
+    WillBeHeapHashMap<RawPtrWillBeMember<const TreeScope>, RawPtrWillBeMember<TreeScopeEventContext>> treeScopeEventContextMap;
+    for (const auto& treeScopeEventContext : m_treeScopeEventContexts)
+        treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext.get());
+    TreeScopeEventContext* rootTree = 0;
+    for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
+        // Use olderShadowRootOrParentTreeScope here for parent-child relationships.
+        // See the definition of trees of trees in the Shado DOM spec: http://w3c.github.io/webcomponents/spec/shadow/
+        TreeScope* parent = treeScopeEventContext.get()->treeScope().olderShadowRootOrParentTreeScope();
+        if (!parent) {
+            ASSERT(!rootTree);
+            rootTree = treeScopeEventContext.get();
+            continue;
         }
-        treeScopeEventContext->adoptEventPath(nodes);
+        ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap.end());
+        treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventContext.get());
     }
+    ASSERT(rootTree);
+    rootTree->calculatePrePostOrderNumber(0);
 }
 
 TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarget, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap)
 {
     if (!treeScope)
         return 0;
-    TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(treeScope, TreeScopeEventContext::create(*treeScope));
-    TreeScopeEventContext* treeScopeEventContext = addResult.iterator->value.get();
-    if (addResult.isNewEntry) {
+    TreeScopeEventContext* treeScopeEventContext;
+    bool isNewEntry;
+    {
+        TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(treeScope, nullptr);
+        isNewEntry = addResult.isNewEntry;
+        if (isNewEntry)
+            addResult.storedValue->value = TreeScopeEventContext::create(*treeScope);
+        treeScopeEventContext = addResult.storedValue->value.get();
+    }
+    if (isNewEntry) {
         TreeScopeEventContext* parentTreeScopeEventContext = ensureTreeScopeEventContext(0, treeScope->olderShadowRootOrParentTreeScope(), treeScopeEventContextMap);
         if (parentTreeScopeEventContext && parentTreeScopeEventContext->target()) {
             treeScopeEventContext->setTarget(parentTreeScopeEventContext->target());
@@ -216,7 +190,6 @@ TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarge
 void EventPath::calculateAdjustedTargets()
 {
     const TreeScope* lastTreeScope = 0;
-    bool isSVGElement = at(0).node()->isSVGElement();
 
     TreeScopeEventContextMap treeScopeEventContextMap;
     TreeScopeEventContext* lastTreeScopeEventContext = 0;
@@ -225,16 +198,7 @@ void EventPath::calculateAdjustedTargets()
         Node* currentNode = at(i).node();
         TreeScope& currentTreeScope = currentNode->treeScope();
         if (lastTreeScope != &currentTreeScope) {
-            if (!isSVGElement) {
-                lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode, &currentTreeScope, treeScopeEventContextMap);
-            } else {
-                TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(&currentTreeScope, TreeScopeEventContext::create(currentTreeScope));
-                lastTreeScopeEventContext = addResult.iterator->value.get();
-                if (addResult.isNewEntry) {
-                    // Don't adjust an event target for SVG.
-                    lastTreeScopeEventContext->setTarget(eventTargetRespectingTargetRules(at(0).node()));
-                }
-            }
+            lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode, &currentTreeScope, treeScopeEventContextMap);
         }
         ASSERT(lastTreeScopeEventContext);
         at(i).setTreeScopeEventContext(lastTreeScopeEventContext);
@@ -245,30 +209,28 @@ void EventPath::calculateAdjustedTargets()
 
 void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& relatedTargetMap)
 {
-    TreeScope* lastTreeScope = 0;
-    EventPath eventPath(const_cast<Node*>(relatedNode));
-    for (size_t i = 0; i < eventPath.size(); ++i) {
-        TreeScope* treeScope = &eventPath[i].node()->treeScope();
-        if (treeScope != lastTreeScope)
-            relatedTargetMap.add(treeScope, eventPath[i].target());
-        lastTreeScope = treeScope;
+    EventPath relatedTargetEventPath(const_cast<Node*>(relatedNode));
+    for (size_t i = 0; i < relatedTargetEventPath.m_treeScopeEventContexts.size(); ++i) {
+        TreeScopeEventContext* treeScopeEventContext = relatedTargetEventPath.m_treeScopeEventContexts[i].get();
+        relatedTargetMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext->target());
     }
 }
 
 EventTarget* EventPath::findRelatedNode(TreeScope* scope, RelatedTargetMap& relatedTargetMap)
 {
-    Vector<TreeScope*, 32> parentTreeScopes;
+    WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32> parentTreeScopes;
     EventTarget* relatedNode = 0;
     while (scope) {
         parentTreeScopes.append(scope);
-        RelatedTargetMap::const_iterator found = relatedTargetMap.find(scope);
-        if (found != relatedTargetMap.end()) {
-            relatedNode = found->value;
+        RelatedTargetMap::const_iterator iter = relatedTargetMap.find(scope);
+        if (iter != relatedTargetMap.end() && iter->value) {
+            relatedNode = iter->value;
             break;
         }
         scope = scope->olderShadowRootOrParentTreeScope();
     }
-    for (Vector<TreeScope*, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
+    ASSERT(relatedNode);
+    for (WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
         relatedTargetMap.add(*iter, relatedNode);
     return relatedNode;
 }
@@ -282,12 +244,18 @@ void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget)
     Node* relatedNode = relatedTarget->toNode();
     if (!relatedNode)
         return;
+    if (target->document() != relatedNode->document())
+        return;
+    if (!target->inDocument() || !relatedNode->inDocument())
+        return;
+
     RelatedTargetMap relatedNodeMap;
     buildRelatedNodeMap(relatedNode, relatedNodeMap);
 
-    for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
-        TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get();
-        treeScopeEventContext->setRelatedTarget(findRelatedNode(&treeScopeEventContext->treeScope(), relatedNodeMap));
+    for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
+        EventTarget* adjustedRelatedTarget = findRelatedNode(&treeScopeEventContext.get()->treeScope(), relatedNodeMap);
+        ASSERT(adjustedRelatedTarget);
+        treeScopeEventContext.get()->setRelatedTarget(adjustedRelatedTarget);
     }
 
     shrinkIfNeeded(target, relatedTarget);
@@ -314,27 +282,27 @@ void EventPath::shrinkIfNeeded(const Node* target, const EventTarget* relatedTar
 
 void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
 {
-    Vector<TouchList*> adjustedTouches;
-    Vector<TouchList*> adjustedTargetTouches;
-    Vector<TouchList*> adjustedChangedTouches;
-    Vector<TreeScope*> treeScopes;
+    WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTouches;
+    WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTargetTouches;
+    WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedChangedTouches;
+    WillBeHeapVector<RawPtrWillBeMember<TreeScope>> treeScopes;
 
-    for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
-        TouchEventContext* touchEventContext = m_treeScopeEventContexts[i]->ensureTouchEventContext();
+    for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
+        TouchEventContext* touchEventContext = treeScopeEventContext->ensureTouchEventContext();
         adjustedTouches.append(&touchEventContext->touches());
         adjustedTargetTouches.append(&touchEventContext->targetTouches());
         adjustedChangedTouches.append(&touchEventContext->changedTouches());
-        treeScopes.append(&m_treeScopeEventContexts[i]->treeScope());
+        treeScopes.append(&treeScopeEventContext->treeScope());
     }
 
     adjustTouchList(node, touchEvent.touches(), adjustedTouches, treeScopes);
     adjustTouchList(node, touchEvent.targetTouches(), adjustedTargetTouches, treeScopes);
     adjustTouchList(node, touchEvent.changedTouches(), adjustedChangedTouches, treeScopes);
 
-#ifndef NDEBUG
-    for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
-        TreeScope& treeScope = m_treeScopeEventContexts[i]->treeScope();
-        TouchEventContext* touchEventContext = m_treeScopeEventContexts[i]->touchEventContext();
+#if ENABLE(ASSERT)
+    for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
+        TreeScope& treeScope = treeScopeEventContext->treeScope();
+        TouchEventContext* touchEventContext = treeScopeEventContext->touchEventContext();
         checkReachability(treeScope, touchEventContext->touches());
         checkReachability(treeScope, touchEventContext->targetTouches());
         checkReachability(treeScope, touchEventContext->changedTouches());
@@ -342,7 +310,7 @@ void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
 #endif
 }
 
-void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, Vector<TouchList*> adjustedTouchList, const Vector<TreeScope*>& treeScopes)
+void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTouchList, const WillBeHeapVector<RawPtrWillBeMember<TreeScope>>& treeScopes)
 {
     if (!touchList)
         return;
@@ -356,7 +324,7 @@ void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, Ve
     }
 }
 
-#ifndef NDEBUG
+#if ENABLE(ASSERT)
 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
 {
     for (size_t i = 0; i < touchList.length(); ++i)
@@ -364,4 +332,12 @@ void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
 }
 #endif
 
+void EventPath::trace(Visitor* visitor)
+{
+    visitor->trace(m_nodeEventContexts);
+    visitor->trace(m_node);
+    visitor->trace(m_event);
+    visitor->trace(m_treeScopeEventContexts);
+}
+
 } // namespace