1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 7 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 8 * Copyright (C) 2011 Andreas Kling (kling@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 "EventListenerMap.h" 35 36#include "Event.h" 37#include "EventException.h" 38#include "EventTarget.h" 39#include <wtf/MainThread.h> 40#include <wtf/StdLibExtras.h> 41#include <wtf/Vector.h> 42 43#ifndef NDEBUG 44#include <wtf/Threading.h> 45#endif 46 47using namespace WTF; 48 49namespace WebCore { 50 51#ifndef NDEBUG 52static Mutex& activeIteratorCountMutex() 53{ 54 DEFINE_STATIC_LOCAL(Mutex, mutex, ()); 55 return mutex; 56} 57 58void EventListenerMap::assertNoActiveIterators() 59{ 60 MutexLocker locker(activeIteratorCountMutex()); 61 ASSERT(!m_activeIteratorCount); 62} 63#endif 64 65EventListenerMap::EventListenerMap() 66#ifndef NDEBUG 67 : m_activeIteratorCount(0) 68#endif 69{ 70} 71 72bool EventListenerMap::contains(const AtomicString& eventType) const 73{ 74 for (unsigned i = 0; i < m_entries.size(); ++i) { 75 if (m_entries[i].first == eventType) 76 return true; 77 } 78 return false; 79} 80 81bool EventListenerMap::containsCapturing(const AtomicString& eventType) const 82{ 83 for (unsigned i = 0; i < m_entries.size(); ++i) { 84 if (m_entries[i].first == eventType) { 85 const EventListenerVector* vector = m_entries[i].second.get(); 86 for (unsigned j = 0; j < vector->size(); ++j) { 87 if (vector->at(j).useCapture) 88 return true; 89 } 90 } 91 } 92 return false; 93} 94 95void EventListenerMap::clear() 96{ 97 assertNoActiveIterators(); 98 99 m_entries.clear(); 100} 101 102Vector<AtomicString> EventListenerMap::eventTypes() const 103{ 104 Vector<AtomicString> types; 105 types.reserveInitialCapacity(m_entries.size()); 106 107 for (unsigned i = 0; i < m_entries.size(); ++i) 108 types.uncheckedAppend(m_entries[i].first); 109 110 return types; 111} 112 113static bool addListenerToVector(EventListenerVector* vector, PassRefPtr<EventListener> listener, bool useCapture) 114{ 115 RegisteredEventListener registeredListener(listener, useCapture); 116 117 if (vector->find(registeredListener) != notFound) 118 return false; // Duplicate listener. 119 120 vector->append(registeredListener); 121 return true; 122} 123 124bool EventListenerMap::add(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 125{ 126 assertNoActiveIterators(); 127 128 for (unsigned i = 0; i < m_entries.size(); ++i) { 129 if (m_entries[i].first == eventType) 130 return addListenerToVector(m_entries[i].second.get(), listener, useCapture); 131 } 132 133 m_entries.append(std::make_pair(eventType, adoptPtr(new EventListenerVector))); 134 return addListenerToVector(m_entries.last().second.get(), listener, useCapture); 135} 136 137static bool removeListenerFromVector(EventListenerVector* listenerVector, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener) 138{ 139 RegisteredEventListener registeredListener(listener, useCapture); 140 indexOfRemovedListener = listenerVector->find(registeredListener); 141 if (indexOfRemovedListener == notFound) 142 return false; 143 listenerVector->remove(indexOfRemovedListener); 144 return true; 145} 146 147bool EventListenerMap::remove(const AtomicString& eventType, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener) 148{ 149 assertNoActiveIterators(); 150 151 for (unsigned i = 0; i < m_entries.size(); ++i) { 152 if (m_entries[i].first == eventType) { 153 bool wasRemoved = removeListenerFromVector(m_entries[i].second.get(), listener, useCapture, indexOfRemovedListener); 154 if (m_entries[i].second->isEmpty()) 155 m_entries.remove(i); 156 return wasRemoved; 157 } 158 } 159 160 return false; 161} 162 163EventListenerVector* EventListenerMap::find(const AtomicString& eventType) 164{ 165 assertNoActiveIterators(); 166 167 for (unsigned i = 0; i < m_entries.size(); ++i) { 168 if (m_entries[i].first == eventType) 169 return m_entries[i].second.get(); 170 } 171 172 return 0; 173} 174 175#if ENABLE(SVG) 176 177static void removeFirstListenerCreatedFromMarkup(EventListenerVector* listenerVector) 178{ 179 bool foundListener = false; 180 181 for (size_t i = 0; i < listenerVector->size(); ++i) { 182 if (!listenerVector->at(i).listener->wasCreatedFromMarkup()) 183 continue; 184 foundListener = true; 185 listenerVector->remove(i); 186 break; 187 } 188 189 ASSERT_UNUSED(foundListener, foundListener); 190} 191 192void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType) 193{ 194 assertNoActiveIterators(); 195 196 for (unsigned i = 0; i < m_entries.size(); ++i) { 197 if (m_entries[i].first == eventType) { 198 removeFirstListenerCreatedFromMarkup(m_entries[i].second.get()); 199 if (m_entries[i].second->isEmpty()) 200 m_entries.remove(i); 201 return; 202 } 203 } 204} 205 206static void copyListenersNotCreatedFromMarkupToTarget(const AtomicString& eventType, EventListenerVector* listenerVector, EventTarget* target) 207{ 208 for (size_t i = 0; i < listenerVector->size(); ++i) { 209 // Event listeners created from markup have already been transfered to the shadow tree during cloning. 210 if ((*listenerVector)[i].listener->wasCreatedFromMarkup()) 211 continue; 212 target->addEventListener(eventType, (*listenerVector)[i].listener, (*listenerVector)[i].useCapture); 213 } 214} 215 216void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target) 217{ 218 assertNoActiveIterators(); 219 220 for (unsigned i = 0; i < m_entries.size(); ++i) 221 copyListenersNotCreatedFromMarkupToTarget(m_entries[i].first, m_entries[i].second.get(), target); 222} 223 224#endif // ENABLE(SVG) 225 226EventListenerIterator::EventListenerIterator() 227 : m_map(0) 228 , m_entryIndex(0) 229 , m_index(0) 230{ 231} 232 233EventListenerIterator::EventListenerIterator(EventTarget* target) 234 : m_map(0) 235 , m_entryIndex(0) 236 , m_index(0) 237{ 238 ASSERT(target); 239 EventTargetData* data = target->eventTargetData(); 240 241 if (!data) 242 return; 243 244 m_map = &data->eventListenerMap; 245 246#ifndef NDEBUG 247 { 248 MutexLocker locker(activeIteratorCountMutex()); 249 m_map->m_activeIteratorCount++; 250 } 251#endif 252} 253 254#ifndef NDEBUG 255EventListenerIterator::~EventListenerIterator() 256{ 257 if (m_map) { 258 MutexLocker locker(activeIteratorCountMutex()); 259 m_map->m_activeIteratorCount--; 260 } 261} 262#endif 263 264EventListener* EventListenerIterator::nextListener() 265{ 266 if (!m_map) 267 return 0; 268 269 for (; m_entryIndex < m_map->m_entries.size(); ++m_entryIndex) { 270 EventListenerVector& listeners = *m_map->m_entries[m_entryIndex].second; 271 if (m_index < listeners.size()) 272 return listeners[m_index++].listener.get(); 273 m_index = 0; 274 } 275 276 return 0; 277} 278 279} // namespace WebCore 280