EventTarget.cpp (8822B)
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/dom/EventTarget.h" 8 9 #include "mozilla/EventListenerManager.h" 10 #include "mozilla/dom/ConstructibleEventTarget.h" 11 #include "mozilla/dom/EventTargetBinding.h" 12 #include "mozilla/dom/Nullable.h" 13 #include "mozilla/dom/WindowProxyHolder.h" 14 #include "nsGlobalWindowInner.h" 15 #include "nsGlobalWindowOuter.h" 16 #include "nsIGlobalObject.h" 17 #include "nsPIDOMWindow.h" 18 #include "nsThreadUtils.h" 19 20 namespace mozilla::dom { 21 22 #ifndef NS_BUILD_REFCNT_LOGGING 23 MozExternalRefCountType EventTarget::NonVirtualAddRef() { 24 return mRefCnt.incr(this); 25 } 26 27 MozExternalRefCountType EventTarget::NonVirtualRelease() { 28 if (mRefCnt.get() == 1) { 29 return Release(); 30 } 31 return mRefCnt.decr(this); 32 } 33 #endif 34 35 NS_IMETHODIMP_(MozExternalRefCountType) EventTarget::AddRef() { 36 MOZ_ASSERT_UNREACHABLE("EventTarget::AddRef should not be called"); 37 return 0; 38 } 39 40 NS_IMETHODIMP_(MozExternalRefCountType) EventTarget::Release() { 41 MOZ_ASSERT_UNREACHABLE("EventTarget::Release should not be called"); 42 return 0; 43 } 44 45 NS_IMETHODIMP EventTarget::QueryInterface(REFNSIID aIID, void** aInstancePtr) { 46 MOZ_ASSERT_UNREACHABLE("EventTarget::QueryInterface should not be called"); 47 *aInstancePtr = nullptr; 48 return NS_ERROR_FAILURE; 49 } 50 51 NS_IMETHODIMP_(void) EventTarget::DeleteCycleCollectable() { 52 MOZ_ASSERT_UNREACHABLE( 53 "EventTarget::DeleteCycleCollectable should not be called"); 54 } 55 56 /* static */ 57 already_AddRefed<EventTarget> EventTarget::Constructor( 58 const GlobalObject& aGlobal, ErrorResult& aRv) { 59 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); 60 if (!global) { 61 aRv.Throw(NS_ERROR_UNEXPECTED); 62 return nullptr; 63 } 64 RefPtr<EventTarget> target = new ConstructibleEventTarget(global); 65 return target.forget(); 66 } 67 68 bool EventTarget::ComputeWantsUntrusted( 69 const Nullable<bool>& aWantsUntrusted, 70 const AddEventListenerOptionsOrBoolean* aOptions, ErrorResult& aRv) { 71 if (aOptions && aOptions->IsAddEventListenerOptions()) { 72 const auto& options = aOptions->GetAsAddEventListenerOptions(); 73 if (options.mWantUntrusted.WasPassed()) { 74 return options.mWantUntrusted.Value(); 75 } 76 } 77 78 if (!aWantsUntrusted.IsNull()) { 79 return aWantsUntrusted.Value(); 80 } 81 82 bool defaultWantsUntrusted = ComputeDefaultWantsUntrusted(aRv); 83 if (aRv.Failed()) { 84 return false; 85 } 86 87 return defaultWantsUntrusted; 88 } 89 90 void EventTarget::AddEventListener( 91 const nsAString& aType, EventListener* aCallback, 92 const AddEventListenerOptionsOrBoolean& aOptions, 93 const Nullable<bool>& aWantsUntrusted) { 94 IgnoredErrorResult rv; 95 bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, &aOptions, rv); 96 if (NS_WARN_IF(rv.Failed())) { 97 return; 98 } 99 100 EventListenerManager* elm = GetOrCreateListenerManager(); 101 if (!elm) { 102 return; 103 } 104 105 elm->AddEventListener(aType, aCallback, aOptions, wantsUntrusted); 106 } 107 108 nsresult EventTarget::AddEventListener(const nsAString& aType, 109 nsIDOMEventListener* aListener, 110 bool aUseCapture, 111 const Nullable<bool>& aWantsUntrusted) { 112 ErrorResult rv; 113 bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, nullptr, rv); 114 if (rv.Failed()) { 115 return rv.StealNSResult(); 116 } 117 118 EventListenerManager* elm = GetOrCreateListenerManager(); 119 NS_ENSURE_STATE(elm); 120 elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted); 121 return NS_OK; 122 } 123 124 void EventTarget::RemoveEventListener( 125 const nsAString& aType, EventListener* aListener, 126 const EventListenerOptionsOrBoolean& aOptions) { 127 EventListenerManager* elm = GetExistingListenerManager(); 128 if (elm) { 129 elm->RemoveEventListener(aType, aListener, aOptions); 130 } 131 } 132 133 void EventTarget::RemoveEventListener(const nsAString& aType, 134 nsIDOMEventListener* aListener, 135 bool aUseCapture) { 136 EventListenerManager* elm = GetExistingListenerManager(); 137 if (elm) { 138 elm->RemoveEventListener(aType, aListener, aUseCapture); 139 } 140 } 141 142 nsresult EventTarget::AddSystemEventListener( 143 const nsAString& aType, nsIDOMEventListener* aListener, bool aUseCapture, 144 const Nullable<bool>& aWantsUntrusted) { 145 ErrorResult rv; 146 bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, nullptr, rv); 147 if (rv.Failed()) { 148 return rv.StealNSResult(); 149 } 150 151 EventListenerManager* elm = GetOrCreateListenerManager(); 152 NS_ENSURE_STATE(elm); 153 154 EventListenerFlags flags; 155 flags.mInSystemGroup = true; 156 flags.mCapture = aUseCapture; 157 flags.mAllowUntrustedEvents = wantsUntrusted; 158 elm->AddEventListenerByType(aListener, aType, flags); 159 return NS_OK; 160 } 161 162 void EventTarget::RemoveSystemEventListener(const nsAString& aType, 163 nsIDOMEventListener* aListener, 164 bool aUseCapture) { 165 EventListenerManager* elm = GetExistingListenerManager(); 166 if (elm) { 167 EventListenerFlags flags; 168 flags.mInSystemGroup = true; 169 flags.mCapture = aUseCapture; 170 elm->RemoveEventListenerByType(aListener, aType, flags); 171 } 172 } 173 174 EventHandlerNonNull* EventTarget::GetEventHandler(nsAtom* aType) { 175 EventListenerManager* elm = GetExistingListenerManager(); 176 return elm ? elm->GetEventHandler(aType) : nullptr; 177 } 178 179 void EventTarget::SetEventHandler(const nsAString& aType, 180 EventHandlerNonNull* aHandler, 181 ErrorResult& aRv) { 182 if (!StringBeginsWith(aType, u"on"_ns)) { 183 aRv.Throw(NS_ERROR_INVALID_ARG); 184 return; 185 } 186 RefPtr<nsAtom> type = NS_Atomize(aType); 187 SetEventHandler(type, aHandler); 188 } 189 190 void EventTarget::SetEventHandler(nsAtom* aType, 191 EventHandlerNonNull* aHandler) { 192 GetOrCreateListenerManager()->SetEventHandler(aType, aHandler); 193 } 194 195 bool EventTarget::HasNonSystemGroupListenersForUntrustedKeyEvents() const { 196 EventListenerManager* elm = GetExistingListenerManager(); 197 return elm && elm->HasNonSystemGroupListenersForUntrustedKeyEvents(); 198 } 199 200 bool EventTarget::HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents() 201 const { 202 EventListenerManager* elm = GetExistingListenerManager(); 203 return elm && 204 elm->HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents(); 205 } 206 207 bool EventTarget::IsApzAware() const { 208 EventListenerManager* elm = GetExistingListenerManager(); 209 return elm && elm->HasApzAwareListeners(); 210 } 211 212 void EventTarget::DispatchEvent(Event& aEvent) { 213 // The caller type doesn't really matter if we don't care about the 214 // return value, but let's be safe and pass NonSystem. 215 (void)DispatchEvent(aEvent, CallerType::NonSystem, IgnoreErrors()); 216 } 217 218 void EventTarget::DispatchEvent(Event& aEvent, ErrorResult& aRv) { 219 // The caller type doesn't really matter if we don't care about the 220 // return value, but let's be safe and pass NonSystem. 221 (void)DispatchEvent(aEvent, CallerType::NonSystem, IgnoreErrors()); 222 } 223 224 Nullable<WindowProxyHolder> EventTarget::GetOwnerGlobalForBindings() { 225 nsPIDOMWindowOuter* win = GetOwnerGlobalForBindingsInternal(); 226 if (!win) { 227 return nullptr; 228 } 229 230 return WindowProxyHolder(win->GetBrowsingContext()); 231 } 232 233 nsPIDOMWindowInner* EventTarget::GetAsInnerWindow() { 234 return IsInnerWindow() ? static_cast<nsGlobalWindowInner*>(this) : nullptr; 235 } 236 237 const nsPIDOMWindowInner* EventTarget::GetAsInnerWindow() const { 238 return IsInnerWindow() ? static_cast<const nsGlobalWindowInner*>(this) 239 : nullptr; 240 } 241 242 nsPIDOMWindowOuter* EventTarget::GetAsOuterWindow() { 243 return IsOuterWindow() ? static_cast<nsGlobalWindowOuter*>(this) : nullptr; 244 } 245 246 const nsPIDOMWindowOuter* EventTarget::GetAsOuterWindow() const { 247 return IsOuterWindow() ? static_cast<const nsGlobalWindowOuter*>(this) 248 : nullptr; 249 } 250 251 nsPIDOMWindowInner* EventTarget::AsInnerWindow() { 252 MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow()); 253 return static_cast<nsGlobalWindowInner*>(this); 254 } 255 256 const nsPIDOMWindowInner* EventTarget::AsInnerWindow() const { 257 MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow()); 258 return static_cast<const nsGlobalWindowInner*>(this); 259 } 260 261 nsPIDOMWindowOuter* EventTarget::AsOuterWindow() { 262 MOZ_DIAGNOSTIC_ASSERT(IsOuterWindow()); 263 return static_cast<nsGlobalWindowOuter*>(this); 264 } 265 266 const nsPIDOMWindowOuter* EventTarget::AsOuterWindow() const { 267 MOZ_DIAGNOSTIC_ASSERT(IsOuterWindow()); 268 return static_cast<const nsGlobalWindowOuter*>(this); 269 } 270 271 } // namespace mozilla::dom