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
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>