Bug 1265621 - Expose outer zip readers in Omnijar::GetReader; r=froydnj
authorJim Chen <nchen@mozilla.com>
Thu, 28 Apr 2016 16:07:02 -0400
changeset 357652 370e94b2ac056add0be2153201bdf30386438351
parent 357651 499b7bf811b3b4d307ea14dae1f3660b219432a5
child 357653 c4aa1cda7cd7ef05c6cbb293ababa4d6e47d7ea2
push id16816
push userbmo:gasolin@mozilla.com
push dateFri, 29 Apr 2016 03:33:20 +0000
reviewersfroydnj
bugs1265621
milestone49.0a1
Bug 1265621 - Expose outer zip readers in Omnijar::GetReader; r=froydnj Previously, Omnijar::GetReader(nsIFile*) returned nullptr when using nested jars. This patch makes it return the outer jar reader in that case, so we don't end up opening the outer jar file again.
xpcom/build/Omnijar.cpp
xpcom/build/Omnijar.h
--- a/xpcom/build/Omnijar.cpp
+++ b/xpcom/build/Omnijar.cpp
@@ -11,33 +11,37 @@
 #include "nsIFile.h"
 #include "nsZipArchive.h"
 #include "nsNetUtil.h"
 
 namespace mozilla {
 
 StaticRefPtr<nsIFile> Omnijar::sPath[2];
 StaticRefPtr<nsZipArchive> Omnijar::sReader[2];
+StaticRefPtr<nsZipArchive> Omnijar::sOuterReader[2];
 bool Omnijar::sInitialized = false;
 bool Omnijar::sIsUnified = false;
-bool Omnijar::sIsNested[2] = { false, false };
 
 static const char* sProp[2] = {
   NS_GRE_DIR, NS_XPCOM_CURRENT_PROCESS_DIR
 };
 
 #define SPROP(Type) ((Type == mozilla::Omnijar::GRE) ? sProp[GRE] : sProp[APP])
 
 void
 Omnijar::CleanUpOne(Type aType)
 {
   if (sReader[aType]) {
     sReader[aType]->CloseArchive();
     sReader[aType] = nullptr;
   }
+  if (sOuterReader[aType]) {
+    sOuterReader[aType]->CloseArchive();
+    sOuterReader[aType] = nullptr;
+  }
   sPath[aType] = nullptr;
 }
 
 void
 Omnijar::InitOne(nsIFile* aPath, Type aType)
 {
   nsCOMPtr<nsIFile> file;
   if (aPath) {
@@ -79,28 +83,30 @@ Omnijar::InitOne(nsIFile* aPath, Type aT
     return;
   }
 
   RefPtr<nsZipArchive> zipReader = new nsZipArchive();
   if (NS_FAILED(zipReader->OpenArchive(file))) {
     return;
   }
 
+  RefPtr<nsZipArchive> outerReader;
   RefPtr<nsZipHandle> handle;
   if (NS_SUCCEEDED(nsZipHandle::Init(zipReader, NS_STRINGIFY(OMNIJAR_NAME),
                                      getter_AddRefs(handle)))) {
+    outerReader = zipReader;
     zipReader = new nsZipArchive();
     if (NS_FAILED(zipReader->OpenArchive(handle))) {
       return;
     }
-    sIsNested[aType] = true;
   }
 
   CleanUpOne(aType);
   sReader[aType] = zipReader;
+  sOuterReader[aType] = outerReader;
   sPath[aType] = file;
 }
 
 void
 Omnijar::Init(nsIFile* aGrePath, nsIFile* aAppPath)
 {
   InitOne(aGrePath, GRE);
   InitOne(aAppPath, APP);
@@ -118,26 +124,26 @@ Omnijar::CleanUp()
 already_AddRefed<nsZipArchive>
 Omnijar::GetReader(nsIFile* aPath)
 {
   MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
 
   bool equals;
   nsresult rv;
 
-  if (sPath[GRE] && !sIsNested[GRE]) {
+  if (sPath[GRE]) {
     rv = sPath[GRE]->Equals(aPath, &equals);
     if (NS_SUCCEEDED(rv) && equals) {
-      return GetReader(GRE);
+      return IsNested(GRE) ? GetOuterReader(GRE) : GetReader(GRE);
     }
   }
-  if (sPath[APP] && !sIsNested[APP]) {
+  if (sPath[APP]) {
     rv = sPath[APP]->Equals(aPath, &equals);
     if (NS_SUCCEEDED(rv) && equals) {
-      return GetReader(APP);
+      return IsNested(APP) ? GetOuterReader(APP) : GetReader(APP);
     }
   }
   return nullptr;
 }
 
 nsresult
 Omnijar::GetURIString(Type aType, nsACString& aResult)
 {
@@ -153,22 +159,22 @@ Omnijar::GetURIString(Type aType, nsACSt
   nsAutoCString omniJarSpec;
   if (sPath[aType]) {
     nsresult rv = NS_GetURLSpecFromActualFile(sPath[aType], omniJarSpec);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     aResult = "jar:";
-    if (sIsNested[aType]) {
+    if (IsNested(aType)) {
       aResult += "jar:";
     }
     aResult += omniJarSpec;
     aResult += "!";
-    if (sIsNested[aType]) {
+    if (IsNested(aType)) {
       aResult += "/" NS_STRINGIFY(OMNIJAR_NAME) "!";
     }
   } else {
     nsCOMPtr<nsIFile> dir;
     nsDirectoryService::gService->Get(SPROP(aType), NS_GET_IID(nsIFile),
                                       getter_AddRefs(dir));
     nsresult rv = NS_GetURLSpecFromActualFile(dir, aResult);
     if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/xpcom/build/Omnijar.h
+++ b/xpcom/build/Omnijar.h
@@ -29,34 +29,61 @@ private:
   static StaticRefPtr<nsIFile> sPath[2];
 
   /**
    * Cached nsZipArchives for the corresponding sPath
    */
   static StaticRefPtr<nsZipArchive> sReader[2];
 
   /**
+   * Cached nsZipArchives for the outer jar, when using nested jars.
+   * Otherwise nullptr.
+   */
+  static StaticRefPtr<nsZipArchive> sOuterReader[2];
+
+  /**
    * Has Omnijar::Init() been called?
    */
   static bool sInitialized;
 
   /**
    * Is using unified GRE/APP jar?
    */
   static bool sIsUnified;
 
-  static bool sIsNested[2];
-
 public:
   enum Type
   {
     GRE = 0,
     APP = 1
   };
 
+private:
+  /**
+   * Returns whether we are using nested jars.
+   */
+  static inline bool IsNested(Type aType)
+  {
+    MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
+    return !!sOuterReader[aType];
+  }
+
+  /**
+   * Returns a nsZipArchive pointer for the outer jar file when using nested
+   * jars. Returns nullptr in the same cases GetPath() would, or if not using
+   * nested jars.
+   */
+  static inline already_AddRefed<nsZipArchive> GetOuterReader(Type aType)
+  {
+    MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
+    RefPtr<nsZipArchive> reader = sOuterReader[aType].get();
+    return reader.forget();
+  }
+
+public:
   /**
    * Returns whether SetBase has been called at least once with
    * a valid nsIFile
    */
   static inline bool IsInitialized() { return sInitialized; }
 
   /**
    * Initializes the Omnijar API with the given directory or file for GRE and