Bug 1451513 Part 1: Allow registering chrome: content resources draft
authorAndrew Swan <aswan@mozilla.com>
Thu, 05 Jul 2018 13:59:25 -0700
changeset 815865 4021e1a901b3294cbf26f2180f02cf04f163e042
parent 814180 6c0fa9a675c91390ca27664ffb626c56e8afea4d
child 815866 52cdd06759c2720547ccbe181a725b7f0b57ce9d
child 816167 e8199765fe97abe8607367e1e62d9d5908e619c5
push id115667
push useraswan@mozilla.com
push dateTue, 10 Jul 2018 04:13:19 +0000
bugs1451513
milestone63.0a1
Bug 1451513 Part 1: Allow registering chrome: content resources MozReview-Commit-ID: IuUnzb24jCN
toolkit/mozapps/extensions/AddonManagerStartup.cpp
toolkit/mozapps/extensions/test/xpcshell/test_registerchrome.js
--- a/toolkit/mozapps/extensions/AddonManagerStartup.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerStartup.cpp
@@ -665,35 +665,38 @@ static bool sObserverRegistered;
 class RegistryEntries final : public nsIJSRAIIHelper
                             , public LinkedListElement<RegistryEntries>
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIJSRAIIHELPER
 
   using Override = AutoTArray<nsCString, 2>;
+  using Content = AutoTArray<nsCString, 2>;
   using Locale = AutoTArray<nsCString, 3>;
 
-  RegistryEntries(FileLocation& location, nsTArray<Override>&& overrides, nsTArray<Locale>&& locales)
+  RegistryEntries(FileLocation& location, nsTArray<Override>&& overrides, nsTArray<Content>&& content, nsTArray<Locale>&& locales)
     : mLocation(location)
     , mOverrides(std::move(overrides))
+    , mContent(std::move(content))
     , mLocales(std::move(locales))
   {}
 
   void Register();
 
 protected:
   virtual ~RegistryEntries()
   {
     Unused << Destruct();
   }
 
 private:
   FileLocation mLocation;
   const nsTArray<Override> mOverrides;
+  const nsTArray<Content> mContent;
   const nsTArray<Locale> mLocales;
 };
 
 NS_IMPL_ISUPPORTS(RegistryEntries, nsIJSRAIIHelper)
 
 void
 RegistryEntries::Register()
 {
@@ -701,16 +704,21 @@ RegistryEntries::Register()
 
   nsChromeRegistry::ManifestProcessingContext context(NS_EXTENSION_LOCATION, mLocation);
 
   for (auto& override : mOverrides) {
     const char* args[] = {override[0].get(), override[1].get()};
     cr->ManifestOverride(context, 0, const_cast<char**>(args), 0);
   }
 
+  for (auto& content: mContent) {
+    const char* args[] = {content[0].get(), content[1].get()};
+    cr->ManifestContent(context, 0, const_cast<char**>(args), 0);
+  }
+
   for (auto& locale : mLocales) {
     const char* args[] = {locale[0].get(), locale[1].get(), locale[2].get()};
     cr->ManifestLocale(context, 0, const_cast<char**>(args), 0);
   }
 }
 
 NS_IMETHODIMP
 RegistryEntries::Destruct()
@@ -746,16 +754,17 @@ AddonManagerStartup::RegisterChrome(nsIU
   NS_ENSURE_ARG_POINTER(manifestURI);
   NS_ENSURE_TRUE(IsArray(locations), NS_ERROR_INVALID_ARG);
 
   FileLocation location;
   MOZ_TRY_VAR(location, GetFileLocation(manifestURI));
 
 
   nsTArray<RegistryEntries::Locale> locales;
+  nsTArray<RegistryEntries::Content> content;
   nsTArray<RegistryEntries::Override> overrides;
 
   JS::RootedObject locs(cx, &locations.toObject());
   JS::RootedValue arrayVal(cx);
   JS::RootedObject array(cx);
 
   for (auto elem : ArrayIter(cx, locs)) {
     arrayVal = elem.Value();
@@ -773,16 +782,19 @@ AddonManagerStartup::RegisterChrome(nsIU
     NS_ENSURE_TRUE(vals.Length() > 0, NS_ERROR_INVALID_ARG);
 
     nsCString type = vals[0];
     vals.RemoveElementAt(0);
 
     if (type.EqualsLiteral("override")) {
       NS_ENSURE_TRUE(vals.Length() == 2, NS_ERROR_INVALID_ARG);
       overrides.AppendElement(vals);
+    } else if (type.EqualsLiteral("content")) {
+      NS_ENSURE_TRUE(vals.Length() == 2, NS_ERROR_INVALID_ARG);
+      content.AppendElement(vals);
     } else if (type.EqualsLiteral("locale")) {
       NS_ENSURE_TRUE(vals.Length() == 3, NS_ERROR_INVALID_ARG);
       locales.AppendElement(vals);
     } else {
       return NS_ERROR_INVALID_ARG;
     }
   }
 
@@ -791,16 +803,17 @@ AddonManagerStartup::RegisterChrome(nsIU
     NS_ENSURE_TRUE(obs, NS_ERROR_UNEXPECTED);
     obs->AddObserver(this, "chrome-manifests-loaded", false);
 
     sObserverRegistered = true;
   }
 
   auto entry = MakeRefPtr<RegistryEntries>(location,
                                            std::move(overrides),
+                                           std::move(content),
                                            std::move(locales));
 
   entry->Register();
   GetRegistryEntries().insertBack(entry);
 
   entry.forget(result);
   return NS_OK;
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_registerchrome.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_registerchrome.js
@@ -11,59 +11,68 @@ add_task(async function() {
 
   let file1 = getFileURI("file1");
   let file2 = getFileURI("file2");
 
   let uri1 = getFileURI("chrome.manifest");
   let uri2 = getFileURI("manifest.json");
 
   let overrideURL = Services.io.newURI("chrome://global/content/foo");
+  let contentURL = Services.io.newURI("chrome://test/content/foo");
   let localeURL = Services.io.newURI("chrome://global/locale/foo");
 
   let origOverrideURL = registry.convertChromeURL(overrideURL);
   let origLocaleURL = registry.convertChromeURL(localeURL);
 
   // eslint-disable-next-line no-unused-vars
   let entry1 = aomStartup.registerChrome(uri1, [
     ["override", "chrome://global/content/foo", file1.spec],
+    ["content", "test", file2.spec + "/"],
     ["locale", "global", "en-US", file2.spec + "/"],
   ]);
 
   let entry2 = aomStartup.registerChrome(uri2, [
     ["override", "chrome://global/content/foo", file2.spec],
+    ["content", "test", file1.spec + "/"],
     ["locale", "global", "en-US", file1.spec + "/"],
   ]);
 
   // Initially, the second entry should override the first.
   equal(registry.convertChromeURL(overrideURL).spec, file2.spec);
-  equal(registry.convertChromeURL(localeURL).spec, file1.spec + "/foo");
+  let file = file1.spec + "/foo";
+  equal(registry.convertChromeURL(contentURL).spec, file);
+  equal(registry.convertChromeURL(localeURL).spec, file);
 
-  // After destroying the second entry, the first entry should not take
+  // After destroying the second entry, the first entry should now take
   // precedence.
   entry2.destruct();
   equal(registry.convertChromeURL(overrideURL).spec, file1.spec);
-  equal(registry.convertChromeURL(localeURL).spec, file2.spec + "/foo");
+  file = file2.spec + "/foo";
+  equal(registry.convertChromeURL(contentURL).spec, file);
+  equal(registry.convertChromeURL(localeURL).spec, file);
 
   // After dropping the reference to the first entry and allowing it to
   // be GCed, we should be back to the original entries.
   entry1 = null;
   Cu.forceGC();
   Cu.forceCC();
   equal(registry.convertChromeURL(overrideURL).spec, origOverrideURL.spec);
   equal(registry.convertChromeURL(localeURL).spec, origLocaleURL.spec);
+  Assert.throws(() => registry.convertChromeURL(contentURL),
+                e => e.result == Cr.NS_ERROR_FILE_NOT_FOUND,
+                "chrome://test/ should no longer be registered");
 });
 
 add_task(async function() {
   const INVALID_VALUES = [
     {},
     "foo",
     ["foo"],
     [{}],
     [[]],
-    [["content", "foo", "bar"]],
     [["locale", "global"]],
     [["locale", "global", "en", "foo", "foo"]],
     [["override", "en"]],
     [["override", "en", "US", "OR"]],
   ];
 
   let uri = getFileURI("chrome.manifest");
   for (let arg of INVALID_VALUES) {