Bug 590242 - Do not open omnijar 3x r=mwu, sr=bsmedberg, a=beltzner
authorTaras Glek <tglek@mozilla.com>
Thu, 09 Sep 2010 14:01:00 -0700
changeset 52345 6b5f659829765728721e7d79750a8340754e98f4
parent 52344 a0a74e68e82a06a25bcfa27d75af1a59ca9afeb0
child 52346 7ada91b32a82e2eb184495ae29a8131e5458b292
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu, bsmedberg, beltzner
bugs590242
milestone2.0b6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 590242 - Do not open omnijar 3x r=mwu, sr=bsmedberg, a=beltzner
modules/libjar/nsJAR.cpp
modules/libjar/nsJAR.h
modules/libjar/nsJARInputStream.cpp
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -42,16 +42,17 @@
  * ***** END LICENSE BLOCK ***** */
 #include <string.h>
 #include "nsJARInputStream.h"
 #include "nsJAR.h"
 #include "nsILocalFile.h"
 #include "nsIConsoleService.h"
 #include "nsICryptoHash.h"
 #include "prprf.h"
+#include "mozilla/Omnijar.h"
 
 #ifdef XP_UNIX
   #include <sys/stat.h>
 #elif defined (XP_WIN) || defined(XP_OS2)
   #include <io.h>
 #endif
 
 //----------------------------------------------
@@ -111,17 +112,18 @@ static PRBool
 DeleteManifestEntry(nsHashKey* aKey, void* aData, void* closure)
 {
 //-- deletes an entry in  mManifestData.
   delete (nsJARManifestItem*)aData;
   return PR_TRUE;
 }
 
 // The following initialization makes a guess of 10 entries per jarfile.
-nsJAR::nsJAR(): mManifestData(nsnull, nsnull, DeleteManifestEntry, nsnull, 10),
+nsJAR::nsJAR(): mZip(new nsZipArchive()),
+                mManifestData(nsnull, nsnull, DeleteManifestEntry, nsnull, 10),
                 mParsedManifest(PR_FALSE),
                 mGlobalStatus(JAR_MANIFEST_NOT_PARSED),
                 mReleaseTime(PR_INTERVAL_NO_TIMEOUT), 
                 mCache(nsnull), 
                 mLock(nsnull),
                 mTotalItemsInManifest(0)
 {
 }
@@ -164,18 +166,28 @@ nsJAR::Open(nsIFile* zipFile)
 {
   NS_ENSURE_ARG_POINTER(zipFile);
   if (mLock) return NS_ERROR_FAILURE; // Already open!
 
   mZipFile = zipFile;
 
   mLock = PR_NewLock();
   NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
-
-  return mZip.OpenArchive(zipFile);
+  
+#ifdef MOZ_OMNIJAR
+  // The omnijar is special, it is opened early on and closed late
+  // this avoids reopening it
+  PRBool equals;
+  nsresult rv = zipFile->Equals(mozilla::OmnijarPath(), &equals);
+  if (NS_SUCCEEDED(rv) && equals) {
+    mZip = mozilla::OmnijarReader();
+    return NS_OK;
+  }
+#endif
+  return mZip->OpenArchive(zipFile);
 }
 
 NS_IMETHODIMP
 nsJAR::OpenInner(nsIZipReader *aZipReader, const char *aZipEntry)
 {
   NS_ENSURE_ARG_POINTER(aZipReader);
   NS_ENSURE_ARG_POINTER(aZipEntry);
   if (mLock) return NS_ERROR_FAILURE; // Already open!
@@ -184,22 +196,22 @@ nsJAR::OpenInner(nsIZipReader *aZipReade
   NS_ENSURE_SUCCESS(rv, rv);
 
   mLock = PR_NewLock();
   NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
 
   mOuterZipEntry.Assign(aZipEntry);
 
   nsRefPtr<nsZipHandle> handle;
-  rv = nsZipHandle::Init(&static_cast<nsJAR*>(aZipReader)->mZip, aZipEntry,
+  rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip.get(), aZipEntry,
                          getter_AddRefs(handle));
   if (NS_FAILED(rv))
     return rv;
 
-  return mZip.OpenArchive(handle);
+  return mZip->OpenArchive(handle);
 }
 
 NS_IMETHODIMP
 nsJAR::GetFile(nsIFile* *result)
 {
   *result = mZipFile;
   NS_IF_ADDREF(*result);
   return NS_OK;
@@ -214,37 +226,44 @@ nsJAR::Close()
   }
 
   mParsedManifest = PR_FALSE;
   mManifestData.Reset();
   mGlobalStatus = JAR_MANIFEST_NOT_PARSED;
   mTotalItemsInManifest = 0;
   mOuterZipEntry.Truncate(0);
 
-  return mZip.CloseArchive();
+#ifdef MOZ_OMNIJAR
+  if (mZip == mozilla::OmnijarReader()) {
+    mZip.forget();
+    mZip = new nsZipArchive();
+    return NS_OK;
+  }
+#endif
+  return mZip->CloseArchive();
 }
 
 NS_IMETHODIMP
 nsJAR::Test(const char *aEntryName)
 {
-  return mZip.Test(aEntryName);
+  return mZip->Test(aEntryName);
 }
 
 NS_IMETHODIMP
 nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
 {
   // nsZipArchive and zlib are not thread safe
   // we need to use a lock to prevent bug #51267
   nsAutoLock lock(mLock);
 
   nsresult rv;
   nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(outFile, &rv);
   if (NS_FAILED(rv)) return rv;
 
-  nsZipItem *item = mZip.GetItem(zipEntry);
+  nsZipItem *item = mZip->GetItem(zipEntry);
   NS_ENSURE_TRUE(item, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
   // Remove existing file or directory so we set permissions correctly.
   // If it's a directory that already exists and contains files, throw
   // an exception and return.
 
   //XXX Bug 332139:
   //XXX If we guarantee that rv in the case of a non-empty directory
@@ -269,54 +288,54 @@ nsJAR::Extract(const char *zipEntry, nsI
     rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, item->Mode(), &fd);
     if (NS_FAILED(rv)) return rv;
 
     // ExtractFile also closes the fd handle and resolves the symlink if needed
     nsCAutoString path;
     rv = outFile->GetNativePath(path);
     if (NS_FAILED(rv)) return rv;
 
-    rv = mZip.ExtractFile(item, path.get(), fd);
+    rv = mZip->ExtractFile(item, path.get(), fd);
   }
   if (NS_FAILED(rv)) return rv;
 
   // nsIFile needs milliseconds, while prtime is in microseconds.
   // non-fatal if this fails, ignore errors
   outFile->SetLastModifiedTime(item->LastModTime() / PR_USEC_PER_MSEC);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsJAR::GetEntry(const char *aEntryName, nsIZipEntry* *result)
 {
-  nsZipItem* zipItem = mZip.GetItem(aEntryName);
+  nsZipItem* zipItem = mZip->GetItem(aEntryName);
   NS_ENSURE_TRUE(zipItem, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
   nsJARItem* jarItem = new nsJARItem(zipItem);
   NS_ENSURE_TRUE(jarItem, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(*result = jarItem);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJAR::HasEntry(const nsACString &aEntryName, PRBool *result)
 {
-  *result = mZip.GetItem(PromiseFlatCString(aEntryName).get()) != nsnull;
+  *result = mZip->GetItem(PromiseFlatCString(aEntryName).get()) != nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJAR::FindEntries(const char *aPattern, nsIUTF8StringEnumerator **result)
 {
   NS_ENSURE_ARG_POINTER(result);
 
   nsZipFind *find;
-  nsresult rv = mZip.FindInit(aPattern, &find);
+  nsresult rv = mZip->FindInit(aPattern, &find);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIUTF8StringEnumerator *zipEnum = new nsJAREnumerator(find);
   if (!zipEnum) {
     delete find;
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
@@ -336,17 +355,17 @@ nsJAR::GetInputStreamWithSpec(const nsAC
 {
   NS_ENSURE_ARG_POINTER(aEntryName);
   NS_ENSURE_ARG_POINTER(result);
 
   // Watch out for the jar:foo.zip!/ (aDir is empty) top-level special case!
   nsZipItem *item = nsnull;
   if (*aEntryName) {
     // First check if item exists in jar
-    item = mZip.GetItem(aEntryName);
+    item = mZip->GetItem(aEntryName);
     if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
   }
   nsJARInputStream* jis = new nsJARInputStream();
   // addref now so we can call InitFile/InitDirectory()
   NS_ENSURE_TRUE(jis, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(*result = jis);
 
   nsresult rv = NS_OK;
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -128,17 +128,17 @@ class nsJAR : public nsIZipReader
     void SetZipReaderCache(nsZipReaderCache* cache) {
       mCache = cache;
     }
 
   protected:
     //-- Private data members
     nsCOMPtr<nsIFile>        mZipFile;        // The zip/jar file on disk
     nsCString                mOuterZipEntry;  // The entry in the zip this zip is reading from
-    nsZipArchive             mZip;            // The underlying zip archive
+    nsAutoPtr<nsZipArchive>  mZip;            // The underlying zip archive
     nsObjectHashtable        mManifestData;   // Stores metadata for each entry
     PRBool                   mParsedManifest; // True if manifest has been parsed
     nsCOMPtr<nsIPrincipal>   mPrincipal;      // The entity which signed this file
     PRInt16                  mGlobalStatus;   // Global signature verification status
     PRIntervalTime           mReleaseTime;    // used by nsZipReaderCache for flushing entries
     nsZipReaderCache*        mCache;          // if cached, this points to the cache it's contained in
     PRLock*                  mLock;	
     PRInt64                  mMtime;
--- a/modules/libjar/nsJARInputStream.cpp
+++ b/modules/libjar/nsJARInputStream.cpp
@@ -82,18 +82,18 @@ nsJARInputStream::InitFile(nsJAR *aJar, 
            mOutCrc = crc32(0L, Z_NULL, 0);
            break;
 
        default:
            return NS_ERROR_NOT_IMPLEMENTED;
     }
    
     // Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
-    mFd = aJar->mZip.GetFD();
-    mZs.next_in = (Bytef *)aJar->mZip.GetData(item);
+    mFd = aJar->mZip->GetFD();
+    mZs.next_in = (Bytef *)aJar->mZip->GetData(item);
     if (!mZs.next_in)
         return NS_ERROR_FILE_CORRUPTED;
     mZs.avail_in = item->Size();
     mOutSize = item->RealSize();
     mZs.total_out = 0;
     return NS_OK;
 }
 
@@ -142,17 +142,17 @@ nsJARInputStream::InitDirectory(nsJAR* a
                 // fall through
             default:
                 escDirName.Append(*curr);
         }
         ++curr;
     }
     nsCAutoString pattern = escDirName + NS_LITERAL_CSTRING("?*~") +
                             escDirName + NS_LITERAL_CSTRING("?*/?*");
-    rv = mJar->mZip.FindInit(pattern.get(), &find);
+    rv = mJar->mZip->FindInit(pattern.get(), &find);
     if (NS_FAILED(rv)) return rv;
 
     const char *name;
     PRUint16 nameLen;
     while ((rv = find->FindNext( &name, &nameLen )) == NS_OK) {
         // Must copy, to make it zero-terminated
         mArray.AppendElement(nsCString(name,nameLen));
     }
@@ -336,17 +336,17 @@ nsJARInputStream::ReadDirectory(char* aB
 
         for ( ;aCount > mBuffer.Length(); mArrPos++) {
             // have we consumed all the directory contents?
             if (arrayLen <= mArrPos)
                 break;
 
             const char * entryName = mArray[mArrPos].get();
             PRUint32 entryNameLen = mArray[mArrPos].Length();
-            nsZipItem* ze = mJar->mZip.GetItem(entryName);
+            nsZipItem* ze = mJar->mZip->GetItem(entryName);
             NS_ENSURE_TRUE(ze, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
             // Last Modified Time
             PRExplodedTime tm;
             PR_ExplodeTime(ze->LastModTime(), PR_GMTParameters, &tm);
             char itemLastModTime[65];
             PR_FormatTimeUSEnglish(itemLastModTime,
                                    sizeof(itemLastModTime),