1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/EventListenerManager.h"
8 #include "mozilla/dom/EventTarget.h"
9 #include "mozilla/dom/EventTargetBinding.h"
10 #include "mozilla/dom/ConstructibleEventTarget.h"
11 #include "mozilla/dom/Nullable.h"
12 #include "mozilla/dom/WindowProxyHolder.h"
13 #include "nsGlobalWindowInner.h"
14 #include "nsGlobalWindowOuter.h"
15 #include "nsIGlobalObject.h"
16 #include "nsPIDOMWindow.h"
17 #include "nsThreadUtils.h"
19 namespace mozilla::dom
{
21 #ifndef NS_BUILD_REFCNT_LOGGING
22 MozExternalRefCountType
EventTarget::NonVirtualAddRef() {
23 return mRefCnt
.incr(this);
26 MozExternalRefCountType
EventTarget::NonVirtualRelease() {
27 if (mRefCnt
.get() == 1) {
30 return mRefCnt
.decr(this);
34 NS_IMETHODIMP_(MozExternalRefCountType
) EventTarget::AddRef() {
35 MOZ_ASSERT_UNREACHABLE("EventTarget::AddRef should not be called");
39 NS_IMETHODIMP_(MozExternalRefCountType
) EventTarget::Release() {
40 MOZ_ASSERT_UNREACHABLE("EventTarget::Release should not be called");
44 NS_IMETHODIMP
EventTarget::QueryInterface(REFNSIID aIID
, void** aInstancePtr
) {
45 MOZ_ASSERT_UNREACHABLE("EventTarget::QueryInterface should not be called");
46 *aInstancePtr
= nullptr;
47 return NS_ERROR_FAILURE
;
50 NS_IMETHODIMP_(void) EventTarget::DeleteCycleCollectable() {
51 MOZ_ASSERT_UNREACHABLE(
52 "EventTarget::DeleteCycleCollectable should not be called");
56 already_AddRefed
<EventTarget
> EventTarget::Constructor(
57 const GlobalObject
& aGlobal
, ErrorResult
& aRv
) {
58 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
60 aRv
.Throw(NS_ERROR_UNEXPECTED
);
63 RefPtr
<EventTarget
> target
= new ConstructibleEventTarget(global
);
64 return target
.forget();
67 bool EventTarget::ComputeWantsUntrusted(
68 const Nullable
<bool>& aWantsUntrusted
,
69 const AddEventListenerOptionsOrBoolean
* aOptions
, ErrorResult
& aRv
) {
70 if (aOptions
&& aOptions
->IsAddEventListenerOptions()) {
71 const auto& options
= aOptions
->GetAsAddEventListenerOptions();
72 if (options
.mWantUntrusted
.WasPassed()) {
73 return options
.mWantUntrusted
.Value();
77 if (!aWantsUntrusted
.IsNull()) {
78 return aWantsUntrusted
.Value();
81 bool defaultWantsUntrusted
= ComputeDefaultWantsUntrusted(aRv
);
86 return defaultWantsUntrusted
;
89 void EventTarget::AddEventListener(
90 const nsAString
& aType
, EventListener
* aCallback
,
91 const AddEventListenerOptionsOrBoolean
& aOptions
,
92 const Nullable
<bool>& aWantsUntrusted
, ErrorResult
& aRv
) {
93 bool wantsUntrusted
= ComputeWantsUntrusted(aWantsUntrusted
, &aOptions
, aRv
);
98 EventListenerManager
* elm
= GetOrCreateListenerManager();
100 aRv
.Throw(NS_ERROR_UNEXPECTED
);
104 elm
->AddEventListener(aType
, aCallback
, aOptions
, wantsUntrusted
);
107 nsresult
EventTarget::AddEventListener(const nsAString
& aType
,
108 nsIDOMEventListener
* aListener
,
110 const Nullable
<bool>& aWantsUntrusted
) {
112 bool wantsUntrusted
= ComputeWantsUntrusted(aWantsUntrusted
, nullptr, rv
);
114 return rv
.StealNSResult();
117 EventListenerManager
* elm
= GetOrCreateListenerManager();
118 NS_ENSURE_STATE(elm
);
119 elm
->AddEventListener(aType
, aListener
, aUseCapture
, wantsUntrusted
);
123 void EventTarget::RemoveEventListener(
124 const nsAString
& aType
, EventListener
* aListener
,
125 const EventListenerOptionsOrBoolean
& aOptions
, ErrorResult
& aRv
) {
126 EventListenerManager
* elm
= GetExistingListenerManager();
128 elm
->RemoveEventListener(aType
, aListener
, aOptions
);
132 void EventTarget::RemoveEventListener(const nsAString
& aType
,
133 nsIDOMEventListener
* aListener
,
135 EventListenerManager
* elm
= GetExistingListenerManager();
137 elm
->RemoveEventListener(aType
, aListener
, aUseCapture
);
141 nsresult
EventTarget::AddSystemEventListener(
142 const nsAString
& aType
, nsIDOMEventListener
* aListener
, bool aUseCapture
,
143 const Nullable
<bool>& aWantsUntrusted
) {
145 bool wantsUntrusted
= ComputeWantsUntrusted(aWantsUntrusted
, nullptr, rv
);
147 return rv
.StealNSResult();
150 EventListenerManager
* elm
= GetOrCreateListenerManager();
151 NS_ENSURE_STATE(elm
);
153 EventListenerFlags flags
;
154 flags
.mInSystemGroup
= true;
155 flags
.mCapture
= aUseCapture
;
156 flags
.mAllowUntrustedEvents
= wantsUntrusted
;
157 elm
->AddEventListenerByType(aListener
, aType
, flags
);
161 void EventTarget::RemoveSystemEventListener(const nsAString
& aType
,
162 nsIDOMEventListener
* aListener
,
164 EventListenerManager
* elm
= GetExistingListenerManager();
166 EventListenerFlags flags
;
167 flags
.mInSystemGroup
= true;
168 flags
.mCapture
= aUseCapture
;
169 elm
->RemoveEventListenerByType(aListener
, aType
, flags
);
173 EventHandlerNonNull
* EventTarget::GetEventHandler(nsAtom
* aType
) {
174 EventListenerManager
* elm
= GetExistingListenerManager();
175 return elm
? elm
->GetEventHandler(aType
) : nullptr;
178 void EventTarget::SetEventHandler(const nsAString
& aType
,
179 EventHandlerNonNull
* aHandler
,
181 if (!StringBeginsWith(aType
, u
"on"_ns
)) {
182 aRv
.Throw(NS_ERROR_INVALID_ARG
);
185 RefPtr
<nsAtom
> type
= NS_Atomize(aType
);
186 SetEventHandler(type
, aHandler
);
189 void EventTarget::SetEventHandler(nsAtom
* aType
,
190 EventHandlerNonNull
* aHandler
) {
191 GetOrCreateListenerManager()->SetEventHandler(aType
, aHandler
);
194 bool EventTarget::HasNonSystemGroupListenersForUntrustedKeyEvents() const {
195 EventListenerManager
* elm
= GetExistingListenerManager();
196 return elm
&& elm
->HasNonSystemGroupListenersForUntrustedKeyEvents();
199 bool EventTarget::HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents()
201 EventListenerManager
* elm
= GetExistingListenerManager();
203 elm
->HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
206 bool EventTarget::IsApzAware() const {
207 EventListenerManager
* elm
= GetExistingListenerManager();
208 return elm
&& elm
->HasApzAwareListeners();
211 void EventTarget::DispatchEvent(Event
& aEvent
) {
212 // The caller type doesn't really matter if we don't care about the
213 // return value, but let's be safe and pass NonSystem.
214 Unused
<< DispatchEvent(aEvent
, CallerType::NonSystem
, IgnoreErrors());
217 void EventTarget::DispatchEvent(Event
& aEvent
, ErrorResult
& aRv
) {
218 // The caller type doesn't really matter if we don't care about the
219 // return value, but let's be safe and pass NonSystem.
220 Unused
<< DispatchEvent(aEvent
, CallerType::NonSystem
, IgnoreErrors());
223 Nullable
<WindowProxyHolder
> EventTarget::GetOwnerGlobalForBindings() {
224 nsPIDOMWindowOuter
* win
= GetOwnerGlobalForBindingsInternal();
229 return WindowProxyHolder(win
->GetBrowsingContext());
232 nsPIDOMWindowInner
* EventTarget::GetAsInnerWindow() {
233 return IsInnerWindow() ? static_cast<nsGlobalWindowInner
*>(this) : nullptr;
236 const nsPIDOMWindowInner
* EventTarget::GetAsInnerWindow() const {
237 return IsInnerWindow() ? static_cast<const nsGlobalWindowInner
*>(this)
241 nsPIDOMWindowOuter
* EventTarget::GetAsOuterWindow() {
242 return IsOuterWindow() ? static_cast<nsGlobalWindowOuter
*>(this) : nullptr;
245 const nsPIDOMWindowOuter
* EventTarget::GetAsOuterWindow() const {
246 return IsOuterWindow() ? static_cast<const nsGlobalWindowOuter
*>(this)
250 nsPIDOMWindowInner
* EventTarget::AsInnerWindow() {
251 MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
252 return static_cast<nsGlobalWindowInner
*>(this);
255 const nsPIDOMWindowInner
* EventTarget::AsInnerWindow() const {
256 MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
257 return static_cast<const nsGlobalWindowInner
*>(this);
260 nsPIDOMWindowOuter
* EventTarget::AsOuterWindow() {
261 MOZ_DIAGNOSTIC_ASSERT(IsOuterWindow());
262 return static_cast<nsGlobalWindowOuter
*>(this);
265 const nsPIDOMWindowOuter
* EventTarget::AsOuterWindow() const {
266 MOZ_DIAGNOSTIC_ASSERT(IsOuterWindow());
267 return static_cast<const nsGlobalWindowOuter
*>(this);
270 } // namespace mozilla::dom