Bug 744710 - Enable getting updates on how many bytes of an appcache update have been downloaded, r=michal
authorHonza Bambas <honzab.moz@firemni.cz>
Tue, 22 May 2012 22:12:40 +0200
changeset 96878 10b04214089d6f778bfa2e3a8fc875b25082cf3f
parent 96877 a67b67adbb2bcbf828caa20a1f4d756659d4af97
child 96879 530d57b9046156350d085d926d2f138f7dbdf2a9
push idunknown
push userunknown
push dateunknown
reviewersmichal
bugs744710
milestone15.0a1
Bug 744710 - Enable getting updates on how many bytes of an appcache update have been downloaded, r=michal
uriloader/prefetch/OfflineCacheUpdateChild.cpp
uriloader/prefetch/OfflineCacheUpdateChild.h
uriloader/prefetch/OfflineCacheUpdateGlue.h
uriloader/prefetch/OfflineCacheUpdateParent.cpp
uriloader/prefetch/POfflineCacheUpdate.ipdl
uriloader/prefetch/nsIOfflineCacheUpdate.idl
uriloader/prefetch/nsOfflineCacheUpdate.cpp
uriloader/prefetch/nsOfflineCacheUpdate.h
--- a/uriloader/prefetch/OfflineCacheUpdateChild.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateChild.cpp
@@ -73,16 +73,17 @@ OfflineCacheUpdateChild::RefcountHitZero
 // OfflineCacheUpdateChild <public>
 //-----------------------------------------------------------------------------
 
 OfflineCacheUpdateChild::OfflineCacheUpdateChild(nsIDOMWindow* aWindow)
     : mState(STATE_UNINITIALIZED)
     , mIsUpgrade(false)
     , mIPCActivated(false)
     , mWindow(aWindow)
+    , mByteProgress(0)
 {
 }
 
 OfflineCacheUpdateChild::~OfflineCacheUpdateChild()
 {
     LOG(("OfflineCacheUpdateChild::~OfflineCacheUpdateChild [%p]", this));
 }
 
@@ -336,16 +337,25 @@ OfflineCacheUpdateChild::RemoveObserver(
             return NS_OK;
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
+OfflineCacheUpdateChild::GetByteProgress(PRUint64 * _result)
+{
+    NS_ENSURE_ARG(_result);
+
+    *_result = mByteProgress;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 OfflineCacheUpdateChild::Schedule()
 {
     LOG(("OfflineCacheUpdateChild::Schedule [%p]", this));
 
     NS_ASSERTION(mWindow, "Window must be provided to the offline cache update child");
 
     nsCOMPtr<nsPIDOMWindow> piWindow = 
         do_QueryInterface(mWindow);
@@ -430,20 +440,23 @@ OfflineCacheUpdateChild::RecvAssociateDo
 
     for (PRInt32 i = 0; i < observers.Count(); i++)
         observers[i]->ApplicationCacheAvailable(cache);
 
     return true;
 }
 
 bool
-OfflineCacheUpdateChild::RecvNotifyStateEvent(const PRUint32 &event)
+OfflineCacheUpdateChild::RecvNotifyStateEvent(const PRUint32 &event,
+                                              const PRUint64 &byteProgress)
 {
     LOG(("OfflineCacheUpdateChild::RecvNotifyStateEvent [%p]", this));
 
+    mByteProgress = byteProgress;
+
     // Convert the public observer state to our internal state
     switch (event) {
         case nsIOfflineCacheUpdateObserver::STATE_CHECKING:
             mState = STATE_CHECKING;
             break;
 
         case nsIOfflineCacheUpdateObserver::STATE_DOWNLOADING:
             mState = STATE_DOWNLOADING;
--- a/uriloader/prefetch/OfflineCacheUpdateChild.h
+++ b/uriloader/prefetch/OfflineCacheUpdateChild.h
@@ -18,24 +18,25 @@
 #include "nsIURI.h"
 #include "nsString.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 namespace docshell {
 
 class OfflineCacheUpdateChild : public nsIOfflineCacheUpdate
-                                , public POfflineCacheUpdateChild
+                              , public POfflineCacheUpdateChild
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOFFLINECACHEUPDATE
 
     virtual bool
-    RecvNotifyStateEvent(const PRUint32& stateEvent);
+    RecvNotifyStateEvent(const PRUint32& stateEvent,
+                         const PRUint64& byteProgress);
 
     virtual bool
     RecvAssociateDocuments(
             const nsCString& cacheGroupId,
             const nsCString& cacheClientId);
 
     virtual bool
     RecvFinish(const bool& succeded,
@@ -80,14 +81,16 @@ private:
     nsCOMArray<nsIOfflineCacheUpdateObserver> mObservers;
 
     /* Document that requested this update */
     nsCOMPtr<nsIDOMDocument> mDocument;
 
     /* Keep reference to the window that owns this update to call the
        parent offline cache update construcor */
     nsCOMPtr<nsIDOMWindow> mWindow;
+
+    PRUint64 mByteProgress;
 };
 
 }
 }
 
 #endif
--- a/uriloader/prefetch/OfflineCacheUpdateGlue.h
+++ b/uriloader/prefetch/OfflineCacheUpdateGlue.h
@@ -26,17 +26,18 @@ namespace docshell {
   NS_SCRIPTABLE NS_IMETHOD GetPartial(bool *aPartial) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetPartial(aPartial); } \
   NS_SCRIPTABLE NS_IMETHOD GetIsUpgrade(bool *aIsUpgrade) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsUpgrade(aIsUpgrade); } \
   NS_SCRIPTABLE NS_IMETHOD GetUpdateDomain(nsACString & aUpdateDomain) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUpdateDomain(aUpdateDomain); } \
   NS_SCRIPTABLE NS_IMETHOD GetManifestURI(nsIURI **aManifestURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetManifestURI(aManifestURI); } \
   NS_SCRIPTABLE NS_IMETHOD GetSucceeded(bool *aSucceeded) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetSucceeded(aSucceeded); } \
   NS_SCRIPTABLE NS_IMETHOD InitPartial(nsIURI *aManifestURI, const nsACString & aClientID, nsIURI *aDocumentURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->InitPartial(aManifestURI, aClientID, aDocumentURI); } \
   NS_SCRIPTABLE NS_IMETHOD AddDynamicURI(nsIURI *aURI) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddDynamicURI(aURI); } \
   NS_SCRIPTABLE NS_IMETHOD AddObserver(nsIOfflineCacheUpdateObserver *aObserver, bool aHoldWeak) { return !_to ? NS_ERROR_NULL_POINTER : _to->AddObserver(aObserver, aHoldWeak); } \
-  NS_SCRIPTABLE NS_IMETHOD RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver) { return !_to ? NS_ERROR_NULL_POINTER : _to->RemoveObserver(aObserver); } 
+  NS_SCRIPTABLE NS_IMETHOD RemoveObserver(nsIOfflineCacheUpdateObserver *aObserver) { return !_to ? NS_ERROR_NULL_POINTER : _to->RemoveObserver(aObserver); } \
+  NS_SCRIPTABLE NS_IMETHOD GetByteProgress(PRUint64 * _result) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetByteProgress(_result); }
 
 class OfflineCacheUpdateGlue : public nsSupportsWeakReference
                                , public nsIOfflineCacheUpdate
                                , public nsIOfflineCacheUpdateObserver
 {
 public:
     NS_DECL_ISUPPORTS
 
--- a/uriloader/prefetch/OfflineCacheUpdateParent.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateParent.cpp
@@ -104,17 +104,19 @@ OfflineCacheUpdateParent::Schedule(const
 NS_IMETHODIMP
 OfflineCacheUpdateParent::UpdateStateChanged(nsIOfflineCacheUpdate *aUpdate, PRUint32 state)
 {
     if (mIPCClosed)
         return NS_ERROR_UNEXPECTED;
 
     LOG(("OfflineCacheUpdateParent::StateEvent [%p]", this));
 
-    SendNotifyStateEvent(state);
+    PRUint64 byteProgress;
+    aUpdate->GetByteProgress(&byteProgress);
+    SendNotifyStateEvent(state, byteProgress);
 
     if (state == nsIOfflineCacheUpdateObserver::STATE_FINISHED) {
         // Tell the child the particulars after the update has finished.
         // Sending the Finish event will release the child side of the protocol
         // and notify "offline-cache-update-completed" on the child process.
         bool isUpgrade;
         aUpdate->GetIsUpgrade(&isUpgrade);
         bool succeeded;
--- a/uriloader/prefetch/POfflineCacheUpdate.ipdl
+++ b/uriloader/prefetch/POfflineCacheUpdate.ipdl
@@ -18,15 +18,15 @@ namespace docshell {
 protocol POfflineCacheUpdate
 {
   manager PBrowser;
 
 parent:
   __delete__();
 
 child:
-  NotifyStateEvent(PRUint32 stateEvent);
+  NotifyStateEvent(PRUint32 stateEvent, PRUint64 byteProgress);
   AssociateDocuments(nsCString cacheGroupId, nsCString cacheClientId);
   Finish(bool succeded, bool isUpgrate);
 };
 
 }
 }
--- a/uriloader/prefetch/nsIOfflineCacheUpdate.idl
+++ b/uriloader/prefetch/nsIOfflineCacheUpdate.idl
@@ -19,16 +19,17 @@ interface nsIApplicationCache;
 interface nsIOfflineCacheUpdateObserver : nsISupports {
   const unsigned long STATE_ERROR = 1;
   const unsigned long STATE_CHECKING = 2;
   const unsigned long STATE_NOUPDATE = 3;
   const unsigned long STATE_OBSOLETE = 4;
   const unsigned long STATE_DOWNLOADING = 5;
   const unsigned long STATE_ITEMSTARTED = 6;
   const unsigned long STATE_ITEMCOMPLETED = 7;
+  const unsigned long STATE_ITEMPROGRESS = 8;
   const unsigned long STATE_FINISHED = 10;
 
   /**
    * aUpdate has changed its state.
    *
    * @param aUpdate
    *        The nsIOfflineCacheUpdate being processed.
    * @param event
@@ -55,17 +56,17 @@ interface nsIOfflineCacheUpdateObserver 
  * Each update object maintains a list of nsIDOMLoadStatus items for the
  * resources it is updating.  The list of these items will be available
  * after the object is scheduled.
  *
  * One update object will be updating at a time.  The active object will
  * load its items one by one, sending itemCompleted() to any registered
  * observers.
  */
-[scriptable, uuid(24605d81-8cf9-4021-8575-7f39aacbf31a)]
+[scriptable, uuid(2FA574B8-AE62-426b-BE95-08E6AA957455)]
 interface nsIOfflineCacheUpdate : nsISupports {
   /**
    * Fetch the status of the running update.  This will return a value
    * defined in nsIDOMOfflineResourceList.
    */
   readonly attribute unsigned short status;
 
   /**
@@ -149,16 +150,21 @@ interface nsIOfflineCacheUpdate : nsISup
 
   /**
    * Remove an observer from the update.
    *
    * @param aObserver
    *        the observer to remove.
    */
   void removeObserver(in nsIOfflineCacheUpdateObserver aObserver);
+
+  /**
+   * Return the number of bytes downloaded so far
+   */
+  readonly attribute PRUint64 byteProgress;
 };
 
 [scriptable, uuid(6fd2030f-7b00-4102-a0e3-d73078821eb1)]
 interface nsIOfflineCacheUpdateService : nsISupports {
     /**
      * Constants for the offline-app permission.
      *
      * XXX: This isn't a great place for this, but it's really the only
--- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
@@ -397,16 +397,19 @@ nsOfflineCacheUpdateItem::OnDataAvailabl
                                           PRUint32 aOffset,
                                           PRUint32 aCount)
 {
     PRUint32 bytesRead = 0;
     aStream->ReadSegments(NS_DiscardSegment, nsnull, aCount, &bytesRead);
     mBytesRead += bytesRead;
     LOG(("loaded %u bytes into offline cache [offset=%u]\n",
          bytesRead, aOffset));
+
+    mUpdate->OnByteProgress(bytesRead);
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOfflineCacheUpdateItem::OnStopRequest(nsIRequest *aRequest,
                                         nsISupports *aContext,
                                         nsresult aStatus)
 {
@@ -414,16 +417,17 @@ nsOfflineCacheUpdateItem::OnStopRequest(
 
     mState = nsIDOMLoadStatus::LOADED;
 
     if (mBytesRead == 0 && aStatus == NS_OK) {
         // we didn't need to read (because LOAD_ONLY_IF_MODIFIED was
         // specified), but the object should report loadedSize as if it
         // did.
         mChannel->GetContentLength(&mBytesRead);
+        mUpdate->OnByteProgress(mBytesRead);
     }
 
     // We need to notify the update that the load is complete, but we
     // want to give the channel a chance to close the cache entries.
     NS_DispatchToCurrentThread(this);
 
     return NS_OK;
 }
@@ -1543,16 +1547,17 @@ nsOfflineCacheUpdate::Begin()
                                               mDocumentURI,
                                               mPreviousApplicationCache,
                                               mClientID);
     if (!mManifestItem) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     mState = STATE_CHECKING;
+    mByteProgress = 0;
     NotifyState(nsIOfflineCacheUpdateObserver::STATE_CHECKING);
 
     nsresult rv = mManifestItem->OpenChannel();
     if (NS_FAILED(rv)) {
         LoadCompleted();
     }
 
     return NS_OK;
@@ -1748,16 +1753,23 @@ nsOfflineCacheUpdate::UpdateFinished(nsO
     mImplicitUpdate = nsnull;
 
     NotifyState(nsIOfflineCacheUpdateObserver::STATE_NOUPDATE);
     Finish();
 
     return NS_OK;
 }
 
+void
+nsOfflineCacheUpdate::OnByteProgress(PRUint64 byteIncrement)
+{
+    mByteProgress += byteIncrement;
+    NotifyState(nsIOfflineCacheUpdateObserver::STATE_ITEMPROGRESS);
+}
+
 nsresult
 nsOfflineCacheUpdate::ScheduleImplicit()
 {
     if (mDocumentURIs.Count() == 0)
         return NS_OK;
 
     nsresult rv;
 
@@ -2080,16 +2092,24 @@ nsOfflineCacheUpdate::RemoveObserver(nsI
             mObservers.RemoveObjectAt(i);
             return NS_OK;
         }
     }
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsOfflineCacheUpdate::GetByteProgress(PRUint64 * _result)
+{
+    NS_ENSURE_ARG(_result);
+
+    *_result = mByteProgress;
+    return NS_OK;
+}
 
 NS_IMETHODIMP
 nsOfflineCacheUpdate::Schedule()
 {
     LOG(("nsOfflineCacheUpdate::Schedule [%p]", this));
 
     nsOfflineCacheUpdateService* service =
         nsOfflineCacheUpdateService::EnsureService();
--- a/uriloader/prefetch/nsOfflineCacheUpdate.h
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.h
@@ -200,16 +200,20 @@ public:
     void ManifestCheckCompleted(nsresult aStatus,
                                 const nsCString &aManifestHash);
     void StickDocument(nsIURI *aDocumentURI);
 
     void SetOwner(nsOfflineCacheUpdateOwner *aOwner);
 
     virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate);
 
+protected:
+    friend class nsOfflineCacheUpdateItem;
+    void OnByteProgress(PRUint64 byteIncrement);
+
 private:
     nsresult HandleManifest(bool *aDoUpdate);
     nsresult AddURI(nsIURI *aURI, PRUint32 aItemType);
 
     nsresult ProcessNextURI();
 
     // Adds items from the previous cache witha type matching aType.
     // If namespaceFilter is non-null, only items matching the
@@ -272,16 +276,18 @@ private:
 
     /* Whena an entry for a pinned app is retried, retries count is
      * increaded. */
     PRUint32 mPinnedEntryRetriesCount;
 
     nsRefPtr<nsOfflineCacheUpdate> mImplicitUpdate;
 
     bool                           mPinned;
+
+    PRUint64                       mByteProgress;
 };
 
 class nsOfflineCacheUpdateService : public nsIOfflineCacheUpdateService
                                   , public nsIObserver
                                   , public nsOfflineCacheUpdateOwner
                                   , public nsSupportsWeakReference
 {
 public: