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