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.
6 #include "core/frame/EventHandlerRegistry.h"
8 #include "core/events/ThreadLocalEventNames.h"
9 #include "core/html/HTMLFrameOwnerElement.h"
10 #include "core/page/Page.h"
11 #include "core/page/scrolling/ScrollingCoordinator.h"
15 EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
16 : m_frameHost(frameHost)
20 EventHandlerRegistry::~EventHandlerRegistry()
25 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
27 if (eventType == EventTypeNames::scroll) {
28 *result = ScrollEvent;
30 } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
31 *result = EventsForTesting;
39 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
42 return &m_targets[handlerClass];
45 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
47 return m_targets[handlerClass].size();
50 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
52 EventTargetSet* targets = &m_targets[handlerClass];
54 if (!targets->add(target).isNewEntry) {
55 // Just incremented refcount, no real change.
59 ASSERT(op == Remove || op == RemoveAll);
60 ASSERT(op == RemoveAll || targets->contains(target));
62 if (op == RemoveAll) {
63 if (!targets->contains(target))
65 targets->removeAll(target);
67 if (!targets->remove(target)) {
68 // Just decremented refcount, no real update.
76 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
78 bool hadHandlers = hasEventHandlers(handlerClass);
79 updateEventHandlerTargets(op, handlerClass, target);
80 bool hasHandlers = hasEventHandlers(handlerClass);
82 if (hadHandlers != hasHandlers) {
83 notifyHasHandlersChanged(handlerClass, hasHandlers);
88 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
90 EventHandlerClass handlerClass;
91 if (!eventTypeToClass(eventType, &handlerClass))
93 updateEventHandlerInternal(op, handlerClass, target);
96 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
98 updateEventHandlerOfType(Add, eventType, &target);
101 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
103 updateEventHandlerOfType(Remove, eventType, &target);
106 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
108 updateEventHandlerInternal(Add, handlerClass, &target);
111 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
113 updateEventHandlerInternal(Remove, handlerClass, &target);
116 void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
118 updateAllEventHandlers(Add, target);
121 void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
123 updateAllEventHandlers(RemoveAll, target);
126 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
128 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
129 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
130 updateEventHandlerInternal(RemoveAll, handlerClass, &target);
134 void EventHandlerRegistry::updateAllEventHandlers(ChangeOperation op, EventTarget& target)
136 if (!target.hasEventListeners())
139 Vector<AtomicString> eventTypes = target.eventTypes();
140 for (size_t i = 0; i < eventTypes.size(); ++i) {
141 EventHandlerClass handlerClass;
142 if (!eventTypeToClass(eventTypes[i], &handlerClass))
144 if (op == RemoveAll) {
145 updateEventHandlerInternal(op, handlerClass, &target);
148 for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
149 updateEventHandlerInternal(op, handlerClass, &target);
153 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
155 ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
157 switch (handlerClass) {
159 if (scrollingCoordinator)
160 scrollingCoordinator->updateHaveScrollEventHandlers();
163 case EventsForTesting:
167 ASSERT_NOT_REACHED();
172 void EventHandlerRegistry::trace(Visitor* visitor)
174 visitor->registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this);
177 void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
179 Vector<EventTarget*> deadNodeTargets;
180 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
181 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
182 const EventTargetSet* targets = &m_targets[handlerClass];
183 for (EventTargetSet::const_iterator it = targets->begin(); it != targets->end(); ++it) {
184 Node* node = it->key->toNode();
185 if (node && !visitor->isAlive(node))
186 deadNodeTargets.append(node);
189 for (size_t i = 0; i < deadNodeTargets.size(); ++i)
190 didRemoveAllEventHandlers(*deadNodeTargets[i]);
193 void EventHandlerRegistry::documentDetached(Document& document)
195 // Remove all event targets under the detached document.
196 for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
197 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
198 Vector<EventTarget*> targetsToRemove;
199 const EventTargetSet* targets = &m_targets[handlerClass];
200 for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
201 if (Node* node = iter->key->toNode()) {
202 for (Document* doc = &node->document(); doc; doc = doc->ownerElement() ? &doc->ownerElement()->document() : 0) {
203 if (doc == &document) {
204 targetsToRemove.append(iter->key);
210 for (size_t i = 0; i < targetsToRemove.size(); ++i)
211 updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
215 void EventHandlerRegistry::checkConsistency() const
218 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
219 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
220 const EventTargetSet* targets = &m_targets[handlerClass];
221 for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
222 if (Node* node = iter->key->toNode()) {
223 // See the comment for |documentDetached| if either of these assertions fails.
224 ASSERT(node->document().frameHost());
225 ASSERT(node->document().frameHost() == &m_frameHost);
229 #endif // ASSERT_ENABLED
232 } // namespace WebCore