LCOV - code coverage report
Current view: top level - dom/events - EventListenerService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 24 200 12.0 %
Date: 2017-07-14 16:53:18 Functions: 7 40 17.5 %
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             : #include "EventListenerService.h"
       8             : #include "mozilla/BasicEvents.h"
       9             : #include "mozilla/EventDispatcher.h"
      10             : #include "mozilla/EventListenerManager.h"
      11             : #include "mozilla/JSEventHandler.h"
      12             : #include "mozilla/Maybe.h"
      13             : #include "nsCOMArray.h"
      14             : #include "nsDOMClassInfoID.h"
      15             : #include "nsIXPConnect.h"
      16             : #include "nsJSUtils.h"
      17             : #include "nsMemory.h"
      18             : #include "nsServiceManagerUtils.h"
      19             : #include "nsArray.h"
      20             : #include "nsThreadUtils.h"
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : using namespace dom;
      25             : 
      26             : /******************************************************************************
      27             :  * mozilla::EventListenerChange
      28             :  ******************************************************************************/
      29             : 
      30           0 : NS_IMPL_ISUPPORTS(EventListenerChange, nsIEventListenerChange)
      31             : 
      32           0 : EventListenerChange::~EventListenerChange()
      33             : {
      34           0 : }
      35             : 
      36           0 : EventListenerChange::EventListenerChange(dom::EventTarget* aTarget) :
      37           0 :   mTarget(aTarget)
      38             : {
      39           0 :   mChangedListenerNames = nsArrayBase::Create();
      40           0 : }
      41             : 
      42             : void
      43           0 : EventListenerChange::AddChangedListenerName(nsIAtom* aEventName)
      44             : {
      45           0 :   mChangedListenerNames->AppendElement(aEventName, false);
      46           0 : }
      47             : 
      48             : NS_IMETHODIMP
      49           0 : EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget)
      50             : {
      51           0 :   NS_ENSURE_ARG_POINTER(aTarget);
      52           0 :   NS_ADDREF(*aTarget = mTarget);
      53           0 :   return NS_OK;
      54             : }
      55             : 
      56             : NS_IMETHODIMP
      57           0 : EventListenerChange::GetChangedListenerNames(nsIArray** aEventNames)
      58             : {
      59           0 :   NS_ENSURE_ARG_POINTER(aEventNames);
      60           0 :   NS_ADDREF(*aEventNames = mChangedListenerNames);
      61           0 :   return NS_OK;
      62             : }
      63             : 
      64             : /******************************************************************************
      65             :  * mozilla::EventListenerInfo
      66             :  ******************************************************************************/
      67             : 
      68           0 : NS_IMPL_CYCLE_COLLECTION(EventListenerInfo, mListener)
      69             : 
      70           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo)
      71           0 :   NS_INTERFACE_MAP_ENTRY(nsIEventListenerInfo)
      72           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      73           0 : NS_INTERFACE_MAP_END
      74             : 
      75           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(EventListenerInfo)
      76           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(EventListenerInfo)
      77             : 
      78             : NS_IMETHODIMP
      79           0 : EventListenerInfo::GetType(nsAString& aType)
      80             : {
      81           0 :   aType = mType;
      82           0 :   return NS_OK;
      83             : }
      84             : 
      85             : NS_IMETHODIMP
      86           0 : EventListenerInfo::GetCapturing(bool* aCapturing)
      87             : {
      88           0 :   *aCapturing = mCapturing;
      89           0 :   return NS_OK;
      90             : }
      91             : 
      92             : NS_IMETHODIMP
      93           0 : EventListenerInfo::GetAllowsUntrusted(bool* aAllowsUntrusted)
      94             : {
      95           0 :   *aAllowsUntrusted = mAllowsUntrusted;
      96           0 :   return NS_OK;
      97             : }
      98             : 
      99             : NS_IMETHODIMP
     100           0 : EventListenerInfo::GetInSystemEventGroup(bool* aInSystemEventGroup)
     101             : {
     102           0 :   *aInSystemEventGroup = mInSystemEventGroup;
     103           0 :   return NS_OK;
     104             : }
     105             : 
     106             : NS_IMETHODIMP
     107           0 : EventListenerInfo::GetListenerObject(JSContext* aCx,
     108             :                                      JS::MutableHandle<JS::Value> aObject)
     109             : {
     110           0 :   Maybe<JSAutoCompartment> ac;
     111           0 :   GetJSVal(aCx, ac, aObject);
     112           0 :   return NS_OK;
     113             : }
     114             : 
     115             : /******************************************************************************
     116             :  * mozilla::EventListenerService
     117             :  ******************************************************************************/
     118             : 
     119         208 : NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService)
     120             : 
     121             : bool
     122           0 : EventListenerInfo::GetJSVal(JSContext* aCx,
     123             :                             Maybe<JSAutoCompartment>& aAc,
     124             :                             JS::MutableHandle<JS::Value> aJSVal)
     125             : {
     126           0 :   aJSVal.setNull();
     127           0 :   nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
     128           0 :   if (wrappedJS) {
     129           0 :     JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject());
     130           0 :     if (!object) {
     131           0 :       return false;
     132             :     }
     133           0 :     aAc.emplace(aCx, object);
     134           0 :     aJSVal.setObject(*object);
     135           0 :     return true;
     136             :   }
     137             : 
     138           0 :   nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener);
     139           0 :   if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) {
     140             :     JS::Handle<JSObject*> handler =
     141           0 :       jsHandler->GetTypedEventHandler().Ptr()->CallableOrNull();
     142           0 :     if (handler) {
     143           0 :       aAc.emplace(aCx, handler);
     144           0 :       aJSVal.setObject(*handler);
     145           0 :       return true;
     146             :     }
     147             :   }
     148           0 :   return false;
     149             : }
     150             : 
     151             : NS_IMETHODIMP
     152           0 : EventListenerInfo::ToSource(nsAString& aResult)
     153             : {
     154           0 :   aResult.SetIsVoid(true);
     155             : 
     156           0 :   AutoSafeJSContext cx;
     157           0 :   Maybe<JSAutoCompartment> ac;
     158           0 :   JS::Rooted<JS::Value> v(cx);
     159           0 :   if (GetJSVal(cx, ac, &v)) {
     160           0 :     JSString* str = JS_ValueToSource(cx, v);
     161           0 :     if (str) {
     162           0 :       nsAutoJSString autoStr;
     163           0 :       if (autoStr.init(cx, str)) {
     164           0 :         aResult.Assign(autoStr);
     165             :       }
     166             :     }
     167             :   }
     168           0 :   return NS_OK;
     169             : }
     170             : 
     171             : EventListenerService*
     172             : EventListenerService::sInstance = nullptr;
     173             : 
     174           2 : EventListenerService::EventListenerService()
     175             : {
     176           2 :   MOZ_ASSERT(!sInstance);
     177           2 :   sInstance = this;
     178           2 : }
     179             : 
     180           0 : EventListenerService::~EventListenerService()
     181             : {
     182           0 :   MOZ_ASSERT(sInstance == this);
     183           0 :   sInstance = nullptr;
     184           0 : }
     185             : 
     186             : NS_IMETHODIMP
     187           0 : EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
     188             :                                          uint32_t* aCount,
     189             :                                          nsIEventListenerInfo*** aOutArray)
     190             : {
     191           0 :   NS_ENSURE_ARG_POINTER(aEventTarget);
     192           0 :   *aCount = 0;
     193           0 :   *aOutArray = nullptr;
     194           0 :   nsCOMArray<nsIEventListenerInfo> listenerInfos;
     195             : 
     196           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
     197           0 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     198             : 
     199           0 :   EventListenerManager* elm = eventTarget->GetExistingListenerManager();
     200           0 :   if (elm) {
     201           0 :     elm->GetListenerInfo(&listenerInfos);
     202             :   }
     203             : 
     204           0 :   int32_t count = listenerInfos.Count();
     205           0 :   if (count == 0) {
     206           0 :     return NS_OK;
     207             :   }
     208             : 
     209           0 :   listenerInfos.Forget(aOutArray);
     210           0 :   *aCount = count;
     211           0 :   return NS_OK;
     212             : }
     213             : 
     214             : NS_IMETHODIMP
     215           0 : EventListenerService::GetEventTargetChainFor(nsIDOMEventTarget* aEventTarget,
     216             :                                              bool aComposed,
     217             :                                              uint32_t* aCount,
     218             :                                              nsIDOMEventTarget*** aOutArray)
     219             : {
     220           0 :   *aCount = 0;
     221           0 :   *aOutArray = nullptr;
     222           0 :   NS_ENSURE_ARG(aEventTarget);
     223           0 :   WidgetEvent event(true, eVoidEvent);
     224           0 :   event.SetComposed(aComposed);
     225           0 :   nsTArray<EventTarget*> targets;
     226             :   nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event,
     227           0 :                                           nullptr, nullptr, nullptr, &targets);
     228           0 :   NS_ENSURE_SUCCESS(rv, rv);
     229           0 :   int32_t count = targets.Length();
     230           0 :   if (count == 0) {
     231           0 :     return NS_OK;
     232             :   }
     233             : 
     234           0 :   *aOutArray =
     235             :     static_cast<nsIDOMEventTarget**>(
     236           0 :       moz_xmalloc(sizeof(nsIDOMEventTarget*) * count));
     237           0 :   NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY);
     238             : 
     239           0 :   for (int32_t i = 0; i < count; ++i) {
     240           0 :     NS_ADDREF((*aOutArray)[i] = targets[i]);
     241             :   }
     242           0 :   *aCount = count;
     243             : 
     244           0 :   return NS_OK;
     245             : }
     246             : 
     247             : NS_IMETHODIMP
     248           0 : EventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget,
     249             :                                       const nsAString& aType,
     250             :                                       bool* aRetVal)
     251             : {
     252           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
     253           0 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     254             : 
     255           0 :   EventListenerManager* elm = eventTarget->GetExistingListenerManager();
     256           0 :   *aRetVal = elm && elm->HasListenersFor(aType);
     257           0 :   return NS_OK;
     258             : }
     259             : 
     260             : NS_IMETHODIMP
     261          14 : EventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
     262             :                                              const nsAString& aType,
     263             :                                              nsIDOMEventListener* aListener,
     264             :                                              bool aUseCapture)
     265             : {
     266          14 :   NS_PRECONDITION(aTarget, "Missing target");
     267          14 :   NS_PRECONDITION(aListener, "Missing listener");
     268             : 
     269          28 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
     270          14 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     271             : 
     272          14 :   EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
     273          14 :   NS_ENSURE_STATE(manager);
     274             : 
     275             :   EventListenerFlags flags =
     276             :     aUseCapture ? TrustedEventsAtSystemGroupCapture() :
     277          14 :                   TrustedEventsAtSystemGroupBubble();
     278          14 :   manager->AddEventListenerByType(aListener, aType, flags);
     279          14 :   return NS_OK;
     280             : }
     281             : 
     282             : NS_IMETHODIMP
     283           0 : EventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget,
     284             :                                                 const nsAString& aType,
     285             :                                                 nsIDOMEventListener* aListener,
     286             :                                                 bool aUseCapture)
     287             : {
     288           0 :   NS_PRECONDITION(aTarget, "Missing target");
     289           0 :   NS_PRECONDITION(aListener, "Missing listener");
     290             : 
     291           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
     292           0 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     293             : 
     294           0 :   EventListenerManager* manager = eventTarget->GetExistingListenerManager();
     295           0 :   if (manager) {
     296             :     EventListenerFlags flags =
     297             :       aUseCapture ? TrustedEventsAtSystemGroupCapture() :
     298           0 :                     TrustedEventsAtSystemGroupBubble();
     299           0 :     manager->RemoveEventListenerByType(aListener, aType, flags);
     300             :   }
     301             : 
     302           0 :   return NS_OK;
     303             : }
     304             : 
     305             : NS_IMETHODIMP
     306           0 : EventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget,
     307             :                                               nsIDOMEventListener* aListener,
     308             :                                               bool aUseCapture,
     309             :                                               bool aWantsUntrusted,
     310             :                                               bool aSystemEventGroup)
     311             : {
     312           0 :   NS_ENSURE_STATE(aTarget && aListener);
     313             : 
     314           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
     315           0 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     316             : 
     317           0 :   EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
     318           0 :   NS_ENSURE_STATE(manager);
     319           0 :   manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted,
     320           0 :                                aSystemEventGroup);
     321           0 :   return NS_OK;
     322             : }
     323             : 
     324             : NS_IMETHODIMP
     325           0 : EventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget,
     326             :                                                  nsIDOMEventListener* aListener,
     327             :                                                  bool aUseCapture,
     328             :                                                  bool aSystemEventGroup)
     329             : {
     330           0 :   NS_ENSURE_STATE(aTarget && aListener);
     331             : 
     332           0 :   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
     333           0 :   NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
     334             : 
     335           0 :   EventListenerManager* manager = eventTarget->GetExistingListenerManager();
     336           0 :   if (manager) {
     337           0 :     manager->RemoveListenerForAllEvents(aListener, aUseCapture, aSystemEventGroup);
     338             :   }
     339           0 :   return NS_OK;
     340             : }
     341             : 
     342             : NS_IMETHODIMP
     343           0 : EventListenerService::AddListenerChangeListener(nsIListenerChangeListener* aListener)
     344             : {
     345           0 :   if (!mChangeListeners.Contains(aListener)) {
     346           0 :     mChangeListeners.AppendElement(aListener);
     347             :   }
     348           0 :   return NS_OK;
     349             : };
     350             : 
     351             : NS_IMETHODIMP
     352           0 : EventListenerService::RemoveListenerChangeListener(nsIListenerChangeListener* aListener)
     353             : {
     354           0 :   mChangeListeners.RemoveElement(aListener);
     355           0 :   return NS_OK;
     356             : };
     357             : 
     358             : void
     359         892 : EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget,
     360             :                                                                   nsIAtom* aName)
     361             : {
     362         892 :   MOZ_ASSERT(NS_IsMainThread());
     363         892 :   MOZ_ASSERT(aTarget);
     364         892 :   if (mChangeListeners.IsEmpty()) {
     365         892 :     return;
     366             :   }
     367             : 
     368           0 :   if (!mPendingListenerChanges) {
     369           0 :     mPendingListenerChanges = nsArrayBase::Create();
     370             :     nsCOMPtr<nsIRunnable> runnable =
     371           0 :       NewRunnableMethod("EventListenerService::NotifyPendingChanges",
     372           0 :                         this, &EventListenerService::NotifyPendingChanges);
     373           0 :     if (nsCOMPtr<nsIGlobalObject> global = aTarget->GetOwnerGlobal()) {
     374           0 :       global->Dispatch(nullptr, TaskCategory::Other, runnable.forget());
     375           0 :     } else if (nsCOMPtr<nsINode> node = do_QueryInterface(aTarget)) {
     376           0 :       node->OwnerDoc()->Dispatch(nullptr, TaskCategory::Other,
     377           0 :                                  runnable.forget());
     378             :     } else {
     379           0 :       NS_DispatchToCurrentThread(runnable);
     380             :     }
     381             :   }
     382             : 
     383             :   RefPtr<EventListenerChange> changes =
     384           0 :     mPendingListenerChangesSet.LookupForAdd(aTarget).OrInsert(
     385           0 :       [this, aTarget] () {
     386           0 :         EventListenerChange* c = new EventListenerChange(aTarget);
     387           0 :         mPendingListenerChanges->AppendElement(c, false);
     388           0 :         return c;
     389           0 :       });
     390           0 :   changes->AddChangedListenerName(aName);
     391             : }
     392             : 
     393             : void
     394           0 : EventListenerService::NotifyPendingChanges()
     395             : {
     396           0 :   nsCOMPtr<nsIMutableArray> changes;
     397           0 :   mPendingListenerChanges.swap(changes);
     398           0 :   mPendingListenerChangesSet.Clear();
     399             : 
     400             :   nsTObserverArray<nsCOMPtr<nsIListenerChangeListener>>::EndLimitedIterator
     401           0 :     iter(mChangeListeners);
     402           0 :   while (iter.HasMore()) {
     403           0 :     nsCOMPtr<nsIListenerChangeListener> listener = iter.GetNext();
     404           0 :     listener->ListenersChanged(changes);
     405             :   }
     406           0 : }
     407             : 
     408             : } // namespace mozilla
     409             : 
     410             : nsresult
     411           2 : NS_NewEventListenerService(nsIEventListenerService** aResult)
     412             : {
     413           2 :   *aResult = new mozilla::EventListenerService();
     414           2 :   NS_ADDREF(*aResult);
     415           2 :   return NS_OK;
     416             : }

Generated by: LCOV version 1.13