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/. */
6 
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 "nsIGlobalObject.h"
14 #include "nsThreadUtils.h"
15 
16 namespace mozilla::dom {
17 
18 /* static */
Constructor(const GlobalObject & aGlobal,ErrorResult & aRv)19 already_AddRefed<EventTarget> EventTarget::Constructor(
20     const GlobalObject& aGlobal, ErrorResult& aRv) {
21   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
22   if (!global) {
23     aRv.Throw(NS_ERROR_UNEXPECTED);
24     return nullptr;
25   }
26   RefPtr<EventTarget> target = new ConstructibleEventTarget(global);
27   return target.forget();
28 }
29 
ComputeWantsUntrusted(const Nullable<bool> & aWantsUntrusted,const AddEventListenerOptionsOrBoolean * aOptions,ErrorResult & aRv)30 bool EventTarget::ComputeWantsUntrusted(
31     const Nullable<bool>& aWantsUntrusted,
32     const AddEventListenerOptionsOrBoolean* aOptions, ErrorResult& aRv) {
33   if (aOptions && aOptions->IsAddEventListenerOptions()) {
34     const auto& options = aOptions->GetAsAddEventListenerOptions();
35     if (options.mWantUntrusted.WasPassed()) {
36       return options.mWantUntrusted.Value();
37     }
38   }
39 
40   if (!aWantsUntrusted.IsNull()) {
41     return aWantsUntrusted.Value();
42   }
43 
44   bool defaultWantsUntrusted = ComputeDefaultWantsUntrusted(aRv);
45   if (aRv.Failed()) {
46     return false;
47   }
48 
49   return defaultWantsUntrusted;
50 }
51 
AddEventListener(const nsAString & aType,EventListener * aCallback,const AddEventListenerOptionsOrBoolean & aOptions,const Nullable<bool> & aWantsUntrusted,ErrorResult & aRv)52 void EventTarget::AddEventListener(
53     const nsAString& aType, EventListener* aCallback,
54     const AddEventListenerOptionsOrBoolean& aOptions,
55     const Nullable<bool>& aWantsUntrusted, ErrorResult& aRv) {
56   bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, &aOptions, aRv);
57   if (aRv.Failed()) {
58     return;
59   }
60 
61   EventListenerManager* elm = GetOrCreateListenerManager();
62   if (!elm) {
63     aRv.Throw(NS_ERROR_UNEXPECTED);
64     return;
65   }
66 
67   elm->AddEventListener(aType, aCallback, aOptions, wantsUntrusted);
68 }
69 
AddEventListener(const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture,const Nullable<bool> & aWantsUntrusted)70 nsresult EventTarget::AddEventListener(const nsAString& aType,
71                                        nsIDOMEventListener* aListener,
72                                        bool aUseCapture,
73                                        const Nullable<bool>& aWantsUntrusted) {
74   ErrorResult rv;
75   bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, nullptr, rv);
76   if (rv.Failed()) {
77     return rv.StealNSResult();
78   }
79 
80   EventListenerManager* elm = GetOrCreateListenerManager();
81   NS_ENSURE_STATE(elm);
82   elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
83   return NS_OK;
84 }
85 
RemoveEventListener(const nsAString & aType,EventListener * aListener,const EventListenerOptionsOrBoolean & aOptions,ErrorResult & aRv)86 void EventTarget::RemoveEventListener(
87     const nsAString& aType, EventListener* aListener,
88     const EventListenerOptionsOrBoolean& aOptions, ErrorResult& aRv) {
89   EventListenerManager* elm = GetExistingListenerManager();
90   if (elm) {
91     elm->RemoveEventListener(aType, aListener, aOptions);
92   }
93 }
94 
RemoveEventListener(const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture)95 void EventTarget::RemoveEventListener(const nsAString& aType,
96                                       nsIDOMEventListener* aListener,
97                                       bool aUseCapture) {
98   EventListenerManager* elm = GetExistingListenerManager();
99   if (elm) {
100     elm->RemoveEventListener(aType, aListener, aUseCapture);
101   }
102 }
103 
AddSystemEventListener(const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture,const Nullable<bool> & aWantsUntrusted)104 nsresult EventTarget::AddSystemEventListener(
105     const nsAString& aType, nsIDOMEventListener* aListener, bool aUseCapture,
106     const Nullable<bool>& aWantsUntrusted) {
107   ErrorResult rv;
108   bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, nullptr, rv);
109   if (rv.Failed()) {
110     return rv.StealNSResult();
111   }
112 
113   EventListenerManager* elm = GetOrCreateListenerManager();
114   NS_ENSURE_STATE(elm);
115 
116   EventListenerFlags flags;
117   flags.mInSystemGroup = true;
118   flags.mCapture = aUseCapture;
119   flags.mAllowUntrustedEvents = wantsUntrusted;
120   elm->AddEventListenerByType(aListener, aType, flags);
121   return NS_OK;
122 }
123 
RemoveSystemEventListener(const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture)124 void EventTarget::RemoveSystemEventListener(const nsAString& aType,
125                                             nsIDOMEventListener* aListener,
126                                             bool aUseCapture) {
127   EventListenerManager* elm = GetExistingListenerManager();
128   if (elm) {
129     EventListenerFlags flags;
130     flags.mInSystemGroup = true;
131     flags.mCapture = aUseCapture;
132     elm->RemoveEventListenerByType(aListener, aType, flags);
133   }
134 }
135 
GetEventHandler(nsAtom * aType)136 EventHandlerNonNull* EventTarget::GetEventHandler(nsAtom* aType) {
137   EventListenerManager* elm = GetExistingListenerManager();
138   return elm ? elm->GetEventHandler(aType) : nullptr;
139 }
140 
SetEventHandler(const nsAString & aType,EventHandlerNonNull * aHandler,ErrorResult & aRv)141 void EventTarget::SetEventHandler(const nsAString& aType,
142                                   EventHandlerNonNull* aHandler,
143                                   ErrorResult& aRv) {
144   if (!StringBeginsWith(aType, u"on"_ns)) {
145     aRv.Throw(NS_ERROR_INVALID_ARG);
146     return;
147   }
148   RefPtr<nsAtom> type = NS_Atomize(aType);
149   SetEventHandler(type, aHandler);
150 }
151 
SetEventHandler(nsAtom * aType,EventHandlerNonNull * aHandler)152 void EventTarget::SetEventHandler(nsAtom* aType,
153                                   EventHandlerNonNull* aHandler) {
154   GetOrCreateListenerManager()->SetEventHandler(aType, aHandler);
155 }
156 
HasNonSystemGroupListenersForUntrustedKeyEvents() const157 bool EventTarget::HasNonSystemGroupListenersForUntrustedKeyEvents() const {
158   EventListenerManager* elm = GetExistingListenerManager();
159   return elm && elm->HasNonSystemGroupListenersForUntrustedKeyEvents();
160 }
161 
HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents() const162 bool EventTarget::HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents()
163     const {
164   EventListenerManager* elm = GetExistingListenerManager();
165   return elm &&
166          elm->HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
167 }
168 
IsApzAware() const169 bool EventTarget::IsApzAware() const {
170   EventListenerManager* elm = GetExistingListenerManager();
171   return elm && elm->HasApzAwareListeners();
172 }
173 
DispatchEvent(Event & aEvent)174 void EventTarget::DispatchEvent(Event& aEvent) {
175   // The caller type doesn't really matter if we don't care about the
176   // return value, but let's be safe and pass NonSystem.
177   Unused << DispatchEvent(aEvent, CallerType::NonSystem, IgnoreErrors());
178 }
179 
DispatchEvent(Event & aEvent,ErrorResult & aRv)180 void EventTarget::DispatchEvent(Event& aEvent, ErrorResult& aRv) {
181   // The caller type doesn't really matter if we don't care about the
182   // return value, but let's be safe and pass NonSystem.
183   Unused << DispatchEvent(aEvent, CallerType::NonSystem, IgnoreErrors());
184 }
185 
GetOwnerGlobalForBindings()186 Nullable<WindowProxyHolder> EventTarget::GetOwnerGlobalForBindings() {
187   nsPIDOMWindowOuter* win = GetOwnerGlobalForBindingsInternal();
188   if (!win) {
189     return nullptr;
190   }
191 
192   return WindowProxyHolder(win->GetBrowsingContext());
193 }
194 
195 }  // namespace mozilla::dom
196