Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / EventHandlerRegistry.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/frame/EventHandlerRegistry.h"
7
8 #include "core/events/ThreadLocalEventNames.h"
9 #include "core/frame/LocalDOMWindow.h"
10 #include "core/frame/LocalFrame.h"
11 #include "core/html/HTMLFrameOwnerElement.h"
12 #include "core/page/Chrome.h"
13 #include "core/page/ChromeClient.h"
14 #include "core/page/Page.h"
15 #include "core/page/scrolling/ScrollingCoordinator.h"
16
17 namespace blink {
18
19 EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
20     : m_frameHost(frameHost)
21 {
22 }
23
24 EventHandlerRegistry::~EventHandlerRegistry()
25 {
26     checkConsistency();
27 }
28
29 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
30 {
31     if (eventType == EventTypeNames::scroll) {
32         *result = ScrollEvent;
33     } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) {
34         *result = WheelEvent;
35     } else if (isTouchEventType(eventType)) {
36         *result = TouchEvent;
37 #if ENABLE(ASSERT)
38     } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
39         *result = EventsForTesting;
40 #endif
41     } else {
42         return false;
43     }
44     return true;
45 }
46
47 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
48 {
49     checkConsistency();
50     return &m_targets[handlerClass];
51 }
52
53 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
54 {
55     checkConsistency();
56     return m_targets[handlerClass].size();
57 }
58
59 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
60 {
61     EventTargetSet* targets = &m_targets[handlerClass];
62     if (op == Add) {
63         if (!targets->add(target).isNewEntry) {
64             // Just incremented refcount, no real change.
65             return false;
66         }
67     } else {
68         ASSERT(op == Remove || op == RemoveAll);
69         ASSERT(op == RemoveAll || targets->contains(target));
70
71         if (op == RemoveAll) {
72             if (!targets->contains(target))
73                 return false;
74             targets->removeAll(target);
75         } else {
76             if (!targets->remove(target)) {
77                 // Just decremented refcount, no real update.
78                 return false;
79             }
80         }
81     }
82     return true;
83 }
84
85 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
86 {
87     bool hadHandlers = m_targets[handlerClass].size();
88     bool targetSetChanged = updateEventHandlerTargets(op, handlerClass, target);
89     bool hasHandlers = m_targets[handlerClass].size();
90
91     if (hadHandlers != hasHandlers)
92         notifyHasHandlersChanged(handlerClass, hasHandlers);
93
94     if (targetSetChanged)
95         notifyDidAddOrRemoveEventHandlerTarget(handlerClass);
96 }
97
98 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
99 {
100     EventHandlerClass handlerClass;
101     if (!eventTypeToClass(eventType, &handlerClass))
102         return;
103     updateEventHandlerInternal(op, handlerClass, target);
104 }
105
106 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
107 {
108     updateEventHandlerOfType(Add, eventType, &target);
109 }
110
111 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
112 {
113     updateEventHandlerOfType(Remove, eventType, &target);
114 }
115
116 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
117 {
118     updateEventHandlerInternal(Add, handlerClass, &target);
119 }
120
121 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
122 {
123     updateEventHandlerInternal(Remove, handlerClass, &target);
124 }
125
126 void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
127 {
128     if (!target.hasEventListeners())
129         return;
130
131     Vector<AtomicString> eventTypes = target.eventTypes();
132     for (size_t i = 0; i < eventTypes.size(); ++i) {
133         EventHandlerClass handlerClass;
134         if (!eventTypeToClass(eventTypes[i], &handlerClass))
135             continue;
136         for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
137             didAddEventHandler(target, handlerClass);
138     }
139 }
140
141 void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
142 {
143     didRemoveAllEventHandlers(target);
144 }
145
146 void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target, FrameHost* oldFrameHost, FrameHost* newFrameHost)
147 {
148     ASSERT(newFrameHost != oldFrameHost);
149     for (size_t i = 0; i < EventHandlerClassCount; ++i) {
150         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
151         const EventTargetSet* targets = &oldFrameHost->eventHandlerRegistry().m_targets[handlerClass];
152         for (unsigned count = targets->count(&target); count > 0; --count)
153             newFrameHost->eventHandlerRegistry().didAddEventHandler(target, handlerClass);
154         oldFrameHost->eventHandlerRegistry().didRemoveAllEventHandlers(target);
155     }
156 }
157
158 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
159 {
160     for (size_t i = 0; i < EventHandlerClassCount; ++i) {
161         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
162         updateEventHandlerInternal(RemoveAll, handlerClass, &target);
163     }
164 }
165
166 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
167 {
168     ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
169
170     switch (handlerClass) {
171     case ScrollEvent:
172         if (scrollingCoordinator)
173             scrollingCoordinator->updateHaveScrollEventHandlers();
174         break;
175     case WheelEvent:
176         if (scrollingCoordinator)
177             scrollingCoordinator->updateHaveWheelEventHandlers();
178         break;
179     case TouchEvent:
180         m_frameHost.chrome().client().needTouchEvents(hasActiveHandlers);
181         break;
182 #if ENABLE(ASSERT)
183     case EventsForTesting:
184         break;
185 #endif
186     default:
187         ASSERT_NOT_REACHED();
188         break;
189     }
190 }
191
192 void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass handlerClass)
193 {
194     ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
195     if (scrollingCoordinator && handlerClass == TouchEvent)
196         scrollingCoordinator->touchEventTargetRectsDidChange();
197 }
198
199 void EventHandlerRegistry::trace(Visitor* visitor)
200 {
201     visitor->registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this);
202 }
203
204 void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
205 {
206     Vector<EventTarget*> deadTargets;
207     for (size_t i = 0; i < EventHandlerClassCount; ++i) {
208         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
209         const EventTargetSet* targets = &m_targets[handlerClass];
210         for (EventTargetSet::const_iterator it = targets->begin(); it != targets->end(); ++it) {
211             Node* node = it->key->toNode();
212             LocalDOMWindow* window = it->key->toDOMWindow();
213             if (node && !visitor->isAlive(node)) {
214                 deadTargets.append(node);
215             } else if (window && !visitor->isAlive(window)) {
216                 deadTargets.append(window);
217             }
218         }
219     }
220     for (size_t i = 0; i < deadTargets.size(); ++i)
221         didRemoveAllEventHandlers(*deadTargets[i]);
222 }
223
224 void EventHandlerRegistry::documentDetached(Document& document)
225 {
226     // Remove all event targets under the detached document.
227     for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
228         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
229         Vector<EventTarget*> targetsToRemove;
230         const EventTargetSet* targets = &m_targets[handlerClass];
231         for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
232             if (Node* node = iter->key->toNode()) {
233                 for (Document* doc = &node->document(); doc; doc = doc->ownerElement() ? &doc->ownerElement()->document() : 0) {
234                     if (doc == &document) {
235                         targetsToRemove.append(iter->key);
236                         break;
237                     }
238                 }
239             } else if (iter->key->toDOMWindow()) {
240                 // DOMWindows may outlive their documents, so we shouldn't remove their handlers
241                 // here.
242             } else {
243                 ASSERT_NOT_REACHED();
244             }
245         }
246         for (size_t i = 0; i < targetsToRemove.size(); ++i)
247             updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
248     }
249 }
250
251 void EventHandlerRegistry::checkConsistency() const
252 {
253 #if ENABLE(ASSERT)
254     for (size_t i = 0; i < EventHandlerClassCount; ++i) {
255         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
256         const EventTargetSet* targets = &m_targets[handlerClass];
257         for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
258             if (Node* node = iter->key->toNode()) {
259                 // See the comment for |documentDetached| if either of these assertions fails.
260                 ASSERT(node->document().frameHost());
261                 ASSERT(node->document().frameHost() == &m_frameHost);
262             } else if (LocalDOMWindow* window = iter->key->toDOMWindow()) {
263                 // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers
264                 // properly.
265                 ASSERT(window->frame());
266                 ASSERT(window->frame()->host());
267                 ASSERT(window->frame()->host() == &m_frameHost);
268             }
269         }
270     }
271 #endif // ENABLE(ASSERT)
272 }
273
274 } // namespace blink