LCOV - code coverage report
Current view: directory - uriloader/prefetch - OfflineCacheUpdateChild.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 197 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

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

Generated by: LCOV version 1.7