Oilpan: fix build after r202625.
[chromium-blink-merge.git] / third_party / WebKit / Source / core / frame / EventHandlerRegistry.cpp
blob8c3098603fd1650e68f676ec24e1f0fdeb5d8720
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.
5 #include "config.h"
6 #include "core/frame/EventHandlerRegistry.h"
8 #include "core/frame/LocalDOMWindow.h"
9 #include "core/frame/LocalFrame.h"
10 #include "core/html/HTMLFrameOwnerElement.h"
11 #include "core/page/ChromeClient.h"
12 #include "core/page/Page.h"
13 #include "core/page/scrolling/ScrollingCoordinator.h"
15 namespace blink {
17 namespace {
19 inline bool isTouchEventType(const AtomicString& eventType)
21 return eventType == EventTypeNames::touchstart
22 || eventType == EventTypeNames::touchmove
23 || eventType == EventTypeNames::touchend
24 || eventType == EventTypeNames::touchcancel;
27 inline bool isPointerEventType(const AtomicString& eventType)
29 return eventType == EventTypeNames::gotpointercapture
30 || eventType == EventTypeNames::lostpointercapture
31 || eventType == EventTypeNames::pointercancel
32 || eventType == EventTypeNames::pointerdown
33 || eventType == EventTypeNames::pointerenter
34 || eventType == EventTypeNames::pointerleave
35 || eventType == EventTypeNames::pointermove
36 || eventType == EventTypeNames::pointerout
37 || eventType == EventTypeNames::pointerover
38 || eventType == EventTypeNames::pointerup;
41 } // namespace
43 EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
44 : m_frameHost(&frameHost)
48 EventHandlerRegistry::~EventHandlerRegistry()
50 checkConsistency();
53 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
55 if (eventType == EventTypeNames::scroll) {
56 *result = ScrollEvent;
57 } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) {
58 *result = WheelEvent;
59 } else if (isTouchEventType(eventType)) {
60 *result = TouchEvent;
61 } else if (isPointerEventType(eventType)) {
62 // The EventHandlerClass is still TouchEvent below since we are firing PointerEvents only from
63 // EventHandler::handleTouchEvent for now. See crbug.com/476565.
64 *result = TouchEvent;
65 #if ENABLE(ASSERT)
66 } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
67 *result = EventsForTesting;
68 #endif
69 } else {
70 return false;
72 return true;
75 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
77 checkConsistency();
78 return &m_targets[handlerClass];
81 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
83 checkConsistency();
84 return m_targets[handlerClass].size();
87 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
89 EventTargetSet* targets = &m_targets[handlerClass];
90 if (op == Add) {
91 if (!targets->add(target).isNewEntry) {
92 // Just incremented refcount, no real change.
93 return false;
95 } else {
96 ASSERT(op == Remove || op == RemoveAll);
97 ASSERT(op == RemoveAll || targets->contains(target));
99 if (op == RemoveAll) {
100 if (!targets->contains(target))
101 return false;
102 targets->removeAll(target);
103 } else {
104 if (!targets->remove(target)) {
105 // Just decremented refcount, no real update.
106 return false;
110 return true;
113 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
115 bool hadHandlers = m_targets[handlerClass].size();
116 bool targetSetChanged = updateEventHandlerTargets(op, handlerClass, target);
117 bool hasHandlers = m_targets[handlerClass].size();
119 if (hadHandlers != hasHandlers)
120 notifyHasHandlersChanged(handlerClass, hasHandlers);
122 if (targetSetChanged)
123 notifyDidAddOrRemoveEventHandlerTarget(handlerClass);
126 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
128 EventHandlerClass handlerClass;
129 if (!eventTypeToClass(eventType, &handlerClass))
130 return;
131 updateEventHandlerInternal(op, handlerClass, target);
134 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
136 updateEventHandlerOfType(Add, eventType, &target);
139 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
141 updateEventHandlerOfType(Remove, eventType, &target);
144 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
146 updateEventHandlerInternal(Add, handlerClass, &target);
149 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
151 updateEventHandlerInternal(Remove, handlerClass, &target);
154 void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
156 if (!target.hasEventListeners())
157 return;
159 Vector<AtomicString> eventTypes = target.eventTypes();
160 for (size_t i = 0; i < eventTypes.size(); ++i) {
161 EventHandlerClass handlerClass;
162 if (!eventTypeToClass(eventTypes[i], &handlerClass))
163 continue;
164 EventListenerVector* listeners = target.getEventListeners(eventTypes[i]);
165 if (!listeners)
166 continue;
167 for (unsigned count = listeners->size(); count > 0; --count)
168 didAddEventHandler(target, handlerClass);
172 void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
174 didRemoveAllEventHandlers(target);
177 void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target, FrameHost* oldFrameHost, FrameHost* newFrameHost)
179 ASSERT(newFrameHost != oldFrameHost);
180 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
181 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
182 const EventTargetSet* targets = &oldFrameHost->eventHandlerRegistry().m_targets[handlerClass];
183 for (unsigned count = targets->count(&target); count > 0; --count)
184 newFrameHost->eventHandlerRegistry().didAddEventHandler(target, handlerClass);
185 oldFrameHost->eventHandlerRegistry().didRemoveAllEventHandlers(target);
189 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
191 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
192 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
193 updateEventHandlerInternal(RemoveAll, handlerClass, &target);
197 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
199 ScrollingCoordinator* scrollingCoordinator = m_frameHost->page().scrollingCoordinator();
201 switch (handlerClass) {
202 case ScrollEvent:
203 if (scrollingCoordinator)
204 scrollingCoordinator->updateHaveScrollEventHandlers();
205 break;
206 case WheelEvent:
207 if (scrollingCoordinator)
208 scrollingCoordinator->updateHaveWheelEventHandlers();
209 break;
210 case TouchEvent:
211 m_frameHost->chromeClient().needTouchEvents(hasActiveHandlers);
212 break;
213 #if ENABLE(ASSERT)
214 case EventsForTesting:
215 break;
216 #endif
217 default:
218 ASSERT_NOT_REACHED();
219 break;
223 void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass handlerClass)
225 ScrollingCoordinator* scrollingCoordinator = m_frameHost->page().scrollingCoordinator();
226 if (scrollingCoordinator && handlerClass == TouchEvent)
227 scrollingCoordinator->touchEventTargetRectsDidChange();
230 DEFINE_TRACE(EventHandlerRegistry)
232 visitor->trace(m_frameHost);
233 visitor->template registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this);
236 void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
238 Vector<EventTarget*> deadTargets;
239 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
240 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
241 const EventTargetSet* targets = &m_targets[handlerClass];
242 for (const auto& eventTarget : *targets) {
243 Node* node = eventTarget.key->toNode();
244 LocalDOMWindow* window = eventTarget.key->toDOMWindow();
245 if (node && !Heap::isHeapObjectAlive(node)) {
246 deadTargets.append(node);
247 } else if (window && !Heap::isHeapObjectAlive(window)) {
248 deadTargets.append(window);
252 for (size_t i = 0; i < deadTargets.size(); ++i)
253 didRemoveAllEventHandlers(*deadTargets[i]);
256 void EventHandlerRegistry::documentDetached(Document& document)
258 // Remove all event targets under the detached document.
259 for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
260 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
261 Vector<EventTarget*> targetsToRemove;
262 const EventTargetSet* targets = &m_targets[handlerClass];
263 for (const auto& eventTarget : *targets) {
264 if (Node* node = eventTarget.key->toNode()) {
265 for (Document* doc = &node->document(); doc; doc = doc->ownerElement() ? &doc->ownerElement()->document() : 0) {
266 if (doc == &document) {
267 targetsToRemove.append(eventTarget.key);
268 break;
271 } else if (eventTarget.key->toDOMWindow()) {
272 // DOMWindows may outlive their documents, so we shouldn't remove their handlers
273 // here.
274 } else {
275 ASSERT_NOT_REACHED();
278 for (size_t i = 0; i < targetsToRemove.size(); ++i)
279 updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
283 void EventHandlerRegistry::checkConsistency() const
285 #if ENABLE(ASSERT)
286 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
287 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
288 const EventTargetSet* targets = &m_targets[handlerClass];
289 for (const auto& eventTarget : *targets) {
290 if (Node* node = eventTarget.key->toNode()) {
291 // See the comment for |documentDetached| if either of these assertions fails.
292 ASSERT(node->document().frameHost());
293 ASSERT(node->document().frameHost() == m_frameHost);
294 } else if (LocalDOMWindow* window = eventTarget.key->toDOMWindow()) {
295 // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers
296 // properly.
297 ASSERT(window->frame());
298 ASSERT(window->frame()->host());
299 ASSERT(window->frame()->host() == m_frameHost);
303 #endif // ENABLE(ASSERT)
306 } // namespace blink