Always enable ENABLE(OFFLINE_WEB_APPLICATIONS)
[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 COMPUTER, 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 COMPUTER, 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 "Event.h"
36 #include "EventException.h"
37 #include <wtf/MainThread.h>
38 #include <wtf/StdLibExtras.h>
39 #include <wtf/Vector.h>
40
41 using namespace WTF;
42
43 namespace WebCore {
44
45 #ifndef NDEBUG
46 static int gEventDispatchForbidden = 0;
47
48 void forbidEventDispatch()
49 {
50     if (!isMainThread())
51         return;
52     ++gEventDispatchForbidden;
53 }
54
55 void allowEventDispatch()
56 {
57     if (!isMainThread())
58         return;
59     if (gEventDispatchForbidden > 0)
60         --gEventDispatchForbidden;
61 }
62
63 bool eventDispatchForbidden()
64 {
65     if (!isMainThread())
66         return false;
67     return gEventDispatchForbidden > 0;
68 }
69 #endif // NDEBUG
70
71 EventTargetData::EventTargetData()
72 {
73 }
74
75 EventTargetData::~EventTargetData()
76 {
77 }
78
79 EventTarget::~EventTarget()
80 {
81 }
82
83 EventSource* EventTarget::toEventSource()
84 {
85     return 0;
86 }
87
88 Node* EventTarget::toNode()
89 {
90     return 0;
91 }
92
93 DOMWindow* EventTarget::toDOMWindow()
94 {
95     return 0;
96 }
97
98 XMLHttpRequest* EventTarget::toXMLHttpRequest()
99 {
100     return 0;
101 }
102
103 XMLHttpRequestUpload* EventTarget::toXMLHttpRequestUpload()
104 {
105     return 0;
106 }
107
108 DOMApplicationCache* EventTarget::toDOMApplicationCache()
109 {
110     return 0;
111 }
112
113 #if ENABLE(SVG)
114 SVGElementInstance* EventTarget::toSVGElementInstance()
115 {
116     return 0;
117 }
118 #endif
119
120 #if ENABLE(WEB_AUDIO)
121 AudioContext* EventTarget::toAudioContext()
122 {
123     return 0;
124 }
125
126 JavaScriptAudioNode* EventTarget::toJavaScriptAudioNode()
127 {
128     return 0;
129 }
130 #endif
131
132 #if ENABLE(WEB_SOCKETS)
133 WebSocket* EventTarget::toWebSocket()
134 {
135     return 0;
136 }
137 #endif
138
139 MessagePort* EventTarget::toMessagePort()
140 {
141     return 0;
142 }
143
144 #if ENABLE(WORKERS)
145 Worker* EventTarget::toWorker()
146 {
147     return 0;
148 }
149
150 DedicatedWorkerContext* EventTarget::toDedicatedWorkerContext()
151 {
152     return 0;
153 }
154 #endif
155
156 #if ENABLE(SHARED_WORKERS)
157 SharedWorker* EventTarget::toSharedWorker()
158 {
159     return 0;
160 }
161 SharedWorkerContext* EventTarget::toSharedWorkerContext()
162 {
163     return 0;
164 }
165 #endif
166
167 #if ENABLE(NOTIFICATIONS)
168 Notification* EventTarget::toNotification()
169 {
170     return 0;
171 }
172 #endif
173
174 #if ENABLE(BLOB)
175 FileReader* EventTarget::toFileReader()
176 {
177     return 0;
178 }
179 #endif
180 #if ENABLE(FILE_SYSTEM)
181 FileWriter* EventTarget::toFileWriter()
182 {
183     return 0;
184 }
185 #endif
186
187 #if ENABLE(INDEXED_DATABASE)
188 IDBDatabase* EventTarget::toIDBDatabase()
189 {
190     return 0;
191 }
192 IDBRequest* EventTarget::toIDBRequest()
193 {
194     return 0;
195 }
196 IDBTransaction* EventTarget::toIDBTransaction()
197 {
198     return 0;
199 }
200 IDBVersionChangeRequest* EventTarget::toIDBVersionChangeRequest()
201 {
202     return 0;
203 }
204 #endif
205
206 #if ENABLE(MEDIA_STREAM)
207 MediaStream* EventTarget::toMediaStream()
208 {
209     return 0;
210 }
211
212 LocalMediaStream* EventTarget::toLocalMediaStream()
213 {
214     return 0;
215 }
216
217 PeerConnection* EventTarget::toPeerConnection()
218 {
219     return 0;
220 }
221 #endif
222
223 bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
224 {
225     EventTargetData* d = ensureEventTargetData();
226     return d->eventListenerMap.add(eventType, listener, useCapture);
227 }
228
229 bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
230 {
231     EventTargetData* d = eventTargetData();
232     if (!d)
233         return false;
234
235     size_t indexOfRemovedListener;
236
237     if (!d->eventListenerMap.remove(eventType, listener, useCapture, indexOfRemovedListener))
238         return false;
239
240     // Notify firing events planning to invoke the listener at 'index' that
241     // they have one less listener to invoke.
242     for (size_t i = 0; i < d->firingEventIterators.size(); ++i) {
243         if (eventType != d->firingEventIterators[i].eventType)
244             continue;
245
246         if (indexOfRemovedListener >= d->firingEventIterators[i].end)
247             continue;
248
249         --d->firingEventIterators[i].end;
250         if (indexOfRemovedListener <= d->firingEventIterators[i].iterator)
251             --d->firingEventIterators[i].iterator;
252     }
253
254     return true;
255 }
256
257 bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
258 {
259     clearAttributeEventListener(eventType);
260     if (!listener)
261         return false;
262     return addEventListener(eventType, listener, false);
263 }
264
265 EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
266 {
267     const EventListenerVector& entry = getEventListeners(eventType);
268     for (size_t i = 0; i < entry.size(); ++i) {
269         if (entry[i].listener->isAttribute())
270             return entry[i].listener.get();
271     }
272     return 0;
273 }
274
275 bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
276 {
277     EventListener* listener = getAttributeEventListener(eventType);
278     if (!listener)
279         return false;
280     return removeEventListener(eventType, listener, false);
281 }
282
283 bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
284 {
285     if (!event || event->type().isEmpty()) {
286         ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
287         return false;
288     }
289
290     if (event->isBeingDispatched()) {
291         ec = EventException::DISPATCH_REQUEST_ERR;
292         return false;
293     }
294
295     if (!scriptExecutionContext())
296         return false;
297
298     return dispatchEvent(event);
299 }
300
301 bool EventTarget::dispatchEvent(PassRefPtr<Event> event)
302 {
303     event->setTarget(this);
304     event->setCurrentTarget(this);
305     event->setEventPhase(Event::AT_TARGET);
306     bool defaultPrevented = fireEventListeners(event.get());
307     event->setEventPhase(0);
308     return defaultPrevented;
309 }
310
311 void EventTarget::uncaughtExceptionInEventHandler()
312 {
313 }
314
315 bool EventTarget::fireEventListeners(Event* event)
316 {
317     ASSERT(!eventDispatchForbidden());
318     ASSERT(event && !event->type().isEmpty());
319
320     EventTargetData* d = eventTargetData();
321     if (!d)
322         return true;
323
324     EventListenerVector* listenerVector = d->eventListenerMap.find(event->type());
325
326     if (listenerVector)
327         fireEventListeners(event, d, *listenerVector);
328     
329     return !event->defaultPrevented();
330 }
331         
332 void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
333 {
334     RefPtr<EventTarget> protect = this;
335
336     // Fire all listeners registered for this event. Don't fire listeners removed
337     // during event dispatch. Also, don't fire event listeners added during event
338     // dispatch. Conveniently, all new event listeners will be added after 'end',
339     // so iterating to 'end' naturally excludes new event listeners.
340
341     size_t i = 0;
342     size_t end = entry.size();
343     d->firingEventIterators.append(FiringEventIterator(event->type(), i, end));
344     for ( ; i < end; ++i) {
345         RegisteredEventListener& registeredListener = entry[i];
346         if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
347             continue;
348         if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
349             continue;
350
351         // If stopImmediatePropagation has been called, we just break out immediately, without
352         // handling any more events on this target.
353         if (event->immediatePropagationStopped())
354             break;
355
356         // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
357         // event listeners, even though that violates some versions of the DOM spec.
358         registeredListener.listener->handleEvent(scriptExecutionContext(), event);
359     }
360     d->firingEventIterators.removeLast();
361 }
362
363 const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
364 {
365     DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ());
366
367     EventTargetData* d = eventTargetData();
368     if (!d)
369         return emptyVector;
370
371     EventListenerVector* listenerVector = d->eventListenerMap.find(eventType);
372     if (!listenerVector)
373         return emptyVector;
374
375     return *listenerVector;
376 }
377
378 void EventTarget::removeAllEventListeners()
379 {
380     EventTargetData* d = eventTargetData();
381     if (!d)
382         return;
383     d->eventListenerMap.clear();
384
385     // Notify firing events planning to invoke the listener at 'index' that
386     // they have one less listener to invoke.
387     for (size_t i = 0; i < d->firingEventIterators.size(); ++i) {
388         d->firingEventIterators[i].iterator = 0;
389         d->firingEventIterators[i].end = 0;
390     }
391 }
392
393 } // namespace WebCore