f09abbeab0f3e1042a2d04d61a7280dc30ee83b7
[WebKit-https.git] / Source / WebCore / dom / EventListenerMap.cpp
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/NeverDestroyed.h>
41 #include <wtf/StdLibExtras.h>
42 #include <wtf/Vector.h>
43
44 using namespace WTF;
45
46 namespace WebCore {
47
48 #ifndef NDEBUG
49 void EventListenerMap::assertNoActiveIterators()
50 {
51     ASSERT(!m_activeIteratorCount);
52 }
53 #endif
54
55 EventListenerMap::EventListenerMap()
56 {
57 }
58
59 bool EventListenerMap::contains(const AtomicString& eventType) const
60 {
61     for (unsigned i = 0; i < m_entries.size(); ++i) {
62         if (m_entries[i].first == eventType)
63             return true;
64     }
65     return false;
66 }
67
68 bool EventListenerMap::containsCapturing(const AtomicString& eventType) const
69 {
70     for (unsigned i = 0; i < m_entries.size(); ++i) {
71         if (m_entries[i].first == eventType) {
72             const EventListenerVector* vector = m_entries[i].second.get();
73             for (unsigned j = 0; j < vector->size(); ++j) {
74                 if (vector->at(j).useCapture)
75                     return true;
76             }
77         }
78     }
79     return false;
80 }
81
82 void EventListenerMap::clear()
83 {
84     assertNoActiveIterators();
85
86     m_entries.clear();
87 }
88
89 Vector<AtomicString> EventListenerMap::eventTypes() const
90 {
91     Vector<AtomicString> types;
92     types.reserveInitialCapacity(m_entries.size());
93
94     for (unsigned i = 0; i < m_entries.size(); ++i)
95         types.uncheckedAppend(m_entries[i].first);
96
97     return types;
98 }
99
100 static bool addListenerToVector(EventListenerVector* vector, PassRefPtr<EventListener> listener, bool useCapture)
101 {
102     RegisteredEventListener registeredListener(listener, useCapture);
103
104     if (vector->find(registeredListener) != notFound)
105         return false; // Duplicate listener.
106
107     vector->append(registeredListener);
108     return true;
109 }
110
111 bool EventListenerMap::add(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
112 {
113     assertNoActiveIterators();
114
115     for (unsigned i = 0; i < m_entries.size(); ++i) {
116         if (m_entries[i].first == eventType)
117             return addListenerToVector(m_entries[i].second.get(), listener, useCapture);
118     }
119
120     m_entries.append(std::make_pair(eventType, std::make_unique<EventListenerVector>()));
121     return addListenerToVector(m_entries.last().second.get(), listener, useCapture);
122 }
123
124 static bool removeListenerFromVector(EventListenerVector* listenerVector, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener)
125 {
126     RegisteredEventListener registeredListener(listener, useCapture);
127     indexOfRemovedListener = listenerVector->find(registeredListener);
128     if (indexOfRemovedListener == notFound)
129         return false;
130     listenerVector->remove(indexOfRemovedListener);
131     return true;
132 }
133
134 bool EventListenerMap::remove(const AtomicString& eventType, EventListener* listener, bool useCapture, size_t& indexOfRemovedListener)
135 {
136     assertNoActiveIterators();
137
138     for (unsigned i = 0; i < m_entries.size(); ++i) {
139         if (m_entries[i].first == eventType) {
140             bool wasRemoved = removeListenerFromVector(m_entries[i].second.get(), listener, useCapture, indexOfRemovedListener);
141             if (m_entries[i].second->isEmpty())
142                 m_entries.remove(i);
143             return wasRemoved;
144         }
145     }
146
147     return false;
148 }
149
150 EventListenerVector* EventListenerMap::find(const AtomicString& eventType)
151 {
152     assertNoActiveIterators();
153
154     for (unsigned i = 0; i < m_entries.size(); ++i) {
155         if (m_entries[i].first == eventType)
156             return m_entries[i].second.get();
157     }
158
159     return nullptr;
160 }
161
162 static void removeFirstListenerCreatedFromMarkup(EventListenerVector& listenerVector)
163 {
164     bool foundListener = listenerVector.removeFirstMatching([] (const RegisteredEventListener& listener) {
165         return listener.listener->wasCreatedFromMarkup();
166     });
167     ASSERT_UNUSED(foundListener, foundListener);
168 }
169
170 void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomicString& eventType)
171 {
172     assertNoActiveIterators();
173
174     for (unsigned i = 0; i < m_entries.size(); ++i) {
175         if (m_entries[i].first == eventType) {
176             removeFirstListenerCreatedFromMarkup(*m_entries[i].second);
177             if (m_entries[i].second->isEmpty())
178                 m_entries.remove(i);
179             return;
180         }
181     }
182 }
183
184 static void copyListenersNotCreatedFromMarkupToTarget(const AtomicString& eventType, EventListenerVector* listenerVector, EventTarget* target)
185 {
186     for (size_t i = 0; i < listenerVector->size(); ++i) {
187         // Event listeners created from markup have already been transfered to the shadow tree during cloning.
188         if ((*listenerVector)[i].listener->wasCreatedFromMarkup())
189             continue;
190         target->addEventListener(eventType, (*listenerVector)[i].listener, (*listenerVector)[i].useCapture);
191     }
192 }
193
194 void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target)
195 {
196     assertNoActiveIterators();
197
198     for (unsigned i = 0; i < m_entries.size(); ++i)
199         copyListenersNotCreatedFromMarkupToTarget(m_entries[i].first, m_entries[i].second.get(), target);
200 }
201
202 EventListenerIterator::EventListenerIterator()
203     : m_map(0)
204     , m_entryIndex(0)
205     , m_index(0)
206 {
207 }
208
209 EventListenerIterator::EventListenerIterator(EventTarget* target)
210     : m_map(0)
211     , m_entryIndex(0)
212     , m_index(0)
213 {
214     ASSERT(target);
215     EventTargetData* data = target->eventTargetData();
216
217     if (!data)
218         return;
219
220     m_map = &data->eventListenerMap;
221
222 #ifndef NDEBUG
223     m_map->m_activeIteratorCount++;
224 #endif
225 }
226
227 #ifndef NDEBUG
228 EventListenerIterator::~EventListenerIterator()
229 {
230     if (m_map)
231         m_map->m_activeIteratorCount--;
232 }
233 #endif
234
235 EventListener* EventListenerIterator::nextListener()
236 {
237     if (!m_map)
238         return 0;
239
240     for (; m_entryIndex < m_map->m_entries.size(); ++m_entryIndex) {
241         EventListenerVector& listeners = *m_map->m_entries[m_entryIndex].second;
242         if (m_index < listeners.size())
243             return listeners[m_index++].listener.get();
244         m_index = 0;
245     }
246
247     return 0;
248 }
249
250 } // namespace WebCore