1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 6 * Copyright (C) 2006 Alexey Proskuryakov (ap (at) webkit.org) 7 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) 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 "core/events/EventListenerMap.h" 36 #include "core/events/ThreadLocalEventNames.h" 37 #include "platform/heap/Handle.h" 38 39 namespace WebCore { 40 41 class LocalDOMWindow; 42 class Event; 43 class ExceptionState; 44 class MessagePort; 45 class Node; 46 class TextTrack; 47 class TextTrackCue; 48 class XMLHttpRequest; 49 class XMLHttpRequestUpload; 50 51 struct FiringEventIterator { 52 FiringEventIterator(const AtomicString& eventType, size_t& iterator, size_t& end) 53 : eventType(eventType) 54 , iterator(iterator) 55 , end(end) 56 { 57 } 58 59 const AtomicString& eventType; 60 size_t& iterator; 61 size_t& end; 62 }; 63 typedef Vector<FiringEventIterator, 1> FiringEventIteratorVector; 64 65 struct EventTargetData { 66 WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED; 67 public: 68 EventTargetData(); 69 ~EventTargetData(); 70 71 EventListenerMap eventListenerMap; 72 OwnPtr<FiringEventIteratorVector> firingEventIterators; 73 }; 74 75 class EventTarget : public WillBeGarbageCollectedMixin { 76 public: 77 #if !ENABLE(OILPAN) 78 void ref() { refEventTarget(); } 79 void deref() { derefEventTarget(); } 80 #endif 81 82 virtual const AtomicString& interfaceName() const = 0; 83 virtual ExecutionContext* executionContext() const = 0; 84 85 virtual Node* toNode(); 86 virtual LocalDOMWindow* toDOMWindow(); 87 virtual MessagePort* toMessagePort(); 88 89 // FIXME: first 2 args to addEventListener and removeEventListener should 90 // be required (per spec), but throwing TypeError breaks legacy content. 91 // http://crbug.com/353484 92 bool addEventListener() { return false; } 93 bool addEventListener(const AtomicString& eventType) { return false; } 94 virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false); 95 bool removeEventListener() { return false; } 96 bool removeEventListener(const AtomicString& eventType) { return false; } 97 virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture = false); 98 virtual void removeAllEventListeners(); 99 virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>); 100 bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>, ExceptionState&); // DOM API 101 virtual void uncaughtExceptionInEventHandler(); 102 103 // Used for legacy "onEvent" attribute APIs. 104 bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); 105 EventListener* getAttributeEventListener(const AtomicString& eventType); 106 107 bool hasEventListeners() const; 108 bool hasEventListeners(const AtomicString& eventType) const; 109 bool hasCapturingEventListeners(const AtomicString& eventType); 110 const EventListenerVector& getEventListeners(const AtomicString& eventType); 111 Vector<AtomicString> eventTypes(); 112 113 bool fireEventListeners(Event*); 114 115 virtual void trace(Visitor*) { } 116 117 virtual bool keepEventInNode(Event*) { return false; }; 118 119 protected: 120 virtual ~EventTarget(); 121 122 // Subclasses should likely not override these themselves; instead, they should subclass EventTargetWithInlineData. 123 virtual EventTargetData* eventTargetData() = 0; 124 virtual EventTargetData& ensureEventTargetData() = 0; 125 126 private: 127 #if !ENABLE(OILPAN) 128 // Subclasses should likely not override these themselves; instead, they should use the REFCOUNTED_EVENT_TARGET() macro. 129 virtual void refEventTarget() = 0; 130 virtual void derefEventTarget() = 0; 131 #endif 132 133 LocalDOMWindow* executingWindow(); 134 void fireEventListeners(Event*, EventTargetData*, EventListenerVector&); 135 void countLegacyEvents(const AtomicString& legacyTypeName, EventListenerVector*, EventListenerVector*); 136 137 bool clearAttributeEventListener(const AtomicString& eventType); 138 139 friend class EventListenerIterator; 140 }; 141 142 class EventTargetWithInlineData : public EventTarget { 143 protected: 144 virtual EventTargetData* eventTargetData() OVERRIDE FINAL { return &m_eventTargetData; } 145 virtual EventTargetData& ensureEventTargetData() OVERRIDE FINAL { return m_eventTargetData; } 146 private: 147 EventTargetData m_eventTargetData; 148 }; 149 150 // FIXME: These macros should be split into separate DEFINE and DECLARE 151 // macros to avoid causing so many header includes. 152 #define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \ 153 EventListener* on##attribute() { return getAttributeEventListener(EventTypeNames::attribute); } \ 154 void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(EventTypeNames::attribute, listener); } \ 155 156 #define DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(attribute) \ 157 static EventListener* on##attribute(EventTarget& eventTarget) { return eventTarget.getAttributeEventListener(EventTypeNames::attribute); } \ 158 static void setOn##attribute(EventTarget& eventTarget, PassRefPtr<EventListener> listener) { eventTarget.setAttributeEventListener(EventTypeNames::attribute, listener); } \ 159 160 #define DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \ 161 EventListener* on##attribute() { return document().getWindowAttributeEventListener(EventTypeNames::attribute); } \ 162 void setOn##attribute(PassRefPtr<EventListener> listener) { document().setWindowAttributeEventListener(EventTypeNames::attribute, listener); } \ 163 164 #define DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \ 165 static EventListener* on##attribute(EventTarget& eventTarget) { \ 166 if (Node* node = eventTarget.toNode()) \ 167 return node->document().getWindowAttributeEventListener(EventTypeNames::attribute); \ 168 ASSERT(eventTarget.toDOMWindow()); \ 169 return eventTarget.getAttributeEventListener(EventTypeNames::attribute); \ 170 } \ 171 static void setOn##attribute(EventTarget& eventTarget, PassRefPtr<EventListener> listener) { \ 172 if (Node* node = eventTarget.toNode()) \ 173 node->document().setWindowAttributeEventListener(EventTypeNames::attribute, listener); \ 174 else { \ 175 ASSERT(eventTarget.toDOMWindow()); \ 176 eventTarget.setAttributeEventListener(EventTypeNames::attribute, listener); \ 177 } \ 178 } 179 180 #define DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(attribute, eventName) \ 181 EventListener* on##attribute() { return getAttributeEventListener(EventTypeNames::eventName); } \ 182 void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(EventTypeNames::eventName, listener); } \ 183 184 #define DECLARE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(recipient, attribute) \ 185 EventListener* on##attribute(); \ 186 void setOn##attribute(PassRefPtr<EventListener> listener); 187 188 #define DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(type, recipient, attribute) \ 189 EventListener* type::on##attribute() { return recipient ? recipient->getAttributeEventListener(EventTypeNames::attribute) : 0; } \ 190 void type::setOn##attribute(PassRefPtr<EventListener> listener) \ 191 { \ 192 if (recipient) \ 193 recipient->setAttributeEventListener(EventTypeNames::attribute, listener); \ 194 } 195 196 inline bool EventTarget::hasEventListeners() const 197 { 198 // FIXME: We should have a const version of eventTargetData. 199 if (const EventTargetData* d = const_cast<EventTarget*>(this)->eventTargetData()) 200 return !d->eventListenerMap.isEmpty(); 201 return false; 202 } 203 204 inline bool EventTarget::hasEventListeners(const AtomicString& eventType) const 205 { 206 // FIXME: We should have const version of eventTargetData. 207 if (const EventTargetData* d = const_cast<EventTarget*>(this)->eventTargetData()) 208 return d->eventListenerMap.contains(eventType); 209 return false; 210 } 211 212 inline bool EventTarget::hasCapturingEventListeners(const AtomicString& eventType) 213 { 214 EventTargetData* d = eventTargetData(); 215 if (!d) 216 return false; 217 return d->eventListenerMap.containsCapturing(eventType); 218 } 219 220 } // namespace WebCore 221 222 #if ENABLE(OILPAN) 223 #define DEFINE_EVENT_TARGET_REFCOUNTING(baseClass) \ 224 public: \ 225 using baseClass::ref; \ 226 using baseClass::deref; \ 227 private: \ 228 typedef int thisIsHereToForceASemiColonAfterThisEventTargetMacro 229 #define DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(baseClass) 230 #else 231 #define DEFINE_EVENT_TARGET_REFCOUNTING(baseClass) \ 232 public: \ 233 using baseClass::ref; \ 234 using baseClass::deref; \ 235 private: \ 236 virtual void refEventTarget() OVERRIDE FINAL { ref(); } \ 237 virtual void derefEventTarget() OVERRIDE FINAL { deref(); } \ 238 typedef int thisIsHereToForceASemiColonAfterThisEventTargetMacro 239 #define DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(baseClass) DEFINE_EVENT_TARGET_REFCOUNTING(baseClass) 240 #endif 241 242 // Use this macro if your EventTarget subclass is also a subclass of WTF::RefCounted. 243 // A ref-counted class that uses a different method of refcounting should use DEFINE_EVENT_TARGET_REFCOUNTING directly. 244 // Both of these macros are meant to be placed just before the "public:" section of the class declaration. 245 #define REFCOUNTED_EVENT_TARGET(className) DEFINE_EVENT_TARGET_REFCOUNTING(RefCountedWillBeRefCountedGarbageCollected<className>) 246 247 #endif // EventTarget_h 248