Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: Source/core/page/EventHandlerRegistry.cpp

Issue 237963014: Track scroll event handlers in nested documents (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: didMove{Into,OutOf}Page Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "core/dom/EventHandlerRegistry.h" 6 #include "core/page/EventHandlerRegistry.h"
7 7
8 #include "core/dom/Document.h"
9 #include "core/events/ThreadLocalEventNames.h" 8 #include "core/events/ThreadLocalEventNames.h"
10 #include "core/events/WheelEvent.h"
11 #include "core/frame/FrameHost.h"
12 #include "core/frame/LocalFrame.h"
13 #include "core/page/Chrome.h"
14 #include "core/page/ChromeClient.h"
15 #include "core/page/Page.h"
16 #include "core/page/scrolling/ScrollingCoordinator.h" 9 #include "core/page/scrolling/ScrollingCoordinator.h"
17 10
18 namespace WebCore { 11 namespace WebCore {
19 12
20 EventHandlerRegistry::HandlerState::HandlerState() 13 EventHandlerRegistry::EventHandlerRegistry(Page& page)
14 : m_page(page)
21 { 15 {
22 } 16 }
23 17
24 EventHandlerRegistry::HandlerState::~HandlerState()
25 {
26 }
27
28 EventHandlerRegistry::EventHandlerRegistry(Document& document)
29 : m_document(document)
30 {
31 }
32
33 EventHandlerRegistry::~EventHandlerRegistry() 18 EventHandlerRegistry::~EventHandlerRegistry()
34 { 19 {
35 } 20 }
36 21
37 const char* EventHandlerRegistry::supplementName() 22 const char* EventHandlerRegistry::supplementName()
38 { 23 {
39 return "EventHandlerRegistry"; 24 return "EventHandlerRegistry";
40 } 25 }
41 26
42 EventHandlerRegistry* EventHandlerRegistry::from(Document& document) 27 EventHandlerRegistry* EventHandlerRegistry::from(Page& page)
43 { 28 {
44 EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(Document Supplement::from(document, supplementName())); 29 EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(Suppleme nt<Page>::from(page, supplementName()));
45 if (!registry) { 30 if (!registry) {
46 registry = new EventHandlerRegistry(document); 31 registry = new EventHandlerRegistry(page);
47 DocumentSupplement::provideTo(document, supplementName(), adoptPtr(regis try)); 32 Supplement<Page>::provideTo(page, supplementName(), adoptPtr(registry));
48 } 33 }
49 return registry; 34 return registry;
50 } 35 }
51 36
52 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, Event HandlerClass* result) 37 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, Event HandlerClass* result)
53 { 38 {
54 if (eventType == EventTypeNames::scroll) { 39 if (eventType == EventTypeNames::scroll) {
55 *result = ScrollEvent; 40 *result = ScrollEvent;
56 } else { 41 } else {
57 return false; 42 return false;
58 } 43 }
59 return true; 44 return true;
60 } 45 }
61 46
62 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClas s handlerClass) const 47 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClas s handlerClass) const
63 { 48 {
64 return m_eventHandlers[handlerClass].targets.get(); 49 return &m_targets[handlerClass];
65 } 50 }
66 51
67 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) cons t 52 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) cons t
68 { 53 {
69 EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get(); 54 return m_targets[handlerClass].size();
70 return targets && targets->size();
71 } 55 }
72 56
73 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa ndlerClass handlerClass, EventTarget* target) 57 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa ndlerClass handlerClass, EventTarget* target)
74 { 58 {
75 EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get(); 59 EventTargetSet* targets = &m_targets[handlerClass];
76 if (op == Add) { 60 if (op == Add) {
77 #if ASSERT_ENABLED
78 if (Node* node = target->toNode())
79 ASSERT(&node->document() == &m_document);
80 #endif // ASSERT_ENABLED
81
82 if (!targets) {
83 m_eventHandlers[handlerClass].targets = adoptPtr(new EventTargetSet) ;
84 targets = m_eventHandlers[handlerClass].targets.get();
85 }
86
87 if (!targets->add(target).isNewEntry) { 61 if (!targets->add(target).isNewEntry) {
88 // Just incremented refcount, no real change. 62 // Just incremented refcount, no real change.
89 return false; 63 return false;
90 } 64 }
91 } else { 65 } else {
92 // Note that we can't assert that |target| is in this document because
93 // it might be in the process of moving out of it.
94 ASSERT(op == Remove || op == RemoveAll); 66 ASSERT(op == Remove || op == RemoveAll);
95 ASSERT(op == RemoveAll || targets->contains(target)); 67 ASSERT(op == RemoveAll || targets->contains(target));
96 if (!targets)
97 return false;
98 68
99 if (op == RemoveAll) { 69 if (op == RemoveAll) {
100 if (!targets->contains(target)) 70 if (!targets->contains(target))
101 return false; 71 return false;
102 targets->removeAll(target); 72 targets->removeAll(target);
103 } else { 73 } else {
104 if (!targets->remove(target)) { 74 if (!targets->remove(target)) {
105 // Just decremented refcount, no real update. 75 // Just decremented refcount, no real update.
106 return false; 76 return false;
107 } 77 }
108 } 78 }
109 } 79 }
110 return true; 80 return true;
111 } 81 }
112 82
113 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventH andlerClass handlerClass, EventTarget* target) 83 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventH andlerClass handlerClass, EventTarget* target)
114 { 84 {
115 // After the document has stopped, all updates become no-ops.
116 if (!m_document.isActive()) {
117 return;
118 }
119
120 bool hadHandlers = hasEventHandlers(handlerClass); 85 bool hadHandlers = hasEventHandlers(handlerClass);
121 updateEventHandlerTargets(op, handlerClass, target); 86 updateEventHandlerTargets(op, handlerClass, target);
122 bool hasHandlers = hasEventHandlers(handlerClass); 87 bool hasHandlers = hasEventHandlers(handlerClass);
123 88
124 // Notify the parent document's registry if we added the first or removed 89 if (hadHandlers != hasHandlers) {
125 // the last handler.
126 if (hadHandlers != hasHandlers && !m_document.parentDocument()) {
127 // This is the root registry; notify clients accordingly.
128 notifyHasHandlersChanged(handlerClass, hasHandlers); 90 notifyHasHandlersChanged(handlerClass, hasHandlers);
129 } 91 }
130 } 92 }
131 93
132 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const At omicString& eventType, EventTarget* target) 94 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const At omicString& eventType, EventTarget* target)
133 { 95 {
134 EventHandlerClass handlerClass; 96 EventHandlerClass handlerClass;
135 if (!eventTypeToClass(eventType, &handlerClass)) 97 if (!eventTypeToClass(eventType, &handlerClass))
136 return; 98 return;
137 updateEventHandlerInternal(op, handlerClass, target); 99 updateEventHandlerInternal(op, handlerClass, target);
(...skipping 12 matching lines...) Expand all
150 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerC lass handlerClass) 112 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerC lass handlerClass)
151 { 113 {
152 updateEventHandlerInternal(Add, handlerClass, &target); 114 updateEventHandlerInternal(Add, handlerClass, &target);
153 } 115 }
154 116
155 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandl erClass handlerClass) 117 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandl erClass handlerClass)
156 { 118 {
157 updateEventHandlerInternal(Remove, handlerClass, &target); 119 updateEventHandlerInternal(Remove, handlerClass, &target);
158 } 120 }
159 121
160 void EventHandlerRegistry::didMoveFromOtherDocument(EventTarget& target, Documen t& oldDocument) 122 void EventHandlerRegistry::didMoveIntoPage(EventTarget& target)
161 { 123 {
162 EventHandlerRegistry* oldRegistry = EventHandlerRegistry::from(oldDocument); 124 if (Node* node = target.toNode())
163 for (size_t i = 0; i < EventHandlerClassCount; ++i) { 125 updateEventHandlersRecursively(Add, node);
164 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); 126 }
165 const EventTargetSet* targets = oldRegistry->eventHandlerTargets(handler Class); 127
166 if (!targets) 128 void EventHandlerRegistry::didMoveOutOfPage(EventTarget& target)
167 continue; 129 {
168 for (unsigned count = targets->count(&target); count > 0; --count) { 130 if (Node* node = target.toNode())
169 oldRegistry->updateEventHandlerInternal(Remove, handlerClass, &targe t); 131 updateEventHandlersRecursively(RemoveAll, node);
170 updateEventHandlerInternal(Add, handlerClass, &target);
171 }
172 }
173 } 132 }
174 133
175 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) 134 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
176 { 135 {
177 for (size_t i = 0; i < EventHandlerClassCount; ++i) { 136 for (size_t i = 0; i < EventHandlerClassCount; ++i) {
178 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); 137 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
179 const EventTargetSet* targets = eventHandlerTargets(handlerClass);
180 if (!targets)
181 continue;
182 updateEventHandlerInternal(RemoveAll, handlerClass, &target); 138 updateEventHandlerInternal(RemoveAll, handlerClass, &target);
183 } 139 }
184 } 140 }
185 141
142 void EventHandlerRegistry::updateEventHandlersRecursively(ChangeOperation op, No de* node)
143 {
144 if (node->hasEventListeners()) {
145 Vector<AtomicString> eventTypes = node->eventTypes();
146 for (size_t i = 0; i < eventTypes.size(); ++i) {
147 EventHandlerClass handlerClass;
148 if (!eventTypeToClass(eventTypes[i], &handlerClass))
149 continue;
150 for (unsigned count = node->getEventListeners(eventTypes[i]).size(); count > 0; --count)
Rick Byers 2014/04/28 21:18:07 Why call this in a loop for RemoveAll? Ideally we
Sami 2014/04/29 14:21:28 Right, I wasn't sure if a fast path RemoveAll was
151 updateEventHandlerInternal(op, handlerClass, node);
152 }
153 }
154 for (Node* child = node->firstChild(); child; child = child->nextSibling())
Rick Byers 2014/04/28 21:18:07 I don't think you want to do this recursively. It
Sami 2014/04/29 14:21:28 Oh, thanks for pointing this out! Definitely don't
155 updateEventHandlersRecursively(op, child);
156 }
157
186 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla ss, bool hasActiveHandlers) 158 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla ss, bool hasActiveHandlers)
187 { 159 {
188 Page* page = m_document.page(); 160 ScrollingCoordinator* scrollingCoordinator = m_page.scrollingCoordinator();
189 ScrollingCoordinator* scrollingCoordinator = page ? page->scrollingCoordinat or() : 0;
190 161
191 switch (handlerClass) { 162 switch (handlerClass) {
192 case ScrollEvent: 163 case ScrollEvent:
193 if (scrollingCoordinator) 164 if (scrollingCoordinator)
194 scrollingCoordinator->updateHaveScrollEventHandlers(); 165 scrollingCoordinator->updateHaveScrollEventHandlers();
195 break; 166 break;
196 default: 167 default:
197 ASSERT_NOT_REACHED(); 168 ASSERT_NOT_REACHED();
198 break; 169 break;
199 } 170 }
200 } 171 }
201 172
202 } // namespace WebCore 173 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698