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, 2008 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 #ifndef EventTarget_h
33 #define EventTarget_h
34 
35 #include "EventNames.h"
36 #include "RegisteredEventListener.h"
37 #include <wtf/Forward.h>
38 #include <wtf/HashMap.h>
39 #include <wtf/text/AtomicStringHash.h>
40 
41 namespace WebCore {
42 
43     class AudioContext;
44     class AbstractWorker;
45     class DedicatedWorkerContext;
46     class DOMApplicationCache;
47     class DOMWindow;
48     class Event;
49     class EventListener;
50     class EventSource;
51     class FileReader;
52     class FileWriter;
53     class IDBDatabase;
54     class IDBRequest;
55     class IDBTransaction;
56     class IDBVersionChangeRequest;
57     class JavaScriptAudioNode;
58     class MessagePort;
59     class Node;
60     class Notification;
61     class SVGElementInstance;
62     class ScriptExecutionContext;
63     class SharedWorker;
64     class SharedWorkerContext;
65     class WebSocket;
66     class Worker;
67     class XMLHttpRequest;
68     class XMLHttpRequestUpload;
69 
70     typedef int ExceptionCode;
71 
72     struct FiringEventIterator {
FiringEventIteratorFiringEventIterator73         FiringEventIterator(const AtomicString& eventType, size_t& iterator, size_t& end)
74             : eventType(eventType)
75             , iterator(iterator)
76             , end(end)
77         {
78         }
79 
80         const AtomicString& eventType;
81         size_t& iterator;
82         size_t& end;
83     };
84     typedef Vector<FiringEventIterator, 1> FiringEventIteratorVector;
85 
86     typedef Vector<RegisteredEventListener, 1> EventListenerVector;
87     typedef HashMap<AtomicString, EventListenerVector*> EventListenerMap;
88 
89     struct EventTargetData {
90         WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED;
91     public:
92         EventTargetData();
93         ~EventTargetData();
94 
95         EventListenerMap eventListenerMap;
96         FiringEventIteratorVector firingEventIterators;
97     };
98 
99     class EventTarget {
100     public:
ref()101         void ref() { refEventTarget(); }
deref()102         void deref() { derefEventTarget(); }
103 
104         virtual EventSource* toEventSource();
105         virtual MessagePort* toMessagePort();
106         virtual Node* toNode();
107         virtual DOMWindow* toDOMWindow();
108         virtual XMLHttpRequest* toXMLHttpRequest();
109         virtual XMLHttpRequestUpload* toXMLHttpRequestUpload();
110 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
111         virtual DOMApplicationCache* toDOMApplicationCache();
112 #endif
113 #if ENABLE(SVG)
114         virtual SVGElementInstance* toSVGElementInstance();
115 #endif
116 #if ENABLE(WORKERS)
117         virtual Worker* toWorker();
118         virtual DedicatedWorkerContext* toDedicatedWorkerContext();
119 #endif
120 #if ENABLE(SHARED_WORKERS)
121         virtual SharedWorker* toSharedWorker();
122         virtual SharedWorkerContext* toSharedWorkerContext();
123 #endif
124 
125 #if ENABLE(WEB_AUDIO)
126         virtual AudioContext* toAudioContext();
127         virtual JavaScriptAudioNode* toJavaScriptAudioNode();
128 #endif
129 
130 #if ENABLE(WEB_SOCKETS)
131         virtual WebSocket* toWebSocket();
132 #endif
133 
134 #if ENABLE(NOTIFICATIONS)
135         virtual Notification* toNotification();
136 #endif
137 #if ENABLE(BLOB)
138         virtual FileReader* toFileReader();
139 #endif
140 #if ENABLE(FILE_SYSTEM)
141         virtual FileWriter* toFileWriter();
142 #endif
143 
144 #if ENABLE(INDEXED_DATABASE)
145         virtual IDBDatabase* toIDBDatabase();
146         virtual IDBRequest* toIDBRequest();
147         virtual IDBTransaction* toIDBTransaction();
148         virtual IDBVersionChangeRequest* toIDBVersionChangeRequest();
149 #endif
150 
151         virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
152 
153         virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
154         virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
155         virtual void removeAllEventListeners();
156         virtual bool dispatchEvent(PassRefPtr<Event>);
157         bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); // DOM API
158         virtual void uncaughtExceptionInEventHandler();
159 
160         // Used for legacy "onEvent" attribute APIs.
161         bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>);
162         bool clearAttributeEventListener(const AtomicString& eventType);
163         EventListener* getAttributeEventListener(const AtomicString& eventType);
164 
165         bool hasEventListeners();
166         bool hasEventListeners(const AtomicString& eventType);
167         const EventListenerVector& getEventListeners(const AtomicString& eventType);
168 
169         bool fireEventListeners(Event*);
170         bool isFiringEventListeners();
171 
172 #if USE(JSC)
173         void visitJSEventListeners(JSC::SlotVisitor&);
174         void invalidateJSEventListeners(JSC::JSObject*);
175 #endif
176 
177     protected:
178         virtual ~EventTarget();
179 
180         virtual EventTargetData* eventTargetData() = 0;
181         virtual EventTargetData* ensureEventTargetData() = 0;
182 
183     private:
184         virtual void refEventTarget() = 0;
185         virtual void derefEventTarget() = 0;
186 
187         void fireEventListeners(Event*, EventTargetData*, EventListenerVector&);
188 
189         friend class EventListenerIterator;
190     };
191 
192     class EventListenerIterator {
193     public:
194         EventListenerIterator();
195 
196         // EventTarget must not be modified while an iterator is active.
197         EventListenerIterator(EventTarget*);
198 
199         EventListener* nextListener();
200 
201     private:
202         EventListenerMap::iterator m_mapIterator;
203         EventListenerMap::iterator m_mapEnd;
204         unsigned m_index;
205     };
206 
207     // FIXME: These macros should be split into separate DEFINE and DECLARE
208     // macros to avoid causing so many header includes.
209     #define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \
210         EventListener* on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \
211         void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \
212 
213     #define DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(attribute) \
214         virtual EventListener* on##attribute(); \
215         virtual void setOn##attribute(PassRefPtr<EventListener> listener); \
216 
217     #define DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(type, attribute) \
218         EventListener* type::on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \
219         void type::setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \
220 
221     #define DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \
222         EventListener* on##attribute() { return document()->getWindowAttributeEventListener(eventNames().attribute##Event); } \
223         void setOn##attribute(PassRefPtr<EventListener> listener) { document()->setWindowAttributeEventListener(eventNames().attribute##Event, listener); } \
224 
225     #define DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(attribute, eventName) \
226         EventListener* on##attribute() { return getAttributeEventListener(eventNames().eventName##Event); } \
227         void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().eventName##Event, listener); } \
228 
229     #define DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(recipient, attribute) \
230         EventListener* on##attribute() { return recipient ? recipient->getAttributeEventListener(eventNames().attribute##Event) : 0; } \
231         void setOn##attribute(PassRefPtr<EventListener> listener) { if (recipient) recipient->setAttributeEventListener(eventNames().attribute##Event, listener); } \
232 
233 #ifndef NDEBUG
234     void forbidEventDispatch();
235     void allowEventDispatch();
236     bool eventDispatchForbidden();
237 #else
forbidEventDispatch()238     inline void forbidEventDispatch() { }
allowEventDispatch()239     inline void allowEventDispatch() { }
240 #endif
241 
242 #if USE(JSC)
visitJSEventListeners(JSC::SlotVisitor & visitor)243     inline void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor)
244     {
245         EventTargetData* d = eventTargetData();
246         if (!d)
247             return;
248 
249         EventListenerMap::iterator end = d->eventListenerMap.end();
250         for (EventListenerMap::iterator it = d->eventListenerMap.begin(); it != end; ++it) {
251             EventListenerVector& entry = *it->second;
252             for (size_t i = 0; i < entry.size(); ++i)
253                 entry[i].listener->visitJSFunction(visitor);
254         }
255     }
256 #endif
257 
isFiringEventListeners()258     inline bool EventTarget::isFiringEventListeners()
259     {
260         EventTargetData* d = eventTargetData();
261         if (!d)
262             return false;
263         return d->firingEventIterators.size() != 0;
264     }
265 
hasEventListeners()266     inline bool EventTarget::hasEventListeners()
267     {
268         EventTargetData* d = eventTargetData();
269         if (!d)
270             return false;
271         return !d->eventListenerMap.isEmpty();
272     }
273 
hasEventListeners(const AtomicString & eventType)274     inline bool EventTarget::hasEventListeners(const AtomicString& eventType)
275     {
276         EventTargetData* d = eventTargetData();
277         if (!d)
278             return false;
279         return d->eventListenerMap.contains(eventType);
280     }
281 
282 } // namespace WebCore
283 
284 #endif // EventTarget_h
285