Bug 533038 - 1. Generalize manifest reading code and add api for reading manifests from jars, r=bsmedberg a=blocking-beta6
authorMichael Wu <mwu@mozilla.com>
Wed, 08 Sep 2010 20:37:11 -0700
changeset 52248 203419a57194e54853acb780adcbbb732d9fffe3
parent 52247 71989679784aeab3db7599c994ee9896bafa5f99
child 52249 4958e6add3c936fe32cffccfe6b2377c766cc9e8
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, blocking-beta6
bugs533038
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 533038 - 1. Generalize manifest reading code and add api for reading manifests from jars, r=bsmedberg a=blocking-beta6
chrome/src/nsChromeRegistry.h
chrome/src/nsChromeRegistryChrome.cpp
modules/libjar/nsZipArchive.h
xpcom/build/nsXULAppAPI.h
xpcom/components/Makefile.in
xpcom/components/ManifestParser.cpp
xpcom/components/ManifestParser.h
xpcom/components/nsComponentManager.cpp
xpcom/components/nsComponentManager.h
xpcom/components/nsManifestZIPLoader.cpp
xpcom/components/nsManifestZIPLoader.h
xpcom/tests/TestRegistrationOrder.cpp
xpcom/tests/regorder/core/component.manifest
xpcom/tests/regorder/core/component2.js
xpcom/tests/regorder/extension2.jar
--- a/chrome/src/nsChromeRegistry.h
+++ b/chrome/src/nsChromeRegistry.h
@@ -137,23 +137,21 @@ public:
   struct ManifestProcessingContext
   {
     ManifestProcessingContext(NSLocationType aType, nsILocalFile* aFile)
       : mType(aType)
       , mFile(aFile)
       , mPath(NULL)
     { }
 
-#ifdef MOZ_OMNIJAR
-    ManifestProcessingContext(NSLocationType aType, const char* aPath)
+    ManifestProcessingContext(NSLocationType aType, nsILocalFile* aFile, const char* aPath)
       : mType(aType)
-      , mFile(mozilla::OmnijarPath())
+      , mFile(aFile)
       , mPath(aPath)
     { }
-#endif
 
     ~ManifestProcessingContext()
     { }
 
     nsIURI* GetManifestURI();
     nsIXPConnect* GetXPConnect();
 
     already_AddRefed<nsIURI> ResolveURI(const char* uri);
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -73,18 +73,16 @@
 #include "nsIPrefService.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIVersionComparator.h"
 #include "nsIXPConnect.h"
 #include "nsIXULAppInfo.h"
 #include "nsIXULRuntime.h"
 
-#include "mozilla/Omnijar.h"
-
 #define UILOCALE_CMD_LINE_ARG "UILocale"
 
 #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
 #define SELECTED_LOCALE_PREF "general.useragent.locale"
 #define SELECTED_SKIN_PREF   "general.skins.selectedSkin"
 
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
@@ -783,32 +781,29 @@ nsChromeRegistry::ManifestProcessingCont
 {
   if (!mManifestURI) {
     nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
     if (!io) {
       NS_WARNING("No IO service trying to process chrome manifests");
       return NULL;
     }
 
-#ifdef MOZ_OMNIJAR
     if (mPath) {
       nsCOMPtr<nsIURI> fileURI;
       io->NewFileURI(mFile, getter_AddRefs(fileURI));
 
       nsCAutoString spec;
       fileURI->GetSpec(spec);
       spec.Insert(NS_LITERAL_CSTRING("jar:"), 0);
       spec.AppendLiteral("!/");
       spec.Append(mPath);
 
       NS_NewURI(getter_AddRefs(mManifestURI), spec, NULL, NULL, io);
     }
-    else
-#endif
-    {
+    else {
       io->NewFileURI(mFile, getter_AddRefs(mManifestURI));
     }
   }
   return mManifestURI;
 }
 
 nsIXPConnect*
 nsChromeRegistry::ManifestProcessingContext::GetXPConnect()
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -41,17 +41,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsZipArchive_h_
 #define nsZipArchive_h_
 
 #define ZIP_TABSIZE   256
 #define ZIP_BUFLEN    (4*1024)      /* Used as output buffer when deflating items to a file */
 
+#ifndef PL_ARENA_CONST_ALIGN_MASK
 #define PL_ARENA_CONST_ALIGN_MASK  (sizeof(void*)-1)
+#endif
 #include "plarena.h"
 
 #include "zlib.h"
 #include "zipstruct.h"
 #include "nsAutoPtr.h"
 #include "nsILocalFile.h"
 #include "mozilla/FileUtils.h"
 
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -370,16 +370,37 @@ enum NSLocationType
   NS_SKIN_LOCATION
 };
 
 XRE_API(nsresult,
         XRE_AddManifestLocation, (NSLocationType aType,
                                   nsILocalFile* aLocation))
 
 /**
+ * Register XPCOM components found in a JAR.
+ * This is similar to XRE_AddManifestLocation except the file specified
+ * must be a zip archive with a manifest named chrome.manifest
+ * This method may be called at any time before or after XRE_main or
+ * XRE_InitEmbedding.
+ *
+ * @param aFiles An array of files or directories.
+ * @param aFileCount the number of items in the aFiles array.
+ * @note appdir/components is registered automatically.
+ *
+ * NS_COMPONENT_LOCATION specifies a location to search for binary XPCOM
+ * components as well as component/chrome manifest files.
+ *
+ * NS_SKIN_LOCATION specifies a location to search for chrome manifest files
+ * which are only allowed to register only skin packages and style overlays.
+ */
+XRE_API(nsresult,
+        XRE_AddJarManifestLocation, (NSLocationType aType,
+                                     nsILocalFile* aLocation))
+
+/**
  * Fire notifications to inform the toolkit about a new profile. This
  * method should be called after XRE_InitEmbedding if the embedder
  * wishes to run with a profile. Normally the embedder should call
  * XRE_LockProfileDirectory to lock the directory before calling this
  * method.
  *
  * @note There are two possibilities for selecting a profile:
  *
--- a/xpcom/components/Makefile.in
+++ b/xpcom/components/Makefile.in
@@ -63,20 +63,16 @@ EXPORTS_mozilla = \
 
 CPPSRCS		= \
 		nsCategoryManager.cpp \
 		nsComponentManager.cpp \
 		ManifestParser.cpp \
 		nsNativeComponentLoader.cpp \
 		$(NULL)
 
-ifdef MOZ_OMNIJAR
-CPPSRCS += nsManifestZIPLoader.cpp
-endif
-
 SDK_XPIDLSRCS	= \
 		nsIClassInfo.idl	      \
 		nsIComponentRegistrar.idl     \
 		nsIFactory.idl		      \
 		nsIModule.idl		      \
 		nsIServiceManager.idl	      \
 		nsIComponentManager.idl       \
 		nsICategoryManager.idl        \
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -645,19 +645,17 @@ void
 ParseManifest(NSLocationType type, nsILocalFile* file,
               char* buf, bool aChromeOnly)
 {
   nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, file, aChromeOnly);
   nsChromeRegistry::ManifestProcessingContext chromecx(type, file);
   ParseManifestCommon(type, file, mgrcx, chromecx, NULL, buf, aChromeOnly);
 }
 
-#ifdef MOZ_OMNIJAR
 void
-ParseManifest(NSLocationType type, const char* jarPath,
+ParseManifest(NSLocationType type, nsIZipReader* reader, const char* jarPath,
               char* buf, bool aChromeOnly)
 {
-  nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, jarPath, aChromeOnly);
-  nsChromeRegistry::ManifestProcessingContext chromecx(type, jarPath);
-  ParseManifestCommon(type, mozilla::OmnijarPath(), mgrcx, chromecx, jarPath,
+  nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, reader, jarPath, aChromeOnly);
+  nsChromeRegistry::ManifestProcessingContext chromecx(type, mgrcx.mFile, jarPath);
+  ParseManifestCommon(type, mgrcx.mFile, mgrcx, chromecx, jarPath,
                       buf, aChromeOnly);
 }
-#endif
--- a/xpcom/components/ManifestParser.h
+++ b/xpcom/components/ManifestParser.h
@@ -37,23 +37,22 @@
 
 #ifndef ManifestParser_h
 #define ManifestParser_h
 
 #include "nsComponentManager.h"
 #include "nsChromeRegistry.h"
 
 class nsILocalFile;
+class nsIZipReader;
 
 void ParseManifest(NSLocationType type, nsILocalFile* file,
                    char* buf, bool aChromeOnly);
 
-#ifdef MOZ_OMNIJAR
-void ParseManifest(NSLocationType type, const char* jarPath,
-                   char* buf, bool aChromeOnly);
-#endif
+void ParseManifest(NSLocationType type, nsIZipReader* reader,
+                   const char* jarPath, char* buf, bool aChromeOnly);
 
 void LogMessage(const char* aMsg, ...);
 
 void LogMessageWithContext(nsILocalFile* aFile, const char* aPath,
                            PRUint32 aLineNumber, const char* aMsg, ...);
 
 #endif // ManifestParser_h
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -101,20 +101,19 @@
 #include NEW_H     // for placement new
 
 
 #ifdef XP_BEOS
 #include <FindDirectory.h>
 #include <Path.h>
 #endif
 
-#ifdef MOZ_OMNIJAR
 #include "mozilla/Omnijar.h"
+#include "nsJAR.h"
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
-#endif
 
 #include "prlog.h"
 
 NS_COM PRLogModuleInfo* nsComponentManagerLog = nsnull;
 
 #if 0 || defined (DEBUG_timeless)
  #define SHOW_DENIED_ON_SHUTDOWN
  #define SHOW_CI_ON_EXISTING_SERVICE
@@ -348,42 +347,42 @@ nsresult nsComponentManagerImpl::Init()
     // Initialize our arena
     NS_TIME_FUNCTION_MARK("Next: init component manager arena");
     PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
 
     mFactories.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
     mContractIDs.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
     mLoaderMap.Init();
     mKnownFileModules.Init();
-#ifdef MOZ_OMNIJAR
     mKnownJARModules.Init();
-#endif
 
     mMon = nsAutoMonitor::NewMonitor("nsComponentManagerImpl");
     if (mMon == nsnull)
         return NS_ERROR_OUT_OF_MEMORY;
 
     nsCOMPtr<nsILocalFile> greDir =
         GetLocationFromDirectoryService(NS_GRE_DIR);
     nsCOMPtr<nsILocalFile> appDir =
         GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
 
     InitializeStaticModules();
     InitializeModuleLocations();
 
     ComponentLocation* cl = sModuleLocations->InsertElementAt(0);
     cl->type = NS_COMPONENT_LOCATION;
     cl->location = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
+    cl->jar = false;
 
     PRBool equals = PR_FALSE;
     appDir->Equals(greDir, &equals);
     if (!equals) {
         cl = sModuleLocations->InsertElementAt(0);
         cl->type = NS_COMPONENT_LOCATION;
         cl->location = CloneAndAppend(greDir, NS_LITERAL_CSTRING("chrome.manifest"));
+        cl->jar = false;
     }
 
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
            ("nsComponentManager: Initialized."));
 
     NS_TIME_FUNCTION_MARK("Next: init native module loader");
     nsresult rv = mNativeModuleLoader.Init();
     if (NS_FAILED(rv))
@@ -392,26 +391,46 @@ nsresult nsComponentManagerImpl::Init()
     nsCategoryManager::GetSingleton()->SuppressNotifications(true);
 
     RegisterModule(&kXPCOMModule, NULL);
 
     for (PRUint32 i = 0; i < sStaticModules->Length(); ++i)
         RegisterModule((*sStaticModules)[i], NULL);
 
 #ifdef MOZ_OMNIJAR
-    mManifestLoader = new nsManifestZIPLoader();
-
-    RegisterOmnijar("chrome.manifest", false);
+    if (mozilla::OmnijarPath()) {
+        nsCOMPtr<nsIZipReader> omnijarReader = new nsJAR();
+        rv = omnijarReader->Open(mozilla::OmnijarPath());
+        if (NS_SUCCEEDED(rv))
+            RegisterJarManifest(omnijarReader, "chrome.manifest", false);
+    }
 #endif
 
     for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
         ComponentLocation& l = sModuleLocations->ElementAt(i);
-        RegisterManifestFile(l.type, l.location, false);
+        if (!l.jar) {
+            RegisterManifestFile(l.type, l.location, false);
+            continue;
+        }
+
+        nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
+        rv = reader->Open(l.location);
+        if (NS_SUCCEEDED(rv))
+            RegisterJarManifest(reader, "chrome.manifest", false);
     }
 
+#ifdef MOZ_OMNIJAR
+    if (mozilla::OmnijarPath()) {
+        cl = sModuleLocations->InsertElementAt(0);
+        cl->type = NS_COMPONENT_LOCATION;
+        cl->location = mozilla::OmnijarPath();
+        cl->jar = true;
+    }
+#endif
+
     nsCategoryManager::GetSingleton()->SuppressNotifications(false);
 
     mStatus = NORMAL;
 
     return NS_OK;
 }
 
 void
@@ -517,26 +536,37 @@ static nsCString
 GetExtension(nsILocalFile* file)
 {
     nsCString extension;
     file->GetNativePath(extension);
     CutExtension(extension);
     return extension;
 }
 
-#ifdef MOZ_OMNIJAR
-void
-nsComponentManagerImpl::RegisterOmnijar(const char* aPath, bool aChromeOnly)
+static already_AddRefed<nsIInputStream>
+LoadEntry(nsIZipReader* aReader, const char* aName)
 {
-    if (!mozilla::OmnijarPath())
-        return;
+    if (!aReader)
+        return NULL;
+
+    nsCOMPtr<nsIInputStream> is;
+    nsresult rv = aReader->GetInputStream(aName, getter_AddRefs(is));
+    if (NS_FAILED(rv))
+        return NULL;
 
-    nsCOMPtr<nsIInputStream> is = mManifestLoader->LoadEntry(aPath);
+    return is.forget();
+}
+
+void
+nsComponentManagerImpl::RegisterJarManifest(nsIZipReader* aReader,
+                                            const char* aPath, bool aChromeOnly)
+{
+    nsCOMPtr<nsIInputStream> is = LoadEntry(aReader, aPath);
     if (!is) {
-        LogMessage("Could not find omnijar manifest entry '%s'.", aPath);
+        LogMessage("Could not find jar manifest entry '%s'.", aPath);
         return;
     }
 
     PRUint32 flen;
     is->Available(&flen);
 
     nsAutoArrayPtr<char> whole(new char[flen + 1]);
     if (!whole)
@@ -555,19 +585,19 @@ nsComponentManagerImpl::RegisterOmnijar(
         if (NS_FAILED(is->Read(whole + totalRead, avail, &read)))
             return;
 
         totalRead += read;
     }
 
     whole[flen] = '\0';
 
-    ParseManifest(NS_COMPONENT_LOCATION, aPath, whole, aChromeOnly);
+    ParseManifest(NS_COMPONENT_LOCATION, aReader, aPath,
+                  whole, aChromeOnly);
 }
-#endif // MOZ_OMNIJAR
 
 namespace {
 struct AutoCloseFD
 {
     AutoCloseFD()
         : mFD(NULL)
     { }
     ~AutoCloseFD() {
@@ -631,46 +661,41 @@ TranslateSlashes(char* path)
 {
     for (; *path; ++path) {
         if ('/' == *path)
             *path = '\\';
     }
 }
 #endif
 
-#ifdef MOZ_OMNIJAR
 static void
 AppendFileToManifestPath(nsCString& path,
                          const char* file)
 {
     PRInt32 i = path.RFindChar('/');
     if (kNotFound == i)
         path.Truncate(0);
     else
         path.Truncate(i + 1);
 
     path.Append(file);
 }
-#endif
 
 void
 nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
 {
     char* file = argv[0];
 
-#ifdef MOZ_OMNIJAR
     if (cx.mPath) {
         nsCAutoString manifest(cx.mPath);
         AppendFileToManifestPath(manifest, file);
 
-        RegisterOmnijar(manifest.get(), cx.mChromeOnly);
+        RegisterJarManifest(cx.mReader, manifest.get(), cx.mChromeOnly);
     }
-    else
-#endif
-    {
+    else {
 #ifdef TRANSLATE_SLASHES
         TranslateSlashes(file);
 #endif
         nsCOMPtr<nsIFile> cfile;
         cx.mFile->GetParent(getter_AddRefs(cfile));
         nsCOMPtr<nsILocalFile> clfile = do_QueryInterface(cfile);
 
         nsresult rv = clfile->AppendRelativeNativePath(nsDependentCString(file));
@@ -681,24 +706,22 @@ nsComponentManagerImpl::ManifestManifest
 
         RegisterManifestFile(cx.mType, clfile, cx.mChromeOnly);
     }
 }
 
 void
 nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
 {
-#ifdef MOZ_OMNIJAR
     if (cx.mPath) {
-        NS_WARNING("Cannot load binary components from the omnijar.");
+        NS_WARNING("Cannot load binary components from a jar.");
         LogMessageWithContext(cx.mFile, cx.mPath, lineno,
-                              "Cannot load binary components from the omnijar.");
+                              "Cannot load binary components from a jar.");
         return;
     }
-#endif
 
     char* file = argv[0];
 
 #ifdef TRANSLATE_SLASHES
     TranslateSlashes(file);
 #endif
 
     nsCOMPtr<nsIFile> cfile;
@@ -718,34 +741,31 @@ nsComponentManagerImpl::ManifestBinaryCo
     RegisterModule(m, clfile);
 }
 
 void
 nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
 {
     char* file = argv[0];
 
-#ifdef MOZ_OMNIJAR
     if (cx.mPath) {
         nsCAutoString manifest(cx.mPath);
         AppendFileToManifestPath(manifest, file);
 
         nsCOMPtr<nsIInputStream> stream =
-            mManifestLoader->LoadEntry(manifest.get());
+            LoadEntry(cx.mReader, manifest.get());
         if (!stream) {
-            NS_WARNING("Failed to load omnijar XPT file.");
+            NS_WARNING("Failed to load XPT file in a jar.");
             return;
         }
 
         xptiInterfaceInfoManager::GetSingleton()
             ->RegisterInputStream(stream);
     }
-    else
-#endif
-    {
+    else {
 #ifdef TRANSLATE_SLASHES
         TranslateSlashes(file);
 #endif
         nsCOMPtr<nsIFile> cfile;
         cx.mFile->GetParent(getter_AddRefs(cfile));
         nsCOMPtr<nsILocalFile> clfile = do_QueryInterface(cfile);
 
         nsresult rv = clfile->AppendRelativeNativePath(nsDependentCString(file));
@@ -788,30 +808,32 @@ nsComponentManagerImpl::ManifestComponen
                               "Trying to re-register CID '%s' already registered by %s.",
                               idstr,
                               existing.get());
         return;
     }
 
     KnownModule* km;
 
-#ifdef MOZ_OMNIJAR
     if (cx.mPath) {
         nsCAutoString manifest(cx.mPath);
         AppendFileToManifestPath(manifest, file);
 
-        km = mKnownJARModules.Get(manifest);
+        nsCAutoString hash;
+        cx.mFile->GetNativePath(hash);
+        hash.AppendLiteral("|");
+        hash.Append(manifest);
+
+        km = mKnownJARModules.Get(hash);
         if (!km) {
-            km = new KnownModule(manifest);
-            mKnownJARModules.Put(manifest, km);
+            km = new KnownModule(cx.mFile, manifest);
+            mKnownJARModules.Put(hash, km);
         }
     }
-    else
-#endif
-    {
+    else {
 #ifdef TRANSLATE_SLASHES
         TranslateSlashes(file);
 #endif
         nsCOMPtr<nsIFile> cfile;
         cx.mFile->GetParent(getter_AddRefs(cfile));
         nsCOMPtr<nsILocalFile> clfile = do_QueryInterface(cfile);
 
         nsresult rv = clfile->AppendRelativeNativePath(nsDependentCString(file));
@@ -876,39 +898,42 @@ nsComponentManagerImpl::ManifestCategory
 
     nsCategoryManager::GetSingleton()->
         AddCategoryEntry(category, key, value);
 }
 
 void
 nsComponentManagerImpl::RereadChromeManifests()
 {
-#ifdef MOZ_OMNIJAR
-    RegisterOmnijar("chrome.manifest", true);
-#endif
-
     for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
         ComponentLocation& l = sModuleLocations->ElementAt(i);
-        RegisterManifestFile(l.type, l.location, true);
+        if (!l.jar) {
+            RegisterManifestFile(l.type, l.location, true);
+            continue;
+        }
+
+        nsresult rv;
+        nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
+        if (NS_SUCCEEDED(rv))
+            rv = reader->Open(l.location);
+        if (NS_SUCCEEDED(rv))
+            RegisterJarManifest(reader, "chrome.manifest", true);
     }
 }
 
 bool
 nsComponentManagerImpl::KnownModule::EnsureLoader()
 {
     if (!mLoader) {
         nsCString extension;
-#if MOZ_OMNIJAR
         if (!mPath.IsEmpty()) {
             extension = mPath;
             CutExtension(extension);
         }
-        else
-#endif
-        {
+        else {
             extension = GetExtension(mFile);
         }
 
         mLoader = nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension);
     }
     return !!mLoader;
 }
 
@@ -916,21 +941,19 @@ bool
 nsComponentManagerImpl::KnownModule::Load()
 {
     if (mFailed)
         return false;
     if (!mModule) {
         if (!EnsureLoader())
             return false;
 
-#ifdef MOZ_OMNIJAR
         if (!mPath.IsEmpty())
-            mModule = mLoader->LoadModuleFromJAR(mozilla::OmnijarPath(), mPath);
+            mModule = mLoader->LoadModuleFromJAR(mFile, mPath);
         else
-#endif
             mModule = mLoader->LoadModule(mFile);
 
         if (!mModule) {
             mFailed = true;
             return false;
         }
     }
     if (!mLoaded) {
@@ -945,24 +968,23 @@ nsComponentManagerImpl::KnownModule::Loa
     }
     return true;
 }
 
 nsCString
 nsComponentManagerImpl::KnownModule::Description() const
 {
     nsCString s;
-#ifdef MOZ_OMNIJAR
     if (!mPath.IsEmpty()) {
-        s.AssignLiteral("omnijar:");
+        mFile->GetNativePath(s);
+        s.Insert(NS_LITERAL_CSTRING("jar:"), 0);
+        s.AppendLiteral("!/");
         s.Append(mPath);
     }
-    else
-#endif
-    if (mFile)
+    else if (mFile)
         mFile->GetNativePath(s);
     else
         s = "<static module>";
     return s;
 }
 
 nsresult nsComponentManagerImpl::Shutdown(void)
 {
@@ -974,19 +996,17 @@ nsresult nsComponentManagerImpl::Shutdow
 
     // Shutdown the component manager
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
 
     // Release all cached factories
     mContractIDs.Clear();
     mFactories.Clear(); // XXX release the objects, don't just clear
     mLoaderMap.Clear();
-#ifdef MOZ_OMNIJAR
     mKnownJARModules.Clear();
-#endif
     mKnownFileModules.Clear();
     mKnownStaticModules.Clear();
 
     mLoaderData.Clear();
 
     delete sStaticModules;
     delete sModuleLocations;
 
@@ -1194,18 +1214,17 @@ nsComponentManagerImpl::CreateInstance(c
     if (factory)
     {
         rv = factory->CreateInstance(aDelegate, aIID, aResult);
         if (NS_SUCCEEDED(rv) && !*aResult) {
             NS_ERROR("Factory did not return an object but returned success!");
             rv = NS_ERROR_SERVICE_NOT_FOUND;
         }
     }
-    else
-    {
+    else {
         // Translate error values
         rv = NS_ERROR_FACTORY_NOT_REGISTERED;
     }
 
 #ifdef PR_LOGGING
     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
     {
         char *buf = aClass.ToString();
@@ -1282,18 +1301,17 @@ nsComponentManagerImpl::CreateInstanceBy
     {
 
         rv = factory->CreateInstance(aDelegate, aIID, aResult);
         if (NS_SUCCEEDED(rv) && !*aResult) {
             NS_ERROR("Factory did not return an object but returned success!");
             rv = NS_ERROR_SERVICE_NOT_FOUND;
         }
     }
-    else
-    {
+    else {
         // Translate error values
         rv = NS_ERROR_FACTORY_NOT_REGISTERED;
     }
 
     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
            ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
             NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
 
@@ -1987,15 +2005,42 @@ XRE_AddStaticComponent(const mozilla::Mo
 EXPORT_XPCOM_API(nsresult)
 XRE_AddManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
 {
     nsComponentManagerImpl::InitializeModuleLocations();
     nsComponentManagerImpl::ComponentLocation* c = 
         nsComponentManagerImpl::sModuleLocations->AppendElement();
     c->type = aType;
     c->location = aLocation;
+    c->jar = false;
 
     if (nsComponentManagerImpl::gComponentManager &&
         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
         nsComponentManagerImpl::gComponentManager->RegisterManifestFile(aType, aLocation, false);
 
     return NS_OK;
 }
+
+EXPORT_XPCOM_API(nsresult)
+XRE_AddJarManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
+{
+    nsComponentManagerImpl::InitializeModuleLocations();
+    nsComponentManagerImpl::ComponentLocation* c = 
+        nsComponentManagerImpl::sModuleLocations->AppendElement();
+    c->type = aType;
+    c->location = aLocation;
+    c->jar = true;
+
+    if (!nsComponentManagerImpl::gComponentManager ||
+        nsComponentManagerImpl::NORMAL != nsComponentManagerImpl::gComponentManager->mStatus)
+        return NS_OK;
+
+    nsresult rv;
+    nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = reader->Open(c->location);
+    if (NS_SUCCEEDED(rv))
+        nsComponentManagerImpl::gComponentManager->RegisterJarManifest(reader, "chrome.manifest", false);
+
+    return NS_OK;
+}
+
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -61,20 +61,18 @@
 #include "nsIFile.h"
 #include "plarena.h"
 #include "nsCOMArray.h"
 #include "nsDataHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "nsClassHashtable.h"
 #include "nsTArray.h"
 
-#ifdef MOZ_OMNIJAR
 #include "mozilla/Omnijar.h"
-#include "nsManifestZIPLoader.h"
-#endif
+#include "nsIZipReader.h"
 
 struct nsFactoryEntry;
 class nsIServiceManager;
 struct PRThread;
 
 #define NS_COMPONENTMANAGER_CID                      \
 { /* 91775d60-d5dc-11d2-92fb-00e09805570f */         \
     0x91775d60,                                      \
@@ -86,24 +84,16 @@ struct PRThread;
 /* keys for registry use */
 extern const char xpcomKeyName[];
 extern const char xpcomComponentsKeyName[];
 extern const char lastModValueName[];
 extern const char fileSizeValueName[];
 extern const char nativeComponentType[];
 extern const char staticComponentType[];
 
-typedef int LoaderType;
-
-// Predefined loader types.
-#define NS_LOADER_TYPE_NATIVE  -1
-#define NS_LOADER_TYPE_STATIC  -2
-#define NS_LOADER_TYPE_JAR     -3
-#define NS_LOADER_TYPE_INVALID -4
-
 #ifdef DEBUG
 #define XPCOM_CHECK_PENDING_CIDS
 #endif
 ////////////////////////////////////////////////////////////////////////////////
 
 extern const mozilla::Module kXPCOMModule;
 
 // Array of Loaders and their type strings
@@ -164,20 +154,22 @@ public:
 
     static void InitializeStaticModules();
     static void InitializeModuleLocations();
 
     struct ComponentLocation
     {
         NSLocationType type;
         nsCOMPtr<nsILocalFile> location;
+        bool jar;
     };
 
     static nsTArray<const mozilla::Module*>* sStaticModules;
     static nsTArray<ComponentLocation>* sModuleLocations;
+    static nsTArray<ComponentLocation>* sJarModuleLocations;
 
     nsNativeModuleLoader mNativeModuleLoader;
 
     class KnownModule
     {
     public:
         /**
          * Static or binary module.
@@ -192,26 +184,24 @@ public:
         KnownModule(nsILocalFile* aFile)
             : mModule(NULL)
             , mFile(aFile)
             , mLoader(NULL)
             , mLoaded(false)
             , mFailed(false)
         { }
 
-#ifdef MOZ_OMNIJAR
-        KnownModule(const nsACString& aPath)
+        KnownModule(nsILocalFile* aFile, const nsACString& aPath)
             : mModule(NULL)
-            , mFile(NULL)
+            , mFile(aFile)
             , mPath(aPath)
             , mLoader(NULL)
             , mLoaded(false)
             , mFailed(false)
         { }
-#endif
 
         ~KnownModule()
         {
             if (mLoaded && mModule->unloadProc)
                 mModule->unloadProc();
         }
 
         bool EnsureLoader();
@@ -226,67 +216,67 @@ public:
          * For error logging, get a description of this module, either the
          * file path, or <static module>.
          */
         nsCString Description() const;
 
     private:
         const mozilla::Module* mModule;
         nsCOMPtr<nsILocalFile> mFile;
-#ifdef MOZ_OMNIJAR
         nsCString mPath;
-#endif
         nsCOMPtr<mozilla::ModuleLoader> mLoader;
         bool mLoaded;
         bool mFailed;
     };
 
     // The KnownModule is kept alive by these members, it is
     // referenced by pointer from the factory entries.
     nsTArray< nsAutoPtr<KnownModule> > mKnownStaticModules;
     nsClassHashtable<nsHashableHashKey, KnownModule> mKnownFileModules;
-#ifdef MOZ_OMNIJAR
+    // The key is a string in this format "<jar path>|<path within jar>"
     nsClassHashtable<nsCStringHashKey, KnownModule> mKnownJARModules;
-#endif
 
     void RegisterModule(const mozilla::Module* aModule,
                         nsILocalFile* aFile);
     void RegisterCIDEntry(const mozilla::Module::CIDEntry* aEntry,
                           KnownModule* aModule);
     void RegisterContractID(const mozilla::Module::ContractIDEntry* aEntry);
 
-#ifdef MOZ_OMNIJAR
-    void RegisterOmnijar(const char* aPath, bool aChromeOnly);
-#endif
+    void RegisterJarManifest(nsIZipReader* aReader,
+                             const char* aPath, bool aChromeOnly);
 
     void RegisterManifestFile(NSLocationType aType, nsILocalFile* aFile,
                               bool aChromeOnly);
 
     struct ManifestProcessingContext
     {
         ManifestProcessingContext(NSLocationType aType, nsILocalFile* aFile, bool aChromeOnly)
             : mType(aType)
             , mFile(aFile)
             , mPath(NULL)
             , mChromeOnly(aChromeOnly)
         { }
 
-#ifdef MOZ_OMNIJAR
-        ManifestProcessingContext(NSLocationType aType, const char* aPath, bool aChromeOnly)
+        ManifestProcessingContext(NSLocationType aType, nsIZipReader* aReader, const char* aPath, bool aChromeOnly)
             : mType(aType)
-            , mFile(mozilla::OmnijarPath())
+            , mReader(aReader)
             , mPath(aPath)
             , mChromeOnly(aChromeOnly)
-        { }
-#endif
+        {
+            nsCOMPtr<nsIFile> file;
+            aReader->GetFile(getter_AddRefs(file));
+            nsCOMPtr<nsILocalFile> localfile = do_QueryInterface(file);
+            mFile = localfile;
+        }
 
         ~ManifestProcessingContext() { }
 
         NSLocationType mType;
         nsILocalFile* mFile;
+        nsIZipReader* mReader;
         const char* mPath;
         bool mChromeOnly;
     };
 
     void ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv);
     void ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv);
     void ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv);
     void ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv);
@@ -316,20 +306,16 @@ public:
                                                  PRThread* aThread);
     inline void RemovePendingService(const nsCID& aServiceCID);
     inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;
 
     nsTArray<PendingServiceInfo> mPendingServices;
 
 private:
     ~nsComponentManagerImpl();
-
-#ifdef MOZ_OMNIJAR
-    nsAutoPtr<nsManifestZIPLoader> mManifestLoader;
-#endif
 };
 
 
 #define NS_MAX_FILENAME_LEN     1024
 
 #define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
 
 struct nsFactoryEntry
deleted file mode 100644
--- a/xpcom/components/nsManifestZIPLoader.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the XPT zip reader.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corp.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *   Alec Flett <alecf@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-#include "nsManifestZIPLoader.h"
-#include "nsJAR.h"
-#include "mozilla/Omnijar.h"
-
-nsManifestZIPLoader::nsManifestZIPLoader() 
-    : mZipReader(new nsJAR())
-{
-    nsresult rv = mZipReader->Open(mozilla::OmnijarPath());
-    if (NS_FAILED(rv))
-        mZipReader = NULL;
-}
-
-nsManifestZIPLoader::~nsManifestZIPLoader()
-{
-}
-
-already_AddRefed<nsIInputStream>
-nsManifestZIPLoader::LoadEntry(const char* aName)
-{
-    if (!mZipReader)
-        return NULL;
-
-    nsCOMPtr<nsIInputStream> is;
-    nsresult rv = mZipReader->GetInputStream(aName, getter_AddRefs(is));
-    if (NS_FAILED(rv))
-        return NULL;
-
-    return is.forget();
-}
deleted file mode 100644
--- a/xpcom/components/nsManifestZIPLoader.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the XPT zip reader.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corp.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *   Alec Flett <alecf@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsCOMPtr.h"
-
-#include "nsIZipReader.h"
-#include "nsIInputStream.h"
-
-class nsManifestZIPLoader
-{
- public:
-    nsManifestZIPLoader();
-    ~nsManifestZIPLoader();
-
-    already_AddRefed<nsIInputStream> LoadEntry(const char* name);
-
- private:
-    nsCOMPtr<nsIZipReader> mZipReader;
-};
-
--- a/xpcom/tests/TestRegistrationOrder.cpp
+++ b/xpcom/tests/TestRegistrationOrder.cpp
@@ -128,16 +128,22 @@ nsresult execRegOrderTest(const char *aT
 }
 
 nsresult TestRegular()
 {
   return execRegOrderTest("TestRegular", SERVICE_A_CONTRACT_ID,
                           kCoreServiceA_CID, kExtServiceA_CID);
 }
 
+nsresult TestJar()
+{
+  return execRegOrderTest("TestJar", SERVICE_B_CONTRACT_ID,
+                          kCoreServiceB_CID, kExtServiceB_CID);
+}
+
 bool TestContractFirst()
 {
   nsCOMPtr<nsIComponentRegistrar> r;
   NS_GetComponentRegistrar(getter_AddRefs(r));
 
   nsCID* cid = NULL;
   nsresult rv = r->ContractIDToCID("@mozilla.org/RegTestOrderC;1", &cid);
   if (NS_FAILED(rv)) {
@@ -162,17 +168,18 @@ GetRegDirectory(const char* basename, co
 {
     nsCOMPtr<nsILocalFile> f;
     nsresult rv = NS_NewNativeLocalFile(nsDependentCString(basename), PR_TRUE,
                                         getter_AddRefs(f));
     if (NS_FAILED(rv))
         return NULL;
 
     f->AppendNative(nsDependentCString(dirname));
-    f->AppendNative(nsDependentCString(leafname));
+    if (leafname)
+        f->AppendNative(nsDependentCString(leafname));
     return f.forget();
 }
 
 
 
 int main(int argc, char** argv)
 {
   if (argc < 2)
@@ -183,21 +190,26 @@ int main(int argc, char** argv)
 
   ScopedLogging logging;
   
   const char *regPath = argv[1];
   XRE_AddManifestLocation(NS_COMPONENT_LOCATION,
                           nsCOMPtr<nsILocalFile>(GetRegDirectory(regPath, "core", "component.manifest")));
   XRE_AddManifestLocation(NS_COMPONENT_LOCATION,
                           nsCOMPtr<nsILocalFile>(GetRegDirectory(regPath, "extension", "extComponent.manifest")));
+  XRE_AddJarManifestLocation(NS_COMPONENT_LOCATION,
+                          nsCOMPtr<nsILocalFile>(GetRegDirectory(regPath, "extension2.jar", NULL)));
   ScopedXPCOM xpcom("RegistrationOrder");
   if (xpcom.failed())
     return 1;
 
   int rv = 0;
   if (NS_FAILED(TestRegular()))
     rv = 1;
 
+  if (NS_FAILED(TestJar()))
+    rv = 1;
+
   if (!TestContractFirst())
     rv = 1;
 
   return rv;
 }
--- a/xpcom/tests/regorder/core/component.manifest
+++ b/xpcom/tests/regorder/core/component.manifest
@@ -1,5 +1,7 @@
 component {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7} component.js
+component {d04d1298-6dac-459b-a13b-bcab235730a0} component2.js
 contract @mozilla.org/RegTestServiceA;1 {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7}
+contract @mozilla.org/RegTestServiceB;1 {d04d1298-6dac-459b-a13b-bcab235730a0}
 
 contract @mozilla.org/RegTestOrderC;1 {ada15884-bb89-473c-8b50-dcfbb8447ff4}
 component {ada15884-bb89-473c-8b50-dcfbb8447ff4} missing.js
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/regorder/core/component2.js
@@ -0,0 +1,71 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Kathleen Brade <brade@pearlcrescent.com>
+ * Mark Smith <mcs@pearlcrescent.com>
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gRegTestCoreComponent =
+{
+  /* nsISupports implementation. */
+  QueryInterface: function (aIID)
+  {
+    if (!aIID.equals(Components.interfaces.nsISupports) &&
+        !aIID.equals(Components.interfaces.nsIFactory))
+      throw Components.results.NS_ERROR_NO_INTERFACE;
+
+    return this;
+  },
+
+  /* nsIFactory implementation. */
+  createInstance: function (aOuter, aIID)
+  {
+    if (null != aOuter)
+      throw Components.results.NS_ERROR_NO_AGGREGATION;
+
+    return this.QueryInterface(aIID);
+  },
+
+  lockFactory: function (aDoLock) {}
+};
+
+const kClassID = Components.ID("{d04d1298-6dac-459b-a13b-bcab235730a0}");
+
+function NSGetFactory(aClassID) {
+  if (!aClassID.equals(kClassID))
+    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+
+  return gRegTestCoreComponent;
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fcab893f6aebd7e57b50dc81d24cc7b90725340b
GIT binary patch
literal 1962
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
OejKFOSOvp#;q*5@l_KZ>