Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / events / EventListenerManager.h
blobcf56282999c580a053ce3305482c0e126298dcc4
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 #ifndef mozilla_EventListenerManager_h_
8 #define mozilla_EventListenerManager_h_
10 #include "mozilla/BasicEvents.h"
11 #include "mozilla/JSEventHandler.h"
12 #include "mozilla/MemoryReporting.h"
13 #include "mozilla/dom/AbortFollower.h"
14 #include "mozilla/dom/EventListenerBinding.h"
15 #include "nsCOMPtr.h"
16 #include "nsCycleCollectionParticipant.h"
17 #include "nsGkAtoms.h"
18 #include "nsIDOMEventListener.h"
19 #include "nsTArray.h"
20 #include "nsTObserverArray.h"
22 class nsIEventListenerInfo;
23 class nsPIDOMWindowInner;
24 class JSTracer;
26 struct EventTypeData;
28 namespace mozilla {
30 class ELMCreationDetector;
31 class EventListenerManager;
32 class ListenerSignalFollower;
34 namespace dom {
35 class Event;
36 class EventTarget;
37 class Element;
38 } // namespace dom
40 using EventListenerHolder =
41 dom::CallbackObjectHolder<dom::EventListener, nsIDOMEventListener>;
43 struct EventListenerFlags {
44 friend class EventListenerManager;
46 private:
47 // If mListenerIsJSListener is true, the listener is implemented by JS.
48 // Otherwise, it's implemented by native code or JS but it's wrapped.
49 bool mListenerIsJSListener : 1;
51 public:
52 // If mCapture is true, it means the listener captures the event. Otherwise,
53 // it's listening at bubbling phase.
54 bool mCapture : 1;
55 // If mInSystemGroup is true, the listener is listening to the events in the
56 // system group.
57 bool mInSystemGroup : 1;
58 // If mAllowUntrustedEvents is true, the listener is listening to the
59 // untrusted events too.
60 bool mAllowUntrustedEvents : 1;
61 // If mPassive is true, the listener will not be calling preventDefault on the
62 // event. (If it does call preventDefault, we should ignore it).
63 bool mPassive : 1;
64 // If mOnce is true, the listener will be removed from the manager before it
65 // is invoked, so that it would only be invoked once.
66 bool mOnce : 1;
68 EventListenerFlags()
69 : mListenerIsJSListener(false),
70 mCapture(false),
71 mInSystemGroup(false),
72 mAllowUntrustedEvents(false),
73 mPassive(false),
74 mOnce(false) {}
76 bool EqualsForAddition(const EventListenerFlags& aOther) const {
77 return (mCapture == aOther.mCapture &&
78 mInSystemGroup == aOther.mInSystemGroup &&
79 mListenerIsJSListener == aOther.mListenerIsJSListener &&
80 mAllowUntrustedEvents == aOther.mAllowUntrustedEvents);
81 // Don't compare mPassive or mOnce
84 bool EqualsForRemoval(const EventListenerFlags& aOther) const {
85 return (mCapture == aOther.mCapture &&
86 mInSystemGroup == aOther.mInSystemGroup &&
87 mListenerIsJSListener == aOther.mListenerIsJSListener);
88 // Don't compare mAllowUntrustedEvents, mPassive, or mOnce
92 inline EventListenerFlags TrustedEventsAtBubble() {
93 EventListenerFlags flags;
94 return flags;
97 inline EventListenerFlags TrustedEventsAtCapture() {
98 EventListenerFlags flags;
99 flags.mCapture = true;
100 return flags;
103 inline EventListenerFlags AllEventsAtBubble() {
104 EventListenerFlags flags;
105 flags.mAllowUntrustedEvents = true;
106 return flags;
109 inline EventListenerFlags AllEventsAtCapture() {
110 EventListenerFlags flags;
111 flags.mCapture = true;
112 flags.mAllowUntrustedEvents = true;
113 return flags;
116 inline EventListenerFlags TrustedEventsAtSystemGroupBubble() {
117 EventListenerFlags flags;
118 flags.mInSystemGroup = true;
119 return flags;
122 inline EventListenerFlags TrustedEventsAtSystemGroupCapture() {
123 EventListenerFlags flags;
124 flags.mCapture = true;
125 flags.mInSystemGroup = true;
126 return flags;
129 inline EventListenerFlags AllEventsAtSystemGroupBubble() {
130 EventListenerFlags flags;
131 flags.mInSystemGroup = true;
132 flags.mAllowUntrustedEvents = true;
133 return flags;
136 inline EventListenerFlags AllEventsAtSystemGroupCapture() {
137 EventListenerFlags flags;
138 flags.mCapture = true;
139 flags.mInSystemGroup = true;
140 flags.mAllowUntrustedEvents = true;
141 return flags;
144 class EventListenerManagerBase {
145 protected:
146 EventListenerManagerBase();
148 void ClearNoListenersForEvents() {
149 mNoListenerForEvents[0] = eVoidEvent;
150 mNoListenerForEvents[1] = eVoidEvent;
151 mNoListenerForEvents[2] = eVoidEvent;
154 EventMessage mNoListenerForEvents[3];
155 uint16_t mMayHaveDOMActivateEventListener : 1;
156 uint16_t mMayHavePaintEventListener : 1;
157 uint16_t mMayHaveMutationListeners : 1;
158 uint16_t mMayHaveCapturingListeners : 1;
159 uint16_t mMayHaveSystemGroupListeners : 1;
160 uint16_t mMayHaveTouchEventListener : 1;
161 uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
162 uint16_t mMayHavePointerEnterLeaveEventListener : 1;
163 uint16_t mMayHaveSelectionChangeEventListener : 1;
164 uint16_t mMayHaveFormSelectEventListener : 1;
165 uint16_t mMayHaveTransitionEventListener : 1;
166 uint16_t mClearingListeners : 1;
167 uint16_t mIsMainThreadELM : 1;
168 uint16_t mMayHaveListenersForUntrustedEvents : 1;
169 // 2 unused flags.
173 * Event listener manager
176 class EventListenerManager final : public EventListenerManagerBase {
177 ~EventListenerManager();
179 public:
180 struct Listener;
181 class ListenerSignalFollower : public dom::AbortFollower {
182 public:
183 explicit ListenerSignalFollower(EventListenerManager* aListenerManager,
184 Listener* aListener, nsAtom* aTypeAtom);
186 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
187 NS_DECL_CYCLE_COLLECTION_CLASS(ListenerSignalFollower)
189 void RunAbortAlgorithm() override;
191 void Disconnect() {
192 mListenerManager = nullptr;
193 mListener.Reset();
194 Unfollow();
197 protected:
198 ~ListenerSignalFollower() = default;
200 EventListenerManager* mListenerManager;
201 EventListenerHolder mListener;
202 RefPtr<nsAtom> mTypeAtom;
203 bool mAllEvents;
204 EventListenerFlags mFlags;
207 struct Listener {
208 RefPtr<ListenerSignalFollower> mSignalFollower;
209 EventListenerHolder mListener;
211 enum ListenerType : uint8_t {
212 // No listener.
213 eNoListener,
214 // A generic C++ implementation of nsIDOMEventListener.
215 eNativeListener,
216 // An event handler attribute using JSEventHandler.
217 eJSEventListener,
218 // A scripted EventListener.
219 eWebIDLListener,
221 ListenerType mListenerType;
223 bool mListenerIsHandler : 1;
224 bool mHandlerIsString : 1;
225 bool mAllEvents : 1;
226 bool mEnabled : 1;
228 EventListenerFlags mFlags;
230 JSEventHandler* GetJSEventHandler() const {
231 return (mListenerType == eJSEventListener)
232 ? static_cast<JSEventHandler*>(mListener.GetXPCOMCallback())
233 : nullptr;
236 Listener()
237 : mListenerType(eNoListener),
238 mListenerIsHandler(false),
239 mHandlerIsString(false),
240 mAllEvents(false),
241 mEnabled(true) {}
243 Listener(Listener&& aOther)
244 : mSignalFollower(std::move(aOther.mSignalFollower)),
245 mListener(std::move(aOther.mListener)),
246 mListenerType(aOther.mListenerType),
247 mListenerIsHandler(aOther.mListenerIsHandler),
248 mHandlerIsString(aOther.mHandlerIsString),
249 mAllEvents(aOther.mAllEvents),
250 mEnabled(aOther.mEnabled),
251 mFlags(aOther.mFlags) {
252 aOther.mListenerType = eNoListener;
253 aOther.mListenerIsHandler = false;
254 aOther.mHandlerIsString = false;
255 aOther.mAllEvents = false;
256 aOther.mEnabled = true;
259 ~Listener() {
260 if ((mListenerType == eJSEventListener) && mListener) {
261 static_cast<JSEventHandler*>(mListener.GetXPCOMCallback())
262 ->Disconnect();
264 if (mSignalFollower) {
265 mSignalFollower->Disconnect();
269 MOZ_ALWAYS_INLINE bool MatchesEventGroup(const WidgetEvent* aEvent) const {
270 return mFlags.mInSystemGroup == aEvent->mFlags.mInSystemGroup;
273 MOZ_ALWAYS_INLINE bool MatchesEventPhase(const WidgetEvent* aEvent) const {
274 return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) ||
275 (!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase));
278 // Allow only trusted events, except when listener permits untrusted
279 // events.
280 MOZ_ALWAYS_INLINE bool AllowsEventTrustedness(
281 const WidgetEvent* aEvent) const {
282 return aEvent->IsTrusted() || mFlags.mAllowUntrustedEvents;
287 * A reference counted subclass of a listener observer array.
289 struct ListenerArray final : public nsAutoTObserverArray<Listener, 1> {
290 NS_INLINE_DECL_REFCOUNTING(EventListenerManager::ListenerArray);
291 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
293 protected:
294 ~ListenerArray() = default;
298 * An entry in the event listener map for a certain event type, carrying the
299 * array of listeners for that type.
301 struct EventListenerMapEntry {
302 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
304 // The event type. Null if this entry is for "all events" listeners.
305 RefPtr<nsAtom> mTypeAtom;
306 // The array of listeners. New listeners are always added at the end.
307 // Always non-null.
308 // This is a RefPtr rather than an inline member for two reasons:
309 // - It needs to be a separate heap allocation so that, if the array of
310 // entries is mutated during iteration, the ListenerArray remains in a
311 // stable place.
312 // - It's a RefPtr rather than a UniquePtr so that iteration can share
313 // ownership of it and make sure that the listener array remains alive
314 // even if the entry is removed during iteration.
315 RefPtr<ListenerArray> mListeners;
319 * The map of event listeners, keyed by event type atom.
321 struct EventListenerMap {
322 bool IsEmpty() const { return mEntries.IsEmpty(); }
323 void Clear() { mEntries.Clear(); }
325 Maybe<size_t> EntryIndexForType(nsAtom* aTypeAtom) const;
326 Maybe<size_t> EntryIndexForAllEvents() const;
328 // Returns null if no entry is present for the given type.
329 RefPtr<ListenerArray> GetListenersForType(nsAtom* aTypeAtom) const;
330 RefPtr<ListenerArray> GetListenersForAllEvents() const;
332 // Never returns null, creates a new empty entry if needed.
333 RefPtr<ListenerArray> GetOrCreateListenersForType(nsAtom* aTypeAtom);
334 RefPtr<ListenerArray> GetOrCreateListenersForAllEvents();
336 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
338 // The array of entries, ordered by event type atom (specifically by the
339 // nsAtom* address). If mEntries contains an entry for "all events"
340 // listeners, that entry will be the first entry, because its atom will be
341 // null so it will be ordered to the front.
342 // All entries have non-empty listener arrays. If a non-empty listener
343 // entry becomes empty, it is removed immediately.
344 AutoTArray<EventListenerMapEntry, 2> mEntries;
347 explicit EventListenerManager(dom::EventTarget* aTarget);
349 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EventListenerManager)
351 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EventListenerManager)
353 void AddEventListener(const nsAString& aType, nsIDOMEventListener* aListener,
354 bool aUseCapture, bool aWantsUntrusted) {
355 AddEventListener(aType, EventListenerHolder(aListener), aUseCapture,
356 aWantsUntrusted);
358 void AddEventListener(const nsAString& aType, dom::EventListener* aListener,
359 const dom::AddEventListenerOptionsOrBoolean& aOptions,
360 bool aWantsUntrusted) {
361 AddEventListener(aType, EventListenerHolder(aListener), aOptions,
362 aWantsUntrusted);
364 void RemoveEventListener(const nsAString& aType,
365 nsIDOMEventListener* aListener, bool aUseCapture) {
366 RemoveEventListener(aType, EventListenerHolder(aListener), aUseCapture);
368 void RemoveEventListener(const nsAString& aType,
369 dom::EventListener* aListener,
370 const dom::EventListenerOptionsOrBoolean& aOptions) {
371 RemoveEventListener(aType, EventListenerHolder(aListener), aOptions);
374 void AddListenerForAllEvents(dom::EventListener* aListener, bool aUseCapture,
375 bool aWantsUntrusted, bool aSystemEventGroup);
376 void RemoveListenerForAllEvents(dom::EventListener* aListener,
377 bool aUseCapture, bool aSystemEventGroup);
380 * Sets events listeners of all types.
381 * @param an event listener
383 void AddEventListenerByType(nsIDOMEventListener* aListener,
384 const nsAString& type,
385 const EventListenerFlags& aFlags) {
386 AddEventListenerByType(EventListenerHolder(aListener), type, aFlags);
388 void AddEventListenerByType(dom::EventListener* aListener,
389 const nsAString& type,
390 const EventListenerFlags& aFlags) {
391 AddEventListenerByType(EventListenerHolder(aListener), type, aFlags);
393 void AddEventListenerByType(
394 EventListenerHolder aListener, const nsAString& type,
395 const EventListenerFlags& aFlags,
396 const dom::Optional<bool>& aPassive = dom::Optional<bool>(),
397 dom::AbortSignal* aSignal = nullptr);
398 void RemoveEventListenerByType(nsIDOMEventListener* aListener,
399 const nsAString& type,
400 const EventListenerFlags& aFlags) {
401 RemoveEventListenerByType(EventListenerHolder(aListener), type, aFlags);
403 void RemoveEventListenerByType(dom::EventListener* aListener,
404 const nsAString& type,
405 const EventListenerFlags& aFlags) {
406 RemoveEventListenerByType(EventListenerHolder(aListener), type, aFlags);
408 void RemoveEventListenerByType(EventListenerHolder aListener,
409 const nsAString& type,
410 const EventListenerFlags& aFlags);
413 * Sets the current "inline" event listener for aName to be a
414 * function compiled from aFunc if !aDeferCompilation. If
415 * aDeferCompilation, then we assume that we can get the string from
416 * mTarget later and compile lazily.
418 * aElement, if not null, is the element the string is associated with.
420 // XXXbz does that play correctly with nodes being adopted across
421 // documents? Need to double-check the spec here.
422 nsresult SetEventHandler(nsAtom* aName, const nsAString& aFunc,
423 bool aDeferCompilation, bool aPermitUntrustedEvents,
424 dom::Element* aElement);
426 * Remove the current "inline" event listener for aName.
428 void RemoveEventHandler(nsAtom* aName);
430 // We only get called from the event dispatch code, which knows to be careful
431 // with what it's doing. We could annotate ourselves as MOZ_CAN_RUN_SCRIPT,
432 // but then the event dispatch code would need a ton of MOZ_KnownLive for
433 // things that come from slightly complicated stack-lifetime data structures.
434 MOZ_CAN_RUN_SCRIPT_BOUNDARY
435 void HandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
436 dom::Event** aDOMEvent, dom::EventTarget* aCurrentTarget,
437 nsEventStatus* aEventStatus, bool aItemInShadowTree) {
438 if (!mMayHaveCapturingListeners && !aEvent->mFlags.mInBubblingPhase) {
439 return;
442 if (!mMayHaveSystemGroupListeners && aEvent->mFlags.mInSystemGroup) {
443 return;
446 if (!aEvent->IsTrusted() && !mMayHaveListenersForUntrustedEvents) {
447 return;
450 // Check if we already know that there is no event listener for the event.
451 if (aEvent->mMessage == eUnidentifiedEvent) {
452 if (mNoListenerForEventAtom == aEvent->mSpecifiedEventType) {
453 return;
455 } else if (mNoListenerForEvents[0] == aEvent->mMessage ||
456 mNoListenerForEvents[1] == aEvent->mMessage ||
457 mNoListenerForEvents[2] == aEvent->mMessage) {
458 return;
461 if (mListenerMap.IsEmpty() || aEvent->PropagationStopped()) {
462 return;
465 HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
466 aEventStatus, aItemInShadowTree);
470 * Tells the event listener manager that its target (which owns it) is
471 * no longer using it (and could go away).
473 void Disconnect();
476 * Allows us to quickly determine if we have mutation listeners registered.
478 bool HasMutationListeners();
481 * Allows us to quickly determine whether we have unload listeners registered.
483 bool HasUnloadListeners();
486 * Allows us to quickly determine whether we have beforeunload listeners
487 * registered.
489 bool HasBeforeUnloadListeners();
492 * Returns the mutation bits depending on which mutation listeners are
493 * registered to this listener manager.
494 * @note If a listener is an nsIDOMMutationListener, all possible mutation
495 * event bits are returned. All bits are also returned if one of the
496 * event listeners is registered to handle DOMSubtreeModified events.
498 uint32_t MutationListenerBits();
501 * Returns true if there is at least one event listener for aEventName.
503 bool HasListenersFor(const nsAString& aEventName) const;
506 * Returns true if there is at least one event listener for aEventNameWithOn.
507 * Note that aEventNameWithOn must start with "on"!
509 bool HasListenersFor(nsAtom* aEventNameWithOn) const;
512 * Similar to HasListenersFor, but ignores system group listeners.
514 bool HasNonSystemGroupListenersFor(nsAtom* aEventNameWithOn) const;
517 * Returns true if there is at least one event listener.
519 bool HasListeners() const;
522 * Sets aList to the list of nsIEventListenerInfo objects representing the
523 * listeners managed by this listener manager.
525 nsresult GetListenerInfo(nsTArray<RefPtr<nsIEventListenerInfo>>& aList);
527 nsresult IsListenerEnabled(nsAString& aType, JSObject* aListener,
528 bool aCapturing, bool aAllowsUntrusted,
529 bool aInSystemEventGroup, bool aIsHandler,
530 bool* aEnabled);
532 nsresult SetListenerEnabled(nsAString& aType, JSObject* aListener,
533 bool aCapturing, bool aAllowsUntrusted,
534 bool aInSystemEventGroup, bool aIsHandler,
535 bool aEnabled);
537 uint32_t GetIdentifierForEvent(nsAtom* aEvent);
539 bool MayHaveDOMActivateListeners() const {
540 return mMayHaveDOMActivateEventListener;
544 * Returns true if there may be a paint event listener registered,
545 * false if there definitely isn't.
547 bool MayHavePaintEventListener() const { return mMayHavePaintEventListener; }
550 * Returns true if there may be a touch event listener registered,
551 * false if there definitely isn't.
553 bool MayHaveTouchEventListener() const { return mMayHaveTouchEventListener; }
555 bool MayHaveMouseEnterLeaveEventListener() const {
556 return mMayHaveMouseEnterLeaveEventListener;
558 bool MayHavePointerEnterLeaveEventListener() const {
559 return mMayHavePointerEnterLeaveEventListener;
561 bool MayHaveSelectionChangeEventListener() const {
562 return mMayHaveSelectionChangeEventListener;
564 bool MayHaveFormSelectEventListener() const {
565 return mMayHaveFormSelectEventListener;
567 bool MayHaveTransitionEventListener() {
568 return mMayHaveTransitionEventListener;
571 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
573 uint32_t ListenerCount() const;
575 void MarkForCC();
577 void TraceListeners(JSTracer* aTrc);
579 dom::EventTarget* GetTarget() { return mTarget; }
581 bool HasNonSystemGroupListenersForUntrustedKeyEvents();
582 bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
584 bool HasApzAwareListeners();
585 bool IsApzAwareEvent(nsAtom* aEvent);
587 bool HasNonPassiveWheelListener();
590 * Remove all event listeners from the event target this EventListenerManager
591 * is for.
593 void RemoveAllListeners();
595 protected:
596 MOZ_CAN_RUN_SCRIPT
597 void HandleEventInternal(nsPresContext* aPresContext, WidgetEvent* aEvent,
598 dom::Event** aDOMEvent,
599 dom::EventTarget* aCurrentTarget,
600 nsEventStatus* aEventStatus, bool aItemInShadowTree);
603 * Iterate the listener array and calls the matching listeners.
605 * Returns true if any listener matching the event group was found.
607 MOZ_CAN_RUN_SCRIPT
608 bool HandleEventWithListenerArray(
609 ListenerArray* aListeners, nsAtom* aTypeAtom, EventMessage aEventMessage,
610 nsPresContext* aPresContext, WidgetEvent* aEvent, dom::Event** aDOMEvent,
611 dom::EventTarget* aCurrentTarget, bool aItemInShadowTree);
614 * Call the listener.
616 * Returns true if we should proceed iterating over the remaining listeners,
617 * or false if iteration should be stopped.
619 MOZ_CAN_RUN_SCRIPT
620 bool HandleEventSingleListener(Listener* aListener, nsAtom* aTypeAtom,
621 WidgetEvent* aEvent, dom::Event* aDOMEvent,
622 dom::EventTarget* aCurrentTarget,
623 bool aItemInShadowTree);
626 * If the given EventMessage has a legacy version that we support, then this
627 * function returns that legacy version. Otherwise, this function simply
628 * returns the passed-in EventMessage.
630 static EventMessage GetLegacyEventMessage(EventMessage aEventMessage);
633 * Get the event message for the given event name.
635 EventMessage GetEventMessage(nsAtom* aEventName) const;
638 * Get the event message and atom for the given event type.
640 EventMessage GetEventMessageAndAtomForListener(const nsAString& aType,
641 nsAtom** aAtom);
643 void ProcessApzAwareEventListenerAdd();
646 * Compile the "inline" event listener for aListener. The
647 * body of the listener can be provided in aBody; if this is null we
648 * will look for it on mTarget. If aBody is provided, aElement should be
649 * as well; otherwise it will also be inferred from mTarget.
651 nsresult CompileEventHandlerInternal(Listener* aListener, nsAtom* aTypeAtom,
652 const nsAString* aBody,
653 dom::Element* aElement);
656 * Find the Listener for the "inline" event listener for aTypeAtom.
658 Listener* FindEventHandler(nsAtom* aTypeAtom);
661 * Set the "inline" event listener for aName to aHandler. aHandler may be
662 * have no actual handler set to indicate that we should lazily get and
663 * compile the string for this listener, but in that case aContext and
664 * aScopeGlobal must be non-null. Otherwise, aContext and aScopeGlobal are
665 * allowed to be null.
667 Listener* SetEventHandlerInternal(nsAtom* aName,
668 const TypedEventHandler& aHandler,
669 bool aPermitUntrustedEvents);
671 bool IsDeviceType(nsAtom* aTypeAtom);
672 void EnableDevice(nsAtom* aTypeAtom);
673 void DisableDevice(nsAtom* aTypeAtom);
675 bool HasListenersForInternal(nsAtom* aEventNameWithOn,
676 bool aIgnoreSystemGroup) const;
678 Listener* GetListenerFor(nsAString& aType, JSObject* aListener,
679 bool aCapturing, bool aAllowsUntrusted,
680 bool aInSystemEventGroup, bool aIsHandler);
682 public:
684 * Set the "inline" event listener for aEventName to aHandler. If
685 * aHandler is null, this will actually remove the event listener
687 void SetEventHandler(nsAtom* aEventName, dom::EventHandlerNonNull* aHandler);
688 void SetEventHandler(dom::OnErrorEventHandlerNonNull* aHandler);
689 void SetEventHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler);
692 * Get the value of the "inline" event listener for aEventName.
693 * This may cause lazy compilation if the listener is uncompiled.
695 * Note: It's the caller's responsibility to make sure to call the right one
696 * of these methods. In particular, "onerror" events use
697 * OnErrorEventHandlerNonNull for some event targets and EventHandlerNonNull
698 * for others.
700 dom::EventHandlerNonNull* GetEventHandler(nsAtom* aEventName) {
701 const TypedEventHandler* typedHandler = GetTypedEventHandler(aEventName);
702 return typedHandler ? typedHandler->NormalEventHandler() : nullptr;
705 dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler() {
706 const TypedEventHandler* typedHandler =
707 GetTypedEventHandler(nsGkAtoms::onerror);
708 return typedHandler ? typedHandler->OnErrorEventHandler() : nullptr;
711 dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler() {
712 const TypedEventHandler* typedHandler =
713 GetTypedEventHandler(nsGkAtoms::onbeforeunload);
714 return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
717 private:
718 already_AddRefed<nsPIDOMWindowInner> WindowFromListener(
719 Listener* aListener, nsAtom* aTypeAtom, bool aItemInShadowTree);
721 protected:
723 * Helper method for implementing the various Get*EventHandler above. Will
724 * return null if we don't have an event handler for this event name.
726 const TypedEventHandler* GetTypedEventHandler(nsAtom* aEventName);
728 void AddEventListener(const nsAString& aType, EventListenerHolder aListener,
729 const dom::AddEventListenerOptionsOrBoolean& aOptions,
730 bool aWantsUntrusted);
731 void AddEventListener(const nsAString& aType, EventListenerHolder aListener,
732 bool aUseCapture, bool aWantsUntrusted);
733 void RemoveEventListener(const nsAString& aType,
734 EventListenerHolder aListener,
735 const dom::EventListenerOptionsOrBoolean& aOptions);
736 void RemoveEventListener(const nsAString& aType,
737 EventListenerHolder aListener, bool aUseCapture);
739 void AddEventListenerInternal(EventListenerHolder aListener,
740 EventMessage aEventMessage, nsAtom* aTypeAtom,
741 const EventListenerFlags& aFlags,
742 bool aHandler = false, bool aAllEvents = false,
743 dom::AbortSignal* aSignal = nullptr);
744 void RemoveEventListenerInternal(EventListenerHolder aListener,
745 nsAtom* aUserType,
746 const EventListenerFlags& aFlags,
747 bool aAllEvents = false);
748 void RemoveAllListenersSilently();
749 void NotifyEventListenerRemoved(nsAtom* aUserType);
750 const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
751 const EventTypeData* GetTypeDataForEventName(nsAtom* aName);
752 nsPIDOMWindowInner* GetInnerWindowForTarget();
753 already_AddRefed<nsPIDOMWindowInner> GetTargetAsInnerWindow() const;
755 bool ListenerCanHandle(const Listener* aListener, const WidgetEvent* aEvent,
756 EventMessage aEventMessage) const;
758 // BE AWARE, a lot of instances of EventListenerManager will be created.
759 // Therefor, we need to keep this class compact. When you add integer
760 // members, please add them to EventListenerManagerBase and check the size
761 // at build time.
763 already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalAndDocument(
764 mozilla::dom::Document** aDoc);
766 void MaybeMarkPassive(EventMessage aMessage, EventListenerFlags& aFlags);
768 EventListenerMap mListenerMap;
769 dom::EventTarget* MOZ_NON_OWNING_REF mTarget;
770 RefPtr<nsAtom> mNoListenerForEventAtom;
772 friend class ELMCreationDetector;
773 static uint32_t sMainThreadCreatedCount;
776 } // namespace mozilla
778 #endif // mozilla_EventListenerManager_h_