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