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