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 "core/events/EventListenerMap.h"
35
36#include "core/events/EventTarget.h"
37#include "wtf/StdLibExtras.h"
38#include "wtf/Vector.h"
39
40#if ENABLE(ASSERT)
41#include "wtf/ThreadingPrimitives.h"
42#endif
43
44using namespace WTF;
45
46namespace blink {
47
48#if ENABLE(ASSERT)
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#if ENABLE(ASSERT)
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
78bool 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
92void 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) != kNotFound)
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 == kNotFound)
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
172static 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
219EventListenerIterator::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#if ENABLE(ASSERT)
240    {
241        MutexLocker locker(activeIteratorCountMutex());
242        m_map->m_activeIteratorCount++;
243    }
244#endif
245}
246
247#if ENABLE(ASSERT)
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 blink
273