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 #ifndef mozilla_EventListenerManager_h_
8 #define mozilla_EventListenerManager_h_
9
10 #include "mozilla/BasicEvents.h"
11 #include "mozilla/dom/EventListenerBinding.h"
12 #include "mozilla/JSEventHandler.h"
13 #include "mozilla/MemoryReporting.h"
14 #include "nsCOMPtr.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsGkAtoms.h"
17 #include "nsIDOMEventListener.h"
18 #include "nsTObserverArray.h"
19
20 class nsIDocShell;
21 class nsIDOMEvent;
22 class nsIEventListenerInfo;
23 class nsPIDOMWindowInner;
24 class JSTracer;
25
26 struct EventTypeData;
27
28 template <class T>
29 class nsCOMArray;
30
31 namespace mozilla {
32
33 class ELMCreationDetector;
34 class EventListenerManager;
35
36 namespace dom {
37 class EventTarget;
38 class Element;
39 } // namespace dom
40
41 typedef dom::CallbackObjectHolder<dom::EventListener, nsIDOMEventListener>
42 EventListenerHolder;
43
44 struct EventListenerFlags {
45 friend class EventListenerManager;
46
47 private:
48 // If mListenerIsJSListener is true, the listener is implemented by JS.
49 // Otherwise, it's implemented by native code or JS but it's wrapped.
50 bool mListenerIsJSListener : 1;
51
52 public:
53 // If mCapture is true, it means the listener captures the event. Otherwise,
54 // it's listening at bubbling phase.
55 bool mCapture : 1;
56 // If mInSystemGroup is true, the listener is listening to the events in the
57 // system group.
58 bool mInSystemGroup : 1;
59 // If mAllowUntrustedEvents is true, the listener is listening to the
60 // untrusted events too.
61 bool mAllowUntrustedEvents : 1;
62 // If mPassive is true, the listener will not be calling preventDefault on the
63 // event. (If it does call preventDefault, we should ignore it).
64 bool mPassive : 1;
65 // If mOnce is true, the listener will be removed from the manager before it
66 // is invoked, so that it would only be invoked once.
67 bool mOnce : 1;
68
EventListenerFlagsEventListenerFlags69 EventListenerFlags()
70 : mListenerIsJSListener(false),
71 mCapture(false),
72 mInSystemGroup(false),
73 mAllowUntrustedEvents(false),
74 mPassive(false),
75 mOnce(false) {}
76
EqualsForAdditionEventListenerFlags77 bool EqualsForAddition(const EventListenerFlags& aOther) const {
78 return (mCapture == aOther.mCapture &&
79 mInSystemGroup == aOther.mInSystemGroup &&
80 mListenerIsJSListener == aOther.mListenerIsJSListener &&
81 mAllowUntrustedEvents == aOther.mAllowUntrustedEvents);
82 // Don't compare mPassive or mOnce
83 }
84
EqualsForRemovalEventListenerFlags85 bool EqualsForRemoval(const EventListenerFlags& aOther) const {
86 return (mCapture == aOther.mCapture &&
87 mInSystemGroup == aOther.mInSystemGroup &&
88 mListenerIsJSListener == aOther.mListenerIsJSListener);
89 // Don't compare mAllowUntrustedEvents, mPassive, or mOnce
90 }
91 };
92
TrustedEventsAtBubble()93 inline EventListenerFlags TrustedEventsAtBubble() {
94 EventListenerFlags flags;
95 return flags;
96 }
97
TrustedEventsAtCapture()98 inline EventListenerFlags TrustedEventsAtCapture() {
99 EventListenerFlags flags;
100 flags.mCapture = true;
101 return flags;
102 }
103
AllEventsAtBubble()104 inline EventListenerFlags AllEventsAtBubble() {
105 EventListenerFlags flags;
106 flags.mAllowUntrustedEvents = true;
107 return flags;
108 }
109
AllEventsAtCapture()110 inline EventListenerFlags AllEventsAtCapture() {
111 EventListenerFlags flags;
112 flags.mCapture = true;
113 flags.mAllowUntrustedEvents = true;
114 return flags;
115 }
116
TrustedEventsAtSystemGroupBubble()117 inline EventListenerFlags TrustedEventsAtSystemGroupBubble() {
118 EventListenerFlags flags;
119 flags.mInSystemGroup = true;
120 return flags;
121 }
122
TrustedEventsAtSystemGroupCapture()123 inline EventListenerFlags TrustedEventsAtSystemGroupCapture() {
124 EventListenerFlags flags;
125 flags.mCapture = true;
126 flags.mInSystemGroup = true;
127 return flags;
128 }
129
AllEventsAtSystemGroupBubble()130 inline EventListenerFlags AllEventsAtSystemGroupBubble() {
131 EventListenerFlags flags;
132 flags.mInSystemGroup = true;
133 flags.mAllowUntrustedEvents = true;
134 return flags;
135 }
136
AllEventsAtSystemGroupCapture()137 inline EventListenerFlags AllEventsAtSystemGroupCapture() {
138 EventListenerFlags flags;
139 flags.mCapture = true;
140 flags.mInSystemGroup = true;
141 flags.mAllowUntrustedEvents = true;
142 return flags;
143 }
144
145 class EventListenerManagerBase {
146 protected:
147 EventListenerManagerBase();
148
149 EventMessage mNoListenerForEvent;
150 uint16_t mMayHavePaintEventListener : 1;
151 uint16_t mMayHaveMutationListeners : 1;
152 uint16_t mMayHaveCapturingListeners : 1;
153 uint16_t mMayHaveSystemGroupListeners : 1;
154 uint16_t mMayHaveTouchEventListener : 1;
155 uint16_t mMayHaveMouseEnterLeaveEventListener : 1;
156 uint16_t mMayHavePointerEnterLeaveEventListener : 1;
157 uint16_t mMayHaveKeyEventListener : 1;
158 uint16_t mMayHaveInputOrCompositionEventListener : 1;
159 uint16_t mMayHaveSelectionChangeEventListener : 1;
160 uint16_t mClearingListeners : 1;
161 uint16_t mIsMainThreadELM : 1;
162 // uint16_t mUnused : 4;
163 };
164
165 /*
166 * Event listener manager
167 */
168
169 class EventListenerManager final : public EventListenerManagerBase {
170 ~EventListenerManager();
171
172 public:
173 struct Listener {
174 EventListenerHolder mListener;
175 RefPtr<nsAtom> mTypeAtom; // for the main thread
176 nsString mTypeString; // for non-main-threads
177 EventMessage mEventMessage;
178
179 enum ListenerType : uint8_t {
180 eNoListener,
181 eNativeListener,
182 eJSEventListener,
183 eWrappedJSListener,
184 eWebIDLListener,
185 };
186 ListenerType mListenerType;
187
188 bool mListenerIsHandler : 1;
189 bool mHandlerIsString : 1;
190 bool mAllEvents : 1;
191 bool mIsChrome : 1;
192
193 EventListenerFlags mFlags;
194
GetJSEventHandlerListener195 JSEventHandler* GetJSEventHandler() const {
196 return (mListenerType == eJSEventListener)
197 ? static_cast<JSEventHandler*>(mListener.GetXPCOMCallback())
198 : nullptr;
199 }
200
ListenerListener201 Listener()
202 : mEventMessage(eVoidEvent),
203 mListenerType(eNoListener),
204 mListenerIsHandler(false),
205 mHandlerIsString(false),
206 mAllEvents(false),
207 mIsChrome(false) {}
208
ListenerListener209 Listener(Listener&& aOther)
210 : mListener(Move(aOther.mListener)),
211 mTypeAtom(aOther.mTypeAtom.forget()),
212 mTypeString(aOther.mTypeString),
213 mEventMessage(aOther.mEventMessage),
214 mListenerType(aOther.mListenerType),
215 mListenerIsHandler(aOther.mListenerIsHandler),
216 mHandlerIsString(aOther.mHandlerIsString),
217 mAllEvents(aOther.mAllEvents),
218 mIsChrome(aOther.mIsChrome) {
219 aOther.mTypeString.Truncate();
220 aOther.mEventMessage = eVoidEvent;
221 aOther.mListenerType = eNoListener;
222 aOther.mListenerIsHandler = false;
223 aOther.mHandlerIsString = false;
224 aOther.mAllEvents = false;
225 aOther.mIsChrome = false;
226 }
227
~ListenerListener228 ~Listener() {
229 if ((mListenerType == eJSEventListener) && mListener) {
230 static_cast<JSEventHandler*>(mListener.GetXPCOMCallback())
231 ->Disconnect();
232 }
233 }
234
IsListeningListener235 MOZ_ALWAYS_INLINE bool IsListening(const WidgetEvent* aEvent) const {
236 if (mFlags.mInSystemGroup != aEvent->mFlags.mInSystemGroup) {
237 return false;
238 }
239 // FIXME Should check !mFlags.mCapture when the event is in target
240 // phase because capture phase event listeners should not be fired.
241 // But it breaks at least <xul:dialog>'s buttons. Bug 235441.
242 return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) ||
243 (!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase));
244 }
245 };
246
247 explicit EventListenerManager(dom::EventTarget* aTarget);
248
249 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EventListenerManager)
250
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EventListenerManager)251 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EventListenerManager)
252
253 void AddEventListener(const nsAString& aType, nsIDOMEventListener* aListener,
254 bool aUseCapture, bool aWantsUntrusted) {
255 AddEventListener(aType, EventListenerHolder(aListener), aUseCapture,
256 aWantsUntrusted);
257 }
AddEventListener(const nsAString & aType,dom::EventListener * aListener,const dom::AddEventListenerOptionsOrBoolean & aOptions,bool aWantsUntrusted)258 void AddEventListener(const nsAString& aType, dom::EventListener* aListener,
259 const dom::AddEventListenerOptionsOrBoolean& aOptions,
260 bool aWantsUntrusted) {
261 AddEventListener(aType, EventListenerHolder(aListener), aOptions,
262 aWantsUntrusted);
263 }
RemoveEventListener(const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture)264 void RemoveEventListener(const nsAString& aType,
265 nsIDOMEventListener* aListener, bool aUseCapture) {
266 RemoveEventListener(aType, EventListenerHolder(aListener), aUseCapture);
267 }
RemoveEventListener(const nsAString & aType,dom::EventListener * aListener,const dom::EventListenerOptionsOrBoolean & aOptions)268 void RemoveEventListener(const nsAString& aType,
269 dom::EventListener* aListener,
270 const dom::EventListenerOptionsOrBoolean& aOptions) {
271 RemoveEventListener(aType, EventListenerHolder(aListener), aOptions);
272 }
273
274 void AddListenerForAllEvents(nsIDOMEventListener* aListener, bool aUseCapture,
275 bool aWantsUntrusted, bool aSystemEventGroup);
276 void RemoveListenerForAllEvents(nsIDOMEventListener* aListener,
277 bool aUseCapture, bool aSystemEventGroup);
278
279 /**
280 * Sets events listeners of all types.
281 * @param an event listener
282 */
AddEventListenerByType(nsIDOMEventListener * aListener,const nsAString & type,const EventListenerFlags & aFlags)283 void AddEventListenerByType(nsIDOMEventListener* aListener,
284 const nsAString& type,
285 const EventListenerFlags& aFlags) {
286 AddEventListenerByType(EventListenerHolder(aListener), type, aFlags);
287 }
288 void AddEventListenerByType(EventListenerHolder aListener,
289 const nsAString& type,
290 const EventListenerFlags& aFlags);
RemoveEventListenerByType(nsIDOMEventListener * aListener,const nsAString & type,const EventListenerFlags & aFlags)291 void RemoveEventListenerByType(nsIDOMEventListener* aListener,
292 const nsAString& type,
293 const EventListenerFlags& aFlags) {
294 RemoveEventListenerByType(EventListenerHolder(aListener), type, aFlags);
295 }
296 void RemoveEventListenerByType(EventListenerHolder aListener,
297 const nsAString& type,
298 const EventListenerFlags& aFlags);
299
300 /**
301 * Sets the current "inline" event listener for aName to be a
302 * function compiled from aFunc if !aDeferCompilation. If
303 * aDeferCompilation, then we assume that we can get the string from
304 * mTarget later and compile lazily.
305 *
306 * aElement, if not null, is the element the string is associated with.
307 */
308 // XXXbz does that play correctly with nodes being adopted across
309 // documents? Need to double-check the spec here.
310 nsresult SetEventHandler(nsAtom* aName, const nsAString& aFunc,
311 bool aDeferCompilation, bool aPermitUntrustedEvents,
312 dom::Element* aElement);
313 /**
314 * Remove the current "inline" event listener for aName.
315 */
316 void RemoveEventHandler(nsAtom* aName, const nsAString& aTypeString);
317
HandleEvent(nsPresContext * aPresContext,WidgetEvent * aEvent,nsIDOMEvent ** aDOMEvent,dom::EventTarget * aCurrentTarget,nsEventStatus * aEventStatus)318 void HandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
319 nsIDOMEvent** aDOMEvent, dom::EventTarget* aCurrentTarget,
320 nsEventStatus* aEventStatus) {
321 if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
322 return;
323 }
324
325 if (!mMayHaveCapturingListeners && !aEvent->mFlags.mInBubblingPhase) {
326 return;
327 }
328
329 if (!mMayHaveSystemGroupListeners && aEvent->mFlags.mInSystemGroup) {
330 return;
331 }
332
333 // Check if we already know that there is no event listener for the event.
334 if (mNoListenerForEvent == aEvent->mMessage &&
335 (mNoListenerForEvent != eUnidentifiedEvent ||
336 mNoListenerForEventAtom == aEvent->mSpecifiedEventType)) {
337 return;
338 }
339 HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
340 aEventStatus);
341 }
342
343 /**
344 * Tells the event listener manager that its target (which owns it) is
345 * no longer using it (and could go away).
346 */
347 void Disconnect();
348
349 /**
350 * Allows us to quickly determine if we have mutation listeners registered.
351 */
352 bool HasMutationListeners();
353
354 /**
355 * Allows us to quickly determine whether we have unload or beforeunload
356 * listeners registered.
357 */
358 bool HasUnloadListeners();
359
360 /**
361 * Returns the mutation bits depending on which mutation listeners are
362 * registered to this listener manager.
363 * @note If a listener is an nsIDOMMutationListener, all possible mutation
364 * event bits are returned. All bits are also returned if one of the
365 * event listeners is registered to handle DOMSubtreeModified events.
366 */
367 uint32_t MutationListenerBits();
368
369 /**
370 * Returns true if there is at least one event listener for aEventName.
371 */
372 bool HasListenersFor(const nsAString& aEventName);
373
374 /**
375 * Returns true if there is at least one event listener for aEventNameWithOn.
376 * Note that aEventNameWithOn must start with "on"!
377 */
378 bool HasListenersFor(nsAtom* aEventNameWithOn);
379
380 /**
381 * Returns true if there is at least one event listener.
382 */
383 bool HasListeners();
384
385 /**
386 * Sets aList to the list of nsIEventListenerInfo objects representing the
387 * listeners managed by this listener manager.
388 */
389 nsresult GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList);
390
391 uint32_t GetIdentifierForEvent(nsAtom* aEvent);
392
393 static void Shutdown();
394
395 /**
396 * Returns true if there may be a paint event listener registered,
397 * false if there definitely isn't.
398 */
MayHavePaintEventListener()399 bool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
400
401 /**
402 * Returns true if there may be a touch event listener registered,
403 * false if there definitely isn't.
404 */
MayHaveTouchEventListener()405 bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
406
MayHaveMouseEnterLeaveEventListener()407 bool MayHaveMouseEnterLeaveEventListener() {
408 return mMayHaveMouseEnterLeaveEventListener;
409 }
MayHavePointerEnterLeaveEventListener()410 bool MayHavePointerEnterLeaveEventListener() {
411 return mMayHavePointerEnterLeaveEventListener;
412 }
MayHaveSelectionChangeEventListener()413 bool MayHaveSelectionChangeEventListener() {
414 return mMayHaveSelectionChangeEventListener;
415 }
416
417 /**
418 * Returns true if there may be a key event listener (keydown, keypress,
419 * or keyup) registered, or false if there definitely isn't.
420 */
MayHaveKeyEventListener()421 bool MayHaveKeyEventListener() { return mMayHaveKeyEventListener; }
422
423 /**
424 * Returns true if there may be an advanced input event listener (input,
425 * compositionstart, compositionupdate, or compositionend) registered,
426 * or false if there definitely isn't.
427 */
MayHaveInputOrCompositionEventListener()428 bool MayHaveInputOrCompositionEventListener() {
429 return mMayHaveInputOrCompositionEventListener;
430 }
431
432 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
433
ListenerCount()434 uint32_t ListenerCount() const { return mListeners.Length(); }
435
436 void MarkForCC();
437
438 void TraceListeners(JSTracer* aTrc);
439
GetTarget()440 dom::EventTarget* GetTarget() { return mTarget; }
441
442 bool HasNonSystemGroupListenersForUntrustedKeyEvents();
443 bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
444
445 bool HasApzAwareListeners();
446 bool IsApzAwareListener(Listener* aListener);
447 bool IsApzAwareEvent(nsAtom* aEvent);
448
449 protected:
450 void HandleEventInternal(nsPresContext* aPresContext, WidgetEvent* aEvent,
451 nsIDOMEvent** aDOMEvent,
452 dom::EventTarget* aCurrentTarget,
453 nsEventStatus* aEventStatus);
454
455 nsresult HandleEventSubType(Listener* aListener, nsIDOMEvent* aDOMEvent,
456 dom::EventTarget* aCurrentTarget);
457
458 /**
459 * If the given EventMessage has a legacy version that we support, then this
460 * function returns that legacy version. Otherwise, this function simply
461 * returns the passed-in EventMessage.
462 */
463 EventMessage GetLegacyEventMessage(EventMessage aEventMessage) const;
464
465 void ProcessApzAwareEventListenerAdd();
466
467 /**
468 * Compile the "inline" event listener for aListener. The
469 * body of the listener can be provided in aBody; if this is null we
470 * will look for it on mTarget. If aBody is provided, aElement should be
471 * as well; otherwise it will also be inferred from mTarget.
472 */
473 nsresult CompileEventHandlerInternal(Listener* aListener,
474 const nsAString* aBody,
475 dom::Element* aElement);
476
477 /**
478 * Find the Listener for the "inline" event listener for aTypeAtom.
479 */
480 Listener* FindEventHandler(EventMessage aEventMessage, nsAtom* aTypeAtom,
481 const nsAString& aTypeString);
482
483 /**
484 * Set the "inline" event listener for aName to aHandler. aHandler may be
485 * have no actual handler set to indicate that we should lazily get and
486 * compile the string for this listener, but in that case aContext and
487 * aScopeGlobal must be non-null. Otherwise, aContext and aScopeGlobal are
488 * allowed to be null.
489 */
490 Listener* SetEventHandlerInternal(nsAtom* aName, const nsAString& aTypeString,
491 const TypedEventHandler& aHandler,
492 bool aPermitUntrustedEvents);
493
494 bool IsDeviceType(EventMessage aEventMessage);
495 void EnableDevice(EventMessage aEventMessage);
496 void DisableDevice(EventMessage aEventMessage);
497
498 public:
499 /**
500 * Set the "inline" event listener for aEventName to aHandler. If
501 * aHandler is null, this will actually remove the event listener
502 */
503 void SetEventHandler(nsAtom* aEventName, const nsAString& aTypeString,
504 dom::EventHandlerNonNull* aHandler);
505 void SetEventHandler(dom::OnErrorEventHandlerNonNull* aHandler);
506 void SetEventHandler(dom::OnBeforeUnloadEventHandlerNonNull* aHandler);
507
508 /**
509 * Get the value of the "inline" event listener for aEventName.
510 * This may cause lazy compilation if the listener is uncompiled.
511 *
512 * Note: It's the caller's responsibility to make sure to call the right one
513 * of these methods. In particular, "onerror" events use
514 * OnErrorEventHandlerNonNull for some event targets and EventHandlerNonNull
515 * for others.
516 */
GetEventHandler(nsAtom * aEventName,const nsAString & aTypeString)517 dom::EventHandlerNonNull* GetEventHandler(nsAtom* aEventName,
518 const nsAString& aTypeString) {
519 const TypedEventHandler* typedHandler =
520 GetTypedEventHandler(aEventName, aTypeString);
521 return typedHandler ? typedHandler->NormalEventHandler() : nullptr;
522 }
523
GetOnErrorEventHandler()524 dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler() {
525 const TypedEventHandler* typedHandler =
526 mIsMainThreadELM
527 ? GetTypedEventHandler(nsGkAtoms::onerror, EmptyString())
528 : GetTypedEventHandler(nullptr, NS_LITERAL_STRING("error"));
529 return typedHandler ? typedHandler->OnErrorEventHandler() : nullptr;
530 }
531
GetOnBeforeUnloadEventHandler()532 dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler() {
533 const TypedEventHandler* typedHandler =
534 GetTypedEventHandler(nsGkAtoms::onbeforeunload, EmptyString());
535 return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
536 }
537
538 protected:
539 /**
540 * Helper method for implementing the various Get*EventHandler above. Will
541 * return null if we don't have an event handler for this event name.
542 */
543 const TypedEventHandler* GetTypedEventHandler(nsAtom* aEventName,
544 const nsAString& aTypeString);
545
546 void AddEventListener(const nsAString& aType, EventListenerHolder aListener,
547 const dom::AddEventListenerOptionsOrBoolean& aOptions,
548 bool aWantsUntrusted);
549 void AddEventListener(const nsAString& aType, EventListenerHolder aListener,
550 bool aUseCapture, bool aWantsUntrusted);
551 void RemoveEventListener(const nsAString& aType,
552 EventListenerHolder aListener,
553 const dom::EventListenerOptionsOrBoolean& aOptions);
554 void RemoveEventListener(const nsAString& aType,
555 EventListenerHolder aListener, bool aUseCapture);
556
557 void AddEventListenerInternal(EventListenerHolder aListener,
558 EventMessage aEventMessage, nsAtom* aTypeAtom,
559 const nsAString& aTypeString,
560 const EventListenerFlags& aFlags,
561 bool aHandler = false, bool aAllEvents = false);
562 void RemoveEventListenerInternal(EventListenerHolder aListener,
563 EventMessage aEventMessage,
564 nsAtom* aUserType,
565 const nsAString& aTypeString,
566 const EventListenerFlags& aFlags,
567 bool aAllEvents = false);
568 void RemoveAllListeners();
569 void NotifyEventListenerRemoved(nsAtom* aUserType,
570 const nsAString& aTypeString);
571 const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
572 const EventTypeData* GetTypeDataForEventName(nsAtom* aName);
573 nsPIDOMWindowInner* GetInnerWindowForTarget();
574 already_AddRefed<nsPIDOMWindowInner> GetTargetAsInnerWindow() const;
575
576 bool ListenerCanHandle(const Listener* aListener, const WidgetEvent* aEvent,
577 EventMessage aEventMessage) const;
578
579 // BE AWARE, a lot of instances of EventListenerManager will be created.
580 // Therefor, we need to keep this class compact. When you add integer
581 // members, please add them to EventListemerManagerBase and check the size
582 // at build time.
583
584 already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalAndDocument(
585 nsIDocument** aDoc);
586
587 nsAutoTObserverArray<Listener, 2> mListeners;
588 dom::EventTarget* MOZ_NON_OWNING_REF mTarget;
589 RefPtr<nsAtom> mNoListenerForEventAtom;
590
591 friend class ELMCreationDetector;
592 static uint32_t sMainThreadCreatedCount;
593 };
594
595 } // namespace mozilla
596
597 /**
598 * NS_AddSystemEventListener() is a helper function for implementing
599 * EventTarget::AddSystemEventListener().
600 */
NS_AddSystemEventListener(mozilla::dom::EventTarget * aTarget,const nsAString & aType,nsIDOMEventListener * aListener,bool aUseCapture,bool aWantsUntrusted)601 inline nsresult NS_AddSystemEventListener(mozilla::dom::EventTarget* aTarget,
602 const nsAString& aType,
603 nsIDOMEventListener* aListener,
604 bool aUseCapture,
605 bool aWantsUntrusted) {
606 mozilla::EventListenerManager* listenerManager =
607 aTarget->GetOrCreateListenerManager();
608 NS_ENSURE_STATE(listenerManager);
609 mozilla::EventListenerFlags flags;
610 flags.mInSystemGroup = true;
611 flags.mCapture = aUseCapture;
612 flags.mAllowUntrustedEvents = aWantsUntrusted;
613 listenerManager->AddEventListenerByType(aListener, aType, flags);
614 return NS_OK;
615 }
616
617 #endif // mozilla_EventListenerManager_h_
618