LCOV - code coverage report
Current view: top level - dom/xul/templates - nsXULSortService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 249 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * This Original Code has been modified by IBM Corporation.
       7             :  * Modifications made by IBM described herein are
       8             :  * Copyright (c) International Business Machines
       9             :  * Corporation, 2000
      10             :  *
      11             :  * Modifications to Mozilla code or documentation
      12             :  * identified per MPL Section 3.3
      13             :  *
      14             :  * Date         Modified by     Description of modification
      15             :  * 03/27/2000   IBM Corp.       Added PR_CALLBACK for Optlink
      16             :  *                               use in OS2
      17             :  */
      18             : 
      19             : /*
      20             :   This file provides the implementation for the sort service manager.
      21             :  */
      22             : 
      23             : #include "nsCOMPtr.h"
      24             : #include "nsIContent.h"
      25             : #include "nsIDOMElement.h"
      26             : #include "nsIDOMNode.h"
      27             : #include "nsIServiceManager.h"
      28             : #include "nsGkAtoms.h"
      29             : #include "nsNameSpaceManager.h"
      30             : #include "nsXULContentUtils.h"
      31             : #include "nsString.h"
      32             : #include "nsQuickSort.h"
      33             : #include "nsWhitespaceTokenizer.h"
      34             : #include "nsXULSortService.h"
      35             : #include "nsXULElement.h"
      36             : #include "nsIXULTemplateBuilder.h"
      37             : #include "nsTemplateMatch.h"
      38             : #include "nsICollation.h"
      39             : #include "nsUnicharUtils.h"
      40             : 
      41           0 : NS_IMPL_ISUPPORTS(XULSortServiceImpl, nsIXULSortService)
      42             : 
      43             : void
      44           0 : XULSortServiceImpl::SetSortHints(nsIContent *aNode, nsSortState* aSortState)
      45             : {
      46             :   // set sort and sortDirection attributes when is sort is done
      47           0 :   aNode->SetAttr(kNameSpaceID_None, nsGkAtoms::sort,
      48           0 :                  aSortState->sort, true);
      49             : 
      50           0 :   nsAutoString direction;
      51           0 :   if (aSortState->direction == nsSortState_descending)
      52           0 :     direction.AssignLiteral("descending");
      53           0 :   else if (aSortState->direction == nsSortState_ascending)
      54           0 :     direction.AssignLiteral("ascending");
      55             :   aNode->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
      56           0 :                  direction, true);
      57             : 
      58             :   // for trees, also set the sort info on the currently sorted column
      59           0 :   if (aNode->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
      60           0 :     if (aSortState->sortKeys.Count() >= 1) {
      61           0 :       nsAutoString sortkey;
      62           0 :       aSortState->sortKeys[0]->ToString(sortkey);
      63           0 :       SetSortColumnHints(aNode, sortkey, direction);
      64             :     }
      65             :   }
      66           0 : }
      67             : 
      68             : void
      69           0 : XULSortServiceImpl::SetSortColumnHints(nsIContent *content,
      70             :                                        const nsAString &sortResource,
      71             :                                        const nsAString &sortDirection)
      72             : {
      73             :   // set sort info on current column. This ensures that the
      74             :   // column header sort indicator is updated properly.
      75           0 :   for (nsIContent* child = content->GetFirstChild();
      76           0 :        child;
      77           0 :        child = child->GetNextSibling()) {
      78           0 :     if (child->IsXULElement(nsGkAtoms::treecols)) {
      79           0 :       SetSortColumnHints(child, sortResource, sortDirection);
      80           0 :     } else if (child->IsXULElement(nsGkAtoms::treecol)) {
      81           0 :       nsAutoString value;
      82           0 :       child->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, value);
      83             :       // also check the resource attribute for older code
      84           0 :       if (value.IsEmpty())
      85           0 :         child->GetAttr(kNameSpaceID_None, nsGkAtoms::resource, value);
      86           0 :       if (value == sortResource) {
      87           0 :         child->SetAttr(kNameSpaceID_None, nsGkAtoms::sortActive,
      88           0 :                        NS_LITERAL_STRING("true"), true);
      89             :         child->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
      90           0 :                        sortDirection, true);
      91             :         // Note: don't break out of loop; want to set/unset
      92             :         // attribs on ALL sort columns
      93           0 :       } else if (!value.IsEmpty()) {
      94             :         child->UnsetAttr(kNameSpaceID_None, nsGkAtoms::sortActive,
      95           0 :                          true);
      96             :         child->UnsetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
      97           0 :                          true);
      98             :       }
      99             :     }
     100             :   }
     101           0 : }
     102             : 
     103             : nsresult
     104           0 : XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
     105             :                                    nsSortState* aSortState,
     106             :                                    nsTArray<contentSortInfo>& aSortItems)
     107             : {
     108             :   // if there is a template attached to the sort node, use the builder to get
     109             :   // the items to be sorted
     110           0 :   RefPtr<nsXULElement> element = nsXULElement::FromContent(aContainer);
     111           0 :   if (element) {
     112           0 :     nsCOMPtr<nsIXULTemplateBuilder> builder = element->GetBuilder();
     113             : 
     114           0 :     if (builder) {
     115           0 :       nsresult rv = builder->GetQueryProcessor(getter_AddRefs(aSortState->processor));
     116           0 :       if (NS_FAILED(rv) || !aSortState->processor)
     117           0 :         return rv;
     118             : 
     119           0 :       return GetTemplateItemsToSort(aContainer, builder, aSortState, aSortItems);
     120             :     }
     121             :   }
     122             : 
     123             :   // if there is no template builder, just get the children. For trees,
     124             :   // get the treechildren element as use that as the parent
     125           0 :   nsCOMPtr<nsIContent> treechildren;
     126           0 :   if (aContainer->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
     127           0 :     nsXULContentUtils::FindChildByTag(aContainer,
     128             :                                       kNameSpaceID_XUL,
     129             :                                       nsGkAtoms::treechildren,
     130           0 :                                       getter_AddRefs(treechildren));
     131           0 :     if (!treechildren)
     132           0 :       return NS_OK;
     133             : 
     134           0 :     aContainer = treechildren;
     135             :   }
     136             : 
     137           0 :   for (nsIContent* child = aContainer->GetFirstChild();
     138           0 :        child;
     139           0 :        child = child->GetNextSibling()) {
     140           0 :     contentSortInfo* cinfo = aSortItems.AppendElement();
     141           0 :     if (!cinfo)
     142           0 :       return NS_ERROR_OUT_OF_MEMORY;
     143             : 
     144           0 :     cinfo->content = child;
     145             :   }
     146             : 
     147           0 :   return NS_OK;
     148             : }
     149             : 
     150             : 
     151             : nsresult
     152           0 : XULSortServiceImpl::GetTemplateItemsToSort(nsIContent* aContainer,
     153             :                                            nsIXULTemplateBuilder* aBuilder,
     154             :                                            nsSortState* aSortState,
     155             :                                            nsTArray<contentSortInfo>& aSortItems)
     156             : {
     157           0 :   for (nsIContent* child = aContainer->GetFirstChild();
     158           0 :        child;
     159           0 :        child = child->GetNextSibling()) {
     160             : 
     161           0 :     nsCOMPtr<nsIDOMElement> childnode = do_QueryInterface(child);
     162             : 
     163           0 :     nsCOMPtr<nsIXULTemplateResult> result;
     164           0 :     nsresult rv = aBuilder->GetResultForContent(childnode, getter_AddRefs(result));
     165           0 :     NS_ENSURE_SUCCESS(rv, rv);
     166             : 
     167           0 :     if (result) {
     168           0 :       contentSortInfo* cinfo = aSortItems.AppendElement();
     169           0 :       if (!cinfo)
     170           0 :         return NS_ERROR_OUT_OF_MEMORY;
     171             : 
     172           0 :       cinfo->content = child;
     173           0 :       cinfo->result = result;
     174             :     }
     175           0 :     else if (!aContainer->IsXULElement(nsGkAtoms::_template)) {
     176           0 :       rv = GetTemplateItemsToSort(child, aBuilder, aSortState, aSortItems);
     177           0 :       NS_ENSURE_SUCCESS(rv, rv);
     178             :     }
     179             :   }
     180             : 
     181           0 :   return NS_OK;
     182             : }
     183             : 
     184             : int
     185           0 : testSortCallback(const void *data1, const void *data2, void *privateData)
     186             : {
     187             :   /// Note: testSortCallback is a small C callback stub for NS_QuickSort
     188           0 :   contentSortInfo *left = (contentSortInfo *)data1;
     189           0 :   contentSortInfo *right = (contentSortInfo *)data2;
     190           0 :   nsSortState* sortState = (nsSortState *)privateData;
     191             : 
     192           0 :   int32_t sortOrder = 0;
     193             : 
     194           0 :   if (sortState->direction == nsSortState_natural && sortState->processor) {
     195             :     // sort in natural order
     196           0 :     sortState->processor->CompareResults(left->result, right->result,
     197           0 :                                          nullptr, sortState->sortHints, &sortOrder);
     198             :   }
     199             :   else {
     200           0 :     int32_t length = sortState->sortKeys.Count();
     201           0 :     for (int32_t t = 0; t < length; t++) {
     202             :       // for templates, use the query processor to do sorting
     203           0 :       if (sortState->processor) {
     204           0 :         sortState->processor->CompareResults(left->result, right->result,
     205             :                                              sortState->sortKeys[t],
     206           0 :                                              sortState->sortHints, &sortOrder);
     207           0 :         if (sortOrder)
     208           0 :           break;
     209             :       }
     210             :       else {
     211             :         // no template, so just compare attributes. Ignore namespaces for now.
     212           0 :         nsAutoString leftstr, rightstr;
     213           0 :         left->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], leftstr);
     214           0 :         right->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], rightstr);
     215             : 
     216           0 :         sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
     217             :       }
     218             :     }
     219             :   }
     220             : 
     221           0 :   if (sortState->direction == nsSortState_descending)
     222           0 :     sortOrder = -sortOrder;
     223             : 
     224           0 :   return sortOrder;
     225             : }
     226             : 
     227             : nsresult
     228           0 : XULSortServiceImpl::SortContainer(nsIContent *aContainer, nsSortState* aSortState)
     229             : {
     230           0 :   nsTArray<contentSortInfo> items;
     231           0 :   nsresult rv = GetItemsToSort(aContainer, aSortState, items);
     232           0 :   NS_ENSURE_SUCCESS(rv, rv);
     233             : 
     234           0 :   uint32_t numResults = items.Length();
     235           0 :   if (!numResults)
     236           0 :     return NS_OK;
     237             : 
     238             :   uint32_t i;
     239             : 
     240             :   // inbetweenSeparatorSort sorts the items between separators independently
     241           0 :   if (aSortState->inbetweenSeparatorSort) {
     242           0 :     uint32_t startIndex = 0;
     243           0 :     for (i = 0; i < numResults; i++) {
     244           0 :       if (i > startIndex + 1) {
     245           0 :         nsAutoString type;
     246           0 :         items[i].result->GetType(type);
     247           0 :         if (type.EqualsLiteral("separator")) {
     248           0 :           if (aSortState->invertSort)
     249           0 :             InvertSortInfo(items, startIndex, i - startIndex);
     250             :           else
     251           0 :             NS_QuickSort((void *)(items.Elements() + startIndex), i - startIndex,
     252           0 :                          sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     253             : 
     254           0 :           startIndex = i + 1;
     255             :         }
     256             :       }
     257             :     }
     258             : 
     259           0 :     if (i > startIndex + 1) {
     260           0 :       if (aSortState->invertSort)
     261           0 :         InvertSortInfo(items, startIndex, i - startIndex);
     262             :       else
     263           0 :         NS_QuickSort((void *)(items.Elements() + startIndex), i - startIndex,
     264           0 :                      sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     265             :     }
     266             :   } else {
     267             :     // if the items are just being inverted, that is, just switching between
     268             :     // ascending and descending, just reverse the list.
     269           0 :     if (aSortState->invertSort)
     270           0 :       InvertSortInfo(items, 0, numResults);
     271             :     else
     272           0 :       NS_QuickSort((void *)items.Elements(), numResults,
     273           0 :                    sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     274             :   }
     275             : 
     276             :   // first remove the items from the old positions
     277           0 :   for (i = 0; i < numResults; i++) {
     278           0 :     nsIContent* child = items[i].content;
     279           0 :     nsIContent* parent = child->GetParent();
     280             : 
     281           0 :     if (parent) {
     282             :       // remember the parent so that it can be reinserted back
     283             :       // into the same parent. This is necessary as multiple rules
     284             :       // may generate results which get placed in different locations.
     285           0 :       items[i].parent = parent;
     286           0 :       int32_t index = parent->IndexOf(child);
     287           0 :       parent->RemoveChildAt(index, true);
     288             :     }
     289             :   }
     290             : 
     291             :   // now add the items back in sorted order
     292           0 :   for (i = 0; i < numResults; i++)
     293             :   {
     294           0 :     nsIContent* child = items[i].content;
     295           0 :     nsIContent* parent = items[i].parent;
     296           0 :     if (parent) {
     297           0 :       parent->AppendChildTo(child, true);
     298             : 
     299             :       // if it's a container in a tree or menu, find its children,
     300             :       // and sort those also
     301           0 :       if (!child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::container,
     302             :                               nsGkAtoms::_true, eCaseMatters))
     303           0 :         continue;
     304             : 
     305           0 :       for (nsIContent* grandchild = child->GetFirstChild();
     306           0 :            grandchild;
     307           0 :            grandchild = grandchild->GetNextSibling()) {
     308           0 :         mozilla::dom::NodeInfo *ni = grandchild->NodeInfo();
     309           0 :         nsIAtom *localName = ni->NameAtom();
     310           0 :         if (ni->NamespaceID() == kNameSpaceID_XUL &&
     311           0 :             (localName == nsGkAtoms::treechildren ||
     312           0 :              localName == nsGkAtoms::menupopup)) {
     313           0 :           SortContainer(grandchild, aSortState);
     314             :         }
     315             :       }
     316             :     }
     317             :   }
     318             : 
     319           0 :   return NS_OK;
     320             : }
     321             : 
     322             : nsresult
     323           0 : XULSortServiceImpl::InvertSortInfo(nsTArray<contentSortInfo>& aData,
     324             :                                    int32_t aStart, int32_t aNumItems)
     325             : {
     326           0 :   if (aNumItems > 1) {
     327             :     // reverse the items in the array starting from aStart
     328           0 :     int32_t upPoint = (aNumItems + 1) / 2 + aStart;
     329           0 :     int32_t downPoint = (aNumItems - 2) / 2 + aStart;
     330           0 :     int32_t half = aNumItems / 2;
     331           0 :     while (half-- > 0) {
     332           0 :       aData[downPoint--].swap(aData[upPoint++]);
     333             :     }
     334             :   }
     335           0 :   return NS_OK;
     336             : }
     337             : 
     338             : nsresult
     339           0 : XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
     340             :                                         nsIContent* aContainer,
     341             :                                         const nsAString& aSortKey,
     342             :                                         const nsAString& aSortHints,
     343             :                                         nsSortState* aSortState)
     344             : {
     345             :   // used as an optimization for the content builder
     346           0 :   if (aContainer != aSortState->lastContainer.get()) {
     347           0 :     aSortState->lastContainer = aContainer;
     348           0 :     aSortState->lastWasFirst = false;
     349           0 :     aSortState->lastWasLast = false;
     350             :   }
     351             : 
     352             :   // The attributes allowed are either:
     353             :   //    sort="key1 key2 ..."
     354             :   // or sortResource="key1" sortResource2="key2"
     355             :   // The latter is for backwards compatibility, and is equivalent to concatenating
     356             :   // both values in the sort attribute
     357           0 :   nsAutoString sort(aSortKey);
     358           0 :   aSortState->sortKeys.Clear();
     359           0 :   if (sort.IsEmpty()) {
     360           0 :     nsAutoString sortResource, sortResource2;
     361           0 :     aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource, sortResource);
     362           0 :     if (!sortResource.IsEmpty()) {
     363           0 :       nsCOMPtr<nsIAtom> sortkeyatom = NS_Atomize(sortResource);
     364           0 :       aSortState->sortKeys.AppendObject(sortkeyatom);
     365           0 :       sort.Append(sortResource);
     366             : 
     367           0 :       aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource2, sortResource2);
     368           0 :       if (!sortResource2.IsEmpty()) {
     369           0 :         nsCOMPtr<nsIAtom> sortkeyatom2 = NS_Atomize(sortResource2);
     370           0 :         aSortState->sortKeys.AppendObject(sortkeyatom2);
     371           0 :         sort.Append(' ');
     372           0 :         sort.Append(sortResource2);
     373             :       }
     374             :     }
     375             :   }
     376             :   else {
     377           0 :     nsWhitespaceTokenizer tokenizer(sort);
     378           0 :     while (tokenizer.hasMoreTokens()) {
     379           0 :       nsCOMPtr<nsIAtom> keyatom = NS_Atomize(tokenizer.nextToken());
     380           0 :       NS_ENSURE_TRUE(keyatom, NS_ERROR_OUT_OF_MEMORY);
     381           0 :       aSortState->sortKeys.AppendObject(keyatom);
     382             :     }
     383             :   }
     384             : 
     385           0 :   aSortState->sort.Assign(sort);
     386           0 :   aSortState->direction = nsSortState_natural;
     387             : 
     388           0 :   bool noNaturalState = false;
     389           0 :   nsWhitespaceTokenizer tokenizer(aSortHints);
     390           0 :   while (tokenizer.hasMoreTokens()) {
     391           0 :     const nsDependentSubstring& token(tokenizer.nextToken());
     392           0 :     if (token.EqualsLiteral("comparecase"))
     393           0 :       aSortState->sortHints |= nsIXULSortService::SORT_COMPARECASE;
     394           0 :     else if (token.EqualsLiteral("integer"))
     395           0 :       aSortState->sortHints |= nsIXULSortService::SORT_INTEGER;
     396           0 :     else if (token.EqualsLiteral("descending"))
     397           0 :       aSortState->direction = nsSortState_descending;
     398           0 :     else if (token.EqualsLiteral("ascending"))
     399           0 :       aSortState->direction = nsSortState_ascending;
     400           0 :     else if (token.EqualsLiteral("twostate"))
     401           0 :       noNaturalState = true;
     402             :   }
     403             : 
     404             :   // if the twostate flag was set, the natural order is skipped and only
     405             :   // ascending and descending are allowed
     406           0 :   if (aSortState->direction == nsSortState_natural && noNaturalState) {
     407           0 :     aSortState->direction = nsSortState_ascending;
     408             :   }
     409             : 
     410             :   // set up sort order info
     411           0 :   aSortState->invertSort = false;
     412             : 
     413           0 :   nsAutoString existingsort;
     414           0 :   aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, existingsort);
     415           0 :   nsAutoString existingsortDirection;
     416           0 :   aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, existingsortDirection);
     417             : 
     418             :   // if just switching direction, set the invertSort flag
     419           0 :   if (sort.Equals(existingsort)) {
     420           0 :     if (aSortState->direction == nsSortState_descending) {
     421           0 :       if (existingsortDirection.EqualsLiteral("ascending"))
     422           0 :         aSortState->invertSort = true;
     423             :     }
     424           0 :     else if (aSortState->direction == nsSortState_ascending &&
     425           0 :              existingsortDirection.EqualsLiteral("descending")) {
     426           0 :       aSortState->invertSort = true;
     427             :     }
     428             :   }
     429             : 
     430             :   // sort items between separators independently
     431           0 :   aSortState->inbetweenSeparatorSort =
     432           0 :     aRootElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortSeparators,
     433             :                               nsGkAtoms::_true, eCaseMatters);
     434             : 
     435             :   // sort static content (non template generated nodes) after generated content
     436           0 :   aSortState->sortStaticsLast = aRootElement->AttrValueIs(kNameSpaceID_None,
     437             :                                   nsGkAtoms::sortStaticsLast,
     438             :                                   nsGkAtoms::_true, eCaseMatters);
     439             : 
     440           0 :   aSortState->initialized = true;
     441             : 
     442           0 :   return NS_OK;
     443             : }
     444             : 
     445             : int32_t
     446           0 : XULSortServiceImpl::CompareValues(const nsAString& aLeft,
     447             :                                   const nsAString& aRight,
     448             :                                   uint32_t aSortHints)
     449             : {
     450           0 :   if (aSortHints & SORT_INTEGER) {
     451             :     nsresult err;
     452           0 :     int32_t leftint = PromiseFlatString(aLeft).ToInteger(&err);
     453           0 :     if (NS_SUCCEEDED(err)) {
     454           0 :       int32_t rightint = PromiseFlatString(aRight).ToInteger(&err);
     455           0 :       if (NS_SUCCEEDED(err)) {
     456           0 :         return leftint - rightint;
     457             :       }
     458             :     }
     459             :     // if they aren't integers, just fall through and compare strings
     460             :   }
     461             : 
     462           0 :   if (aSortHints & SORT_COMPARECASE) {
     463           0 :     return ::Compare(aLeft, aRight);
     464             :   }
     465             : 
     466           0 :   nsICollation* collation = nsXULContentUtils::GetCollation();
     467           0 :   if (collation) {
     468             :     int32_t result;
     469             :     collation->CompareString(nsICollation::kCollationCaseInSensitive,
     470           0 :                              aLeft, aRight, &result);
     471           0 :     return result;
     472             :   }
     473             : 
     474           0 :   return ::Compare(aLeft, aRight, nsCaseInsensitiveStringComparator());
     475             : }
     476             : 
     477             : NS_IMETHODIMP
     478           0 : XULSortServiceImpl::Sort(nsIDOMNode* aNode,
     479             :                          const nsAString& aSortKey,
     480             :                          const nsAString& aSortHints)
     481             : {
     482             :   // get root content node
     483           0 :   nsCOMPtr<nsIContent> sortNode = do_QueryInterface(aNode);
     484           0 :   if (!sortNode)
     485           0 :     return NS_ERROR_FAILURE;
     486             : 
     487           0 :   nsSortState sortState;
     488           0 :   nsresult rv = InitializeSortState(sortNode, sortNode,
     489           0 :                                     aSortKey, aSortHints, &sortState);
     490           0 :   NS_ENSURE_SUCCESS(rv, rv);
     491             : 
     492             :   // store sort info in attributes on content
     493           0 :   SetSortHints(sortNode, &sortState);
     494           0 :   rv = SortContainer(sortNode, &sortState);
     495             : 
     496           0 :   sortState.processor = nullptr; // don't hang on to this reference
     497           0 :   return rv;
     498             : }
     499             : 
     500             : nsresult
     501           0 : NS_NewXULSortService(nsIXULSortService** sortService)
     502             : {
     503           0 :   *sortService = new XULSortServiceImpl();
     504           0 :   NS_ADDREF(*sortService);
     505           0 :   return NS_OK;
     506             : }

Generated by: LCOV version 1.13