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 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 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    DEPRECATED_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, std::make_unique<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
175static void removeFirstListenerCreatedFromMarkup(EventListenerVector* listenerVector)
176{
177    bool foundListener = false;
178
179    for (size_t i = 0; i < listenerVector->size(); ++i) {
180        if (!listenerVector->at(i).listener->wasCreatedFromMarkup())
181            continue;
182        foundListener = true;
183        listenerVector->remove(i);
184        break;
185    }
186
187    ASSERT_UNUSED(foundListener, foundListener);
188}
189
190void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType)
191{
192    assertNoActiveIterators();
193
194    for (unsigned i = 0; i < m_entries.size(); ++i) {
195        if (m_entries[i].first == eventType) {
196            removeFirstListenerCreatedFromMarkup(m_entries[i].second.get());
197            if (m_entries[i].second->isEmpty())
198                m_entries.remove(i);
199            return;
200        }
201    }
202}
203
204static void copyListenersNotCreatedFromMarkupToTarget(const AtomicString& eventType, EventListenerVector* listenerVector, EventTarget* target)
205{
206    for (size_t i = 0; i < listenerVector->size(); ++i) {
207        // Event listeners created from markup have already been transfered to the shadow tree during cloning.
208        if ((*listenerVector)[i].listener->wasCreatedFromMarkup())
209            continue;
210        target->addEventListener(eventType, (*listenerVector)[i].listener, (*listenerVector)[i].useCapture);
211    }
212}
213
214void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target)
215{
216    assertNoActiveIterators();
217
218    for (unsigned i = 0; i < m_entries.size(); ++i)
219        copyListenersNotCreatedFromMarkupToTarget(m_entries[i].first, m_entries[i].second.get(), target);
220}
221
222EventListenerIterator::EventListenerIterator()
223    : m_map(0)
224    , m_entryIndex(0)
225    , m_index(0)
226{
227}
228
229EventListenerIterator::EventListenerIterator(EventTarget* target)
230    : m_map(0)
231    , m_entryIndex(0)
232    , m_index(0)
233{
234    ASSERT(target);
235    EventTargetData* data = target->eventTargetData();
236
237    if (!data)
238        return;
239
240    m_map = &data->eventListenerMap;
241
242#ifndef NDEBUG
243    {
244        MutexLocker locker(activeIteratorCountMutex());
245        m_map->m_activeIteratorCount++;
246    }
247#endif
248}
249
250#ifndef NDEBUG
251EventListenerIterator::~EventListenerIterator()
252{
253    if (m_map) {
254        MutexLocker locker(activeIteratorCountMutex());
255        m_map->m_activeIteratorCount--;
256    }
257}
258#endif
259
260EventListener* EventListenerIterator::nextListener()
261{
262    if (!m_map)
263        return 0;
264
265    for (; m_entryIndex < m_map->m_entries.size(); ++m_entryIndex) {
266        EventListenerVector& listeners = *m_map->m_entries[m_entryIndex].second;
267        if (m_index < listeners.size())
268            return listeners[m_index++].listener.get();
269        m_index = 0;
270    }
271
272    return 0;
273}
274
275} // namespace WebCore
276