Bug 780145 - ArchiveReader doesn't unzip large files, r=jst
authorAndrea Marchesini <baku@mozilla.com>
Wed, 08 Aug 2012 11:11:15 -0700
changeset 107306 7e0466ba65c45490309046d9e63173ab68a3ec38
parent 107305 34ae2864bbd8cf109162c7b75595b63ceb4ee7c7
child 107307 e6fff75af75fe27c97120d6b27fb1f24269578b8
push idunknown
push userunknown
push dateunknown
reviewersjst
bugs780145
milestone17.0a1
Bug 780145 - ArchiveReader doesn't unzip large files, r=jst
dom/file/ArchiveEvent.cpp
dom/file/ArchiveEvent.h
dom/file/ArchiveReader.cpp
dom/file/ArchiveRequest.cpp
dom/file/ArchiveZipEvent.cpp
dom/file/ArchiveZipEvent.h
dom/file/ArchiveZipFile.cpp
dom/file/ArchiveZipFile.h
--- a/dom/file/ArchiveEvent.cpp
+++ b/dom/file/ArchiveEvent.cpp
@@ -8,18 +8,24 @@
 
 #include "nsContentUtils.h"
 #include "nsCExternalHandlerService.h"
 
 USING_FILE_NAMESPACE
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(ArchiveItem)
 
+ArchiveItem::ArchiveItem()
+{
+  MOZ_COUNT_CTOR(ArchiveItem);
+}
+
 ArchiveItem::~ArchiveItem()
 {
+  MOZ_COUNT_DTOR(ArchiveItem);
 }
 
 
 nsCString
 ArchiveItem::GetType()
 {
   return mType.IsEmpty() ? nsCString("binary/octet-stream") : mType;
 }
--- a/dom/file/ArchiveEvent.h
+++ b/dom/file/ArchiveEvent.h
@@ -19,16 +19,17 @@ BEGIN_FILE_NAMESPACE
 
 // This class contains all the info needed for a single item
 // It must contain the implementation of the File() method.
 class ArchiveItem : public nsISupports
 {
 public:
   NS_DECL_ISUPPORTS
 
+  ArchiveItem();
   virtual ~ArchiveItem();
 
   // Getter/Setter for the type
   virtual nsCString GetType();
   virtual void SetType(const nsCString& aType);
 
   // Getter for the filename
   virtual nsCString GetFilename() = 0;
--- a/dom/file/ArchiveReader.cpp
+++ b/dom/file/ArchiveReader.cpp
@@ -18,21 +18,23 @@
 
 USING_FILE_NAMESPACE
 
 ArchiveReader::ArchiveReader()
 : mBlob(nullptr),
   mWindow(nullptr),
   mStatus(NOT_STARTED)
 {
+  MOZ_COUNT_CTOR(ArchiveReader);
   nsLayoutStatics::AddRef();
 }
 
 ArchiveReader::~ArchiveReader()
 {
+  MOZ_COUNT_DTOR(ArchiveReader);
   nsLayoutStatics::Release();
 }
 
 NS_IMETHODIMP
 ArchiveReader::Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
--- a/dom/file/ArchiveRequest.cpp
+++ b/dom/file/ArchiveRequest.cpp
@@ -46,25 +46,27 @@ ArchiveRequestEvent::Run()
 
 /* ArchiveRequest */
 
 ArchiveRequest::ArchiveRequest(nsIDOMWindow* aWindow,
                                ArchiveReader* aReader)
 : DOMRequest(aWindow),
   mArchiveReader(aReader)
 {
+  MOZ_COUNT_CTOR(ArchiveRequest);
   nsLayoutStatics::AddRef();
 
   /* An event to make this request asynchronous: */
   nsRefPtr<ArchiveRequestEvent> event = new ArchiveRequestEvent(this);
   NS_DispatchToCurrentThread(event);
 }
 
 ArchiveRequest::~ArchiveRequest()
 {
+  MOZ_COUNT_DTOR(ArchiveRequest);
   nsLayoutStatics::Release();
 }
 
 nsresult
 ArchiveRequest::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
   aVisitor.mParentTarget = nullptr;
--- a/dom/file/ArchiveZipEvent.cpp
+++ b/dom/file/ArchiveZipEvent.cpp
@@ -17,16 +17,22 @@ USING_FILE_NAMESPACE
 #endif
 
 // ArchiveZipItem
 ArchiveZipItem::ArchiveZipItem(const char* aFilename,
                                ZipCentral& aCentralStruct)
 : mFilename(aFilename),
   mCentralStruct(aCentralStruct)
 {
+  MOZ_COUNT_CTOR(ArchiveZipItem);
+}
+
+ArchiveZipItem::~ArchiveZipItem()
+{
+  MOZ_COUNT_DTOR(ArchiveZipItem);
 }
 
 // Getter/Setter for the filename
 nsCString
 ArchiveZipItem::GetFilename()
 {
   return mFilename;
 }
--- a/dom/file/ArchiveZipEvent.h
+++ b/dom/file/ArchiveZipEvent.h
@@ -14,16 +14,17 @@
 
 BEGIN_FILE_NAMESPACE
 
 class ArchiveZipItem : public ArchiveItem
 {
 public:
   ArchiveZipItem(const char* aFilename,
                  ZipCentral& aCentralStruct);
+  virtual ~ArchiveZipItem();
 
   void SetFilename(const nsCString& aFilename);
   nsCString GetFilename();
 
   // From zipItem to DOMFile:
   virtual nsIDOMFile* File(ArchiveReader* aArchiveReader);
 
 public: // for the event
--- a/dom/file/ArchiveZipFile.cpp
+++ b/dom/file/ArchiveZipFile.cpp
@@ -25,21 +25,24 @@ public:
                      PRUint32 aStart,
                      PRUint32 aLength,
                      ZipCentral& aCentral)
   : mArchiveReader(aReader),
     mCentral(aCentral),
     mFilename(aFilename),
     mStart(aStart),
     mLength(aLength),
-    mRunning(false)
-  {}
+    mStatus(NotStarted)
+  {
+    MOZ_COUNT_CTOR(ArchiveInputStream);
+  }
 
-  ~ArchiveInputStream()
+  virtual ~ArchiveInputStream()
   {
+    MOZ_COUNT_DTOR(ArchiveInputStream);
     Close();
   }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
 
 private:
   nsresult Init();
@@ -48,17 +51,21 @@ private: // data
   nsRefPtr<ArchiveReader> mArchiveReader;
   ZipCentral mCentral;
   nsString mFilename;
   PRUint32 mStart;
   PRUint32 mLength;
 
   z_stream mZs;
 
-  bool mRunning;
+  enum {
+    NotStarted,
+    Started,
+    Done
+  } mStatus;
 
   struct {
     nsCOMPtr<nsIInputStream> inputStream;
     unsigned char input[ZIP_CHUNK];
     PRUint32 sizeToBeRead;
     bool compressed; // a zip file can contain stored or compressed files
   } mData;
 };
@@ -142,26 +149,25 @@ ArchiveInputStream::Init()
 
       if (ret == 0)
         return NS_ERROR_UNEXPECTED;
 
       done -= ret;
     }
   }
 
-  mRunning = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::Close()
 {
-  if (mRunning) {
+  if (mStatus != NotStarted) {
     inflateEnd(&mZs);
-    mRunning = false;
+    mStatus = NotStarted;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::Available(PRUint32* _retval)
 {
@@ -172,48 +178,57 @@ ArchiveInputStream::Available(PRUint32* 
 NS_IMETHODIMP
 ArchiveInputStream::Read(char* aBuffer,
                          PRUint32 aCount,
                          PRUint32* _retval)
 {
   NS_ENSURE_ARG_POINTER(aBuffer);
   NS_ENSURE_ARG_POINTER(_retval);
 
-  PRUint32 ret;
   nsresult rv;
 
   // This is the first time:
-  if (!mRunning) {
+  if (mStatus == NotStarted) {
+    mStatus = Started;
+
     rv = Init();
     if (rv != NS_OK)
       return rv;
+
+    // Let's set avail_out to -1 so we read something from the stream.
+    mZs.avail_out = (uInt)-1;
   }
 
   // Nothing more can be read
-  if (mData.sizeToBeRead == 0) {
+  if (mStatus == Done) {
     *_retval = 0;
     return NS_OK;
   }
 
   // Stored file:
   if (!mData.compressed)
   {
     rv = mData.inputStream->Read(aBuffer,
                                  (mData.sizeToBeRead > aCount ?
                                       aCount : mData.sizeToBeRead),
                                  _retval);
-    if (rv == NS_OK)
+    if (rv == NS_OK) {
       mData.sizeToBeRead -= *_retval;
 
+      if (mData.sizeToBeRead == 0)
+        mStatus = Done;
+    }
+
     return rv;
   }
 
   // We have nothing ready to be processed:
-  if (mZs.avail_out == 0)
+  if (mZs.avail_out != 0 && mData.sizeToBeRead != 0)
   {
+    PRUint32 ret;
     rv = mData.inputStream->Read((char*)mData.input,
                                  (mData.sizeToBeRead > sizeof(mData.input) ?
                                       sizeof(mData.input) : mData.sizeToBeRead),
                                  &ret);
     if (rv != NS_OK)
       return rv;
 
     // Terminator:
@@ -225,20 +240,23 @@ ArchiveInputStream::Read(char* aBuffer,
     mData.sizeToBeRead -= ret;
     mZs.avail_in = ret;
     mZs.next_in = mData.input;
   }
 
   mZs.avail_out = aCount;
   mZs.next_out = (unsigned char*)aBuffer;
 
-  ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
-  if (ret != Z_OK && ret != Z_STREAM_END)
+  int ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
+  if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END)
     return NS_ERROR_UNEXPECTED;
 
+  if (ret == Z_STREAM_END)
+    mStatus = Done;
+
   *_retval = aCount - mZs.avail_out;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::ReadSegments(nsWriteSegmentFun aWriter,
                                  void* aClosure,
                                  PRUint32 aCount,
--- a/dom/file/ArchiveZipFile.h
+++ b/dom/file/ArchiveZipFile.h
@@ -25,30 +25,37 @@ public:
                  ZipCentral& aCentral,
                  ArchiveReader* aReader)
   : nsDOMFileCC(aName, aContentType, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
+    MOZ_COUNT_CTOR(ArchiveZipFile);
   }
 
   ArchiveZipFile(const nsAString& aName,
                  const nsAString& aContentType,
                  PRUint64 aStart,
                  PRUint64 aLength,
                  ZipCentral& aCentral,
                  ArchiveReader* aReader)
   : nsDOMFileCC(aContentType, aStart, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
+    MOZ_COUNT_CTOR(ArchiveZipFile);
+  }
+
+  virtual ~ArchiveZipFile()
+  {
+    MOZ_COUNT_DTOR(ArchiveZipFile);
   }
 
   // Overrides:
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ArchiveZipFile, nsIDOMFile)