Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / events / EventPath.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Neither the name of Google Inc. nor the names of its
11  * contributors may be used to endorse or promote products derived from
12  * this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "core/events/EventPath.h"
29
30 #include "core/EventNames.h"
31 #include "core/dom/Document.h"
32 #include "core/dom/Touch.h"
33 #include "core/dom/TouchList.h"
34 #include "core/dom/shadow/InsertionPoint.h"
35 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/events/TouchEvent.h"
37 #include "core/events/TouchEventContext.h"
38
39 namespace blink {
40
41 EventTarget* EventPath::eventTargetRespectingTargetRules(Node* referenceNode)
42 {
43     ASSERT(referenceNode);
44
45     if (referenceNode->isPseudoElement())
46         return referenceNode->parentNode();
47
48     return referenceNode;
49 }
50
51 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
52 {
53     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
54     // Changing this breaks existing sites.
55     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
56     const AtomicString eventType = event.type();
57     return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host()
58         && (eventType == EventTypeNames::abort
59             || eventType == EventTypeNames::change
60             || eventType == EventTypeNames::error
61             || eventType == EventTypeNames::load
62             || eventType == EventTypeNames::reset
63             || eventType == EventTypeNames::resize
64             || eventType == EventTypeNames::scroll
65             || eventType == EventTypeNames::select
66             || eventType == EventTypeNames::selectstart);
67 }
68
69 EventPath::EventPath(Event* event)
70     : m_node(nullptr)
71     , m_event(event)
72 {
73 }
74
75 EventPath::EventPath(Node* node)
76     : m_node(node)
77     , m_event(nullptr)
78 {
79     resetWith(node);
80 }
81
82 void EventPath::resetWith(Node* node)
83 {
84     ASSERT(node);
85     m_node = node;
86     m_nodeEventContexts.clear();
87     m_treeScopeEventContexts.clear();
88     calculatePath();
89     calculateAdjustedTargets();
90     calculateTreeScopePrePostOrderNumbers();
91 }
92
93 void EventPath::addNodeEventContext(Node* node)
94 {
95     m_nodeEventContexts.append(NodeEventContext(node, eventTargetRespectingTargetRules(node)));
96 }
97
98 void EventPath::calculatePath()
99 {
100     ASSERT(m_node);
101     ASSERT(m_nodeEventContexts.isEmpty());
102     m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node.get()));
103
104     Node* current = m_node;
105     addNodeEventContext(current);
106     if (!m_node->inDocument())
107         return;
108     while (current) {
109         if (m_event && current->keepEventInNode(m_event))
110             break;
111         WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
112         collectDestinationInsertionPoints(*current, insertionPoints);
113         if (!insertionPoints.isEmpty()) {
114             for (const auto& insertionPoint : insertionPoints) {
115                 if (insertionPoint->isShadowInsertionPoint()) {
116                     ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
117                     ASSERT(containingShadowRoot);
118                     if (!containingShadowRoot->isOldest())
119                         addNodeEventContext(containingShadowRoot->olderShadowRoot());
120                 }
121                 addNodeEventContext(insertionPoint);
122             }
123             current = insertionPoints.last();
124             continue;
125         }
126         if (current->isShadowRoot()) {
127             if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(current), *m_node))
128                 break;
129             current = current->shadowHost();
130             addNodeEventContext(current);
131         } else {
132             current = current->parentNode();
133             if (current)
134                 addNodeEventContext(current);
135         }
136     }
137 }
138
139 void EventPath::calculateTreeScopePrePostOrderNumbers()
140 {
141     // Precondition:
142     //   - TreeScopes in m_treeScopeEventContexts must be *connected* in the same tree of trees.
143     //   - The root tree must be included.
144     WillBeHeapHashMap<RawPtrWillBeMember<const TreeScope>, RawPtrWillBeMember<TreeScopeEventContext>> treeScopeEventContextMap;
145     for (const auto& treeScopeEventContext : m_treeScopeEventContexts)
146         treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext.get());
147     TreeScopeEventContext* rootTree = 0;
148     for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
149         // Use olderShadowRootOrParentTreeScope here for parent-child relationships.
150         // See the definition of trees of trees in the Shado DOM spec: http://w3c.github.io/webcomponents/spec/shadow/
151         TreeScope* parent = treeScopeEventContext.get()->treeScope().olderShadowRootOrParentTreeScope();
152         if (!parent) {
153             ASSERT(!rootTree);
154             rootTree = treeScopeEventContext.get();
155             continue;
156         }
157         ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap.end());
158         treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventContext.get());
159     }
160     ASSERT(rootTree);
161     rootTree->calculatePrePostOrderNumber(0);
162 }
163
164 TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarget, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap)
165 {
166     if (!treeScope)
167         return 0;
168     TreeScopeEventContext* treeScopeEventContext;
169     bool isNewEntry;
170     {
171         TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(treeScope, nullptr);
172         isNewEntry = addResult.isNewEntry;
173         if (isNewEntry)
174             addResult.storedValue->value = TreeScopeEventContext::create(*treeScope);
175         treeScopeEventContext = addResult.storedValue->value.get();
176     }
177     if (isNewEntry) {
178         TreeScopeEventContext* parentTreeScopeEventContext = ensureTreeScopeEventContext(0, treeScope->olderShadowRootOrParentTreeScope(), treeScopeEventContextMap);
179         if (parentTreeScopeEventContext && parentTreeScopeEventContext->target()) {
180             treeScopeEventContext->setTarget(parentTreeScopeEventContext->target());
181         } else if (currentTarget) {
182             treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(currentTarget));
183         }
184     } else if (!treeScopeEventContext->target() && currentTarget) {
185         treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(currentTarget));
186     }
187     return treeScopeEventContext;
188 }
189
190 void EventPath::calculateAdjustedTargets()
191 {
192     const TreeScope* lastTreeScope = 0;
193
194     TreeScopeEventContextMap treeScopeEventContextMap;
195     TreeScopeEventContext* lastTreeScopeEventContext = 0;
196
197     for (size_t i = 0; i < size(); ++i) {
198         Node* currentNode = at(i).node();
199         TreeScope& currentTreeScope = currentNode->treeScope();
200         if (lastTreeScope != &currentTreeScope) {
201             lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode, &currentTreeScope, treeScopeEventContextMap);
202         }
203         ASSERT(lastTreeScopeEventContext);
204         at(i).setTreeScopeEventContext(lastTreeScopeEventContext);
205         lastTreeScope = &currentTreeScope;
206     }
207     m_treeScopeEventContexts.appendRange(treeScopeEventContextMap.values().begin(), treeScopeEventContextMap.values().end());
208 }
209
210 void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& relatedTargetMap)
211 {
212     EventPath relatedTargetEventPath(const_cast<Node*>(relatedNode));
213     for (size_t i = 0; i < relatedTargetEventPath.m_treeScopeEventContexts.size(); ++i) {
214         TreeScopeEventContext* treeScopeEventContext = relatedTargetEventPath.m_treeScopeEventContexts[i].get();
215         relatedTargetMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext->target());
216     }
217 }
218
219 EventTarget* EventPath::findRelatedNode(TreeScope* scope, RelatedTargetMap& relatedTargetMap)
220 {
221     WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32> parentTreeScopes;
222     EventTarget* relatedNode = 0;
223     while (scope) {
224         parentTreeScopes.append(scope);
225         RelatedTargetMap::const_iterator iter = relatedTargetMap.find(scope);
226         if (iter != relatedTargetMap.end() && iter->value) {
227             relatedNode = iter->value;
228             break;
229         }
230         scope = scope->olderShadowRootOrParentTreeScope();
231     }
232     ASSERT(relatedNode);
233     for (WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
234         relatedTargetMap.add(*iter, relatedNode);
235     return relatedNode;
236 }
237
238 void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget)
239 {
240     if (!target)
241         return;
242     if (!relatedTarget)
243         return;
244     Node* relatedNode = relatedTarget->toNode();
245     if (!relatedNode)
246         return;
247     if (target->document() != relatedNode->document())
248         return;
249     if (!target->inDocument() || !relatedNode->inDocument())
250         return;
251
252     RelatedTargetMap relatedNodeMap;
253     buildRelatedNodeMap(relatedNode, relatedNodeMap);
254
255     for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
256         EventTarget* adjustedRelatedTarget = findRelatedNode(&treeScopeEventContext.get()->treeScope(), relatedNodeMap);
257         ASSERT(adjustedRelatedTarget);
258         treeScopeEventContext.get()->setRelatedTarget(adjustedRelatedTarget);
259     }
260
261     shrinkIfNeeded(target, relatedTarget);
262 }
263
264 void EventPath::shrinkIfNeeded(const Node* target, const EventTarget* relatedTarget)
265 {
266     // Synthetic mouse events can have a relatedTarget which is identical to the target.
267     bool targetIsIdenticalToToRelatedTarget = (target == relatedTarget);
268
269     for (size_t i = 0; i < size(); ++i) {
270         if (targetIsIdenticalToToRelatedTarget) {
271             if (target->treeScope().rootNode() == at(i).node()) {
272                 shrink(i + 1);
273                 break;
274             }
275         } else if (at(i).target() == at(i).relatedTarget()) {
276             // Event dispatching should be stopped here.
277             shrink(i);
278             break;
279         }
280     }
281 }
282
283 void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
284 {
285     WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTouches;
286     WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTargetTouches;
287     WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedChangedTouches;
288     WillBeHeapVector<RawPtrWillBeMember<TreeScope>> treeScopes;
289
290     for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
291         TouchEventContext* touchEventContext = treeScopeEventContext->ensureTouchEventContext();
292         adjustedTouches.append(&touchEventContext->touches());
293         adjustedTargetTouches.append(&touchEventContext->targetTouches());
294         adjustedChangedTouches.append(&touchEventContext->changedTouches());
295         treeScopes.append(&treeScopeEventContext->treeScope());
296     }
297
298     adjustTouchList(node, touchEvent.touches(), adjustedTouches, treeScopes);
299     adjustTouchList(node, touchEvent.targetTouches(), adjustedTargetTouches, treeScopes);
300     adjustTouchList(node, touchEvent.changedTouches(), adjustedChangedTouches, treeScopes);
301
302 #if ENABLE(ASSERT)
303     for (const auto& treeScopeEventContext : m_treeScopeEventContexts) {
304         TreeScope& treeScope = treeScopeEventContext->treeScope();
305         TouchEventContext* touchEventContext = treeScopeEventContext->touchEventContext();
306         checkReachability(treeScope, touchEventContext->touches());
307         checkReachability(treeScope, touchEventContext->targetTouches());
308         checkReachability(treeScope, touchEventContext->changedTouches());
309     }
310 #endif
311 }
312
313 void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, WillBeHeapVector<RawPtrWillBeMember<TouchList>> adjustedTouchList, const WillBeHeapVector<RawPtrWillBeMember<TreeScope>>& treeScopes)
314 {
315     if (!touchList)
316         return;
317     for (size_t i = 0; i < touchList->length(); ++i) {
318         const Touch& touch = *touchList->item(i);
319         RelatedTargetMap relatedNodeMap;
320         buildRelatedNodeMap(touch.target()->toNode(), relatedNodeMap);
321         for (size_t j = 0; j < treeScopes.size(); ++j) {
322             adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNode(treeScopes[j], relatedNodeMap)));
323         }
324     }
325 }
326
327 #if ENABLE(ASSERT)
328 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
329 {
330     for (size_t i = 0; i < touchList.length(); ++i)
331         ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(treeScope));
332 }
333 #endif
334
335 void EventPath::trace(Visitor* visitor)
336 {
337     visitor->trace(m_nodeEventContexts);
338     visitor->trace(m_node);
339     visitor->trace(m_event);
340     visitor->trace(m_treeScopeEventContexts);
341 }
342
343 } // namespace