| OLD | NEW |
| (Empty) |
| 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/page/Chrome.h" | |
| 12 #include "core/page/ChromeClient.h" | |
| 13 #include "core/page/Page.h" | |
| 14 #include "core/page/scrolling/ScrollingCoordinator.h" | |
| 15 | |
| 16 namespace blink { | |
| 17 | |
| 18 EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost) | |
| 19 : m_frameHost(frameHost) | |
| 20 { | |
| 21 } | |
| 22 | |
| 23 EventHandlerRegistry::~EventHandlerRegistry() | |
| 24 { | |
| 25 checkConsistency(); | |
| 26 } | |
| 27 | |
| 28 bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, Event
HandlerClass* result) | |
| 29 { | |
| 30 if (eventType == EventTypeNames::scroll) { | |
| 31 *result = ScrollEvent; | |
| 32 } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames
::mousewheel) { | |
| 33 *result = WheelEvent; | |
| 34 } else if (isTouchEventType(eventType)) { | |
| 35 *result = TouchEvent; | |
| 36 #if ENABLE(ASSERT) | |
| 37 } else if (eventType == EventTypeNames::load || eventType == EventTypeNames:
:mousemove || eventType == EventTypeNames::touchstart) { | |
| 38 *result = EventsForTesting; | |
| 39 #endif | |
| 40 } else { | |
| 41 return false; | |
| 42 } | |
| 43 return true; | |
| 44 } | |
| 45 | |
| 46 const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClas
s handlerClass) const | |
| 47 { | |
| 48 checkConsistency(); | |
| 49 return &m_targets[handlerClass]; | |
| 50 } | |
| 51 | |
| 52 bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) cons
t | |
| 53 { | |
| 54 checkConsistency(); | |
| 55 return m_targets[handlerClass].size(); | |
| 56 } | |
| 57 | |
| 58 bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa
ndlerClass handlerClass, EventTarget* target) | |
| 59 { | |
| 60 EventTargetSet* targets = &m_targets[handlerClass]; | |
| 61 if (op == Add) { | |
| 62 if (!targets->add(target).isNewEntry) { | |
| 63 // Just incremented refcount, no real change. | |
| 64 return false; | |
| 65 } | |
| 66 } else { | |
| 67 ASSERT(op == Remove || op == RemoveAll); | |
| 68 ASSERT(op == RemoveAll || targets->contains(target)); | |
| 69 | |
| 70 if (op == RemoveAll) { | |
| 71 if (!targets->contains(target)) | |
| 72 return false; | |
| 73 targets->removeAll(target); | |
| 74 } else { | |
| 75 if (!targets->remove(target)) { | |
| 76 // Just decremented refcount, no real update. | |
| 77 return false; | |
| 78 } | |
| 79 } | |
| 80 } | |
| 81 return true; | |
| 82 } | |
| 83 | |
| 84 void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventH
andlerClass handlerClass, EventTarget* target) | |
| 85 { | |
| 86 bool hadHandlers = m_targets[handlerClass].size(); | |
| 87 bool targetSetChanged = updateEventHandlerTargets(op, handlerClass, target); | |
| 88 bool hasHandlers = m_targets[handlerClass].size(); | |
| 89 | |
| 90 if (hadHandlers != hasHandlers) | |
| 91 notifyHasHandlersChanged(handlerClass, hasHandlers); | |
| 92 | |
| 93 if (targetSetChanged) | |
| 94 notifyDidAddOrRemoveEventHandlerTarget(handlerClass); | |
| 95 } | |
| 96 | |
| 97 void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const At
omicString& eventType, EventTarget* target) | |
| 98 { | |
| 99 EventHandlerClass handlerClass; | |
| 100 if (!eventTypeToClass(eventType, &handlerClass)) | |
| 101 return; | |
| 102 updateEventHandlerInternal(op, handlerClass, target); | |
| 103 } | |
| 104 | |
| 105 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicS
tring& eventType) | |
| 106 { | |
| 107 updateEventHandlerOfType(Add, eventType, &target); | |
| 108 } | |
| 109 | |
| 110 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const Atom
icString& eventType) | |
| 111 { | |
| 112 updateEventHandlerOfType(Remove, eventType, &target); | |
| 113 } | |
| 114 | |
| 115 void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerC
lass handlerClass) | |
| 116 { | |
| 117 updateEventHandlerInternal(Add, handlerClass, &target); | |
| 118 } | |
| 119 | |
| 120 void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandl
erClass handlerClass) | |
| 121 { | |
| 122 updateEventHandlerInternal(Remove, handlerClass, &target); | |
| 123 } | |
| 124 | |
| 125 void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target) | |
| 126 { | |
| 127 if (!target.hasEventListeners()) | |
| 128 return; | |
| 129 | |
| 130 Vector<AtomicString> eventTypes = target.eventTypes(); | |
| 131 for (size_t i = 0; i < eventTypes.size(); ++i) { | |
| 132 EventHandlerClass handlerClass; | |
| 133 if (!eventTypeToClass(eventTypes[i], &handlerClass)) | |
| 134 continue; | |
| 135 for (unsigned count = target.getEventListeners(eventTypes[i]).size(); co
unt > 0; --count) | |
| 136 didAddEventHandler(target, handlerClass); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target) | |
| 141 { | |
| 142 didRemoveAllEventHandlers(target); | |
| 143 } | |
| 144 | |
| 145 void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target, FrameHo
st* oldFrameHost, FrameHost* newFrameHost) | |
| 146 { | |
| 147 ASSERT(newFrameHost != oldFrameHost); | |
| 148 for (size_t i = 0; i < EventHandlerClassCount; ++i) { | |
| 149 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); | |
| 150 const EventTargetSet* targets = &oldFrameHost->eventHandlerRegistry().m_
targets[handlerClass]; | |
| 151 for (unsigned count = targets->count(&target); count > 0; --count) | |
| 152 newFrameHost->eventHandlerRegistry().didAddEventHandler(target, hand
lerClass); | |
| 153 oldFrameHost->eventHandlerRegistry().didRemoveAllEventHandlers(target); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) | |
| 158 { | |
| 159 for (size_t i = 0; i < EventHandlerClassCount; ++i) { | |
| 160 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); | |
| 161 updateEventHandlerInternal(RemoveAll, handlerClass, &target); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla
ss, bool hasActiveHandlers) | |
| 166 { | |
| 167 switch (handlerClass) { | |
| 168 // FIXME(sky): Remove these enums from the EventHandlerClass entirely. | |
| 169 case ScrollEvent: | |
| 170 case WheelEvent: | |
| 171 break; | |
| 172 case TouchEvent: | |
| 173 m_frameHost.chrome().client().needTouchEvents(hasActiveHandlers); | |
| 174 break; | |
| 175 #if ENABLE(ASSERT) | |
| 176 case EventsForTesting: | |
| 177 break; | |
| 178 #endif | |
| 179 default: | |
| 180 ASSERT_NOT_REACHED(); | |
| 181 break; | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerCl
ass handlerClass) | |
| 186 { | |
| 187 ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoo
rdinator(); | |
| 188 if (scrollingCoordinator && handlerClass == TouchEvent) | |
| 189 scrollingCoordinator->touchEventTargetRectsDidChange(); | |
| 190 } | |
| 191 | |
| 192 void EventHandlerRegistry::documentDetached(Document& document) | |
| 193 { | |
| 194 // Remove all event targets under the detached document. | |
| 195 for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCoun
t; ++handlerClassIndex) { | |
| 196 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerC
lassIndex); | |
| 197 Vector<EventTarget*> targetsToRemove; | |
| 198 const EventTargetSet* targets = &m_targets[handlerClass]; | |
| 199 for (EventTargetSet::const_iterator iter = targets->begin(); iter != tar
gets->end(); ++iter) { | |
| 200 if (Node* node = iter->key->toNode()) { | |
| 201 if (node->document() == &document) { | |
| 202 targetsToRemove.append(iter->key); | |
| 203 break; | |
| 204 } | |
| 205 } else if (iter->key->toDOMWindow()) { | |
| 206 // DOMWindows may outlive their documents, so we shouldn't remov
e their handlers | |
| 207 // here. | |
| 208 } else { | |
| 209 ASSERT_NOT_REACHED(); | |
| 210 } | |
| 211 } | |
| 212 for (size_t i = 0; i < targetsToRemove.size(); ++i) | |
| 213 updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[
i]); | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 void EventHandlerRegistry::checkConsistency() const | |
| 218 { | |
| 219 #if ENABLE(ASSERT) | |
| 220 for (size_t i = 0; i < EventHandlerClassCount; ++i) { | |
| 221 EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); | |
| 222 const EventTargetSet* targets = &m_targets[handlerClass]; | |
| 223 for (EventTargetSet::const_iterator iter = targets->begin(); iter != tar
gets->end(); ++iter) { | |
| 224 if (Node* node = iter->key->toNode()) { | |
| 225 // See the comment for |documentDetached| if either of these ass
ertions fails. | |
| 226 ASSERT(node->document().frameHost()); | |
| 227 ASSERT(node->document().frameHost() == &m_frameHost); | |
| 228 } else if (LocalDOMWindow* window = iter->key->toDOMWindow()) { | |
| 229 // If any of these assertions fail, LocalDOMWindow failed to unr
egister its handlers | |
| 230 // properly. | |
| 231 ASSERT(window->frame()); | |
| 232 ASSERT(window->frame()->host()); | |
| 233 ASSERT(window->frame()->host() == &m_frameHost); | |
| 234 } | |
| 235 } | |
| 236 } | |
| 237 #endif // ENABLE(ASSERT) | |
| 238 } | |
| 239 | |
| 240 } // namespace blink | |
| OLD | NEW |