LCOV - code coverage report
Current view: top level - dom/events - EventListenerManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 105 129 81.4 %
Date: 2017-07-14 16:53:18 Functions: 25 38 65.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13