Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / events / EventTarget.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6  * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
7  *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@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 "core/events/EventTarget.h"
34
35 #include "bindings/core/v8/ExceptionState.h"
36 #include "bindings/core/v8/V8DOMActivityLogger.h"
37 #include "core/dom/ExceptionCode.h"
38 #include "core/editing/Editor.h"
39 #include "core/events/Event.h"
40 #include "core/inspector/InspectorInstrumentation.h"
41 #include "core/frame/LocalDOMWindow.h"
42 #include "core/frame/UseCounter.h"
43 #include "platform/EventDispatchForbiddenScope.h"
44 #include "platform/RuntimeEnabledFeatures.h"
45 #include "wtf/StdLibExtras.h"
46 #include "wtf/Threading.h"
47 #include "wtf/Vector.h"
48
49 using namespace WTF;
50
51 namespace blink {
52
53 EventTargetData::EventTargetData()
54 {
55 }
56
57 EventTargetData::~EventTargetData()
58 {
59 }
60
61 EventTarget::EventTarget()
62 {
63 }
64
65 EventTarget::~EventTarget()
66 {
67 }
68
69 Node* EventTarget::toNode()
70 {
71     return 0;
72 }
73
74 LocalDOMWindow* EventTarget::toDOMWindow()
75 {
76     return 0;
77 }
78
79 MessagePort* EventTarget::toMessagePort()
80 {
81     return 0;
82 }
83
84 inline LocalDOMWindow* EventTarget::executingWindow()
85 {
86     if (ExecutionContext* context = executionContext())
87         return context->executingWindow();
88     return 0;
89 }
90
91 bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
92 {
93     // FIXME: listener null check should throw TypeError (and be done in
94     // generated bindings), but breaks legacy content. http://crbug.com/249598
95     if (!listener)
96         return false;
97
98     V8DOMActivityLogger* activityLogger = V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
99     if (activityLogger) {
100         Vector<String> argv;
101         argv.append(toNode() ? toNode()->nodeName() : interfaceName());
102         argv.append(eventType);
103         activityLogger->logEvent("blinkAddEventListener", argv.size(), argv.data());
104     }
105
106     return ensureEventTargetData().eventListenerMap.add(eventType, listener, useCapture);
107 }
108
109 bool EventTarget::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
110 {
111     // FIXME: listener null check should throw TypeError (and be done in
112     // generated bindings), but breaks legacy content. http://crbug.com/249598
113     if (!listener)
114         return false;
115
116     EventTargetData* d = eventTargetData();
117     if (!d)
118         return false;
119
120     size_t indexOfRemovedListener;
121
122     if (!d->eventListenerMap.remove(eventType, listener.get(), useCapture, indexOfRemovedListener))
123         return false;
124
125     // Notify firing events planning to invoke the listener at 'index' that
126     // they have one less listener to invoke.
127     if (!d->firingEventIterators)
128         return true;
129     for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
130         FiringEventIterator& firingIterator = d->firingEventIterators->at(i);
131         if (eventType != firingIterator.eventType)
132             continue;
133
134         if (indexOfRemovedListener >= firingIterator.end)
135             continue;
136
137         --firingIterator.end;
138         if (indexOfRemovedListener <= firingIterator.iterator)
139             --firingIterator.iterator;
140     }
141
142     return true;
143 }
144
145 bool EventTarget::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
146 {
147     clearAttributeEventListener(eventType);
148     if (!listener)
149         return false;
150     return addEventListener(eventType, listener, false);
151 }
152
153 EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
154 {
155     const EventListenerVector& entry = getEventListeners(eventType);
156     for (const auto& eventListener : entry) {
157         EventListener* listener = eventListener.listener.get();
158         if (listener->isAttribute() && listener->belongsToTheCurrentWorld())
159             return listener;
160     }
161     return 0;
162 }
163
164 bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
165 {
166     EventListener* listener = getAttributeEventListener(eventType);
167     if (!listener)
168         return false;
169     return removeEventListener(eventType, listener, false);
170 }
171
172 bool EventTarget::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event, ExceptionState& exceptionState)
173 {
174     if (!event) {
175         exceptionState.throwDOMException(InvalidStateError, "The event provided is null.");
176         return false;
177     }
178     if (event->type().isEmpty()) {
179         exceptionState.throwDOMException(InvalidStateError, "The event provided is uninitialized.");
180         return false;
181     }
182     if (event->isBeingDispatched()) {
183         exceptionState.throwDOMException(InvalidStateError, "The event is already being dispatched.");
184         return false;
185     }
186
187     if (!executionContext())
188         return false;
189
190     return dispatchEvent(event);
191 }
192
193 bool EventTarget::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
194 {
195     event->setTarget(this);
196     event->setCurrentTarget(this);
197     event->setEventPhase(Event::AT_TARGET);
198     bool defaultPrevented = fireEventListeners(event.get());
199     event->setEventPhase(0);
200     return defaultPrevented;
201 }
202
203 void EventTarget::uncaughtExceptionInEventHandler()
204 {
205 }
206
207 static const AtomicString& legacyType(const Event* event)
208 {
209     if (event->type() == EventTypeNames::transitionend)
210         return EventTypeNames::webkitTransitionEnd;
211
212     if (event->type() == EventTypeNames::animationstart)
213         return EventTypeNames::webkitAnimationStart;
214
215     if (event->type() == EventTypeNames::animationend)
216         return EventTypeNames::webkitAnimationEnd;
217
218     if (event->type() == EventTypeNames::animationiteration)
219         return EventTypeNames::webkitAnimationIteration;
220
221     if (event->type() == EventTypeNames::wheel)
222         return EventTypeNames::mousewheel;
223
224     return emptyAtom;
225 }
226
227 void EventTarget::countLegacyEvents(const AtomicString& legacyTypeName, EventListenerVector* listenersVector, EventListenerVector* legacyListenersVector)
228 {
229     UseCounter::Feature unprefixedFeature;
230     UseCounter::Feature prefixedFeature;
231     UseCounter::Feature prefixedAndUnprefixedFeature;
232     if (legacyTypeName == EventTypeNames::webkitTransitionEnd) {
233         prefixedFeature = UseCounter::PrefixedTransitionEndEvent;
234         unprefixedFeature = UseCounter::UnprefixedTransitionEndEvent;
235         prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedTransitionEndEvent;
236     } else if (legacyTypeName == EventTypeNames::webkitAnimationEnd) {
237         prefixedFeature = UseCounter::PrefixedAnimationEndEvent;
238         unprefixedFeature = UseCounter::UnprefixedAnimationEndEvent;
239         prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationEndEvent;
240     } else if (legacyTypeName == EventTypeNames::webkitAnimationStart) {
241         prefixedFeature = UseCounter::PrefixedAnimationStartEvent;
242         unprefixedFeature = UseCounter::UnprefixedAnimationStartEvent;
243         prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationStartEvent;
244     } else if (legacyTypeName == EventTypeNames::webkitAnimationIteration) {
245         prefixedFeature = UseCounter::PrefixedAnimationIterationEvent;
246         unprefixedFeature = UseCounter::UnprefixedAnimationIterationEvent;
247         prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationIterationEvent;
248     } else {
249         return;
250     }
251
252     if (LocalDOMWindow* executingWindow = this->executingWindow()) {
253         if (legacyListenersVector) {
254             if (listenersVector)
255                 UseCounter::count(executingWindow->document(), prefixedAndUnprefixedFeature);
256             else
257                 UseCounter::count(executingWindow->document(), prefixedFeature);
258         } else if (listenersVector) {
259             UseCounter::count(executingWindow->document(), unprefixedFeature);
260         }
261     }
262 }
263
264 bool EventTarget::fireEventListeners(Event* event)
265 {
266     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
267     ASSERT(event && !event->type().isEmpty());
268
269     EventTargetData* d = eventTargetData();
270     if (!d)
271         return true;
272
273     EventListenerVector* legacyListenersVector = 0;
274     AtomicString legacyTypeName = legacyType(event);
275     if (!legacyTypeName.isEmpty())
276         legacyListenersVector = d->eventListenerMap.find(legacyTypeName);
277
278     EventListenerVector* listenersVector = d->eventListenerMap.find(event->type());
279     if (!RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled() && (event->type() == EventTypeNames::animationiteration || event->type() == EventTypeNames::animationend
280         || event->type() == EventTypeNames::animationstart)
281         // Some code out-there uses custom events to dispatch unprefixed animation events manually,
282         // we can safely remove all this block when cssAnimationUnprefixedEnabled is always on, this
283         // is really a special case. DO NOT ADD MORE EVENTS HERE.
284         && event->interfaceName() != EventNames::CustomEvent)
285         listenersVector = 0;
286
287     if (listenersVector) {
288         fireEventListeners(event, d, *listenersVector);
289     } else if (legacyListenersVector) {
290         AtomicString unprefixedTypeName = event->type();
291         event->setType(legacyTypeName);
292         fireEventListeners(event, d, *legacyListenersVector);
293         event->setType(unprefixedTypeName);
294     }
295
296     Editor::countEvent(executionContext(), event);
297     countLegacyEvents(legacyTypeName, listenersVector, legacyListenersVector);
298     return !event->defaultPrevented();
299 }
300
301 void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
302 {
303     RefPtrWillBeRawPtr<EventTarget> protect(this);
304
305     // Fire all listeners registered for this event. Don't fire listeners removed
306     // during event dispatch. Also, don't fire event listeners added during event
307     // dispatch. Conveniently, all new event listeners will be added after or at
308     // index |size|, so iterating up to (but not including) |size| naturally excludes
309     // new event listeners.
310
311     if (event->type() == EventTypeNames::beforeunload) {
312         if (LocalDOMWindow* executingWindow = this->executingWindow()) {
313             if (executingWindow->top())
314                 UseCounter::count(executingWindow->document(), UseCounter::SubFrameBeforeUnloadFired);
315             UseCounter::count(executingWindow->document(), UseCounter::DocumentBeforeUnloadFired);
316         }
317     } else if (event->type() == EventTypeNames::unload) {
318         if (LocalDOMWindow* executingWindow = this->executingWindow())
319             UseCounter::count(executingWindow->document(), UseCounter::DocumentUnloadFired);
320     } else if (event->type() == EventTypeNames::DOMFocusIn || event->type() == EventTypeNames::DOMFocusOut) {
321         if (LocalDOMWindow* executingWindow = this->executingWindow())
322             UseCounter::count(executingWindow->document(), UseCounter::DOMFocusInOutEvent);
323     } else if (event->type() == EventTypeNames::focusin || event->type() == EventTypeNames::focusout) {
324         if (LocalDOMWindow* executingWindow = this->executingWindow())
325             UseCounter::count(executingWindow->document(), UseCounter::FocusInOutEvent);
326     }
327
328     size_t i = 0;
329     size_t size = entry.size();
330     if (!d->firingEventIterators)
331         d->firingEventIterators = adoptPtr(new FiringEventIteratorVector);
332     d->firingEventIterators->append(FiringEventIterator(event->type(), i, size));
333     for ( ; i < size; ++i) {
334         RegisteredEventListener& registeredListener = entry[i];
335         if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
336             continue;
337         if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
338             continue;
339
340         // If stopImmediatePropagation has been called, we just break out immediately, without
341         // handling any more events on this target.
342         if (event->immediatePropagationStopped())
343             break;
344
345         ExecutionContext* context = executionContext();
346         if (!context)
347             break;
348
349         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(this, event, registeredListener.listener.get(), registeredListener.useCapture);
350         // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
351         // event listeners, even though that violates some versions of the DOM spec.
352         registeredListener.listener->handleEvent(context, event);
353         InspectorInstrumentation::didHandleEvent(cookie);
354     }
355     d->firingEventIterators->removeLast();
356 }
357
358 const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
359 {
360     AtomicallyInitializedStatic(EventListenerVector*, emptyVector = new EventListenerVector);
361
362     EventTargetData* d = eventTargetData();
363     if (!d)
364         return *emptyVector;
365
366     EventListenerVector* listenerVector = d->eventListenerMap.find(eventType);
367     if (!listenerVector)
368         return *emptyVector;
369
370     return *listenerVector;
371 }
372
373 Vector<AtomicString> EventTarget::eventTypes()
374 {
375     EventTargetData* d = eventTargetData();
376     return d ? d->eventListenerMap.eventTypes() : Vector<AtomicString>();
377 }
378
379 void EventTarget::removeAllEventListeners()
380 {
381     EventTargetData* d = eventTargetData();
382     if (!d)
383         return;
384     d->eventListenerMap.clear();
385
386     // Notify firing events planning to invoke the listener at 'index' that
387     // they have one less listener to invoke.
388     if (d->firingEventIterators) {
389         for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
390             d->firingEventIterators->at(i).iterator = 0;
391             d->firingEventIterators->at(i).end = 0;
392         }
393     }
394 }
395
396 } // namespace blink