LCOV - code coverage report
Current view: top level - dom/events - DOMEventTargetHelper.h (source / functions) Hit Total Coverage
Test: output.info Lines: 40 56 71.4 %
Date: 2017-07-14 16:53:18 Functions: 16 28 57.1 %
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_DOMEventTargetHelper_h_
       8             : #define mozilla_DOMEventTargetHelper_h_
       9             : 
      10             : #include "nsCOMPtr.h"
      11             : #include "nsGkAtoms.h"
      12             : #include "nsCycleCollectionParticipant.h"
      13             : #include "nsPIDOMWindow.h"
      14             : #include "nsIScriptGlobalObject.h"
      15             : #include "nsIScriptContext.h"
      16             : #include "nsIWeakReferenceUtils.h"
      17             : #include "MainThreadUtils.h"
      18             : #include "mozilla/Attributes.h"
      19             : #include "mozilla/EventListenerManager.h"
      20             : #include "mozilla/dom/EventTarget.h"
      21             : 
      22             : struct JSCompartment;
      23             : class nsIDocument;
      24             : 
      25             : namespace mozilla {
      26             : 
      27             : class ErrorResult;
      28             : 
      29             : #define NS_DOMEVENTTARGETHELPER_IID \
      30             : { 0xa28385c6, 0x9451, 0x4d7e, \
      31             :   { 0xa3, 0xdd, 0xf4, 0xb6, 0x87, 0x2f, 0xa4, 0x76 } }
      32             : 
      33             : class DOMEventTargetHelper : public dom::EventTarget
      34             : {
      35             : public:
      36          13 :   DOMEventTargetHelper()
      37          13 :     : mParentObject(nullptr)
      38             :     , mOwnerWindow(nullptr)
      39             :     , mHasOrHasHadOwnerWindow(false)
      40          13 :     , mIsKeptAlive(false)
      41             :   {
      42          13 :   }
      43           9 :   explicit DOMEventTargetHelper(nsPIDOMWindowInner* aWindow)
      44           9 :     : mParentObject(nullptr)
      45             :     , mOwnerWindow(nullptr)
      46             :     , mHasOrHasHadOwnerWindow(false)
      47           9 :     , mIsKeptAlive(false)
      48             :   {
      49           9 :     BindToOwner(aWindow);
      50           9 :   }
      51           2 :   explicit DOMEventTargetHelper(nsIGlobalObject* aGlobalObject)
      52           2 :     : mParentObject(nullptr)
      53             :     , mOwnerWindow(nullptr)
      54             :     , mHasOrHasHadOwnerWindow(false)
      55           2 :     , mIsKeptAlive(false)
      56             :   {
      57           2 :     BindToOwner(aGlobalObject);
      58           2 :   }
      59           3 :   explicit DOMEventTargetHelper(DOMEventTargetHelper* aOther)
      60           3 :     : mParentObject(nullptr)
      61             :     , mOwnerWindow(nullptr)
      62             :     , mHasOrHasHadOwnerWindow(false)
      63           3 :     , mIsKeptAlive(false)
      64             :   {
      65           3 :     BindToOwner(aOther);
      66           3 :   }
      67             : 
      68             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      69        6638 :   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(DOMEventTargetHelper)
      70             : 
      71             :   NS_DECL_NSIDOMEVENTTARGET
      72             : 
      73             :   virtual EventListenerManager* GetExistingListenerManager() const override;
      74             :   virtual EventListenerManager* GetOrCreateListenerManager() override;
      75             : 
      76             :   using dom::EventTarget::RemoveEventListener;
      77             :   virtual void AddEventListener(const nsAString& aType,
      78             :                                 dom::EventListener* aListener,
      79             :                                 const dom::AddEventListenerOptionsOrBoolean& aOptions,
      80             :                                 const dom::Nullable<bool>& aWantsUntrusted,
      81             :                                 ErrorResult& aRv) override;
      82             : 
      83             :   NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMEVENTTARGETHELPER_IID)
      84             : 
      85           0 :   void GetParentObject(nsIScriptGlobalObject **aParentObject)
      86             :   {
      87           0 :     if (mParentObject) {
      88           0 :       CallQueryInterface(mParentObject, aParentObject);
      89             :     } else {
      90           0 :       *aParentObject = nullptr;
      91             :     }
      92           0 :   }
      93             : 
      94           0 :   static DOMEventTargetHelper* FromSupports(nsISupports* aSupports)
      95             :   {
      96           0 :     dom::EventTarget* target = static_cast<dom::EventTarget*>(aSupports);
      97             : #ifdef DEBUG
      98             :     {
      99           0 :       nsCOMPtr<dom::EventTarget> target_qi = do_QueryInterface(aSupports);
     100             : 
     101             :       // If this assertion fires the QI implementation for the object in
     102             :       // question doesn't use the EventTarget pointer as the
     103             :       // nsISupports pointer. That must be fixed, or we'll crash...
     104           0 :       NS_ASSERTION(target_qi == target, "Uh, fix QI!");
     105             :     }
     106             : #endif
     107             : 
     108           0 :     return static_cast<DOMEventTargetHelper*>(target);
     109             :   }
     110             : 
     111          14 :   bool HasListenersFor(const nsAString& aType)
     112             :   {
     113          14 :     return mListenerManager && mListenerManager->HasListenersFor(aType);
     114             :   }
     115             : 
     116           6 :   bool HasListenersFor(nsIAtom* aTypeWithOn)
     117             :   {
     118           6 :     return mListenerManager && mListenerManager->HasListenersFor(aTypeWithOn);
     119             :   }
     120             : 
     121             :   nsresult SetEventHandler(nsIAtom* aType,
     122             :                            JSContext* aCx,
     123             :                            const JS::Value& aValue);
     124             :   using dom::EventTarget::SetEventHandler;
     125             :   void GetEventHandler(nsIAtom* aType,
     126             :                        JSContext* aCx,
     127             :                        JS::Value* aValue);
     128             :   using dom::EventTarget::GetEventHandler;
     129           0 :   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override
     130             :   {
     131           0 :     return nsPIDOMWindowOuter::GetFromCurrentInner(GetOwner());
     132             :   }
     133             : 
     134         296 :   nsresult CheckInnerWindowCorrectness() const
     135             :   {
     136         296 :     NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
     137         296 :     if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
     138           0 :       return NS_ERROR_FAILURE;
     139             :     }
     140         296 :     return NS_OK;
     141             :   }
     142             : 
     143         218 :   nsPIDOMWindowInner* GetOwner() const { return mOwnerWindow; }
     144             :   // Like GetOwner, but only returns non-null if the window being returned is
     145             :   // current (in the "current document" sense of the HTML spec).
     146             :   nsPIDOMWindowInner* GetWindowIfCurrent() const;
     147             :   // Returns the document associated with this event target, if that document is
     148             :   // the current document of its browsing context.  Will return null otherwise.
     149             :   nsIDocument* GetDocumentIfCurrent() const;
     150             :   void BindToOwner(nsIGlobalObject* aOwner);
     151             :   void BindToOwner(nsPIDOMWindowInner* aOwner);
     152             :   void BindToOwner(DOMEventTargetHelper* aOther);
     153             :   virtual void DisconnectFromOwner();
     154          48 :   nsIGlobalObject* GetParentObject() const
     155             :   {
     156          48 :     return GetOwnerGlobal();
     157             :   }
     158          52 :   virtual nsIGlobalObject* GetOwnerGlobal() const override
     159             :   {
     160         104 :     nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
     161         104 :     return parentObject;
     162             :   }
     163           8 :   bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
     164             : 
     165             :   virtual void EventListenerAdded(nsIAtom* aType) override;
     166             :   virtual void EventListenerAdded(const nsAString& aType) override;
     167             : 
     168             :   virtual void EventListenerRemoved(nsIAtom* aType) override;
     169             :   virtual void EventListenerRemoved(const nsAString& aType) override;
     170             : 
     171         172 :   virtual void EventListenerWasAdded(const nsAString& aType,
     172             :                                      ErrorResult& aRv,
     173         172 :                                      JSCompartment* aCompartment = nullptr) {}
     174          24 :   virtual void EventListenerWasRemoved(const nsAString& aType,
     175             :                                        ErrorResult& aRv,
     176          24 :                                        JSCompartment* aCompartment = nullptr) {}
     177             : 
     178             :   // Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
     179             :   nsresult DispatchTrustedEvent(const nsAString& aEventName);
     180             : protected:
     181             :   virtual ~DOMEventTargetHelper();
     182             : 
     183             :   nsresult WantsUntrusted(bool* aRetVal);
     184             : 
     185             :   void MaybeUpdateKeepAlive();
     186             :   void MaybeDontKeepAlive();
     187             : 
     188             :   // If this method returns true your object is kept alive until it returns
     189             :   // false. You can use this method instead using
     190             :   // NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN macro.
     191           0 :   virtual bool IsCertainlyAliveForCC() const
     192             :   {
     193           0 :     return mIsKeptAlive;
     194             :   }
     195             : 
     196             :   RefPtr<EventListenerManager> mListenerManager;
     197             :   // Make |event| trusted and dispatch |aEvent| to |this|.
     198             :   nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent);
     199             : 
     200           0 :   virtual void LastRelease() {}
     201             : 
     202             :   void KeepAliveIfHasListenersFor(const nsAString& aType);
     203             :   void KeepAliveIfHasListenersFor(nsIAtom* aType);
     204             : 
     205             :   void IgnoreKeepAliveIfHasListenersFor(const nsAString& aType);
     206             :   void IgnoreKeepAliveIfHasListenersFor(nsIAtom* aType);
     207             : 
     208             : private:
     209             :   // Inner window or sandbox.
     210             :   nsWeakPtr                  mParentObject;
     211             :   // mParentObject pre QI-ed and cached (inner window)
     212             :   // (it is needed for off main thread access)
     213             :   // It is obtained in BindToOwner and reset in DisconnectFromOwner.
     214             :   nsPIDOMWindowInner* MOZ_NON_OWNING_REF mOwnerWindow;
     215             :   bool                       mHasOrHasHadOwnerWindow;
     216             : 
     217          27 :   struct {
     218             :     nsTArray<nsString> mStrings;
     219             :     nsTArray<nsCOMPtr<nsIAtom>> mAtoms;
     220             :   } mKeepingAliveTypes;
     221             : 
     222             :   bool mIsKeptAlive;
     223             : };
     224             : 
     225             : NS_DEFINE_STATIC_IID_ACCESSOR(DOMEventTargetHelper,
     226             :                               NS_DOMEVENTTARGETHELPER_IID)
     227             : 
     228             : } // namespace mozilla
     229             : 
     230             : // XPIDL event handlers
     231             : #define NS_IMPL_EVENT_HANDLER(_class, _event)                                 \
     232             :     NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx,                       \
     233             :                                         JS::MutableHandle<JS::Value> aValue)  \
     234             :     {                                                                         \
     235             :       GetEventHandler(nsGkAtoms::on##_event, aCx, aValue.address());          \
     236             :       return NS_OK;                                                           \
     237             :     }                                                                         \
     238             :     NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx,                       \
     239             :                                         JS::Handle<JS::Value> aValue)         \
     240             :     {                                                                         \
     241             :       return SetEventHandler(nsGkAtoms::on##_event, aCx, aValue);             \
     242             :     }
     243             : 
     244             : #define NS_IMPL_FORWARD_EVENT_HANDLER(_class, _event, _baseclass)             \
     245             :     NS_IMETHODIMP _class::GetOn##_event(JSContext* aCx,                       \
     246             :                                         JS::MutableHandle<JS::Value> aValue)  \
     247             :     {                                                                         \
     248             :       return _baseclass::GetOn##_event(aCx, aValue);                          \
     249             :     }                                                                         \
     250             :     NS_IMETHODIMP _class::SetOn##_event(JSContext* aCx,                       \
     251             :                                         JS::Handle<JS::Value> aValue)         \
     252             :     {                                                                         \
     253             :       return _baseclass::SetOn##_event(aCx, aValue);                          \
     254             :     }
     255             : 
     256             : // WebIDL event handlers
     257             : #define IMPL_EVENT_HANDLER(_event)                                        \
     258             :   inline mozilla::dom::EventHandlerNonNull* GetOn##_event()               \
     259             :   {                                                                       \
     260             :     if (NS_IsMainThread()) {                                              \
     261             :       return GetEventHandler(nsGkAtoms::on##_event, EmptyString());       \
     262             :     }                                                                     \
     263             :     return GetEventHandler(nullptr, NS_LITERAL_STRING(#_event));          \
     264             :   }                                                                       \
     265             :   inline void SetOn##_event(mozilla::dom::EventHandlerNonNull* aCallback) \
     266             :   {                                                                       \
     267             :     if (NS_IsMainThread()) {                                              \
     268             :       SetEventHandler(nsGkAtoms::on##_event, EmptyString(), aCallback);   \
     269             :     } else {                                                              \
     270             :       SetEventHandler(nullptr, NS_LITERAL_STRING(#_event), aCallback);    \
     271             :     }                                                                     \
     272             :   }
     273             : 
     274             : /* Use this macro to declare functions that forward the behavior of this
     275             :  * interface to another object.
     276             :  * This macro doesn't forward GetEventTargetParent because sometimes subclasses
     277             :  * want to override it.
     278             :  */
     279             : #define NS_FORWARD_NSIDOMEVENTTARGET_NOGETEVENTTARGETPARENT(_to) \
     280             :   NS_IMETHOD AddEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture, bool wantsUntrusted, uint8_t _argc) { \
     281             :     return _to AddEventListener(type, listener, useCapture, wantsUntrusted, _argc); \
     282             :   } \
     283             :   NS_IMETHOD AddSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture, bool aWantsUntrusted, uint8_t _argc) { \
     284             :     return _to AddSystemEventListener(type, listener, aUseCapture, aWantsUntrusted, _argc); \
     285             :   } \
     286             :   NS_IMETHOD RemoveEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture) { \
     287             :     return _to RemoveEventListener(type, listener, useCapture); \
     288             :   } \
     289             :   NS_IMETHOD RemoveSystemEventListener(const nsAString & type, nsIDOMEventListener *listener, bool aUseCapture) { \
     290             :     return _to RemoveSystemEventListener(type, listener, aUseCapture); \
     291             :   } \
     292             :   NS_IMETHOD DispatchEvent(nsIDOMEvent *evt, bool *_retval) { \
     293             :     return _to DispatchEvent(evt, _retval); \
     294             :   } \
     295             :   virtual mozilla::dom::EventTarget* GetTargetForDOMEvent() { \
     296             :     return _to GetTargetForDOMEvent(); \
     297             :   } \
     298             :   virtual mozilla::dom::EventTarget* GetTargetForEventTargetChain() { \
     299             :     return _to GetTargetForEventTargetChain(); \
     300             :   } \
     301             :   virtual nsresult WillHandleEvent( \
     302             :                      mozilla::EventChainPostVisitor & aVisitor) { \
     303             :     return _to WillHandleEvent(aVisitor); \
     304             :   } \
     305             :   virtual nsresult PostHandleEvent( \
     306             :                      mozilla::EventChainPostVisitor & aVisitor) { \
     307             :     return _to PostHandleEvent(aVisitor); \
     308             :   } \
     309             :   virtual nsresult DispatchDOMEvent(mozilla::WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus) { \
     310             :     return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); \
     311             :   } \
     312             :   virtual mozilla::EventListenerManager* GetOrCreateListenerManager() { \
     313             :     return _to GetOrCreateListenerManager(); \
     314             :   } \
     315             :   virtual mozilla::EventListenerManager* GetExistingListenerManager() const { \
     316             :     return _to GetExistingListenerManager(); \
     317             :   } \
     318             :   virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv) { \
     319             :     return _to GetContextForEventHandlers(aRv); \
     320             :   }
     321             : 
     322             : #define NS_REALLY_FORWARD_NSIDOMEVENTTARGET(_class) \
     323             :   using _class::AddEventListener;                   \
     324             :   using _class::RemoveEventListener;                \
     325             :   NS_FORWARD_NSIDOMEVENTTARGET(_class::)            \
     326             :   virtual mozilla::EventListenerManager*            \
     327             :   GetOrCreateListenerManager() override {           \
     328             :     return _class::GetOrCreateListenerManager();    \
     329             :   }                                                 \
     330             :   virtual mozilla::EventListenerManager*            \
     331             :   GetExistingListenerManager() const override {     \
     332             :     return _class::GetExistingListenerManager();    \
     333             :   }
     334             : 
     335             : #endif // mozilla_DOMEventTargetHelper_h_

Generated by: LCOV version 1.13