LCOV - code coverage report
Current view: directory - accessible/src/base - nsAccDocManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 174 0 0.0 %
Date: 2012-06-02 Functions: 21 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Mozilla Foundation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Alexander Surkov <surkov.alexander@gmail.com> (original author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsAccDocManager.h"
      40                 : 
      41                 : #include "nsAccessibilityService.h"
      42                 : #include "nsAccUtils.h"
      43                 : #include "nsApplicationAccessible.h"
      44                 : #include "nsOuterDocAccessible.h"
      45                 : #include "nsRootAccessibleWrap.h"
      46                 : #include "States.h"
      47                 : 
      48                 : #include "nsCURILoader.h"
      49                 : #include "nsDocShellLoadTypes.h"
      50                 : #include "nsIChannel.h"
      51                 : #include "nsIContentViewer.h"
      52                 : #include "nsIDOMDocument.h"
      53                 : #include "nsEventListenerManager.h"
      54                 : #include "nsIDOMEventTarget.h"
      55                 : #include "nsIDOMWindow.h"
      56                 : #include "nsIInterfaceRequestorUtils.h"
      57                 : #include "nsIWebNavigation.h"
      58                 : #include "nsServiceManagerUtils.h"
      59                 : 
      60                 : using namespace mozilla::a11y;
      61                 : 
      62                 : ////////////////////////////////////////////////////////////////////////////////
      63                 : // nsAccDocManager
      64                 : ////////////////////////////////////////////////////////////////////////////////
      65                 : 
      66                 : ////////////////////////////////////////////////////////////////////////////////
      67                 : // nsAccDocManager public
      68                 : 
      69                 : nsDocAccessible*
      70               0 : nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
      71                 : {
      72               0 :   if (!aDocument)
      73               0 :     return nsnull;
      74                 : 
      75                 :   // Ensure CacheChildren is called before we query cache.
      76               0 :   nsAccessNode::GetApplicationAccessible()->EnsureChildren();
      77                 : 
      78               0 :   nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
      79               0 :   if (docAcc)
      80               0 :     return docAcc;
      81                 : 
      82               0 :   return CreateDocOrRootAccessible(aDocument);
      83                 : }
      84                 : 
      85                 : nsAccessible*
      86               0 : nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
      87                 : {
      88                 :   nsSearchAccessibleInCacheArg arg;
      89               0 :   arg.mNode = aNode;
      90                 : 
      91                 :   mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
      92               0 :                                     static_cast<void*>(&arg));
      93                 : 
      94               0 :   return arg.mAccessible;
      95                 : }
      96                 : 
      97                 : #ifdef DEBUG
      98                 : bool
      99               0 : nsAccDocManager::IsProcessingRefreshDriverNotification() const
     100                 : {
     101               0 :   bool isDocRefreshing = false;
     102                 :   mDocAccessibleCache.EnumerateRead(SearchIfDocIsRefreshing,
     103               0 :                                     static_cast<void*>(&isDocRefreshing));
     104                 : 
     105               0 :   return isDocRefreshing;
     106                 : }
     107                 : #endif
     108                 : 
     109                 : 
     110                 : ////////////////////////////////////////////////////////////////////////////////
     111                 : // nsAccDocManager protected
     112                 : 
     113                 : bool
     114               0 : nsAccDocManager::Init()
     115                 : {
     116               0 :   mDocAccessibleCache.Init(4);
     117                 : 
     118                 :   nsCOMPtr<nsIWebProgress> progress =
     119               0 :     do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
     120                 : 
     121               0 :   if (!progress)
     122               0 :     return false;
     123                 : 
     124               0 :   progress->AddProgressListener(static_cast<nsIWebProgressListener*>(this),
     125               0 :                                 nsIWebProgress::NOTIFY_STATE_DOCUMENT);
     126                 : 
     127               0 :   return true;
     128                 : }
     129                 : 
     130                 : void
     131               0 : nsAccDocManager::Shutdown()
     132                 : {
     133                 :   nsCOMPtr<nsIWebProgress> progress =
     134               0 :     do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
     135                 : 
     136               0 :   if (progress)
     137               0 :     progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
     138                 : 
     139               0 :   ClearDocCache();
     140               0 : }
     141                 : 
     142                 : ////////////////////////////////////////////////////////////////////////////////
     143                 : // nsISupports
     144                 : 
     145               0 : NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
     146                 :                               nsIWebProgressListener,
     147                 :                               nsIDOMEventListener,
     148                 :                               nsISupportsWeakReference)
     149                 : 
     150                 : ////////////////////////////////////////////////////////////////////////////////
     151                 : // nsIWebProgressListener
     152                 : 
     153                 : NS_IMETHODIMP
     154               0 : nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
     155                 :                                nsIRequest *aRequest, PRUint32 aStateFlags,
     156                 :                                nsresult aStatus)
     157                 : {
     158               0 :   NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
     159                 : 
     160               0 :   if (nsAccessibilityService::IsShutdown() || !aWebProgress ||
     161                 :       (aStateFlags & (STATE_START | STATE_STOP)) == 0)
     162               0 :     return NS_OK;
     163                 : 
     164               0 :   nsCOMPtr<nsIDOMWindow> DOMWindow;
     165               0 :   aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow));
     166               0 :   NS_ENSURE_STATE(DOMWindow);
     167                 : 
     168               0 :   nsCOMPtr<nsIDOMDocument> DOMDocument;
     169               0 :   DOMWindow->GetDocument(getter_AddRefs(DOMDocument));
     170               0 :   NS_ENSURE_STATE(DOMDocument);
     171                 : 
     172               0 :   nsCOMPtr<nsIDocument> document(do_QueryInterface(DOMDocument));
     173                 : 
     174                 :   // Document was loaded.
     175               0 :   if (aStateFlags & STATE_STOP) {
     176                 :     NS_LOG_ACCDOCLOAD("document loaded", aWebProgress, aRequest, aStateFlags)
     177                 : 
     178                 :     // Figure out an event type to notify the document has been loaded.
     179               0 :     PRUint32 eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED;
     180                 : 
     181                 :     // Some XUL documents get start state and then stop state with failure
     182                 :     // status when everything is ok. Fire document load complete event in this
     183                 :     // case.
     184               0 :     if (NS_SUCCEEDED(aStatus) || !nsCoreUtils::IsContentDocument(document))
     185               0 :       eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
     186                 : 
     187                 :     // If end consumer has been retargeted for loaded content then do not fire
     188                 :     // any event because it means no new document has been loaded, for example,
     189                 :     // it happens when user clicks on file link.
     190               0 :     if (aRequest) {
     191               0 :       PRUint32 loadFlags = 0;
     192               0 :       aRequest->GetLoadFlags(&loadFlags);
     193               0 :       if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
     194               0 :         eventType = 0;
     195                 :     }
     196                 : 
     197               0 :     HandleDOMDocumentLoad(document, eventType);
     198               0 :     return NS_OK;
     199                 :   }
     200                 : 
     201                 :   // Document loading was started.
     202                 :   NS_LOG_ACCDOCLOAD("start document loading", aWebProgress, aRequest,
     203                 :                     aStateFlags)
     204                 : 
     205               0 :   nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
     206               0 :   if (!docAcc)
     207               0 :     return NS_OK;
     208                 : 
     209               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(DOMWindow));
     210               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
     211               0 :   NS_ENSURE_STATE(docShell);
     212                 : 
     213               0 :   bool isReloading = false;
     214                 :   PRUint32 loadType;
     215               0 :   docShell->GetLoadType(&loadType);
     216               0 :   if (loadType == LOAD_RELOAD_NORMAL ||
     217                 :       loadType == LOAD_RELOAD_BYPASS_CACHE ||
     218                 :       loadType == LOAD_RELOAD_BYPASS_PROXY ||
     219                 :       loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
     220               0 :     isReloading = true;
     221                 :   }
     222                 : 
     223               0 :   docAcc->NotifyOfLoading(isReloading);
     224               0 :   return NS_OK;
     225                 : }
     226                 : 
     227                 : NS_IMETHODIMP
     228               0 : nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress,
     229                 :                                   nsIRequest *aRequest,
     230                 :                                   PRInt32 aCurSelfProgress,
     231                 :                                   PRInt32 aMaxSelfProgress,
     232                 :                                   PRInt32 aCurTotalProgress,
     233                 :                                   PRInt32 aMaxTotalProgress)
     234                 : {
     235               0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     236               0 :   return NS_OK;
     237                 : }
     238                 : 
     239                 : NS_IMETHODIMP
     240               0 : nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress,
     241                 :                                   nsIRequest *aRequest, nsIURI *aLocation,
     242                 :                                   PRUint32 aFlags)
     243                 : {
     244               0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     245               0 :   return NS_OK;
     246                 : }
     247                 : 
     248                 : NS_IMETHODIMP
     249               0 : nsAccDocManager::OnStatusChange(nsIWebProgress *aWebProgress,
     250                 :                                 nsIRequest *aRequest, nsresult aStatus,
     251                 :                                 const PRUnichar *aMessage)
     252                 : {
     253               0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     254               0 :   return NS_OK;
     255                 : }
     256                 : 
     257                 : NS_IMETHODIMP
     258               0 : nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress,
     259                 :                                   nsIRequest *aRequest,
     260                 :                                   PRUint32 aState)
     261                 : {
     262               0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     263               0 :   return NS_OK;
     264                 : }
     265                 : 
     266                 : ////////////////////////////////////////////////////////////////////////////////
     267                 : // nsIDOMEventListener
     268                 : 
     269                 : NS_IMETHODIMP
     270               0 : nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
     271                 : {
     272               0 :   nsAutoString type;
     273               0 :   aEvent->GetType(type);
     274                 : 
     275               0 :   nsCOMPtr<nsIDOMEventTarget> target;
     276               0 :   aEvent->GetTarget(getter_AddRefs(target));
     277                 : 
     278               0 :   nsCOMPtr<nsIDocument> document(do_QueryInterface(target));
     279               0 :   NS_ASSERTION(document, "pagehide or DOMContentLoaded for non document!");
     280               0 :   if (!document)
     281               0 :     return NS_OK;
     282                 : 
     283               0 :   if (type.EqualsLiteral("pagehide")) {
     284                 :     // 'pagehide' event is registered on every DOM document we create an
     285                 :     // accessible for, process the event for the target. This document
     286                 :     // accessible and all its sub document accessible are shutdown as result of
     287                 :     // processing.
     288                 : 
     289                 :     NS_LOG_ACCDOCDESTROY("received 'pagehide' event", document)
     290                 : 
     291                 :     // Ignore 'pagehide' on temporary documents since we ignore them entirely in
     292                 :     // accessibility.
     293               0 :     if (document->IsInitialDocument())
     294               0 :       return NS_OK;
     295                 : 
     296                 :     // Shutdown this one and sub document accessibles.
     297                 : 
     298                 :     // We're allowed to not remove listeners when accessible document is
     299                 :     // shutdown since we don't keep strong reference on chrome event target and
     300                 :     // listeners are removed automatically when chrome event target goes away.
     301               0 :     nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(document);
     302               0 :     if (docAccessible)
     303               0 :       docAccessible->Shutdown();
     304                 : 
     305               0 :     return NS_OK;
     306                 :   }
     307                 : 
     308                 :   // XXX: handle error pages loading separately since they get neither
     309                 :   // webprogress notifications nor 'pageshow' event.
     310               0 :   if (type.EqualsLiteral("DOMContentLoaded") &&
     311               0 :       nsCoreUtils::IsErrorPage(document)) {
     312                 :     NS_LOG_ACCDOCLOAD2("handled 'DOMContentLoaded' event", document)
     313                 :     HandleDOMDocumentLoad(document,
     314               0 :                           nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
     315                 :   }
     316                 : 
     317               0 :   return NS_OK;
     318                 : }
     319                 : 
     320                 : ////////////////////////////////////////////////////////////////////////////////
     321                 : // nsAccDocManager private
     322                 : 
     323                 : void
     324               0 : nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
     325                 :                                        PRUint32 aLoadEventType)
     326                 : {
     327                 :   // Document accessible can be created before we were notified the DOM document
     328                 :   // was loaded completely. However if it's not created yet then create it.
     329               0 :   nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
     330               0 :   if (!docAcc) {
     331               0 :     docAcc = CreateDocOrRootAccessible(aDocument);
     332               0 :     if (!docAcc)
     333               0 :       return;
     334                 :   }
     335                 : 
     336               0 :   docAcc->NotifyOfLoad(aLoadEventType);
     337                 : }
     338                 : 
     339                 : void
     340               0 : nsAccDocManager::AddListeners(nsIDocument *aDocument,
     341                 :                               bool aAddDOMContentLoadedListener)
     342                 : {
     343               0 :   nsPIDOMWindow *window = aDocument->GetWindow();
     344               0 :   nsIDOMEventTarget *target = window->GetChromeEventHandler();
     345               0 :   nsEventListenerManager* elm = target->GetListenerManager(true);
     346               0 :   elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
     347               0 :                               NS_EVENT_FLAG_CAPTURE);
     348                 : 
     349                 :   NS_LOG_ACCDOCCREATE_TEXT("  added 'pagehide' listener")
     350                 : 
     351               0 :   if (aAddDOMContentLoadedListener) {
     352               0 :     elm->AddEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
     353               0 :                                 NS_EVENT_FLAG_CAPTURE);
     354                 :     NS_LOG_ACCDOCCREATE_TEXT("  added 'DOMContentLoaded' listener")
     355                 :   }
     356               0 : }
     357                 : 
     358                 : nsDocAccessible*
     359               0 : nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
     360                 : {
     361                 :   // Ignore temporary, hiding, resource documents and documents without
     362                 :   // docshell.
     363               0 :   if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
     364               0 :       aDocument->IsResourceDoc() || !aDocument->IsActive())
     365               0 :     return nsnull;
     366                 : 
     367                 :   // Ignore documents without presshell and not having root frame.
     368               0 :   nsIPresShell* presShell = aDocument->GetShell();
     369               0 :   if (!presShell || !presShell->GetRootFrame())
     370               0 :     return nsnull;
     371                 : 
     372                 :   // Do not create document accessible until role content is loaded, otherwise
     373                 :   // we get accessible document with wrong role.
     374               0 :   nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
     375               0 :   if (!rootElm)
     376               0 :     return nsnull;
     377                 : 
     378               0 :   bool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);
     379                 : 
     380               0 :   nsDocAccessible* parentDocAcc = nsnull;
     381               0 :   if (!isRootDoc) {
     382                 :     // XXXaaronl: ideally we would traverse the presshell chain. Since there's
     383                 :     // no easy way to do that, we cheat and use the document hierarchy.
     384               0 :     parentDocAcc = GetDocAccessible(aDocument->GetParentDocument());
     385               0 :     NS_ASSERTION(parentDocAcc,
     386                 :                  "Can't create an accessible for the document!");
     387               0 :     if (!parentDocAcc)
     388               0 :       return nsnull;
     389                 :   }
     390                 : 
     391                 :   // We only create root accessibles for the true root, otherwise create a
     392                 :   // doc accessible.
     393                 :   nsRefPtr<nsDocAccessible> docAcc = isRootDoc ?
     394               0 :     new nsRootAccessibleWrap(aDocument, rootElm, presShell) :
     395               0 :     new nsDocAccessibleWrap(aDocument, rootElm, presShell);
     396                 : 
     397                 :   // Cache the document accessible into document cache.
     398               0 :   if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
     399               0 :     return nsnull;
     400                 : 
     401                 :   // Initialize the document accessible.
     402               0 :   if (!docAcc->Init()) {
     403               0 :     docAcc->Shutdown();
     404               0 :     return nsnull;
     405                 :   }
     406               0 :   docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument));
     407                 : 
     408                 :   // Bind the document to the tree.
     409               0 :   if (isRootDoc) {
     410               0 :     nsAccessible* appAcc = nsAccessNode::GetApplicationAccessible();
     411               0 :     if (!appAcc->AppendChild(docAcc)) {
     412               0 :       docAcc->Shutdown();
     413               0 :       return nsnull;
     414                 :     }
     415                 : 
     416                 :     // Fire reorder event to notify new accessible document has been attached to
     417                 :     // the tree. The reorder event is delivered after the document tree is
     418                 :     // constructed because event processing and tree construction are done by
     419                 :     // the same document.
     420                 :     nsRefPtr<AccEvent> reorderEvent =
     421                 :       new AccEvent(nsIAccessibleEvent::EVENT_REORDER, appAcc, eAutoDetect,
     422               0 :                    AccEvent::eCoalesceFromSameSubtree);
     423               0 :     docAcc->FireDelayedAccessibleEvent(reorderEvent);
     424                 : 
     425                 :   } else {
     426               0 :     parentDocAcc->BindChildDocument(docAcc);
     427                 :   }
     428                 : 
     429                 :   NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
     430                 :   NS_LOG_ACCDOCCREATE_STACK
     431                 : 
     432               0 :   AddListeners(aDocument, isRootDoc);
     433               0 :   return docAcc;
     434                 : }
     435                 : 
     436                 : ////////////////////////////////////////////////////////////////////////////////
     437                 : // nsAccDocManager static
     438                 : 
     439                 : PLDHashOperator
     440               0 : nsAccDocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
     441                 :                                          nsDocAccessible* aDocAccessible,
     442                 :                                          void* aUserArg)
     443                 : {
     444               0 :   NS_ASSERTION(aDocAccessible,
     445                 :                "No doc accessible for the object in doc accessible cache!");
     446               0 :   *reinterpret_cast<nsDocAccessible**>(aUserArg) = aDocAccessible;
     447                 : 
     448               0 :   return PL_DHASH_STOP;
     449                 : }
     450                 : 
     451                 : void
     452               0 : nsAccDocManager::ClearDocCache()
     453                 : {
     454               0 :   nsDocAccessible* docAcc = nsnull;
     455               0 :   while (mDocAccessibleCache.EnumerateRead(GetFirstEntryInDocCache, static_cast<void*>(&docAcc))) {
     456               0 :     if (docAcc)
     457               0 :       docAcc->Shutdown();
     458                 :   }
     459               0 : }
     460                 : 
     461                 : PLDHashOperator
     462               0 : nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
     463                 :                                             nsDocAccessible* aDocAccessible,
     464                 :                                             void* aUserArg)
     465                 : {
     466               0 :   NS_ASSERTION(aDocAccessible,
     467                 :                "No doc accessible for the object in doc accessible cache!");
     468                 : 
     469               0 :   if (aDocAccessible) {
     470                 :     nsSearchAccessibleInCacheArg* arg =
     471               0 :       static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
     472               0 :     arg->mAccessible = aDocAccessible->GetAccessible(arg->mNode);
     473               0 :     if (arg->mAccessible)
     474               0 :       return PL_DHASH_STOP;
     475                 :   }
     476                 : 
     477               0 :   return PL_DHASH_NEXT;
     478                 : }
     479                 : 
     480                 : #ifdef DEBUG
     481                 : PLDHashOperator
     482               0 : nsAccDocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
     483                 :                                          nsDocAccessible* aDocAccessible,
     484                 :                                          void* aUserArg)
     485                 : {
     486               0 :   NS_ASSERTION(aDocAccessible,
     487                 :                "No doc accessible for the object in doc accessible cache!");
     488                 : 
     489               0 :   if (aDocAccessible && aDocAccessible->mNotificationController &&
     490               0 :       aDocAccessible->mNotificationController->IsUpdating()) {
     491               0 :     *(static_cast<bool*>(aUserArg)) = true;
     492               0 :     return PL_DHASH_STOP;
     493                 :   }
     494                 : 
     495               0 :   return PL_DHASH_NEXT;
     496                 : }
     497                 : #endif

Generated by: LCOV version 1.7