1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 * Copyright (C) 2006 Alexey Proskuryakov (ap (at) webkit.org) 7 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 8 * Copyright (C) 2011 Andreas Kling (kling (at) webkit.org) 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 27 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 #include "config.h" 34 #include "core/events/EventListenerMap.h" 35 36 #include "core/events/EventTarget.h" 37 #include "wtf/StdLibExtras.h" 38 #include "wtf/Vector.h" 39 40 #ifndef NDEBUG 41 #include "wtf/ThreadingPrimitives.h" 42 #endif 43 44 using namespace WTF; 45 46 namespace WebCore { 47 48 #ifndef NDEBUG 49 static Mutex& activeIteratorCountMutex() 50 { 51 DEFINE_STATIC_LOCAL(Mutex, mutex, ()); 52 return mutex; 53 } 54 55 void EventListenerMap::assertNoActiveIterators() 56 { 57 MutexLocker locker(activeIteratorCountMutex()); 58 ASSERT(!m_activeIteratorCount); 59 } 60 #endif 61 62 EventListenerMap::EventListenerMap() 63 #ifndef NDEBUG 64 : m_activeIteratorCount(0) 65 #endif 66 { 67 } 68 69 bool EventListenerMap::contains(const AtomicString& eventType) const 70 { 71 for (unsigned i = 0; i < m_entries.size(); ++i) { 72 if (m_entries[i].first == eventType) 73 return true; 74 } 75 return false; 76 } 77 78 bool EventListenerMap::containsCapturing(const AtomicString& eventType) const 79 { 80 for (unsigned i = 0; i < m_entries.size(); ++i) { 81 if (m_entries[i].first == eventType) { 82 const EventListenerVector* vector = m_entries[i].second.get(); 83 for (unsigned j = 0; j < vector->size(); ++j) { 84 if (vector->at(j).useCapture) 85 return true; 86 } 87 } 88 } 89 return false; 90 } 91 92 void EventListenerMap::clear() 93 { 94 assertNoActiveIterators(); 95 96 m_entries.clear(); 97 } 98 99 Vector<AtomicString> EventListenerMap::eventTypes() const 100 { 101 Vector<AtomicString> types; 102 types.reserveInitialCapacity(m_entries.size()); 103 104 for (unsigned i = 0; i < m_entries.size(); ++i) 105 types.uncheckedAppend(m_entries[i].first); 106 107 return types; 108 } 109 110 static bool addListenerToVector(EventListenerVector* vector, PassRefPtr<EventListener> listener, bool useCapture) 111 { 112 RegisteredEventListener registeredListener(listener, useCapture); 113 114 if (vector->find(registeredListener) != kNotFound) 115 return false; // Duplicate listener. 116 117 vector->append(registeredListener); 118 return true; 119 } 120 121 bool EventListenerMap::add(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 122 { 123 assertNoActiveIterators(); 124 125 for (unsigned i = 0; i < m_entries.size(); ++i) { 126 if (m_entries[i].first == eventType) 127 return addListenerToVector(m_entries[i].second.get(), listener, useCapture); 128 } 129 130 m_entries.append(std::make_pair(eventType, adoptPtr(new EventListenerVector))); 131 return addListenerToVector(m_entries.last().second.get(), listener, useCapture); 132 } 133 134 static bool removeListenerFromVector(EventListenerVector* listenerVector, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener) 135 { 136 RegisteredEventListener registeredListener(listener, useCapture); 137 indexOfRemovedListener = listenerVector->find(registeredListener); 138 if (indexOfRemovedListener == kNotFound) 139 return false; 140 listenerVector->remove(indexOfRemovedListener); 141 return true; 142 } 143 144 bool EventListenerMap::remove(const AtomicString& eventType, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener) 145 { 146 assertNoActiveIterators(); 147 148 for (unsigned i = 0; i < m_entries.size(); ++i) { 149 if (m_entries[i].first == eventType) { 150 bool wasRemoved = removeListenerFromVector(m_entries[i].second.get(), listener, useCapture, indexOfRemovedListener); 151 if (m_entries[i].second->isEmpty()) 152 m_entries.remove(i); 153 return wasRemoved; 154 } 155 } 156 157 return false; 158 } 159 160 EventListenerVector* EventListenerMap::find(const AtomicString& eventType) 161 { 162 assertNoActiveIterators(); 163 164 for (unsigned i = 0; i < m_entries.size(); ++i) { 165 if (m_entries[i].first == eventType) 166 return m_entries[i].second.get(); 167 } 168 169 return 0; 170 } 171 172 static void removeFirstListenerCreatedFromMarkup(EventListenerVector* listenerVector) 173 { 174 bool foundListener = false; 175 176 for (size_t i = 0; i < listenerVector->size(); ++i) { 177 if (!listenerVector->at(i).listener->wasCreatedFromMarkup()) 178 continue; 179 foundListener = true; 180 listenerVector->remove(i); 181 break; 182 } 183 184 ASSERT_UNUSED(foundListener, foundListener); 185 } 186 187 void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType) 188 { 189 assertNoActiveIterators(); 190 191 for (unsigned i = 0; i < m_entries.size(); ++i) { 192 if (m_entries[i].first == eventType) { 193 removeFirstListenerCreatedFromMarkup(m_entries[i].second.get()); 194 if (m_entries[i].second->isEmpty()) 195 m_entries.remove(i); 196 return; 197 } 198 } 199 } 200 201 static void copyListenersNotCreatedFromMarkupToTarget(const AtomicString& eventType, EventListenerVector* listenerVector, EventTarget* target) 202 { 203 for (size_t i = 0; i < listenerVector->size(); ++i) { 204 // Event listeners created from markup have already been transfered to the shadow tree during cloning. 205 if ((*listenerVector)[i].listener->wasCreatedFromMarkup()) 206 continue; 207 target->addEventListener(eventType, (*listenerVector)[i].listener, (*listenerVector)[i].useCapture); 208 } 209 } 210 211 void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target) 212 { 213 assertNoActiveIterators(); 214 215 for (unsigned i = 0; i < m_entries.size(); ++i) 216 copyListenersNotCreatedFromMarkupToTarget(m_entries[i].first, m_entries[i].second.get(), target); 217 } 218 219 EventListenerIterator::EventListenerIterator() 220 : m_map(0) 221 , m_entryIndex(0) 222 , m_index(0) 223 { 224 } 225 226 EventListenerIterator::EventListenerIterator(EventTarget* target) 227 : m_map(0) 228 , m_entryIndex(0) 229 , m_index(0) 230 { 231 ASSERT(target); 232 EventTargetData* data = target->eventTargetData(); 233 234 if (!data) 235 return; 236 237 m_map = &data->eventListenerMap; 238 239 #ifndef NDEBUG 240 { 241 MutexLocker locker(activeIteratorCountMutex()); 242 m_map->m_activeIteratorCount++; 243 } 244 #endif 245 } 246 247 #ifndef NDEBUG 248 EventListenerIterator::~EventListenerIterator() 249 { 250 if (m_map) { 251 MutexLocker locker(activeIteratorCountMutex()); 252 m_map->m_activeIteratorCount--; 253 } 254 } 255 #endif 256 257 EventListener* EventListenerIterator::nextListener() 258 { 259 if (!m_map) 260 return 0; 261 262 for (; m_entryIndex < m_map->m_entries.size(); ++m_entryIndex) { 263 EventListenerVector& listeners = *m_map->m_entries[m_entryIndex].second; 264 if (m_index < listeners.size()) 265 return listeners[m_index++].listener.get(); 266 m_index = 0; 267 } 268 269 return 0; 270 } 271 272 } // namespace WebCore 273