Bug 564667: Allow bootstrapped add-ons to have chrome URLs. r=dtownsend, sr=bsmedberg
authorHernan Rodriguez Colmeiro <colmeiro@gmail.com>
Fri, 29 Jul 2011 11:20:47 +0200
changeset 74552 acd21e50bd12c9a3260ad64848d80ed34ed25295
parent 74551 c1a6e33244953b6ed858e59c36bc01363d4c2aee
child 74553 f839abc8f1503c22dbe2183ee568fae277f05b9d
push id67
push userclegnitto@mozilla.com
push dateFri, 04 Nov 2011 22:39:41 +0000
treeherdermozilla-release@04778346a3b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdtownsend, bsmedberg
bugs564667
milestone8.0a1
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 564667: Allow bootstrapped add-ons to have chrome URLs. r=dtownsend, sr=bsmedberg
chrome/test/unit/data/test_bug564667.xpi
chrome/test/unit/data/test_bug564667/chrome.manifest
chrome/test/unit/data/test_bug564667/loaded.manifest
chrome/test/unit/test_bug564667.js
chrome/test/unit/xpcshell.ini
xpcom/build/nsXULAppAPI.h
xpcom/components/ManifestParser.cpp
xpcom/components/nsComponentManager.cpp
xpcom/components/nsComponentManager.h
xpcom/components/nsIComponentManager.idl
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..be1632d8ca90969c3835124b7d8308360d744cea
GIT binary patch
literal 569
zc$^FHW@Zs#U|`^2h-!Fax8`u4{6QdZ2O|RmKZ6WIaz;^pZmM2xVqRuiYH>+u2qy#c
zoJ%r(+po&_l~!;wFtU6FsstO*I^iJKVFjMH_jaxeo`+W5E!_~DxM3~7!Yrf6RSU|t
z<nMnqYm@9L8;?o<e^1U}U3<MNgROaQX~u%x+X6G*3+-Z=V6cqMPW^aLz%#)Jr}7th
zt3~Et%S{Q+E9>NXXSsKe0ZVql><OuQMsF;y_dj5_@%riOx$WDuO<_meHhDgYTpP|-
z;3Y9fNn*<8zf7Eb4PvssdpWzGuF>gbe7HpE*e0fxm6fN@^YQXe*ADPke(S7yx}zgg
zZ~nG!v4pqZme21C+`||E4~e4a=XU3A>?~IU@~jvjA(4}xn39@;8WPigiDC;0?{nw1
zJ<n<f255Nd>KO(#Fbeq3*H*W;G*k~|)SEeLxwI6|WEO@1Z$>6LW?Vrp!2kk4Cc~0O
t5DOzBSRoOCW;L>*n7%+ZlnY2<_=y$bCk#Vb*+3eZfN&L%t^}FD004Z7u^0dV
new file mode 100644
--- /dev/null
+++ b/chrome/test/unit/data/test_bug564667/chrome.manifest
@@ -0,0 +1,16 @@
+# Locally defined URLs
+content  test1       test/
+locale   test1 en-US test/
+skin     test1 test  test/
+
+# Test Override
+content testOverride  test/
+override chrome://testOverride/content file:///test1/override
+
+
+# Load external manifest
+manifest loaded.manifest
+
+# Failure Cases
+overlay   chrome://test1/content/overlay.xul   chrome://test1/content/test1.xul
+style     chrome://test1/content/style.xul     chrome://test1/content/test1.css
new file mode 100644
--- /dev/null
+++ b/chrome/test/unit/data/test_bug564667/loaded.manifest
@@ -0,0 +1,2 @@
+content  test2         test/
+locale   test2  en-US  test/
new file mode 100644
--- /dev/null
+++ b/chrome/test/unit/test_bug564667.js
@@ -0,0 +1,155 @@
+/* ***** 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
+ *      the Mozilla Foundation.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Hernan Rodriguez Colmeiro <colmeiro@gmail.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 *****
+ */
+
+const UNPACKAGED_ADDON = do_get_file("data/test_bug564667");
+const PACKAGED_ADDON = do_get_file("data/test_bug564667.xpi");
+
+var gIOS = Cc["@mozilla.org/network/io-service;1"].
+           getService(Ci.nsIIOService);
+
+var gCR = Cc["@mozilla.org/chrome/chrome-registry;1"].
+          getService(Ci.nsIChromeRegistry).
+          QueryInterface(Ci.nsIXULOverlayProvider);
+
+/*
+ * Checks that a mapping was added
+ */
+function test_mapping(chromeURL, target) {
+  var uri = gIOS.newURI(chromeURL, null, null);
+
+  try {
+    var result = gCR.convertChromeURL(uri);
+    do_check_eq(result.spec, target);
+  }
+  catch (ex) {
+    do_throw(chromeURL + " not Registered");
+  }
+}
+
+/*
+ * Checks that a mapping was removed
+ */
+function test_removed_mapping(chromeURL, target) {
+  var uri = gIOS.newURI(chromeURL, null, null);
+  try {
+    var result = gCR.convertChromeURL(uri);
+    do_throw(chromeURL + " not removed");
+  }
+  catch (ex) {
+    // This should throw
+  }
+}
+
+/*
+ * Checks if any overlay was added after loading
+ * the manifest files
+ *
+ * @param type The type of overlay: overlay|style
+ */
+function test_no_overlays(chromeURL, target, type) {
+  var type = type || "overlay";
+  var uri = gIOS.newURI(chromeURL, null, null);
+  var present = false, elem;
+
+  var overlays = (type == "overlay") ?
+      gCR.getXULOverlays(uri) : gCR.getStyleOverlays(uri);
+
+  // We shouldn't be allowed to register overlays nor styles
+  if (overlays.hasMoreElements()) {
+    if (type == "styles")
+      do_throw("Style Registered: " + chromeURL);
+    else
+      do_throw("Overlay Registered: " + chromeURL);
+  }
+}
+
+function testManifest(manifestPath, baseURI) {
+
+  // ------------------  Add manifest file ------------------------
+  Components.manager.addBootstrappedManifestLocation(manifestPath);
+
+  // Test Adding Content URL
+  test_mapping("chrome://test1/content", baseURI + "test/test1.xul");
+
+  // Test Adding Locale URL
+  test_mapping("chrome://test1/locale", baseURI + "test/test1.dtd");
+
+  // Test Adding Skin URL
+  test_mapping("chrome://test1/skin", baseURI + "test/test1.css");
+
+  // Test Adding Manifest URL
+  test_mapping("chrome://test2/content", baseURI + "test/test2.xul");
+  test_mapping("chrome://test2/locale", baseURI + "test/test2.dtd");
+
+  // Test Adding Override
+  test_mapping("chrome://testOverride/content", 'file:///test1/override')
+
+  // Test Not-Adding Overlays
+  test_no_overlays("chrome://test1/content/overlay.xul",
+                   "chrome://test1/content/test1.xul");
+
+  // Test Not-Adding Styles
+  test_no_overlays("chrome://test1/content/style.xul",
+                   "chrome://test1/content/test1.css", "styles");
+
+
+  // ------------------  Remove manifest file ------------------------
+  Components.manager.removeBootstrappedManifestLocation(manifestPath);
+
+  // Test Removing Content URL
+  test_removed_mapping("chrome://test1/content", baseURI + "test/test1.xul");
+
+  // Test Removing Content URL
+  test_removed_mapping("chrome://test1/locale", baseURI + "test/test1.dtd");
+
+  // Test Removing Skin URL
+  test_removed_mapping("chrome://test1/skin", baseURI + "test/test1.css");
+
+  // Test Removing Manifest URL
+  test_removed_mapping("chrome://test2/content", baseURI + "test/test2.xul");
+  test_removed_mapping("chrome://test2/locale", baseURI + "test/test2.dtd");
+}
+
+function run_test() {
+  // Test an unpackaged addon
+  testManifest(UNPACKAGED_ADDON, gIOS.newFileURI(UNPACKAGED_ADDON).spec);
+
+  // Test a packaged addon
+  testManifest(PACKAGED_ADDON, "jar:" + gIOS.newFileURI(PACKAGED_ADDON).spec + "!/");
+}
--- a/chrome/test/unit/xpcshell.ini
+++ b/chrome/test/unit/xpcshell.ini
@@ -5,12 +5,13 @@ tail =
 [test_abi.js]
 [test_bug292789.js]
 [test_bug380398.js]
 [test_bug397073.js]
 [test_bug399707.js]
 [test_bug401153.js]
 [test_bug415367.js]
 [test_bug519468.js]
+[test_bug564667.js]
 [test_crlf.js]
 [test_data_protocol_registration.js]
 [test_no_remote_registration.js]
 [test_resolve_uris.js]
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -368,17 +368,18 @@ XRE_API(nsresult,
  * 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.
  */
 enum NSLocationType
 {
   NS_COMPONENT_LOCATION,
-  NS_SKIN_LOCATION
+  NS_SKIN_LOCATION,
+  NS_BOOTSTRAPPED_LOCATION
 };
 
 XRE_API(nsresult,
         XRE_AddManifestLocation, (NSLocationType aType,
                                   nsILocalFile* aLocation))
 
 /**
  * Register XPCOM components found in a JAR.
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -71,57 +71,59 @@ struct ManifestDirective
   int argc;
 
   // Some directives should only be delivered for NS_COMPONENT_LOCATION
   // manifests.
   bool componentonly;
 
   bool ischrome;
 
+  bool allowbootstrap;
+
   // The platform/contentaccessible flags only apply to content directives.
   bool contentflags;
 
   // Function to handle this directive. This isn't a union because C++ still
   // hasn't learned how to initialize unions in a sane way.
   void (nsComponentManagerImpl::*mgrfunc)
     (nsComponentManagerImpl::ManifestProcessingContext& cx,
      int lineno, char *const * argv);
   void (nsChromeRegistry::*regfunc)
     (nsChromeRegistry::ManifestProcessingContext& cx,
      int lineno, char *const *argv,
      bool platform, bool contentaccessible);
 
   bool isContract;
 };
 static const ManifestDirective kParsingTable[] = {
-  { "manifest", 1, false, true, false,
+  { "manifest",         1, false, true, true, false,
     &nsComponentManagerImpl::ManifestManifest, NULL },
-  { "binary-component", 1, true, false, false,
+  { "binary-component", 1, true, false, false, false,
     &nsComponentManagerImpl::ManifestBinaryComponent, NULL },
-  { "interfaces",       1, true, false, false,
+  { "interfaces",       1, true, false, false, false,
     &nsComponentManagerImpl::ManifestXPT, NULL },
-  { "component",        2, true, false, false,
+  { "component",        2, true, false, false, false,
     &nsComponentManagerImpl::ManifestComponent, NULL },
-  { "contract",         2, true, false, false,
+  { "contract",         2, true, false, false, false,
     &nsComponentManagerImpl::ManifestContract, NULL, true},
-  { "category",         3, true, false, false,
+  { "category",         3, true, false, false, false,
     &nsComponentManagerImpl::ManifestCategory, NULL },
-  { "content",          2, true, true,  true,
+  { "content",          2, true, true, true,  true,
     NULL, &nsChromeRegistry::ManifestContent },
-  { "locale",           3, true, true,  false,
+  { "locale",           3, true, true, true,  false,
     NULL, &nsChromeRegistry::ManifestLocale },
-  { "skin",             3, false, true,  false,
+  { "skin",             3, false, true, true,  false,
     NULL, &nsChromeRegistry::ManifestSkin },
-  { "overlay",          2, true, true,  false,
+  { "overlay",          2, true, true, false,  false,
     NULL, &nsChromeRegistry::ManifestOverlay },
-  { "style",            2, false, true,  false,
+  { "style",            2, false, true, false,  false,
     NULL, &nsChromeRegistry::ManifestStyle },
-  { "override",         2, true, true,  false,
+  { "override",         2, true, true, true,  false,
     NULL, &nsChromeRegistry::ManifestOverride },
-  { "resource",         2, true, true,  false,
+  { "resource",         2, true, true, false,  false,
     NULL, &nsChromeRegistry::ManifestResource }
 };
 
 static const char kWhitespace[] = "\t ";
 
 static bool IsNewline(char c)
 {
   return c == '\n' || c == '\r';
@@ -445,17 +447,17 @@ ParseManifestCommon(NSLocationType aType
     nsCAutoString s;
     rv = xapp->GetID(s);
     if (NS_SUCCEEDED(rv))
       CopyUTF8toUTF16(s, appID);
 
     rv = xapp->GetVersion(s);
     if (NS_SUCCEEDED(rv))
       CopyUTF8toUTF16(s, appVersion);
-    
+
     nsCOMPtr<nsIXULRuntime> xruntime (do_QueryInterface(xapp));
     if (xruntime) {
       rv = xruntime->GetOS(s);
       if (NS_SUCCEEDED(rv)) {
         ToLowerCase(s);
         CopyUTF8toUTF16(s, osTarget);
       }
 
@@ -533,23 +535,32 @@ ParseManifestCommon(NSLocationType aType
     for (const ManifestDirective* d = kParsingTable;
 	 d < kParsingTable + NS_ARRAY_LENGTH(kParsingTable);
 	 ++d) {
       if (!strcmp(d->directive, token)) {
 	directive = d;
 	break;
       }
     }
+
     if (!directive) {
       LogMessageWithContext(aFile, aPath, line,
                             "Ignoring unrecognized chrome manifest directive '%s'.",
                             token);
       continue;
     }
-    if (directive->componentonly && NS_COMPONENT_LOCATION != aType) {
+
+    if (!directive->allowbootstrap && NS_BOOTSTRAPPED_LOCATION == aType) {
+      LogMessageWithContext(aFile, aPath, line,
+                            "Bootstrapped manifest not allowed to use '%s' directive.",
+                            token);
+      continue;
+    }
+
+    if (directive->componentonly && NS_SKIN_LOCATION == aType) {
       LogMessageWithContext(aFile, aPath, line,
                             "Skin manifest not allowed to use '%s' directive.",
                             token);
       continue;
     }
 
     NS_ASSERTION(directive->argc < 4, "Need to reset argv array length");
     char* argv[4];
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -84,16 +84,17 @@
 #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
 #include "nsThreadUtils.h"
 #include "prthread.h"
 #include "private/pprthred.h"
 #include "nsTArray.h"
 #include "prio.h"
 #include "mozilla/FunctionTimer.h"
 #include "ManifestParser.h"
+#include "mozilla/Services.h"
 
 #include "nsManifestLineReader.h"
 #include "mozilla/GenericFactory.h"
 #include "nsSupportsPrimitives.h"
 #include "nsArrayEnumerator.h"
 #include "nsStringEnumerator.h"
 
 #include NEW_H     // for placement new
@@ -401,17 +402,17 @@ nsresult nsComponentManagerImpl::Init()
         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);
+            RegisterJarManifest(l.type, reader, "chrome.manifest", false);
     }
 
     nsCategoryManager::GetSingleton()->SuppressNotifications(false);
 
     mStatus = NORMAL;
 
     return NS_OK;
 }
@@ -537,17 +538,17 @@ LoadEntry(nsIZipReader* aReader, const c
     nsresult rv = aReader->GetInputStream(aName, getter_AddRefs(is));
     if (NS_FAILED(rv))
         return NULL;
 
     return is.forget();
 }
 
 void
-nsComponentManagerImpl::RegisterJarManifest(nsIZipReader* aReader,
+nsComponentManagerImpl::RegisterJarManifest(NSLocationType aType, nsIZipReader* aReader,
                                             const char* aPath, bool aChromeOnly)
 {
     nsCOMPtr<nsIInputStream> is = LoadEntry(aReader, aPath);
     if (!is) {
         LogMessage("Could not find jar manifest entry '%s'.", aPath);
         return;
     }
 
@@ -571,17 +572,17 @@ nsComponentManagerImpl::RegisterJarManif
         if (NS_FAILED(is->Read(whole + totalRead, avail, &read)))
             return;
 
         totalRead += read;
     }
 
     whole[flen] = '\0';
 
-    ParseManifest(NS_COMPONENT_LOCATION, aReader, aPath,
+    ParseManifest(aType, aReader, aPath,
                   whole, aChromeOnly);
 }
 
 namespace {
 struct AutoCloseFD
 {
     AutoCloseFD()
         : mFD(NULL)
@@ -669,17 +670,17 @@ void
 nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
 {
     char* file = argv[0];
 
     if (cx.mPath) {
         nsCAutoString manifest(cx.mPath);
         AppendFileToManifestPath(manifest, file);
 
-        RegisterJarManifest(cx.mReader, manifest.get(), cx.mChromeOnly);
+        RegisterJarManifest(cx.mType, cx.mReader, manifest.get(), cx.mChromeOnly);
     }
     else {
 #ifdef TRANSLATE_SLASHES
         TranslateSlashes(file);
 #endif
         nsCOMPtr<nsIFile> cfile;
         cx.mFile->GetParent(getter_AddRefs(cfile));
         nsCOMPtr<nsILocalFile> clfile = do_QueryInterface(cfile);
@@ -906,17 +907,17 @@ nsComponentManagerImpl::RereadChromeMani
             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);
+            RegisterJarManifest(l.type, reader, "chrome.manifest", true);
     }
 }
 
 bool
 nsComponentManagerImpl::KnownModule::EnsureLoader()
 {
     if (!mLoader) {
         nsCString extension;
@@ -2031,16 +2032,67 @@ XRE_AddStaticComponent(const mozilla::Mo
 
     if (nsComponentManagerImpl::gComponentManager &&
         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
         nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, NULL);
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsComponentManagerImpl::AddBootstrappedManifestLocation(nsILocalFile* aLocation)
+{
+  nsString path;
+  nsresult rv = aLocation->GetPath(path);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
+    return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
+  }
+
+  nsCOMPtr<nsILocalFile> manifest =
+    CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
+  return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsILocalFile* aLocation)
+{
+  nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService();
+  if (!cr)
+    return NS_ERROR_FAILURE;
+
+  bool isJar = false;
+  nsCOMPtr<nsILocalFile> manifest;
+  nsString path;
+  nsresult rv = aLocation->GetPath(path);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
+    isJar = true;
+    manifest = aLocation;
+  } else {
+    manifest = CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
+  }
+
+  nsComponentManagerImpl::ComponentLocation elem = {
+    NS_BOOTSTRAPPED_LOCATION,
+    manifest,
+    isJar
+  };
+
+  // Remove reference.
+  nsComponentManagerImpl::sModuleLocations->RemoveElement(elem, ComponentLocationComparator());
+
+  rv = cr->CheckForNewChrome();
+  return rv;
+}
+
 EXPORT_XPCOM_API(nsresult)
 XRE_AddManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
 {
     nsComponentManagerImpl::InitializeModuleLocations();
     nsComponentManagerImpl::ComponentLocation* c = 
         nsComponentManagerImpl::sModuleLocations->AppendElement();
     c->type = aType;
     c->location = aLocation;
@@ -2068,13 +2120,13 @@ XRE_AddJarManifestLocation(NSLocationTyp
         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);
+        nsComponentManagerImpl::gComponentManager->RegisterJarManifest(aType, reader, "chrome.manifest", false);
 
     return NS_OK;
 }
 
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -157,16 +157,32 @@ public:
 
     struct ComponentLocation
     {
         NSLocationType type;
         nsCOMPtr<nsILocalFile> location;
         bool jar;
     };
 
+    class ComponentLocationComparator
+    {
+    public:
+      PRBool Equals(const ComponentLocation& a, const ComponentLocation& b) const
+      {
+        if (a.type == b.type && a.jar == b.jar) {
+          PRBool res;
+          nsresult rv = a.location->Equals(b.location, &res);
+          NS_ASSERTION(NS_SUCCEEDED(rv), "Error comparing locations");
+          return res;
+        }
+
+        return PR_FALSE;
+      }
+    };
+
     static nsTArray<const mozilla::Module*>* sStaticModules;
     static nsTArray<ComponentLocation>* sModuleLocations;
     static nsTArray<ComponentLocation>* sJarModuleLocations;
 
     nsNativeModuleLoader mNativeModuleLoader;
 
     class KnownModule
     {
@@ -235,17 +251,17 @@ public:
     nsClassHashtable<nsCStringHashKey, KnownModule> mKnownJARModules;
 
     void RegisterModule(const mozilla::Module* aModule,
                         nsILocalFile* aFile);
     void RegisterCIDEntry(const mozilla::Module::CIDEntry* aEntry,
                           KnownModule* aModule);
     void RegisterContractID(const mozilla::Module::ContractIDEntry* aEntry);
 
-    void RegisterJarManifest(nsIZipReader* aReader,
+    void RegisterJarManifest(NSLocationType aType, nsIZipReader* aReader,
                              const char* aPath, bool aChromeOnly);
 
     void RegisterManifestFile(NSLocationType aType, nsILocalFile* aFile,
                               bool aChromeOnly);
 
     struct ManifestProcessingContext
     {
         ManifestProcessingContext(NSLocationType aType, nsILocalFile* aFile, bool aChromeOnly)
--- a/xpcom/components/nsIComponentManager.idl
+++ b/xpcom/components/nsIComponentManager.idl
@@ -36,19 +36,20 @@
  * ***** END LICENSE BLOCK ***** */
   
 /**
  * The nsIComponentManager interface.
  */
 
 #include "nsISupports.idl"
 
+interface nsILocalFile;
 interface nsIFactory;
 
-[scriptable, uuid(a88e5a60-205a-4bb1-94e1-2628daf51eae)]
+[scriptable, uuid(1d940426-5fe5-42c3-84ae-a300f2d9ebd5)]
 interface nsIComponentManager : nsISupports
 {    
     /**
      * getClassObject
      *
      * Returns the factory object that can be used to create instances of
      * CID aClass
      *
@@ -94,16 +95,37 @@ interface nsIComponentManager : nsISuppo
      * @param aContractID : aContractID of object instance requested
      * @param aDelegate : Used for aggregation
      * @param aIID : IID of interface requested
      */
     void createInstanceByContractID(in string aContractID,
                                     in nsISupports aDelegate,
                                     in nsIIDRef aIID, 
                                     [iid_is(aIID),retval] out nsQIResult result);
+
+    /**
+     * addBootstrappedManifestLocation
+     *
+     * Adds a bootstrapped manifest location on runtime.
+     *
+     * @param aLocation : A directory where chrome.manifest resides,
+     *                    or an XPI with it on the root.
+     */
+    void addBootstrappedManifestLocation(in nsILocalFile aLocation);
+
+    /**
+     * removeBootstrappedManifestLocation
+     *
+     * Removes a bootstrapped manifest location on runtime.
+     *
+     * @param aLocation : A directory where chrome.manifest resides,
+     *                    or an XPI with it on the root.
+     */
+    void removeBootstrappedManifestLocation(in nsILocalFile aLocation);
+
 };
 
 
 %{ C++
 #ifdef MOZILLA_INTERNAL_API
 #include "nsComponentManagerUtils.h"
 #endif
 %} C++