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 73534 acd21e50bd12c9a3260ad64848d80ed34ed25295
parent 73533 c1a6e33244953b6ed858e59c36bc01363d4c2aee
child 73535 f839abc8f1503c22dbe2183ee568fae277f05b9d
push idunknown
push userunknown
push dateunknown
reviewersdtownsend, bsmedberg
bugs564667
milestone8.0a1
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++