LCOV - code coverage report
Current view: top level - dom/events - DOMEventTargetHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 143 251 57.0 %
Date: 2017-07-14 16:53:18 Functions: 32 48 66.7 %
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 "nsContentUtils.h"
       8             : #include "nsIDocument.h"
       9             : #include "mozilla/Sprintf.h"
      10             : #include "nsGlobalWindow.h"
      11             : #include "mozilla/dom/ScriptSettings.h"
      12             : #include "mozilla/DOMEventTargetHelper.h"
      13             : #include "mozilla/EventDispatcher.h"
      14             : #include "mozilla/EventListenerManager.h"
      15             : #include "mozilla/Likely.h"
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : using namespace dom;
      20             : 
      21             : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMEventTargetHelper)
      22             : 
      23          47 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMEventTargetHelper)
      24          47 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
      25          47 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      26             : 
      27          22 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
      28          22 :   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
      29             :     char name[512];
      30           0 :     nsAutoString uri;
      31           0 :     if (tmp->mOwnerWindow && tmp->mOwnerWindow->GetExtantDoc()) {
      32           0 :       Unused << tmp->mOwnerWindow->GetExtantDoc()->GetDocumentURI(uri);
      33             :     }
      34             : 
      35           0 :     nsXPCOMCycleCollectionParticipant* participant = nullptr;
      36           0 :     CallQueryInterface(tmp, &participant);
      37             : 
      38           0 :     SprintfLiteral(name, "%s %s",
      39           0 :                    participant->ClassName(),
      40           0 :                    NS_ConvertUTF16toUTF8(uri).get());
      41           0 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
      42             :   } else {
      43          22 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())
      44             :   }
      45             : 
      46          22 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
      47          22 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      48             : 
      49           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMEventTargetHelper)
      50           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      51           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
      52           0 :   tmp->MaybeDontKeepAlive();
      53           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      54             : 
      55           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(DOMEventTargetHelper)
      56           0 :   bool hasLiveWrapper = tmp->HasKnownLiveWrapper();
      57           0 :   if (hasLiveWrapper || tmp->IsCertainlyAliveForCC()) {
      58           0 :     if (tmp->mListenerManager) {
      59           0 :       tmp->mListenerManager->MarkForCC();
      60             :     }
      61           0 :     if (!hasLiveWrapper && tmp->PreservingWrapper()) {
      62           0 :       tmp->MarkWrapperLive();
      63             :     }
      64           0 :     return true;
      65             :   }
      66           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
      67             : 
      68           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(DOMEventTargetHelper)
      69           0 :   return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
      70             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
      71             : 
      72           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(DOMEventTargetHelper)
      73           0 :   return tmp->HasKnownLiveWrapper();
      74             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
      75             : 
      76         825 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMEventTargetHelper)
      77         714 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      78         662 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      79         655 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
      80         619 :   NS_INTERFACE_MAP_ENTRY(dom::EventTarget)
      81         314 :   NS_INTERFACE_MAP_ENTRY(DOMEventTargetHelper)
      82         237 : NS_INTERFACE_MAP_END
      83             : 
      84        3186 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMEventTargetHelper)
      85        3083 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(DOMEventTargetHelper,
      86             :                                                    LastRelease())
      87             : 
      88         198 : NS_IMPL_DOMTARGET_DEFAULTS(DOMEventTargetHelper)
      89             : 
      90           0 : DOMEventTargetHelper::~DOMEventTargetHelper()
      91             : {
      92           0 :   if (nsPIDOMWindowInner* owner = GetOwner()) {
      93           0 :     nsGlobalWindow::Cast(owner)->RemoveEventTargetObject(this);
      94             :   }
      95           0 :   if (mListenerManager) {
      96           0 :     mListenerManager->Disconnect();
      97             :   }
      98           0 :   ReleaseWrapper(this);
      99           0 : }
     100             : 
     101             : void
     102           9 : DOMEventTargetHelper::BindToOwner(nsPIDOMWindowInner* aOwner)
     103             : {
     104          18 :   nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOwner);
     105           9 :   BindToOwner(glob);
     106           9 : }
     107             : 
     108             : void
     109          14 : DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
     110             : {
     111          28 :   nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
     112          14 :   if (parentObject) {
     113           0 :     if (mOwnerWindow) {
     114           0 :       nsGlobalWindow::Cast(mOwnerWindow)->RemoveEventTargetObject(this);
     115           0 :       mOwnerWindow = nullptr;
     116             :     }
     117           0 :     mParentObject = nullptr;
     118           0 :     mHasOrHasHadOwnerWindow = false;
     119             :   }
     120          14 :   if (aOwner) {
     121          11 :     mParentObject = do_GetWeakReference(aOwner);
     122          11 :     MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
     123             :     // Let's cache the result of this QI for fast access and off main thread usage
     124          11 :     mOwnerWindow = nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
     125          11 :     if (mOwnerWindow) {
     126          11 :       mHasOrHasHadOwnerWindow = true;
     127          11 :       nsGlobalWindow::Cast(mOwnerWindow)->AddEventTargetObject(this);
     128             :     }
     129             :   }
     130          14 : }
     131             : 
     132             : void
     133           3 : DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther)
     134             : {
     135           3 :   if (mOwnerWindow) {
     136           0 :     nsGlobalWindow::Cast(mOwnerWindow)->RemoveEventTargetObject(this);
     137           0 :     mOwnerWindow = nullptr;
     138           0 :     mParentObject = nullptr;
     139           0 :     mHasOrHasHadOwnerWindow = false;
     140             :   }
     141           3 :   if (aOther) {
     142           3 :     mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
     143           3 :     if (aOther->GetParentObject()) {
     144           0 :       mParentObject = do_GetWeakReference(aOther->GetParentObject());
     145           0 :       MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
     146             :       // Let's cache the result of this QI for fast access and off main thread usage
     147           0 :       mOwnerWindow = nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOther->GetParentObject())).get();
     148           0 :       if (mOwnerWindow) {
     149           0 :         mHasOrHasHadOwnerWindow = true;
     150           0 :         nsGlobalWindow::Cast(mOwnerWindow)->AddEventTargetObject(this);
     151             :       }
     152             :     }
     153             :   }
     154           3 : }
     155             : 
     156             : void
     157           1 : DOMEventTargetHelper::DisconnectFromOwner()
     158             : {
     159           1 :   mOwnerWindow = nullptr;
     160           1 :   mParentObject = nullptr;
     161             :   // Event listeners can't be handled anymore, so we can release them here.
     162           1 :   if (mListenerManager) {
     163           0 :     mListenerManager->Disconnect();
     164           0 :     mListenerManager = nullptr;
     165             :   }
     166             : 
     167           1 :   MaybeDontKeepAlive();
     168           1 : }
     169             : 
     170             : nsPIDOMWindowInner*
     171         144 : DOMEventTargetHelper::GetWindowIfCurrent() const
     172             : {
     173         144 :   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     174           0 :     return nullptr;
     175             :   }
     176             : 
     177         144 :   return GetOwner();
     178             : }
     179             : 
     180             : nsIDocument*
     181         144 : DOMEventTargetHelper::GetDocumentIfCurrent() const
     182             : {
     183         144 :   nsPIDOMWindowInner* win = GetWindowIfCurrent();
     184         144 :   if (!win) {
     185         144 :     return nullptr;
     186             :   }
     187             : 
     188           0 :   return win->GetDoc();
     189             : }
     190             : 
     191             : NS_IMETHODIMP
     192          27 : DOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
     193             :                                           nsIDOMEventListener* aListener,
     194             :                                           bool aUseCapture)
     195             : {
     196          27 :   EventListenerManager* elm = GetExistingListenerManager();
     197          27 :   if (elm) {
     198          27 :     elm->RemoveEventListener(aType, aListener, aUseCapture);
     199             :   }
     200             : 
     201          27 :   return NS_OK;
     202             : }
     203             : 
     204           1 : NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(DOMEventTargetHelper)
     205             : 
     206             : NS_IMETHODIMP
     207         160 : DOMEventTargetHelper::AddEventListener(const nsAString& aType,
     208             :                                        nsIDOMEventListener* aListener,
     209             :                                        bool aUseCapture,
     210             :                                        bool aWantsUntrusted,
     211             :                                        uint8_t aOptionalArgc)
     212             : {
     213         160 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
     214             :                "Won't check if this is chrome, you want to set "
     215             :                "aWantsUntrusted to false or make the aWantsUntrusted "
     216             :                "explicit by making aOptionalArgc non-zero.");
     217             : 
     218         160 :   if (aOptionalArgc < 2) {
     219         135 :     nsresult rv = WantsUntrusted(&aWantsUntrusted);
     220         135 :     NS_ENSURE_SUCCESS(rv, rv);
     221             :   }
     222             : 
     223         160 :   EventListenerManager* elm = GetOrCreateListenerManager();
     224         160 :   NS_ENSURE_STATE(elm);
     225         160 :   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
     226         160 :   return NS_OK;
     227             : }
     228             : 
     229             : void
     230           1 : DOMEventTargetHelper::AddEventListener(const nsAString& aType,
     231             :                                        EventListener* aListener,
     232             :                                        const AddEventListenerOptionsOrBoolean& aOptions,
     233             :                                        const Nullable<bool>& aWantsUntrusted,
     234             :                                        ErrorResult& aRv)
     235             : {
     236             :   bool wantsUntrusted;
     237           1 :   if (aWantsUntrusted.IsNull()) {
     238           0 :     nsresult rv = WantsUntrusted(&wantsUntrusted);
     239           0 :     if (NS_FAILED(rv)) {
     240           0 :       aRv.Throw(rv);
     241           0 :       return;
     242             :     }
     243             :   } else {
     244           1 :     wantsUntrusted = aWantsUntrusted.Value();
     245             :   }
     246             : 
     247           1 :   EventListenerManager* elm = GetOrCreateListenerManager();
     248           1 :   if (!elm) {
     249           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     250           0 :     return;
     251             :   }
     252             : 
     253           1 :   elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
     254             : }
     255             : 
     256             : NS_IMETHODIMP
     257           1 : DOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
     258             :                                              nsIDOMEventListener* aListener,
     259             :                                              bool aUseCapture,
     260             :                                              bool aWantsUntrusted,
     261             :                                              uint8_t aOptionalArgc)
     262             : {
     263           1 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
     264             :                "Won't check if this is chrome, you want to set "
     265             :                "aWantsUntrusted to false or make the aWantsUntrusted "
     266             :                "explicit by making aOptionalArgc non-zero.");
     267             : 
     268           1 :   if (aOptionalArgc < 2) {
     269           1 :     nsresult rv = WantsUntrusted(&aWantsUntrusted);
     270           1 :     NS_ENSURE_SUCCESS(rv, rv);
     271             :   }
     272             : 
     273           1 :   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
     274           1 :                                    aWantsUntrusted);
     275             : }
     276             : 
     277             : NS_IMETHODIMP
     278           3 : DOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
     279             : {
     280           3 :   nsEventStatus status = nsEventStatus_eIgnore;
     281             :   nsresult rv =
     282           3 :     EventDispatcher::DispatchDOMEvent(this, nullptr, aEvent, nullptr, &status);
     283             : 
     284           3 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
     285           3 :   return rv;
     286             : }
     287             : 
     288             : nsresult
     289           1 : DOMEventTargetHelper::DispatchTrustedEvent(const nsAString& aEventName)
     290             : {
     291           2 :   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
     292           1 :   event->InitEvent(aEventName, false, false);
     293             : 
     294           2 :   return DispatchTrustedEvent(event);
     295             : }
     296             : 
     297             : nsresult
     298           1 : DOMEventTargetHelper::DispatchTrustedEvent(nsIDOMEvent* event)
     299             : {
     300           1 :   event->SetTrusted(true);
     301             : 
     302             :   bool dummy;
     303           1 :   return DispatchEvent(event, &dummy);
     304             : }
     305             : 
     306             : nsresult
     307           0 : DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
     308             :                                       JSContext* aCx,
     309             :                                       const JS::Value& aValue)
     310             : {
     311           0 :   RefPtr<EventHandlerNonNull> handler;
     312           0 :   JS::Rooted<JSObject*> callable(aCx);
     313           0 :   if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
     314           0 :     handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal());
     315             :   }
     316           0 :   SetEventHandler(aType, EmptyString(), handler);
     317           0 :   return NS_OK;
     318             : }
     319             : 
     320             : void
     321           0 : DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
     322             :                                       JSContext* aCx,
     323             :                                       JS::Value* aValue)
     324             : {
     325           0 :   EventHandlerNonNull* handler = GetEventHandler(aType, EmptyString());
     326           0 :   if (handler) {
     327           0 :     *aValue = JS::ObjectOrNullValue(handler->CallableOrNull());
     328             :   } else {
     329           0 :     *aValue = JS::NullValue();
     330             :   }
     331           0 : }
     332             : 
     333             : nsresult
     334          36 : DOMEventTargetHelper::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     335             : {
     336          36 :   aVisitor.mCanHandle = true;
     337          36 :   aVisitor.mParentTarget = nullptr;
     338          36 :   return NS_OK;
     339             : }
     340             : 
     341             : nsresult
     342          72 : DOMEventTargetHelper::PostHandleEvent(EventChainPostVisitor& aVisitor)
     343             : {
     344          72 :   return NS_OK;
     345             : }
     346             : 
     347             : nsresult
     348          35 : DOMEventTargetHelper::DispatchDOMEvent(WidgetEvent* aEvent,
     349             :                                        nsIDOMEvent* aDOMEvent,
     350             :                                        nsPresContext* aPresContext,
     351             :                                        nsEventStatus* aEventStatus)
     352             : {
     353          35 :   return EventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent,
     354          35 :                                            aPresContext, aEventStatus);
     355             : }
     356             : 
     357             : EventListenerManager*
     358         172 : DOMEventTargetHelper::GetOrCreateListenerManager()
     359             : {
     360         172 :   if (!mListenerManager) {
     361           9 :     mListenerManager = new EventListenerManager(this);
     362             :   }
     363             : 
     364         172 :   return mListenerManager;
     365             : }
     366             : 
     367             : EventListenerManager*
     368         133 : DOMEventTargetHelper::GetExistingListenerManager() const
     369             : {
     370         133 :   return mListenerManager;
     371             : }
     372             : 
     373             : nsIScriptContext*
     374           0 : DOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
     375             : {
     376           0 :   *aRv = CheckInnerWindowCorrectness();
     377           0 :   if (NS_FAILED(*aRv)) {
     378           0 :     return nullptr;
     379             :   }
     380           0 :   nsPIDOMWindowInner* owner = GetOwner();
     381           0 :   return owner ? nsGlobalWindow::Cast(owner)->GetContextInternal()
     382           0 :                : nullptr;
     383             : }
     384             : 
     385             : nsresult
     386         136 : DOMEventTargetHelper::WantsUntrusted(bool* aRetVal)
     387             : {
     388         136 :   nsresult rv = CheckInnerWindowCorrectness();
     389         136 :   NS_ENSURE_SUCCESS(rv, rv);
     390             : 
     391         272 :   nsCOMPtr<nsIDocument> doc = GetDocumentIfCurrent();
     392             :   // We can let listeners on workers to always handle all the events.
     393         136 :   *aRetVal = (doc && !nsContentUtils::IsChromeDoc(doc)) || !NS_IsMainThread();
     394         136 :   return rv;
     395             : }
     396             : 
     397             : void
     398         172 : DOMEventTargetHelper::EventListenerAdded(nsIAtom* aType)
     399             : {
     400         344 :   IgnoredErrorResult rv;
     401         172 :   EventListenerWasAdded(Substring(nsDependentAtomString(aType), 2), rv);
     402         172 :   MaybeUpdateKeepAlive();
     403         172 : }
     404             : 
     405             : void
     406           0 : DOMEventTargetHelper::EventListenerAdded(const nsAString& aType)
     407             : {
     408           0 :   IgnoredErrorResult rv;
     409           0 :   EventListenerWasAdded(aType, rv);
     410           0 :   MaybeUpdateKeepAlive();
     411           0 : }
     412             : 
     413             : void
     414          24 : DOMEventTargetHelper::EventListenerRemoved(nsIAtom* aType)
     415             : {
     416          48 :   IgnoredErrorResult rv;
     417          24 :   EventListenerWasRemoved(Substring(nsDependentAtomString(aType), 2), rv);
     418          24 :   MaybeUpdateKeepAlive();
     419          24 : }
     420             : 
     421             : void
     422           0 : DOMEventTargetHelper::EventListenerRemoved(const nsAString& aType)
     423             : {
     424           0 :   IgnoredErrorResult rv;
     425           0 :   EventListenerWasRemoved(aType, rv);
     426           0 :   MaybeUpdateKeepAlive();
     427           0 : }
     428             : 
     429             : void
     430           3 : DOMEventTargetHelper::KeepAliveIfHasListenersFor(const nsAString& aType)
     431             : {
     432           3 :   mKeepingAliveTypes.mStrings.AppendElement(aType);
     433           3 :   MaybeUpdateKeepAlive();
     434           3 : }
     435             : 
     436             : void
     437           0 : DOMEventTargetHelper::KeepAliveIfHasListenersFor(nsIAtom* aType)
     438             : {
     439           0 :   mKeepingAliveTypes.mAtoms.AppendElement(aType);
     440           0 :   MaybeUpdateKeepAlive();
     441           0 : }
     442             : 
     443             : void
     444           0 : DOMEventTargetHelper::IgnoreKeepAliveIfHasListenersFor(const nsAString& aType)
     445             : {
     446           0 :   mKeepingAliveTypes.mStrings.RemoveElement(aType);
     447           0 :   MaybeUpdateKeepAlive();
     448           0 : }
     449             : 
     450             : void
     451           0 : DOMEventTargetHelper::IgnoreKeepAliveIfHasListenersFor(nsIAtom* aType)
     452             : {
     453           0 :   mKeepingAliveTypes.mAtoms.RemoveElement(aType);
     454           0 :   MaybeUpdateKeepAlive();
     455           0 : }
     456             : 
     457             : void
     458         199 : DOMEventTargetHelper::MaybeUpdateKeepAlive()
     459             : {
     460         199 :   bool shouldBeKeptAlive = false;
     461             : 
     462         199 :   if (!mKeepingAliveTypes.mAtoms.IsEmpty()) {
     463           0 :     for (uint32_t i = 0; i < mKeepingAliveTypes.mAtoms.Length(); ++i) {
     464           0 :       if (HasListenersFor(mKeepingAliveTypes.mAtoms[i])) {
     465           0 :         shouldBeKeptAlive = true;
     466           0 :         break;
     467             :       }
     468             :     }
     469             :   }
     470             : 
     471         199 :   if (!shouldBeKeptAlive && !mKeepingAliveTypes.mStrings.IsEmpty()) {
     472           7 :     for (uint32_t i = 0; i < mKeepingAliveTypes.mStrings.Length(); ++i) {
     473           4 :       if (HasListenersFor(mKeepingAliveTypes.mStrings[i])) {
     474           1 :         shouldBeKeptAlive = true;
     475           1 :         break;
     476             :       }
     477             :     }
     478             :   }
     479             : 
     480         199 :   if (shouldBeKeptAlive == mIsKeptAlive) {
     481         198 :     return;
     482             :   }
     483             : 
     484           1 :   mIsKeptAlive = shouldBeKeptAlive;
     485           1 :   if (mIsKeptAlive) {
     486           1 :     AddRef();
     487             :   } else {
     488           0 :     Release();
     489             :   }
     490             : }
     491             : 
     492             : void
     493           1 : DOMEventTargetHelper::MaybeDontKeepAlive()
     494             : {
     495           1 :   if (mIsKeptAlive) {
     496           0 :     mIsKeptAlive = false;
     497           0 :     Release();
     498             :   }
     499           1 : }
     500             : 
     501             : } // namespace mozilla

Generated by: LCOV version 1.13