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