Upstream version 7.36.149.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/html/HTMLFrameOwnerElement.h"
10 #include "core/page/Page.h"
11 #include "core/page/scrolling/ScrollingCoordinator.h"
12
13 namespace WebCore {
14
15 EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
16     : m_frameHost(frameHost)
17 {
18 }
19
20 EventHandlerRegistry::~EventHandlerRegistry()
21 {
22     checkConsistency();
23 }
24
25 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
26 {
27     if (eventType == EventTypeNames::scroll) {
28         *result = ScrollEvent;
29 #if ASSERT_ENABLED
30     } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
31         *result = EventsForTesting;
32 #endif
33     } else {
34         return false;
35     }
36     return true;
37 }
38
39 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
40 {
41     checkConsistency();
42     return &m_targets[handlerClass];
43 }
44
45 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
46 {
47     return m_targets[handlerClass].size();
48 }
49
50 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
51 {
52     EventTargetSet* targets = &m_targets[handlerClass];
53     if (op == Add) {
54         if (!targets->add(target).isNewEntry) {
55             // Just incremented refcount, no real change.
56             return false;
57         }
58     } else {
59         ASSERT(op == Remove || op == RemoveAll);
60         ASSERT(op == RemoveAll || targets->contains(target));
61
62         if (op == RemoveAll) {
63             if (!targets->contains(target))
64                 return false;
65             targets->removeAll(target);
66         } else {
67             if (!targets->remove(target)) {
68                 // Just decremented refcount, no real update.
69                 return false;
70             }
71         }
72     }
73     return true;
74 }
75
76 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
77 {
78     bool hadHandlers = hasEventHandlers(handlerClass);
79     updateEventHandlerTargets(op, handlerClass, target);
80     bool hasHandlers = hasEventHandlers(handlerClass);
81
82     if (hadHandlers != hasHandlers) {
83         notifyHasHandlersChanged(handlerClass, hasHandlers);
84     }
85     checkConsistency();
86 }
87
88 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
89 {
90     EventHandlerClass handlerClass;
91     if (!eventTypeToClass(eventType, &handlerClass))
92         return;
93     updateEventHandlerInternal(op, handlerClass, target);
94 }
95
96 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
97 {
98     updateEventHandlerOfType(Add, eventType, &target);
99 }
100
101 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
102 {
103     updateEventHandlerOfType(Remove, eventType, &target);
104 }
105
106 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
107 {
108     updateEventHandlerInternal(Add, handlerClass, &target);
109 }
110
111 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
112 {
113     updateEventHandlerInternal(Remove, handlerClass, &target);
114 }
115
116 void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
117 {
118     updateAllEventHandlers(Add, target);
119 }
120
121 void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
122 {
123     updateAllEventHandlers(RemoveAll, target);
124 }
125
126 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
127 {
128     for (size_t i = 0; i < EventHandlerClassCount; ++i) {
129         EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
130         updateEventHandlerInternal(RemoveAll, handlerClass, &target);
131     }
132 }
133
134 void EventHandlerRegistry::updateAllEventHandlers(ChangeOperation op, EventTarget& target)
135 {
136     if (!target.hasEventListeners())
137         return;
138
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))
143             continue;
144         if (op == RemoveAll) {
145             updateEventHandlerInternal(op, handlerClass, &target);
146             continue;
147         }
148         for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
149             updateEventHandlerInternal(op, handlerClass, &target);
150     }
151 }
152
153 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
154 {
155     ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
156
157     switch (handlerClass) {
158     case ScrollEvent:
159         if (scrollingCoordinator)
160             scrollingCoordinator->updateHaveScrollEventHandlers();
161         break;
162 #if ASSERT_ENABLED
163     case EventsForTesting:
164         break;
165 #endif
166     default:
167         ASSERT_NOT_REACHED();
168         break;
169     }
170 }
171
172 void EventHandlerRegistry::trace(Visitor* visitor)
173 {
174     visitor->registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this);
175 }
176
177 void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
178 {
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);
187         }
188     }
189     for (size_t i = 0; i < deadNodeTargets.size(); ++i)
190         didRemoveAllEventHandlers(*deadNodeTargets[i]);
191 }
192
193 void EventHandlerRegistry::documentDetached(Document& document)
194 {
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);
205                         break;
206                     }
207                 }
208             }
209         }
210         for (size_t i = 0; i < targetsToRemove.size(); ++i)
211             updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
212     }
213 }
214
215 void EventHandlerRegistry::checkConsistency() const
216 {
217 #if ASSERT_ENABLED
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);
226             }
227         }
228     }
229 #endif // ASSERT_ENABLED
230 }
231
232 } // namespace WebCore