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-2017 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 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 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#pragma once
32
33#include "EventListenerMap.h"
34#include "EventTargetInterfaces.h"
35#include "ExceptionOr.h"
36#include "ScriptWrappable.h"
37#include <memory>
38#include <wtf/Forward.h>
39#include <wtf/IsoMalloc.h>
40#include <wtf/Variant.h>
41
42namespace WebCore {
43
44class DOMWrapperWorld;
45
46struct EventTargetData {
47 WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED;
48public:
49 EventTargetData() = default;
50 EventListenerMap eventListenerMap;
51 bool isFiringEventListeners { false };
52};
53
54class EventTarget : public ScriptWrappable {
55 WTF_MAKE_ISO_ALLOCATED(EventTarget);
56public:
57 void ref() { refEventTarget(); }
58 void deref() { derefEventTarget(); }
59
60 virtual EventTargetInterface eventTargetInterface() const = 0;
61 virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
62
63 virtual bool isNode() const;
64 virtual bool isPaymentRequest() const;
65
66 struct ListenerOptions {
67 ListenerOptions(bool capture = false)
68 : capture(capture)
69 { }
70
71 bool capture { false };
72 };
73
74 struct AddEventListenerOptions : ListenerOptions {
75 AddEventListenerOptions(bool capture = false, Optional<bool> passive = WTF::nullopt, bool once = false)
76 : ListenerOptions(capture)
77 , passive(passive)
78 , once(once)
79 { }
80
81 Optional<bool> passive;
82 bool once { false };
83 };
84
85 using AddEventListenerOptionsOrBoolean = Variant<AddEventListenerOptions, bool>;
86 WEBCORE_EXPORT void addEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&&, AddEventListenerOptionsOrBoolean&&);
87 using ListenerOptionsOrBoolean = Variant<ListenerOptions, bool>;
88 WEBCORE_EXPORT void removeEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&&, ListenerOptionsOrBoolean&&);
89 WEBCORE_EXPORT ExceptionOr<bool> dispatchEventForBindings(Event&);
90
91 virtual bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions& = { });
92 virtual bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&);
93
94 virtual void removeAllEventListeners();
95 virtual void dispatchEvent(Event&);
96 virtual void uncaughtExceptionInEventHandler();
97
98 // Used for legacy "onevent" attributes.
99 bool setAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&&, DOMWrapperWorld&);
100 EventListener* attributeEventListener(const AtomString& eventType, DOMWrapperWorld&);
101
102 bool hasEventListeners() const;
103 bool hasEventListeners(const AtomString& eventType) const;
104 bool hasCapturingEventListeners(const AtomString& eventType);
105 bool hasActiveEventListeners(const AtomString& eventType) const;
106
107 Vector<AtomString> eventTypes();
108 const EventListenerVector& eventListeners(const AtomString& eventType);
109
110 enum class EventInvokePhase { Capturing, Bubbling };
111 void fireEventListeners(Event&, EventInvokePhase);
112 bool isFiringEventListeners() const;
113
114 void visitJSEventListeners(JSC::SlotVisitor&);
115 void invalidateJSEventListeners(JSC::JSObject*);
116
117protected:
118 virtual ~EventTarget() = default;
119
120 virtual EventTargetData* eventTargetData() = 0;
121 virtual EventTargetData* eventTargetDataConcurrently() = 0;
122 virtual EventTargetData& ensureEventTargetData() = 0;
123 const EventTargetData* eventTargetData() const;
124
125private:
126 virtual void refEventTarget() = 0;
127 virtual void derefEventTarget() = 0;
128
129 void innerInvokeEventListeners(Event&, EventListenerVector, EventInvokePhase);
130
131 friend class EventListenerIterator;
132};
133
134class EventTargetWithInlineData : public EventTarget {
135 WTF_MAKE_ISO_ALLOCATED(EventTargetWithInlineData);
136protected:
137 EventTargetData* eventTargetData() final { return &m_eventTargetData; }
138 EventTargetData* eventTargetDataConcurrently() final { return &m_eventTargetData; }
139 EventTargetData& ensureEventTargetData() final { return m_eventTargetData; }
140private:
141 EventTargetData m_eventTargetData;
142};
143
144inline const EventTargetData* EventTarget::eventTargetData() const
145{
146 return const_cast<EventTarget*>(this)->eventTargetData();
147}
148
149inline bool EventTarget::isFiringEventListeners() const
150{
151 auto* data = eventTargetData();
152 return data && data->isFiringEventListeners;
153}
154
155inline bool EventTarget::hasEventListeners() const
156{
157 auto* data = eventTargetData();
158 return data && !data->eventListenerMap.isEmpty();
159}
160
161inline bool EventTarget::hasEventListeners(const AtomString& eventType) const
162{
163 auto* data = eventTargetData();
164 return data && data->eventListenerMap.contains(eventType);
165}
166
167inline bool EventTarget::hasCapturingEventListeners(const AtomString& eventType)
168{
169 auto* data = eventTargetData();
170 return data && data->eventListenerMap.containsCapturing(eventType);
171}
172
173} // namespace WebCore
174