blob: ad0b72b8288fd441bcc85bdcc2e12c3541b058ac [file] [log] [blame]
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001/*
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 "core/dom/EventListenerMap.h"
35
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010036#include "core/dom/EventTarget.h"
Ben Murdoch591b9582013-07-10 11:41:44 +010037#include "wtf/StdLibExtras.h"
38#include "wtf/Vector.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010039
40#ifndef NDEBUG
Ben Murdoch591b9582013-07-10 11:41:44 +010041#include "wtf/Threading.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010042#endif
43
44using namespace WTF;
45
46namespace WebCore {
47
48#ifndef NDEBUG
49static Mutex& activeIteratorCountMutex()
50{
51 DEFINE_STATIC_LOCAL(Mutex, mutex, ());
52 return mutex;
53}
54
55void EventListenerMap::assertNoActiveIterators()
56{
57 MutexLocker locker(activeIteratorCountMutex());
58 ASSERT(!m_activeIteratorCount);
59}
60#endif
61
62EventListenerMap::EventListenerMap()
63#ifndef NDEBUG
64 : m_activeIteratorCount(0)
65#endif
66{
67}
68
69bool 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
Ben Murdoche69819b2013-07-17 14:56:49 +010078bool 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
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010092void EventListenerMap::clear()
93{
94 assertNoActiveIterators();
95
96 m_entries.clear();
97}
98
99Vector<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
110static bool addListenerToVector(EventListenerVector* vector, PassRefPtr<EventListener> listener, bool useCapture)
111{
112 RegisteredEventListener registeredListener(listener, useCapture);
113
114 if (vector->find(registeredListener) != notFound)
115 return false; // Duplicate listener.
116
117 vector->append(registeredListener);
118 return true;
119}
120
121bool 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
134static 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 == notFound)
139 return false;
140 listenerVector->remove(indexOfRemovedListener);
141 return true;
142}
143
144bool 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
160EventListenerVector* 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
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100172static 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
187void 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
201static 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
211void 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
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100219EventListenerIterator::EventListenerIterator()
220 : m_map(0)
221 , m_entryIndex(0)
222 , m_index(0)
223{
224}
225
226EventListenerIterator::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
248EventListenerIterator::~EventListenerIterator()
249{
250 if (m_map) {
251 MutexLocker locker(activeIteratorCountMutex());
252 m_map->m_activeIteratorCount--;
253 }
254}
255#endif
256
257EventListener* 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