Upstream version 7.36.149.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 "EventNames.h"
31 #include "RuntimeEnabledFeatures.h"
32 #include "SVGNames.h"
33 #include "core/dom/FullscreenElementStack.h"
34 #include "core/dom/Touch.h"
35 #include "core/dom/TouchList.h"
36 #include "core/dom/shadow/InsertionPoint.h"
37 #include "core/dom/shadow/ShadowRoot.h"
38 #include "core/events/FocusEvent.h"
39 #include "core/events/MouseEvent.h"
40 #include "core/events/TouchEvent.h"
41 #include "core/events/TouchEventContext.h"
42 #include "core/svg/SVGElementInstance.h"
43 #include "core/svg/SVGUseElement.h"
44
45 namespace WebCore {
46
47 // SVG1.1 specified that the <use> instance tree would expose the target
48 // element for events. This has been deprecated and will be removed.
49 // See: crbug.com/313438
50 static bool usesDeprecatedSVGUseTreeEventRules(Node* node)
51 {
52     return node->isSVGElement() && toSVGElement(node)->inUseShadowTree();
53 }
54
55 EventTarget* EventPath::eventTargetRespectingTargetRules(Node* referenceNode)
56 {
57     ASSERT(referenceNode);
58
59     if (referenceNode->isPseudoElement())
60         return referenceNode->parentNode();
61
62     if (!usesDeprecatedSVGUseTreeEventRules(referenceNode))
63         return referenceNode;
64
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     Node& rootNode = referenceNode->treeScope().rootNode();
68     Element* shadowHostElement = rootNode.isShadowRoot() ? toShadowRoot(rootNode).host() : 0;
69     // At this time, SVG nodes are not supported in non-<use> shadow trees.
70     if (!isSVGUseElement(shadowHostElement))
71         return referenceNode;
72     SVGUseElement& useElement = toSVGUseElement(*shadowHostElement);
73     if (SVGElementInstance* instance = useElement.instanceForShadowTreeElement(referenceNode))
74         return instance;
75
76     return referenceNode;
77 }
78
79 static inline bool inTheSameScope(ShadowRoot* shadowRoot, EventTarget* target)
80 {
81     return target->toNode() && target->toNode()->treeScope().rootNode() == shadowRoot;
82 }
83
84 static inline EventDispatchBehavior determineDispatchBehavior(Event* event, ShadowRoot* shadowRoot, EventTarget* target)
85 {
86     // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
87     // Changing this breaks existing sites.
88     // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
89     const AtomicString eventType = event->type();
90     if (inTheSameScope(shadowRoot, target)
91         && (eventType == EventTypeNames::abort
92             || eventType == EventTypeNames::change
93             || eventType == EventTypeNames::error
94             || eventType == EventTypeNames::load
95             || eventType == EventTypeNames::reset
96             || eventType == EventTypeNames::resize
97             || eventType == EventTypeNames::scroll
98             || eventType == EventTypeNames::select
99             || eventType == EventTypeNames::selectstart))
100         return StayInsideShadowDOM;
101
102     return RetargetEvent;
103 }
104
105 EventPath::EventPath(Event* event)
106     : m_node(0)
107     , m_event(event)
108 {
109 }
110
111 EventPath::EventPath(Node* node)
112     : m_node(node)
113     , m_event(nullptr)
114 {
115     resetWith(node);
116 }
117
118 void EventPath::resetWith(Node* node)
119 {
120     ASSERT(node);
121     m_node = node;
122     m_nodeEventContexts.clear();
123     m_treeScopeEventContexts.clear();
124     calculatePath();
125     calculateAdjustedTargets();
126     if (!usesDeprecatedSVGUseTreeEventRules(node))
127         calculateTreeScopePrePostOrderNumbers();
128 }
129
130 void EventPath::addNodeEventContext(Node* node)
131 {
132     m_nodeEventContexts.append(NodeEventContext(node, eventTargetRespectingTargetRules(node)));
133 }
134
135 void EventPath::calculatePath()
136 {
137     ASSERT(m_node);
138     ASSERT(m_nodeEventContexts.isEmpty());
139     m_node->document().updateDistributionForNodeIfNeeded(const_cast<Node*>(m_node));
140
141     Node* current = m_node;
142     addNodeEventContext(current);
143     if (!m_node->inDocument())
144         return;
145     while (current) {
146         if (current->isShadowRoot() && m_event && determineDispatchBehavior(m_event, toShadowRoot(current), m_node) == StayInsideShadowDOM)
147             break;
148         Vector<InsertionPoint*, 8> insertionPoints;
149         collectDestinationInsertionPoints(*current, insertionPoints);
150         if (!insertionPoints.isEmpty()) {
151             for (size_t i = 0; i < insertionPoints.size(); ++i) {
152                 InsertionPoint* insertionPoint = insertionPoints[i];
153                 if (insertionPoint->isShadowInsertionPoint()) {
154                     ShadowRoot* containingShadowRoot = insertionPoint->containingShadowRoot();
155                     ASSERT(containingShadowRoot);
156                     if (!containingShadowRoot->isOldest())
157                         addNodeEventContext(containingShadowRoot->olderShadowRoot());
158                 }
159                 addNodeEventContext(insertionPoint);
160             }
161             current = insertionPoints.last();
162             continue;
163         }
164         if (current->isShadowRoot()) {
165             current = current->shadowHost();
166             addNodeEventContext(current);
167         } else {
168             current = current->parentNode();
169             if (current)
170                 addNodeEventContext(current);
171         }
172     }
173 }
174
175 void EventPath::calculateTreeScopePrePostOrderNumbers()
176 {
177     // Precondition:
178     //   - TreeScopes in m_treeScopeEventContexts must be *connected* in the same tree of trees.
179     //   - The root tree must be included.
180     HashMap<const TreeScope*, TreeScopeEventContext*> treeScopeEventContextMap;
181     for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i)
182         treeScopeEventContextMap.add(&m_treeScopeEventContexts[i]->treeScope(), m_treeScopeEventContexts[i].get());
183     TreeScopeEventContext* rootTree = 0;
184     for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
185         TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get();
186         // Use olderShadowRootOrParentTreeScope here for parent-child relationships.
187         // See the definition of trees of trees in the Shado DOM spec: http://w3c.github.io/webcomponents/spec/shadow/
188         TreeScope* parent = treeScopeEventContext->treeScope().olderShadowRootOrParentTreeScope();
189         if (!parent) {
190             ASSERT(!rootTree);
191             rootTree = treeScopeEventContext;
192             continue;
193         }
194         ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap.end());
195         treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventContext);
196     }
197     ASSERT(rootTree);
198     rootTree->calculatePrePostOrderNumber(0);
199 }
200
201 TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarget, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap)
202 {
203     if (!treeScope)
204         return 0;
205     TreeScopeEventContext* treeScopeEventContext;
206     bool isNewEntry;
207     {
208         TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(treeScope, nullptr);
209         if ((isNewEntry = addResult.isNewEntry))
210             addResult.storedValue->value = TreeScopeEventContext::create(*treeScope);
211         treeScopeEventContext = addResult.storedValue->value.get();
212     }
213     if (isNewEntry) {
214         TreeScopeEventContext* parentTreeScopeEventContext = ensureTreeScopeEventContext(0, treeScope->olderShadowRootOrParentTreeScope(), treeScopeEventContextMap);
215         if (parentTreeScopeEventContext && parentTreeScopeEventContext->target()) {
216             treeScopeEventContext->setTarget(parentTreeScopeEventContext->target());
217         } else if (currentTarget) {
218             treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(currentTarget));
219         }
220     } else if (!treeScopeEventContext->target() && currentTarget) {
221         treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(currentTarget));
222     }
223     return treeScopeEventContext;
224 }
225
226 void EventPath::calculateAdjustedTargets()
227 {
228     const TreeScope* lastTreeScope = 0;
229     bool useDeprecatedSVGUseTreeEventRules = usesDeprecatedSVGUseTreeEventRules(at(0).node());
230
231     TreeScopeEventContextMap treeScopeEventContextMap;
232     TreeScopeEventContext* lastTreeScopeEventContext = 0;
233
234     for (size_t i = 0; i < size(); ++i) {
235         Node* currentNode = at(i).node();
236         TreeScope& currentTreeScope = currentNode->treeScope();
237         if (lastTreeScope != &currentTreeScope) {
238             if (!useDeprecatedSVGUseTreeEventRules) {
239                 lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode, &currentTreeScope, treeScopeEventContextMap);
240             } else {
241                 TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(&currentTreeScope, TreeScopeEventContext::create(currentTreeScope));
242                 lastTreeScopeEventContext = addResult.storedValue->value.get();
243                 if (addResult.isNewEntry) {
244                     // Don't adjust an event target for SVG.
245                     lastTreeScopeEventContext->setTarget(eventTargetRespectingTargetRules(at(0).node()));
246                 }
247             }
248         }
249         ASSERT(lastTreeScopeEventContext);
250         at(i).setTreeScopeEventContext(lastTreeScopeEventContext);
251         lastTreeScope = &currentTreeScope;
252     }
253     m_treeScopeEventContexts.appendRange(treeScopeEventContextMap.values().begin(), treeScopeEventContextMap.values().end());
254 }
255
256 void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& relatedTargetMap)
257 {
258     EventPath relatedTargetEventPath(const_cast<Node*>(relatedNode));
259     for (size_t i = 0; i < relatedTargetEventPath.m_treeScopeEventContexts.size(); ++i) {
260         TreeScopeEventContext* treeScopeEventContext = relatedTargetEventPath.m_treeScopeEventContexts[i].get();
261         relatedTargetMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext->target());
262     }
263 }
264
265 EventTarget* EventPath::findRelatedNode(TreeScope* scope, RelatedTargetMap& relatedTargetMap)
266 {
267     Vector<TreeScope*, 32> parentTreeScopes;
268     EventTarget* relatedNode = 0;
269     while (scope) {
270         parentTreeScopes.append(scope);
271         RelatedTargetMap::const_iterator iter = relatedTargetMap.find(scope);
272         if (iter != relatedTargetMap.end() && iter->value) {
273             relatedNode = iter->value;
274             break;
275         }
276         scope = scope->olderShadowRootOrParentTreeScope();
277     }
278     ASSERT(relatedNode);
279     for (Vector<TreeScope*, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
280         relatedTargetMap.add(*iter, relatedNode);
281     return relatedNode;
282 }
283
284 void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget)
285 {
286     if (!target)
287         return;
288     if (!relatedTarget)
289         return;
290     Node* relatedNode = relatedTarget->toNode();
291     if (!relatedNode)
292         return;
293     if (target->document() != relatedNode->document())
294         return;
295     if (!target->inDocument() || !relatedNode->inDocument())
296         return;
297
298     RelatedTargetMap relatedNodeMap;
299     buildRelatedNodeMap(relatedNode, relatedNodeMap);
300
301     for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
302         TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get();
303         EventTarget* adjustedRelatedTarget = findRelatedNode(&treeScopeEventContext->treeScope(), relatedNodeMap);
304         ASSERT(adjustedRelatedTarget);
305         treeScopeEventContext->setRelatedTarget(adjustedRelatedTarget);
306     }
307
308     shrinkIfNeeded(target, relatedTarget);
309 }
310
311 void EventPath::shrinkIfNeeded(const Node* target, const EventTarget* relatedTarget)
312 {
313     // Synthetic mouse events can have a relatedTarget which is identical to the target.
314     bool targetIsIdenticalToToRelatedTarget = (target == relatedTarget);
315
316     for (size_t i = 0; i < size(); ++i) {
317         if (targetIsIdenticalToToRelatedTarget) {
318             if (target->treeScope().rootNode() == at(i).node()) {
319                 shrink(i + 1);
320                 break;
321             }
322         } else if (at(i).target() == at(i).relatedTarget()) {
323             // Event dispatching should be stopped here.
324             shrink(i);
325             break;
326         }
327     }
328 }
329
330 void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
331 {
332     WillBeHeapVector<RawPtrWillBeMember<TouchList> > adjustedTouches;
333     WillBeHeapVector<RawPtrWillBeMember<TouchList> > adjustedTargetTouches;
334     WillBeHeapVector<RawPtrWillBeMember<TouchList> > adjustedChangedTouches;
335     Vector<TreeScope*> treeScopes;
336
337     for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
338         TouchEventContext* touchEventContext = m_treeScopeEventContexts[i]->ensureTouchEventContext();
339         adjustedTouches.append(&touchEventContext->touches());
340         adjustedTargetTouches.append(&touchEventContext->targetTouches());
341         adjustedChangedTouches.append(&touchEventContext->changedTouches());
342         treeScopes.append(&m_treeScopeEventContexts[i]->treeScope());
343     }
344
345     adjustTouchList(node, touchEvent.touches(), adjustedTouches, treeScopes);
346     adjustTouchList(node, touchEvent.targetTouches(), adjustedTargetTouches, treeScopes);
347     adjustTouchList(node, touchEvent.changedTouches(), adjustedChangedTouches, treeScopes);
348
349 #ifndef NDEBUG
350     for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) {
351         TreeScope& treeScope = m_treeScopeEventContexts[i]->treeScope();
352         TouchEventContext* touchEventContext = m_treeScopeEventContexts[i]->touchEventContext();
353         checkReachability(treeScope, touchEventContext->touches());
354         checkReachability(treeScope, touchEventContext->targetTouches());
355         checkReachability(treeScope, touchEventContext->changedTouches());
356     }
357 #endif
358 }
359
360 void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, WillBeHeapVector<RawPtrWillBeMember<TouchList> > adjustedTouchList, const Vector<TreeScope*>& treeScopes)
361 {
362     if (!touchList)
363         return;
364     for (size_t i = 0; i < touchList->length(); ++i) {
365         const Touch& touch = *touchList->item(i);
366         RelatedTargetMap relatedNodeMap;
367         buildRelatedNodeMap(touch.target()->toNode(), relatedNodeMap);
368         for (size_t j = 0; j < treeScopes.size(); ++j) {
369             adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNode(treeScopes[j], relatedNodeMap)));
370         }
371     }
372 }
373
374 #ifndef NDEBUG
375 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
376 {
377     for (size_t i = 0; i < touchList.length(); ++i)
378         ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(treeScope));
379 }
380 #endif
381
382 void EventPath::trace(Visitor* visitor)
383 {
384     visitor->trace(m_event);
385 }
386
387 } // namespace