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 } 72 73 EventTargetData::~EventTargetData() 74 { 75 deleteAllValues(eventListenerMap); 76 } 77 78 EventTarget::~EventTarget() 79 { 80 } 81 82 EventSource* EventTarget::toEventSource() 83 { 84 return 0; 85 } 86 87 Node* EventTarget::toNode() 88 { 89 return 0; 90 } 91 92 DOMWindow* EventTarget::toDOMWindow() 93 { 94 return 0; 95 } 96 97 XMLHttpRequest* EventTarget::toXMLHttpRequest() 98 { 99 return 0; 100 } 101 102 XMLHttpRequestUpload* EventTarget::toXMLHttpRequestUpload() 103 { 104 return 0; 105 } 106 107 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 108 DOMApplicationCache* EventTarget::toDOMApplicationCache() 109 { 110 return 0; 111 } 112 #endif 113 114 #if ENABLE(SVG) 115 SVGElementInstance* EventTarget::toSVGElementInstance() 116 { 117 return 0; 118 } 119 #endif 120 121 #if ENABLE(WEB_AUDIO) 122 AudioContext* EventTarget::toAudioContext() 123 { 124 return 0; 125 } 126 127 JavaScriptAudioNode* EventTarget::toJavaScriptAudioNode() 128 { 129 return 0; 130 } 131 #endif 132 133 #if ENABLE(WEB_SOCKETS) 134 WebSocket* EventTarget::toWebSocket() 135 { 136 return 0; 137 } 138 #endif 139 140 MessagePort* EventTarget::toMessagePort() 141 { 142 return 0; 143 } 144 145 #if ENABLE(WORKERS) 146 Worker* EventTarget::toWorker() 147 { 148 return 0; 149 } 150 151 DedicatedWorkerContext* EventTarget::toDedicatedWorkerContext() 152 { 153 return 0; 154 } 155 #endif 156 157 #if ENABLE(SHARED_WORKERS) 158 SharedWorker* EventTarget::toSharedWorker() 159 { 160 return 0; 161 } 162 SharedWorkerContext* EventTarget::toSharedWorkerContext() 163 { 164 return 0; 165 } 166 #endif 167 168 #if ENABLE(NOTIFICATIONS) 169 Notification* EventTarget::toNotification() 170 { 171 return 0; 172 } 173 #endif 174 175 #if ENABLE(BLOB) 176 FileReader* EventTarget::toFileReader() 177 { 178 return 0; 179 } 180 #endif 181 #if ENABLE(FILE_SYSTEM) 182 FileWriter* EventTarget::toFileWriter() 183 { 184 return 0; 185 } 186 #endif 187 188 #if ENABLE(INDEXED_DATABASE) 189 IDBDatabase* EventTarget::toIDBDatabase() 190 { 191 return 0; 192 } 193 IDBRequest* EventTarget::toIDBRequest() 194 { 195 return 0; 196 } 197 IDBTransaction* EventTarget::toIDBTransaction() 198 { 199 return 0; 200 } 201 IDBVersionChangeRequest* EventTarget::toIDBVersionChangeRequest() 202 { 203 return 0; 204 } 205 #endif 206 207 bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 208 { 209 EventTargetData* d = ensureEventTargetData(); 210 211 pair<EventListenerMap::iterator, bool> result = d->eventListenerMap.add(eventType, 0); 212 EventListenerVector*& entry = result.first->second; 213 const bool isNewEntry = result.second; 214 if (isNewEntry) 215 entry = new EventListenerVector(); 216 217 RegisteredEventListener registeredListener(listener, useCapture); 218 if (!isNewEntry) { 219 if (entry->find(registeredListener) != notFound) // duplicate listener 220 return false; 221 } 222 223 entry->append(registeredListener); 224 return true; 225 } 226 227 bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 228 { 229 EventTargetData* d = eventTargetData(); 230 if (!d) 231 return false; 232 233 EventListenerMap::iterator result = d->eventListenerMap.find(eventType); 234 if (result == d->eventListenerMap.end()) 235 return false; 236 EventListenerVector* entry = result->second; 237 238 RegisteredEventListener registeredListener(listener, useCapture); 239 size_t index = entry->find(registeredListener); 240 if (index == notFound) 241 return false; 242 243 entry->remove(index); 244 if (entry->isEmpty()) { 245 delete entry; 246 d->eventListenerMap.remove(result); 247 } 248 249 // Notify firing events planning to invoke the listener at 'index' that 250 // they have one less listener to invoke. 251 for (size_t i = 0; i < d->firingEventIterators.size(); ++i) { 252 if (eventType != d->firingEventIterators[i].eventType) 253 continue; 254 255 if (index >= d->firingEventIterators[i].end) 256 continue; 257 258 --d->firingEventIterators[i].end; 259 if (index <= d->firingEventIterators[i].iterator) 260 --d->firingEventIterators[i].iterator; 261 } 262 263 return true; 264 } 265 266 bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) 267 { 268 clearAttributeEventListener(eventType); 269 if (!listener) 270 return false; 271 return addEventListener(eventType, listener, false); 272 } 273 274 EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType) 275 { 276 const EventListenerVector& entry = getEventListeners(eventType); 277 for (size_t i = 0; i < entry.size(); ++i) { 278 if (entry[i].listener->isAttribute()) 279 return entry[i].listener.get(); 280 } 281 return 0; 282 } 283 284 bool EventTarget::clearAttributeEventListener(const AtomicString& eventType) 285 { 286 EventListener* listener = getAttributeEventListener(eventType); 287 if (!listener) 288 return false; 289 return removeEventListener(eventType, listener, false); 290 } 291 292 bool EventTarget::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) 293 { 294 if (!event || event->type().isEmpty()) { 295 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; 296 return false; 297 } 298 299 if (!scriptExecutionContext()) 300 return false; 301 302 return dispatchEvent(event); 303 } 304 305 bool EventTarget::dispatchEvent(PassRefPtr<Event> event) 306 { 307 event->setTarget(this); 308 event->setCurrentTarget(this); 309 event->setEventPhase(Event::AT_TARGET); 310 return fireEventListeners(event.get()); 311 } 312 313 void EventTarget::uncaughtExceptionInEventHandler() 314 { 315 } 316 317 bool EventTarget::fireEventListeners(Event* event) 318 { 319 ASSERT(!eventDispatchForbidden()); 320 ASSERT(event && !event->type().isEmpty()); 321 322 EventTargetData* d = eventTargetData(); 323 if (!d) 324 return true; 325 326 EventListenerMap::iterator result = d->eventListenerMap.find(event->type()); 327 if (result != d->eventListenerMap.end()) 328 fireEventListeners(event, d, *result->second); 329 330 return !event->defaultPrevented(); 331 } 332 333 void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry) 334 { 335 RefPtr<EventTarget> protect = this; 336 337 // Fire all listeners registered for this event. Don't fire listeners removed 338 // during event dispatch. Also, don't fire event listeners added during event 339 // dispatch. Conveniently, all new event listeners will be added after 'end', 340 // so iterating to 'end' naturally excludes new event listeners. 341 342 size_t i = 0; 343 size_t end = entry.size(); 344 d->firingEventIterators.append(FiringEventIterator(event->type(), i, end)); 345 for ( ; i < end; ++i) { 346 RegisteredEventListener& registeredListener = entry[i]; 347 if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture) 348 continue; 349 if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture) 350 continue; 351 352 // If stopImmediatePropagation has been called, we just break out immediately, without 353 // handling any more events on this target. 354 if (event->immediatePropagationStopped()) 355 break; 356 357 // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling 358 // event listeners, even though that violates some versions of the DOM spec. 359 registeredListener.listener->handleEvent(scriptExecutionContext(), event); 360 } 361 d->firingEventIterators.removeLast(); 362 } 363 364 const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType) 365 { 366 DEFINE_STATIC_LOCAL(EventListenerVector, emptyVector, ()); 367 368 EventTargetData* d = eventTargetData(); 369 if (!d) 370 return emptyVector; 371 EventListenerMap::iterator it = d->eventListenerMap.find(eventType); 372 if (it == d->eventListenerMap.end()) 373 return emptyVector; 374 return *it->second; 375 } 376 377 void EventTarget::removeAllEventListeners() 378 { 379 EventTargetData* d = eventTargetData(); 380 if (!d) 381 return; 382 deleteAllValues(d->eventListenerMap); 383 d->eventListenerMap.clear(); 384 385 // Notify firing events planning to invoke the listener at 'index' that 386 // they have one less listener to invoke. 387 for (size_t i = 0; i < d->firingEventIterators.size(); ++i) { 388 d->firingEventIterators[i].iterator = 0; 389 d->firingEventIterators[i].end = 0; 390 } 391 } 392 393 } // namespace WebCore 394