LCOV - code coverage report
Current view: top level - uriloader/prefetch - OfflineCacheUpdateChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 209 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 27 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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             : #include "BackgroundUtils.h"
       7             : #include "OfflineCacheUpdateChild.h"
       8             : #include "nsOfflineCacheUpdate.h"
       9             : #include "mozilla/dom/ContentChild.h"
      10             : #include "mozilla/dom/TabChild.h"
      11             : #include "mozilla/ipc/URIUtils.h"
      12             : #include "mozilla/net/NeckoCommon.h"
      13             : 
      14             : #include "nsIApplicationCacheContainer.h"
      15             : #include "nsIApplicationCacheChannel.h"
      16             : #include "nsIApplicationCacheService.h"
      17             : #include "nsIDocShell.h"
      18             : #include "nsIDocShellTreeItem.h"
      19             : #include "nsIDocShellTreeOwner.h"
      20             : #include "nsPIDOMWindow.h"
      21             : #include "nsIDOMOfflineResourceList.h"
      22             : #include "nsIDocument.h"
      23             : #include "nsIObserverService.h"
      24             : #include "nsIURL.h"
      25             : #include "nsITabChild.h"
      26             : #include "nsNetCID.h"
      27             : #include "nsNetUtil.h"
      28             : #include "nsServiceManagerUtils.h"
      29             : #include "nsStreamUtils.h"
      30             : #include "nsThreadUtils.h"
      31             : #include "nsProxyRelease.h"
      32             : #include "mozilla/Logging.h"
      33             : #include "nsIAsyncVerifyRedirectCallback.h"
      34             : 
      35             : using namespace mozilla::ipc;
      36             : using namespace mozilla::net;
      37             : using mozilla::dom::TabChild;
      38             : using mozilla::dom::ContentChild;
      39             : 
      40             : //
      41             : // To enable logging (see mozilla/Logging.h for full details):
      42             : //
      43             : //    set MOZ_LOG=nsOfflineCacheUpdate:5
      44             : //    set MOZ_LOG_FILE=offlineupdate.log
      45             : //
      46             : // this enables LogLevel::Debug level information and places all output in
      47             : // the file offlineupdate.log
      48             : //
      49             : extern mozilla::LazyLogModule gOfflineCacheUpdateLog;
      50             : 
      51             : #undef LOG
      52             : #define LOG(args) MOZ_LOG(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug, args)
      53             : 
      54             : #undef LOG_ENABLED
      55             : #define LOG_ENABLED() MOZ_LOG_TEST(gOfflineCacheUpdateLog, mozilla::LogLevel::Debug)
      56             : 
      57             : namespace mozilla {
      58             : namespace docshell {
      59             : 
      60             : //-----------------------------------------------------------------------------
      61             : // OfflineCacheUpdateChild::nsISupports
      62             : //-----------------------------------------------------------------------------
      63             : 
      64           0 : NS_INTERFACE_MAP_BEGIN(OfflineCacheUpdateChild)
      65           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      66           0 :   NS_INTERFACE_MAP_ENTRY(nsIOfflineCacheUpdate)
      67           0 : NS_INTERFACE_MAP_END
      68             : 
      69           0 : NS_IMPL_ADDREF(OfflineCacheUpdateChild)
      70           0 : NS_IMPL_RELEASE(OfflineCacheUpdateChild)
      71             : 
      72             : //-----------------------------------------------------------------------------
      73             : // OfflineCacheUpdateChild <public>
      74             : //-----------------------------------------------------------------------------
      75             : 
      76           0 : OfflineCacheUpdateChild::OfflineCacheUpdateChild(nsPIDOMWindowInner* aWindow)
      77             :     : mState(STATE_UNINITIALIZED)
      78             :     , mIsUpgrade(false)
      79             :     , mSucceeded(false)
      80             :     , mWindow(aWindow)
      81           0 :     , mByteProgress(0)
      82             : {
      83           0 : }
      84             : 
      85           0 : OfflineCacheUpdateChild::~OfflineCacheUpdateChild()
      86             : {
      87           0 :     LOG(("OfflineCacheUpdateChild::~OfflineCacheUpdateChild [%p]", this));
      88           0 : }
      89             : 
      90             : void
      91           0 : OfflineCacheUpdateChild::GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers)
      92             : {
      93           0 :     for (int32_t i = 0; i < mWeakObservers.Count(); i++) {
      94             :         nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
      95           0 :             do_QueryReferent(mWeakObservers[i]);
      96           0 :         if (observer)
      97           0 :             aObservers.AppendObject(observer);
      98             :         else
      99           0 :             mWeakObservers.RemoveObjectAt(i--);
     100             :     }
     101             : 
     102           0 :     for (int32_t i = 0; i < mObservers.Count(); i++) {
     103           0 :         aObservers.AppendObject(mObservers[i]);
     104             :     }
     105           0 : }
     106             : 
     107             : void
     108           0 : OfflineCacheUpdateChild::SetDocument(nsIDOMDocument *aDocument)
     109             : {
     110             :     // The design is one document for one cache update on the content process.
     111           0 :     NS_ASSERTION(!mDocument, "Setting more then a single document on a child offline cache update");
     112             : 
     113           0 :     LOG(("Document %p added to update child %p", aDocument, this));
     114             : 
     115             :     // Add document only if it was not loaded from an offline cache.
     116             :     // If it were loaded from an offline cache then it has already
     117             :     // been associated with it and must not be again cached as
     118             :     // implicit (which are the reasons we collect documents here).
     119           0 :     nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
     120           0 :     if (!document)
     121           0 :         return;
     122             : 
     123           0 :     nsIChannel* channel = document->GetChannel();
     124             :     nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
     125           0 :         do_QueryInterface(channel);
     126           0 :     if (!appCacheChannel)
     127           0 :         return;
     128             : 
     129             :     bool loadedFromAppCache;
     130           0 :     appCacheChannel->GetLoadedFromApplicationCache(&loadedFromAppCache);
     131           0 :     if (loadedFromAppCache)
     132           0 :         return;
     133             : 
     134           0 :     mDocument = aDocument;
     135             : }
     136             : 
     137             : nsresult
     138           0 : OfflineCacheUpdateChild::AssociateDocument(nsIDOMDocument *aDocument,
     139             :                                         nsIApplicationCache *aApplicationCache)
     140             : {
     141             :     // Check that the document that requested this update was
     142             :     // previously associated with an application cache.  If not, it
     143             :     // should be associated with the new one.
     144             :     nsCOMPtr<nsIApplicationCacheContainer> container =
     145           0 :         do_QueryInterface(aDocument);
     146           0 :     if (!container)
     147           0 :         return NS_OK;
     148             : 
     149           0 :     nsCOMPtr<nsIApplicationCache> existingCache;
     150           0 :     nsresult rv = container->GetApplicationCache(getter_AddRefs(existingCache));
     151           0 :     NS_ENSURE_SUCCESS(rv, rv);
     152             : 
     153           0 :     if (!existingCache) {
     154           0 :         if (LOG_ENABLED()) {
     155           0 :             nsAutoCString clientID;
     156           0 :             if (aApplicationCache) {
     157           0 :                 aApplicationCache->GetClientID(clientID);
     158             :             }
     159           0 :             LOG(("Update %p: associating app cache %s to document %p",
     160             :                  this, clientID.get(), aDocument));
     161             :         }
     162             : 
     163           0 :         rv = container->SetApplicationCache(aApplicationCache);
     164           0 :         NS_ENSURE_SUCCESS(rv, rv);
     165             :     }
     166             : 
     167           0 :     return NS_OK;
     168             : }
     169             : 
     170             : //-----------------------------------------------------------------------------
     171             : // OfflineCacheUpdateChild::nsIOfflineCacheUpdate
     172             : //-----------------------------------------------------------------------------
     173             : 
     174             : NS_IMETHODIMP
     175           0 : OfflineCacheUpdateChild::Init(nsIURI *aManifestURI,
     176             :                               nsIURI *aDocumentURI,
     177             :                               nsIPrincipal *aLoadingPrincipal,
     178             :                               nsIDOMDocument *aDocument,
     179             :                               nsIFile *aCustomProfileDir)
     180             : {
     181             :     nsresult rv;
     182             : 
     183             :     // Make sure the service has been initialized
     184             :     nsOfflineCacheUpdateService* service =
     185           0 :         nsOfflineCacheUpdateService::EnsureService();
     186           0 :     if (!service)
     187           0 :         return NS_ERROR_FAILURE;
     188             : 
     189           0 :     if (aCustomProfileDir) {
     190           0 :         NS_ERROR("Custom Offline Cache Update not supported on child process");
     191           0 :         return NS_ERROR_NOT_IMPLEMENTED;
     192             :     }
     193             : 
     194           0 :     LOG(("OfflineCacheUpdateChild::Init [%p]", this));
     195             : 
     196             :     // Only http and https applications are supported.
     197             :     bool match;
     198           0 :     rv = aManifestURI->SchemeIs("http", &match);
     199           0 :     NS_ENSURE_SUCCESS(rv, rv);
     200             : 
     201           0 :     if (!match) {
     202           0 :         rv = aManifestURI->SchemeIs("https", &match);
     203           0 :         NS_ENSURE_SUCCESS(rv, rv);
     204           0 :         if (!match)
     205           0 :             return NS_ERROR_ABORT;
     206             :     }
     207             : 
     208           0 :     mManifestURI = aManifestURI;
     209             : 
     210           0 :     rv = mManifestURI->GetAsciiHost(mUpdateDomain);
     211           0 :     NS_ENSURE_SUCCESS(rv, rv);
     212             : 
     213           0 :     mDocumentURI = aDocumentURI;
     214           0 :     mLoadingPrincipal = aLoadingPrincipal;
     215             : 
     216           0 :     mState = STATE_INITIALIZED;
     217             : 
     218           0 :     if (aDocument)
     219           0 :         SetDocument(aDocument);
     220             : 
     221           0 :     return NS_OK;
     222             : }
     223             : 
     224             : NS_IMETHODIMP
     225           0 : OfflineCacheUpdateChild::InitPartial(nsIURI *aManifestURI,
     226             :                                   const nsACString& clientID,
     227             :                                   nsIURI *aDocumentURI,
     228             :                                   nsIPrincipal *aLoadingPrincipal)
     229             : {
     230           0 :     NS_NOTREACHED("Not expected to do partial offline cache updates"
     231             :                   " on the child process");
     232             :     // For now leaving this method, we may discover we need it.
     233           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     234             : }
     235             : 
     236             : NS_IMETHODIMP
     237           0 : OfflineCacheUpdateChild::InitForUpdateCheck(nsIURI *aManifestURI,
     238             :                                             nsIPrincipal* aLoadingPrincipal,
     239             :                                             nsIObserver *aObserver)
     240             : {
     241           0 :     NS_NOTREACHED("Not expected to do only update checks"
     242             :                   " from the child process");
     243           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     244             : }
     245             : 
     246             : NS_IMETHODIMP
     247           0 : OfflineCacheUpdateChild::GetUpdateDomain(nsACString &aUpdateDomain)
     248             : {
     249           0 :     NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
     250             : 
     251           0 :     aUpdateDomain = mUpdateDomain;
     252           0 :     return NS_OK;
     253             : }
     254             : 
     255             : NS_IMETHODIMP
     256           0 : OfflineCacheUpdateChild::GetStatus(uint16_t *aStatus)
     257             : {
     258           0 :     switch (mState) {
     259             :     case STATE_CHECKING :
     260           0 :         *aStatus = nsIDOMOfflineResourceList::CHECKING;
     261           0 :         return NS_OK;
     262             :     case STATE_DOWNLOADING :
     263           0 :         *aStatus = nsIDOMOfflineResourceList::DOWNLOADING;
     264           0 :         return NS_OK;
     265             :     default :
     266           0 :         *aStatus = nsIDOMOfflineResourceList::IDLE;
     267           0 :         return NS_OK;
     268             :     }
     269             : 
     270             :     return NS_ERROR_FAILURE;
     271             : }
     272             : 
     273             : NS_IMETHODIMP
     274           0 : OfflineCacheUpdateChild::GetPartial(bool *aPartial)
     275             : {
     276           0 :     *aPartial = false;
     277           0 :     return NS_OK;
     278             : }
     279             : 
     280             : NS_IMETHODIMP
     281           0 : OfflineCacheUpdateChild::GetManifestURI(nsIURI **aManifestURI)
     282             : {
     283           0 :     NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
     284             : 
     285           0 :     NS_IF_ADDREF(*aManifestURI = mManifestURI);
     286           0 :     return NS_OK;
     287             : }
     288             : 
     289             : NS_IMETHODIMP
     290           0 : OfflineCacheUpdateChild::GetSucceeded(bool *aSucceeded)
     291             : {
     292           0 :     NS_ENSURE_TRUE(mState == STATE_FINISHED, NS_ERROR_NOT_AVAILABLE);
     293             : 
     294           0 :     *aSucceeded = mSucceeded;
     295             : 
     296           0 :     return NS_OK;
     297             : }
     298             : 
     299             : NS_IMETHODIMP
     300           0 : OfflineCacheUpdateChild::GetIsUpgrade(bool *aIsUpgrade)
     301             : {
     302           0 :     NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
     303             : 
     304           0 :     *aIsUpgrade = mIsUpgrade;
     305             : 
     306           0 :     return NS_OK;
     307             : }
     308             : 
     309             : NS_IMETHODIMP
     310           0 : OfflineCacheUpdateChild::AddDynamicURI(nsIURI *aURI)
     311             : {
     312           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     313             : }
     314             : 
     315             : NS_IMETHODIMP
     316           0 : OfflineCacheUpdateChild::Cancel()
     317             : {
     318           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     319             : }
     320             : 
     321             : NS_IMETHODIMP
     322           0 : OfflineCacheUpdateChild::AddObserver(nsIOfflineCacheUpdateObserver *aObserver,
     323             :                                   bool aHoldWeak)
     324             : {
     325           0 :     LOG(("OfflineCacheUpdateChild::AddObserver [%p]", this));
     326             : 
     327           0 :     NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
     328             : 
     329           0 :     if (aHoldWeak) {
     330           0 :         nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(aObserver);
     331           0 :         mWeakObservers.AppendObject(weakRef);
     332             :     } else {
     333           0 :         mObservers.AppendObject(aObserver);
     334             :     }
     335             : 
     336           0 :     return NS_OK;
     337             : }
     338             : 
     339             : NS_IMETHODIMP
     340           0 : OfflineCacheUpdateChild::RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver)
     341             : {
     342           0 :     LOG(("OfflineCacheUpdateChild::RemoveObserver [%p]", this));
     343             : 
     344           0 :     NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
     345             : 
     346           0 :     for (int32_t i = 0; i < mWeakObservers.Count(); i++) {
     347             :         nsCOMPtr<nsIOfflineCacheUpdateObserver> observer =
     348           0 :             do_QueryReferent(mWeakObservers[i]);
     349           0 :         if (observer == aObserver) {
     350           0 :             mWeakObservers.RemoveObjectAt(i);
     351           0 :             return NS_OK;
     352             :         }
     353             :     }
     354             : 
     355           0 :     for (int32_t i = 0; i < mObservers.Count(); i++) {
     356           0 :         if (mObservers[i] == aObserver) {
     357           0 :             mObservers.RemoveObjectAt(i);
     358           0 :             return NS_OK;
     359             :         }
     360             :     }
     361             : 
     362           0 :     return NS_OK;
     363             : }
     364             : 
     365             : NS_IMETHODIMP
     366           0 : OfflineCacheUpdateChild::GetByteProgress(uint64_t * _result)
     367             : {
     368           0 :     NS_ENSURE_ARG(_result);
     369             : 
     370           0 :     *_result = mByteProgress;
     371           0 :     return NS_OK;
     372             : }
     373             : 
     374             : NS_IMETHODIMP
     375           0 : OfflineCacheUpdateChild::Schedule()
     376             : {
     377           0 :     LOG(("OfflineCacheUpdateChild::Schedule [%p]", this));
     378             : 
     379           0 :     NS_ASSERTION(mWindow, "Window must be provided to the offline cache update child");
     380             : 
     381           0 :     nsCOMPtr<nsPIDOMWindowInner> window = mWindow.forget();
     382           0 :     nsCOMPtr<nsIDocShell >docshell = window->GetDocShell();
     383           0 :     if (!docshell) {
     384           0 :       NS_WARNING("doc shell tree item is null");
     385           0 :       return NS_ERROR_FAILURE;
     386             :     }
     387             : 
     388           0 :     nsCOMPtr<nsITabChild> tabchild = docshell->GetTabChild();
     389             :     // because owner implements nsITabChild, we can assume that it is
     390             :     // the one and only TabChild.
     391           0 :     TabChild* child = tabchild ? static_cast<TabChild*>(tabchild.get()) : nullptr;
     392             : 
     393           0 :     if (MissingRequiredTabChild(child, "offlinecacheupdate")) {
     394           0 :       return NS_ERROR_FAILURE;
     395             :     }
     396             : 
     397           0 :     URIParams manifestURI, documentURI;
     398           0 :     SerializeURI(mManifestURI, manifestURI);
     399           0 :     SerializeURI(mDocumentURI, documentURI);
     400             : 
     401           0 :     nsresult rv = NS_OK;
     402           0 :     PrincipalInfo loadingPrincipalInfo;
     403           0 :     rv = PrincipalToPrincipalInfo(mLoadingPrincipal,
     404           0 :                                   &loadingPrincipalInfo);
     405           0 :     NS_ENSURE_SUCCESS(rv, rv);
     406             : 
     407             :     nsCOMPtr<nsIObserverService> observerService =
     408           0 :       mozilla::services::GetObserverService();
     409           0 :     if (observerService) {
     410           0 :       LOG(("Calling offline-cache-update-added"));
     411           0 :       observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
     412             :                                        "offline-cache-update-added",
     413           0 :                                        nullptr);
     414           0 :       LOG(("Done offline-cache-update-added"));
     415             :     }
     416             : 
     417             :     // mDocument is non-null if both:
     418             :     // 1. this update was initiated by a document that referred a manifest
     419             :     // 2. the document has not already been loaded from the application cache
     420             :     // This tells the update to cache this document even in case the manifest
     421             :     // has not been changed since the last fetch.
     422             :     // See also nsOfflineCacheUpdate::ScheduleImplicit.
     423           0 :     bool stickDocument = mDocument != nullptr; 
     424             : 
     425             :     // Need to addref ourself here, because the IPC stack doesn't hold
     426             :     // a reference to us. Will be released in RecvFinish() that identifies 
     427             :     // the work has been done.
     428           0 :     ContentChild::GetSingleton()->SendPOfflineCacheUpdateConstructor(
     429             :         this, manifestURI, documentURI, loadingPrincipalInfo,
     430           0 :         stickDocument);
     431             : 
     432             :     // ContentChild::DeallocPOfflineCacheUpdate will release this.
     433           0 :     NS_ADDREF_THIS();
     434             : 
     435           0 :     return NS_OK;
     436             : }
     437             : 
     438             : mozilla::ipc::IPCResult
     439           0 : OfflineCacheUpdateChild::RecvAssociateDocuments(const nsCString &cacheGroupId,
     440             :                                                   const nsCString &cacheClientId)
     441             : {
     442           0 :     LOG(("OfflineCacheUpdateChild::RecvAssociateDocuments [%p, cache=%s]", this, cacheClientId.get()));
     443             : 
     444             :     nsresult rv;
     445             : 
     446             :     nsCOMPtr<nsIApplicationCache> cache =
     447           0 :         do_CreateInstance(NS_APPLICATIONCACHE_CONTRACTID, &rv);
     448           0 :     if (NS_FAILED(rv))
     449           0 :       return IPC_OK();
     450             : 
     451           0 :     cache->InitAsHandle(cacheGroupId, cacheClientId);
     452             : 
     453           0 :     if (mDocument) {
     454           0 :         AssociateDocument(mDocument, cache);
     455             :     }
     456             : 
     457           0 :     nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
     458           0 :     GatherObservers(observers);
     459             : 
     460           0 :     for (int32_t i = 0; i < observers.Count(); i++)
     461           0 :         observers[i]->ApplicationCacheAvailable(cache);
     462             : 
     463           0 :     return IPC_OK();
     464             : }
     465             : 
     466             : mozilla::ipc::IPCResult
     467           0 : OfflineCacheUpdateChild::RecvNotifyStateEvent(const uint32_t &event,
     468             :                                               const uint64_t &byteProgress)
     469             : {
     470           0 :     LOG(("OfflineCacheUpdateChild::RecvNotifyStateEvent [%p]", this));
     471             : 
     472           0 :     mByteProgress = byteProgress;
     473             : 
     474             :     // Convert the public observer state to our internal state
     475           0 :     switch (event) {
     476             :         case nsIOfflineCacheUpdateObserver::STATE_CHECKING:
     477           0 :             mState = STATE_CHECKING;
     478           0 :             break;
     479             : 
     480             :         case nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING:
     481           0 :             mState = STATE_DOWNLOADING;
     482           0 :             break;
     483             : 
     484             :         default:
     485           0 :             break;
     486             :     }
     487             : 
     488           0 :     nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
     489           0 :     GatherObservers(observers);
     490             : 
     491           0 :     for (int32_t i = 0; i < observers.Count(); i++)
     492           0 :         observers[i]->UpdateStateChanged(this, event);
     493             : 
     494           0 :     return IPC_OK();
     495             : }
     496             : 
     497             : mozilla::ipc::IPCResult
     498           0 : OfflineCacheUpdateChild::RecvFinish(const bool &succeeded,
     499             :                                     const bool &isUpgrade)
     500             : {
     501           0 :     LOG(("OfflineCacheUpdateChild::RecvFinish [%p]", this));
     502             : 
     503           0 :     RefPtr<OfflineCacheUpdateChild> kungFuDeathGrip(this);
     504             : 
     505           0 :     mState = STATE_FINISHED;
     506           0 :     mSucceeded = succeeded;
     507           0 :     mIsUpgrade = isUpgrade;
     508             : 
     509             :     nsCOMPtr<nsIObserverService> observerService =
     510           0 :       mozilla::services::GetObserverService();
     511           0 :     if (observerService) {
     512           0 :         LOG(("Calling offline-cache-update-completed"));
     513           0 :         observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
     514             :                                          "offline-cache-update-completed",
     515           0 :                                          nullptr);
     516           0 :         LOG(("Done offline-cache-update-completed"));
     517             :     }
     518             : 
     519             :     // This is by contract the last notification from the parent, release
     520             :     // us now. This is corresponding to AddRef in Schedule().
     521             :     // TabChild::DeallocPOfflineCacheUpdate will call Release.
     522           0 :     OfflineCacheUpdateChild::Send__delete__(this);
     523             : 
     524           0 :     return IPC_OK();
     525             : }
     526             : 
     527             : } // namespace docshell
     528             : } // namespace mozilla

Generated by: LCOV version 1.13