Crash in WebCore::UserGestureIndicator::processingUserGesture with WebWorkers
[WebKit-https.git] / Source / WebCore / dom / EventTarget.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  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29  *
30  */
31
32 #include "config.h"
33 #include "EventTarget.h"
34
35 #include "EventException.h"
36 #include "InspectorInstrumentation.h"
37 #include "ScriptController.h"
38 #include "WebKitTransitionEvent.h"
39 #include <wtf/MainThread.h>
40 #include <wtf/Ref.h>
41 #include <wtf/StdLibExtras.h>
42 #include <wtf/Vector.h>
43
44 using namespace WTF;
45
46 namespace WebCore {
47
48 EventTargetData::EventTargetData()
49 {
50 }
51
52 EventTargetData::~EventTargetData()
53 {
54 }
55
56 EventTarget::~EventTarget()
57 {
58 }
59
60 Node* EventTarget::toNode()
61 {
62     return 0;
63 }
64
65 DOMWindow* EventTarget::toDOMWindow()
66 {
67     return 0;
68 }
69
70 bool EventTarget::isMessagePort() const
71 {
72     return false;
73 }
74
75 bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
76 {
77     return ensureEventTargetData().eventListenerMap.add(eventType, listener, useCapture);
78 }
79
80 bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
81 {
82     EventTargetData* d = eventTargetData();
83     if (!d)
84         return false;
85
86     size_t indexOfRemovedListener;
87
88     if (!d->eventListenerMap.remove(eventType, listener, useCapture, indexOfRemovedListener))
89         return false;
90
91     // Notify firing events planning to invoke the listener at 'index' that
92     // they have one less listener to invoke.
93     if (!d->firingEventIterators)
94         return true;
95     for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
96         FiringEventIterator& firingIterator = d->firingEventIterators->at(i);
97         if (eventType != firingIterator.eventType)
98             continue;
99
100         if (indexOfRemovedListener >= firingIterator.size)
101             continue;
102
103         --firingIterator.size;
104         if (indexOfRemovedListener <= firingIterator.iterator)
105             --firingIterator.iterator;
106     }
107
108     return true;
109 }
110
111 bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
112 {
113     clearAttributeEventListener(eventType);
114     if (!listener)
115         return false;
116     return addEventListener(eventType, listener, false);
117 }
118
119 EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
120 {
121     const EventListenerVector& entry = getEventListeners(eventType);
122     for (size_t i = 0; i < entry.size(); ++i) {
123         if (entry[i].listener->isAttribute())
124             return entry[i].listener.get();
125     }
126     return 0;
127 }
128
129 bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
130 {
131     EventListener* listener = getAttributeEventListener(eventType);
132     if (!listener)
133         return false;
134     return removeEventListener(eventType, listener, false);
135 }
136
137 bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
138 {
139     if (!event || event->type().isEmpty()) {
140         ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
141         return false;
142     }
143
144     if (event->isBeingDispatched()) {
145         ec = EventException::DISPATCH_REQUEST_ERR;
146         return false;
147     }
148
149     if (!scriptExecutionContext())
150         return false;
151
152     return dispatchEvent(event);
153 }
154
155 bool EventTarget::dispatchEvent(PassRefPtr<Event> event)
156 {
157     event->setTarget(this);
158     event->setCurrentTarget(this);
159     event->setEventPhase(Event::AT_TARGET);
160     bool defaultPrevented = fireEventListeners(event.get());
161     event->setEventPhase(0);
162     return defaultPrevented;
163 }
164
165 void EventTarget::uncaughtExceptionInEventHandler()
166 {
167 }
168
169 static const AtomicString& legacyType(const Event* event)
170 {
171     if (event->type() == eventNames().transitionendEvent)
172         return eventNames().webkitTransitionEndEvent;
173
174     if (event->type() == eventNames().wheelEvent)
175         return eventNames().mousewheelEvent;
176
177     return emptyAtom;
178 }
179
180 bool EventTarget::fireEventListeners(Event* event)
181 {
182     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
183     ASSERT(event && !event->type().isEmpty());
184
185     EventTargetData* d = eventTargetData();
186     if (!d)
187         return true;
188
189     EventListenerVector* legacyListenersVector = 0;
190     const AtomicString& legacyTypeName = legacyType(event);
191     if (!legacyTypeName.isEmpty())
192         legacyListenersVector = d->eventListenerMap.find(legacyTypeName);
193
194     EventListenerVector* listenersVector = d->eventListenerMap.find(event->type());
195
196     if (listenersVector)
197         fireEventListeners(event, d, *listenersVector);
198     else if (legacyListenersVector) {
199         AtomicString typeName = event->type();
200         event->setType(legacyTypeName);
201         fireEventListeners(event, d, *legacyListenersVector);
202         event->setType(typeName);
203     }
204
205     return !event->defaultPrevented();
206 }
207         
208 void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
209 {
210     Ref<EventTarget> protect(*this);
211
212     // Fire all listeners registered for this event. Don't fire listeners removed during event dispatch.
213     // Also, don't fire event listeners added during event dispatch. Conveniently, all new event listeners will be added
214     // after or at index |size|, so iterating up to (but not including) |size| naturally excludes new event listeners.
215
216     size_t i = 0;
217     size_t size = entry.size();
218     if (!d->firingEventIterators)
219         d->firingEventIterators = std::make_unique<FiringEventIteratorVector>();
220     d->firingEventIterators->append(FiringEventIterator(event->type(), i, size));
221
222     ScriptExecutionContext* context = scriptExecutionContext();
223     Document* document = nullptr;
224     InspectorInstrumentationCookie willDispatchEventCookie;
225     if (is<Document>(context)) {
226         document = downcast<Document>(context);
227         willDispatchEventCookie = InspectorInstrumentation::willDispatchEvent(document, *event, size > 0);
228     }
229
230     for (; i < size; ++i) {
231         RegisteredEventListener& registeredListener = entry[i];
232         if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
233             continue;
234         if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
235             continue;
236
237         // If stopImmediatePropagation has been called, we just break out immediately, without
238         // handling any more events on this target.
239         if (event->immediatePropagationStopped())
240             break;
241
242         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(context, event);
243         // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
244         // event listeners, even though that violates some versions of the DOM spec.
245         registeredListener.listener->handleEvent(context, event);
246         InspectorInstrumentation::didHandleEvent(cookie);
247     }
248     d->firingEventIterators->removeLast();
249
250     if (document)
251         InspectorInstrumentation::didDispatchEvent(willDispatchEventCookie);
252 }
253
254 const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
255 {
256     DEPRECATED_DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ());
257
258     EventTargetData* d = eventTargetData();
259     if (!d)
260         return emptyVector;
261
262     EventListenerVector* listenerVector = d->eventListenerMap.find(eventType);
263     if (!listenerVector)
264         return emptyVector;
265
266     return *listenerVector;
267 }
268
269 void EventTarget::removeAllEventListeners()
270 {
271     EventTargetData* d = eventTargetData();
272     if (!d)
273         return;
274     d->eventListenerMap.clear();
275
276     // Notify firing events planning to invoke the listener at 'index' that
277     // they have one less listener to invoke.
278     if (d->firingEventIterators) {
279         for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
280             d->firingEventIterators->at(i).iterator = 0;
281             d->firingEventIterators->at(i).size = 0;
282         }
283     }
284 }
285
286 } // namespace WebCore