Home | History | Annotate | Download | only in events
      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