/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * (C) 2007, 2008 Nikolas Zimmermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "EventListenerMap.h" #include "EventTargetInterfaces.h" #include "ExceptionOr.h" #include "ScriptWrappable.h" #include #include #include namespace WebCore { class DOMWindow; class DOMWrapperWorld; class Node; struct EventTargetData { WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED; public: EventTargetData() = default; EventListenerMap eventListenerMap; bool isFiringEventListeners { false }; }; enum EventTargetInterface { #define DOM_EVENT_INTERFACE_DECLARE(name) name##EventTargetInterfaceType, DOM_EVENT_TARGET_INTERFACES_FOR_EACH(DOM_EVENT_INTERFACE_DECLARE) #undef DOM_EVENT_INTERFACE_DECLARE }; class EventTarget : public ScriptWrappable { public: void ref() { refEventTarget(); } void deref() { derefEventTarget(); } virtual EventTargetInterface eventTargetInterface() const = 0; virtual ScriptExecutionContext* scriptExecutionContext() const = 0; virtual Node* toNode(); virtual DOMWindow* toDOMWindow(); virtual bool isMessagePort() const; struct ListenerOptions { ListenerOptions(bool capture = false) : capture(capture) { } bool capture; }; struct AddEventListenerOptions : ListenerOptions { AddEventListenerOptions(bool capture = false, bool passive = false, bool once = false) : ListenerOptions(capture) , passive(passive) , once(once) { } bool passive; bool once; }; using AddEventListenerOptionsOrBoolean = Variant; WEBCORE_EXPORT void addEventListenerForBindings(const AtomicString& eventType, RefPtr&&, AddEventListenerOptionsOrBoolean&&); using ListenerOptionsOrBoolean = Variant; WEBCORE_EXPORT void removeEventListenerForBindings(const AtomicString& eventType, RefPtr&&, ListenerOptionsOrBoolean&&); WEBCORE_EXPORT ExceptionOr dispatchEventForBindings(Event&); virtual bool addEventListener(const AtomicString& eventType, Ref&&, const AddEventListenerOptions& = { }); virtual bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&); virtual void removeAllEventListeners(); virtual bool dispatchEvent(Event&); virtual void uncaughtExceptionInEventHandler(); // Used for legacy "onevent" attributes. bool setAttributeEventListener(const AtomicString& eventType, RefPtr&&, DOMWrapperWorld&); EventListener* attributeEventListener(const AtomicString& eventType, DOMWrapperWorld&); bool hasEventListeners() const; bool hasEventListeners(const AtomicString& eventType) const; bool hasCapturingEventListeners(const AtomicString& eventType); bool hasActiveEventListeners(const AtomicString& eventType) const; const EventListenerVector& eventListeners(const AtomicString& eventType); bool fireEventListeners(Event&); bool isFiringEventListeners() const; void visitJSEventListeners(JSC::SlotVisitor&); void invalidateJSEventListeners(JSC::JSObject*); protected: virtual ~EventTarget() = default; virtual EventTargetData* eventTargetData() = 0; virtual EventTargetData* eventTargetDataConcurrently() = 0; virtual EventTargetData& ensureEventTargetData() = 0; const EventTargetData* eventTargetData() const; private: virtual void refEventTarget() = 0; virtual void derefEventTarget() = 0; void fireEventListeners(Event&, EventListenerVector); friend class EventListenerIterator; }; class EventTargetWithInlineData : public EventTarget { protected: EventTargetData* eventTargetData() final { return &m_eventTargetData; } EventTargetData* eventTargetDataConcurrently() final { return &m_eventTargetData; } EventTargetData& ensureEventTargetData() final { return m_eventTargetData; } private: EventTargetData m_eventTargetData; }; inline const EventTargetData* EventTarget::eventTargetData() const { return const_cast(this)->eventTargetData(); } inline bool EventTarget::isFiringEventListeners() const { auto* data = eventTargetData(); return data && data->isFiringEventListeners; } inline bool EventTarget::hasEventListeners() const { auto* data = eventTargetData(); return data && !data->eventListenerMap.isEmpty(); } inline bool EventTarget::hasEventListeners(const AtomicString& eventType) const { auto* data = eventTargetData(); return data && data->eventListenerMap.contains(eventType); } inline bool EventTarget::hasCapturingEventListeners(const AtomicString& eventType) { auto* data = eventTargetData(); return data && data->eventListenerMap.containsCapturing(eventType); } } // namespace WebCore