Bug 687194 - Update content processes when dynamic chrome registration occurs. r=mossop
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 25 Jul 2014 16:17:36 -0400
changeset 196200 f4bbd83d67e09ee189c0cfa6615a53ec5bc9e2c8
parent 196199 3a3c113c0da7e2ad3280672c2da8ab236dc47f0e
child 196201 eacefc24c9592817b1167886780b3f246f68f9c9
push idunknown
push userunknown
push dateunknown
reviewersmossop
bugs687194
milestone34.0a1
Bug 687194 - Update content processes when dynamic chrome registration occurs. r=mossop
chrome/RegistryMessageUtils.h
chrome/nsChromeRegistryChrome.cpp
chrome/nsChromeRegistryChrome.h
chrome/nsChromeRegistryContent.cpp
chrome/nsChromeRegistryContent.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/PContent.ipdl
--- a/chrome/RegistryMessageUtils.h
+++ b/chrome/RegistryMessageUtils.h
@@ -8,37 +8,58 @@
 
 #include "ipc/IPCMessageUtils.h"
 #include "nsString.h"
 
 struct SerializedURI
 {
   nsCString spec;
   nsCString charset;
+
+  bool operator ==(const SerializedURI& rhs) const
+  {
+      return spec.Equals(rhs.spec) &&
+             charset.Equals(rhs.charset);
+  }
 };
 
 struct ChromePackage
 {
   nsCString package;
   SerializedURI contentBaseURI;
   SerializedURI localeBaseURI;
   SerializedURI skinBaseURI;
   uint32_t flags;
+
+  bool operator ==(const ChromePackage& rhs) const
+  {
+    return package.Equals(rhs.package) &&
+           contentBaseURI == rhs.contentBaseURI &&
+           localeBaseURI == rhs.localeBaseURI &&
+           skinBaseURI == rhs.skinBaseURI &&
+           flags == rhs.flags;
+  }
 };
 
 struct ResourceMapping
 {
   nsCString resource;
   SerializedURI resolvedURI;
 };
 
 struct OverrideMapping
 {
   SerializedURI originalURI;
   SerializedURI overrideURI;
+
+  bool operator==(const OverrideMapping& rhs) const
+  {
+      return originalURI == rhs.originalURI &&
+             overrideURI == rhs.overrideURI;
+  }
 };
 
 namespace IPC {
 
 template<>
 struct ParamTraits<SerializedURI>
 {
   typedef SerializedURI paramType;
--- a/chrome/nsChromeRegistryChrome.cpp
+++ b/chrome/nsChromeRegistryChrome.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 sw=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/PContentParent.h"
+#include "mozilla/dom/ContentParent.h"
 #include "RegistryMessageUtils.h"
 #include "nsResProtocolHandler.h"
 
 #include "nsChromeRegistryChrome.h"
 
 #if defined(XP_WIN)
 #include <windows.h>
 #elif defined(XP_MACOSX)
@@ -19,16 +20,17 @@
 #include "nsComponentManager.h"
 #include "nsEnumeratorUtils.h"
 #include "nsNetUtil.h"
 #include "nsStringEnumerator.h"
 #include "nsTextFormatter.h"
 #include "nsXPCOMCIDInternal.h"
 
 #include "mozilla/LookAndFeel.h"
+#include "mozilla/unused.h"
 
 #include "nsICommandLine.h"
 #include "nsILocaleService.h"
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "mozilla/Preferences.h"
 #include "nsIResProtocolHandler.h"
@@ -39,16 +41,18 @@
 #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"
 #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
 
 using namespace mozilla;
+using mozilla::dom::ContentParent;
+using mozilla::dom::PContentParent;
 
 static PLDHashOperator
 RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, uint32_t number, void *arg)
 {
   return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE);
 }
 
 // We use a "best-fit" algorithm for matching locales and themes. 
@@ -94,16 +98,17 @@ LanguagesMatch(const nsACString& a, cons
       return (*as == '-');
   }
 
   return false;
 }
 
 nsChromeRegistryChrome::nsChromeRegistryChrome()
   : mProfileLoaded(false)
+  , mDynamicRegistration(true)
 {
   mPackagesHash.ops = nullptr;
 }
 
 nsChromeRegistryChrome::~nsChromeRegistryChrome()
 {
   if (mPackagesHash.ops)
     PL_DHashTableFinish(&mPackagesHash);
@@ -384,17 +389,23 @@ nsChromeRegistryChrome::Observe(nsISuppo
 NS_IMETHODIMP
 nsChromeRegistryChrome::CheckForNewChrome()
 {
   PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nullptr);
   mOverlayHash.Clear();
   mStyleHash.Clear();
   mOverrideTable.Clear();
 
+  mDynamicRegistration = false;
+
   nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
+
+  mDynamicRegistration = true;
+
+  SendRegisteredChrome(nullptr);
   return NS_OK;
 }
 
 nsresult nsChromeRegistryChrome::UpdateSelectedLocale()
 {
   nsresult rv = NS_OK;
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (prefs) {
@@ -471,45 +482,63 @@ nsChromeRegistryChrome::SendRegisteredCh
 
   //FIXME: Some substitutions are set up lazily and might not exist yet
   nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
   nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
   rph->CollectSubstitutions(resources);
 
   mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides);
 
-  bool success = aParent->SendRegisterChrome(packages, resources, overrides,
-                                             mSelectedLocale);
-  NS_ENSURE_TRUE_VOID(success);
+  if (aParent) {
+    bool success = aParent->SendRegisterChrome(packages, resources, overrides,
+                                               mSelectedLocale, false);
+    NS_ENSURE_TRUE_VOID(success);
+  } else {
+    nsTArray<ContentParent*> parents;
+    ContentParent::GetAll(parents);
+    if (!parents.Length())
+      return;
+
+    for (PRUint32 i = 0; i < parents.Length(); i++) {
+      DebugOnly<bool> success =
+        parents[i]->SendRegisterChrome(packages, resources, overrides,
+                                       mSelectedLocale, true);
+      NS_WARN_IF_FALSE(success, "couldn't reset a child's registered chrome");
+    }
+  }
+}
+
+/* static */ void
+nsChromeRegistryChrome::ChromePackageFromPackageEntry(PackageEntry* aPackage,
+                                                      ChromePackage* aChromePackage,
+                                                      const nsCString& aSelectedLocale,
+                                                      const nsCString& aSelectedSkin)
+{
+  SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
+  SerializeURI(aPackage->locales.GetBase(aSelectedLocale,
+                                         nsProviderArray::LOCALE),
+               aChromePackage->localeBaseURI);
+  SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
+               aChromePackage->skinBaseURI);
+  aChromePackage->package = aPackage->package;
+  aChromePackage->flags = aPackage->flags;
 }
 
 PLDHashOperator
 nsChromeRegistryChrome::CollectPackages(PLDHashTable *table,
                                   PLDHashEntryHdr *entry,
                                   uint32_t number,
                                   void *arg)
 {
   EnumerationArgs* args = static_cast<EnumerationArgs*>(arg);
   PackageEntry* package = static_cast<PackageEntry*>(entry);
 
-  SerializedURI contentURI, localeURI, skinURI;
-
-  SerializeURI(package->baseURI, contentURI);
-  SerializeURI(package->locales.GetBase(args->selectedLocale,
-                                        nsProviderArray::LOCALE), localeURI);
-  SerializeURI(package->skins.GetBase(args->selectedSkin, nsProviderArray::ANY),
-               skinURI);
-  
-  ChromePackage chromePackage = {
-    package->package,
-    contentURI,
-    localeURI,
-    skinURI,
-    package->flags
-  };
+  ChromePackage chromePackage;
+  ChromePackageFromPackageEntry(package, &chromePackage,
+                                args->selectedLocale, args->selectedSkin);
   args->packages.AppendElement(chromePackage);
   return (PLDHashOperator)PL_DHASH_NEXT;
 }
 
 static bool
 CanLoadResource(nsIURI* aResourceURI)
 {
   bool isLocalResource = false;
@@ -784,16 +813,29 @@ EnsureLowerCase(char *aBuf)
 {
   for (; *aBuf; ++aBuf) {
     char ch = *aBuf;
     if (ch >= 'A' && ch <= 'Z')
       *aBuf = ch + 'a' - 'A';
   }
 }
 
+static void
+SendManifestEntry(const ChromeRegistryItem &aItem)
+{
+  nsTArray<ContentParent*> parents;
+  ContentParent::GetAll(parents);
+  if (!parents.Length())
+    return;
+
+  for (uint32_t i = 0; i < parents.Length(); i++) {
+    unused << parents[i]->SendRegisterChromeItem(aItem);
+  }
+}
+
 void
 nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
                                         char *const * argv, bool platform,
                                         bool contentaccessible)
 {
   char* package = argv[0];
   char* uri = argv[1];
 
@@ -821,16 +863,22 @@ nsChromeRegistryChrome::ManifestContent(
     return;
 
   entry->baseURI = resolved;
 
   if (platform)
     entry->flags |= PLATFORM_PACKAGE;
   if (contentaccessible)
     entry->flags |= CONTENT_ACCESSIBLE;
+
+  if (mDynamicRegistration) {
+    ChromePackage chromePackage;
+    ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin);
+    SendManifestEntry(chromePackage);
+  }
 }
 
 void
 nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
                                        char *const * argv, bool platform,
                                        bool contentaccessible)
 {
   char* package = argv[0];
@@ -856,16 +904,22 @@ nsChromeRegistryChrome::ManifestLocale(M
   PackageEntry* entry =
     static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                     & (const nsACString&) nsDependentCString(package),
                                                     PL_DHASH_ADD));
   if (!entry)
     return;
 
   entry->locales.SetBase(nsDependentCString(provider), resolved);
+
+  if (mDynamicRegistration) {
+    ChromePackage chromePackage;
+    ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin);
+    SendManifestEntry(chromePackage);
+  }
 }
 
 void
 nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
                                      char *const * argv, bool platform,
                                      bool contentaccessible)
 {
   char* package = argv[0];
@@ -891,16 +945,22 @@ nsChromeRegistryChrome::ManifestSkin(Man
   PackageEntry* entry =
     static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                     & (const nsACString&) nsDependentCString(package),
                                                     PL_DHASH_ADD));
   if (!entry)
     return;
 
   entry->skins.SetBase(nsDependentCString(provider), resolved);
+
+  if (mDynamicRegistration) {
+    ChromePackage chromePackage;
+    ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin);
+    SendManifestEntry(chromePackage);
+  }
 }
 
 void
 nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
                                         char *const * argv, bool platform,
                                         bool contentaccessible)
 {
   char* base = argv[0];
@@ -965,16 +1025,27 @@ nsChromeRegistryChrome::ManifestOverride
   }
 
   if (!CanLoadResource(resolveduri)) {
     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
                           "Cannot register non-local URI '%s' for an override.", resolved);
     return;
   }
   mOverrideTable.Put(chromeuri, resolveduri);
+
+  if (mDynamicRegistration) {
+    SerializedURI serializedChrome;
+    SerializedURI serializedOverride;
+
+    SerializeURI(chromeuri, serializedChrome);
+    SerializeURI(resolveduri, serializedOverride);
+
+    OverrideMapping override = { serializedChrome, serializedOverride };
+    SendManifestEntry(override);
+  }
 }
 
 void
 nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
                                          char *const * argv, bool platform,
                                          bool contentaccessible)
 {
   char* package = argv[0];
--- a/chrome/nsChromeRegistryChrome.h
+++ b/chrome/nsChromeRegistryChrome.h
@@ -13,16 +13,17 @@
 
 namespace mozilla {
 namespace dom {
 class PContentParent;
 }
 }
 
 class nsIPrefBranch;
+struct ChromePackage;
 
 class nsChromeRegistryChrome : public nsChromeRegistry
 {
  public:
   nsChromeRegistryChrome();
   ~nsChromeRegistryChrome();
 
   nsresult Init() MOZ_OVERRIDE;
@@ -39,20 +40,28 @@ class nsChromeRegistryChrome : public ns
                      const char16_t *someData) MOZ_OVERRIDE;
 
 #ifdef MOZ_XUL
   NS_IMETHOD GetXULOverlays(nsIURI *aURI,
                             nsISimpleEnumerator **_retval) MOZ_OVERRIDE;
   NS_IMETHOD GetStyleOverlays(nsIURI *aURI,
                               nsISimpleEnumerator **_retval) MOZ_OVERRIDE;
 #endif
-  
+
+  // If aChild is non-null then it is a new child to notify. If aChild is
+  // null, then we have installed new chrome and we are resetting all of our
+  // children's registered chrome.
   void SendRegisteredChrome(mozilla::dom::PContentParent* aChild);
 
  private:
+  struct PackageEntry;
+  static void ChromePackageFromPackageEntry(PackageEntry* aPackage,
+                                            ChromePackage* aChromePackage,
+                                            const nsCString& aSelectedLocale,
+                                            const nsCString& aSelectedSkin);
   static PLDHashOperator CollectPackages(PLDHashTable *table,
                                          PLDHashEntryHdr *entry,
                                          uint32_t number, void *arg);
 
   nsresult OverrideLocalePackage(const nsACString& aPackage,
                                  nsACString& aOverride);
   nsresult SelectLocaleFromPref(nsIPrefBranch* prefs);
   nsresult UpdateSelectedLocale() MOZ_OVERRIDE;
@@ -150,17 +159,18 @@ class nsChromeRegistryChrome : public ns
   };
 
   // Hashes on the file to be overlaid (chrome://browser/content/browser.xul)
   // to a list of overlays/stylesheets
   OverlayListHash mOverlayHash;
   OverlayListHash mStyleHash;
 
   bool mProfileLoaded;
-  
+  bool mDynamicRegistration;
+
   nsCString mSelectedLocale;
   nsCString mSelectedSkin;
 
   // Hash of package names ("global") to PackageEntry objects
   PLDHashTable mPackagesHash;
 
   virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
                                char *const * argv, bool platform,
--- a/chrome/nsChromeRegistryContent.cpp
+++ b/chrome/nsChromeRegistryContent.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sts=2 sw=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RegistryMessageUtils.h"
 #include "nsChromeRegistryContent.h"
 #include "nsString.h"
 #include "nsNetUtil.h"
@@ -13,21 +14,28 @@ nsChromeRegistryContent::nsChromeRegistr
 {
 }
 
 void
 nsChromeRegistryContent::RegisterRemoteChrome(
     const InfallibleTArray<ChromePackage>& aPackages,
     const InfallibleTArray<ResourceMapping>& aResources,
     const InfallibleTArray<OverrideMapping>& aOverrides,
-    const nsACString& aLocale)
+    const nsACString& aLocale,
+    bool aReset)
 {
-  NS_ABORT_IF_FALSE(mLocale == nsDependentCString(""),
+  NS_ABORT_IF_FALSE(aReset || mLocale.IsEmpty(),
                     "RegisterChrome twice?");
 
+  if (aReset) {
+    mPackagesHash.Clear();
+    mOverrideTable.Clear();
+    // XXX Can't clear resources.
+  }
+
   for (uint32_t i = aPackages.Length(); i > 0; ) {
     --i;
     RegisterPackage(aPackages[i]);
   }
 
   for (uint32_t i = aResources.Length(); i > 0; ) {
     --i;
     RegisterResource(aResources[i]);
@@ -101,17 +109,17 @@ nsChromeRegistryContent::RegisterResourc
   if (!rph)
     return;
 
   nsCOMPtr<nsIURI> resolvedURI;
   if (aResource.resolvedURI.spec.Length()) {
     nsresult rv = NS_NewURI(getter_AddRefs(resolvedURI),
                             aResource.resolvedURI.spec,
                             aResource.resolvedURI.charset.get(),
-                            nullptr, io);                 
+                            nullptr, io);
     if (NS_FAILED(rv))
       return;
   }
 
   rv = rph->SetSubstitution(aResource.resource, resolvedURI);
   if (NS_FAILED(rv))
     return;
 }
--- a/chrome/nsChromeRegistryContent.h
+++ b/chrome/nsChromeRegistryContent.h
@@ -12,52 +12,53 @@
 struct ChromePackage;
 struct ResourceMapping;
 struct OverrideMapping;
 
 class nsChromeRegistryContent : public nsChromeRegistry
 {
  public:
   nsChromeRegistryContent();
-  
+
   void RegisterRemoteChrome(const InfallibleTArray<ChromePackage>& aPackages,
                             const InfallibleTArray<ResourceMapping>& aResources,
                             const InfallibleTArray<OverrideMapping>& aOverrides,
-                            const nsACString& aLocale);
+                            const nsACString& aLocale,
+                            bool aReset);
 
   NS_IMETHOD GetLocalesForPackage(const nsACString& aPackage,
                                   nsIUTF8StringEnumerator* *aResult) MOZ_OVERRIDE;
   NS_IMETHOD CheckForNewChrome() MOZ_OVERRIDE;
   NS_IMETHOD CheckForOSAccessibility() MOZ_OVERRIDE;
   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
                      const char16_t* aData) MOZ_OVERRIDE;
   NS_IMETHOD IsLocaleRTL(const nsACString& package,
                          bool *aResult) MOZ_OVERRIDE;
   NS_IMETHOD GetSelectedLocale(const nsACString& aPackage,
                                nsACString& aLocale) MOZ_OVERRIDE;
   NS_IMETHOD GetStyleOverlays(nsIURI *aChromeURL,
                               nsISimpleEnumerator **aResult) MOZ_OVERRIDE;
   NS_IMETHOD GetXULOverlays(nsIURI *aChromeURL,
                             nsISimpleEnumerator **aResult) MOZ_OVERRIDE;
 
+  void RegisterPackage(const ChromePackage& aPackage);
+  void RegisterOverride(const OverrideMapping& aOverride);
+  void RegisterResource(const ResourceMapping& aResource);
+
  private:
   struct PackageEntry
   {
     PackageEntry() : flags(0) { }
     ~PackageEntry() { }
 
     nsCOMPtr<nsIURI> contentBaseURI;
     nsCOMPtr<nsIURI> localeBaseURI;
     nsCOMPtr<nsIURI> skinBaseURI;
     uint32_t         flags;
   };
-  
-  void RegisterPackage(const ChromePackage& aPackage);
-  void RegisterResource(const ResourceMapping& aResource);
-  void RegisterOverride(const OverrideMapping& aOverride);
 
   nsresult UpdateSelectedLocale() MOZ_OVERRIDE;
   nsIURI* GetBaseURIFromPackage(const nsCString& aPackage,
                      const nsCString& aProvider,
                      const nsCString& aPath) MOZ_OVERRIDE;
   nsresult GetFlagsFromPackage(const nsCString& aPackage, uint32_t* aFlags) MOZ_OVERRIDE;
 
   nsClassHashtable<nsCStringHashKey, PackageEntry> mPackagesHash;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1369,22 +1369,47 @@ ContentChild::DeallocPSpeechSynthesisChi
     return false;
 #endif
 }
 
 bool
 ContentChild::RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
                                  const InfallibleTArray<ResourceMapping>& resources,
                                  const InfallibleTArray<OverrideMapping>& overrides,
-                                 const nsCString& locale)
+                                 const nsCString& locale,
+                                 const bool& reset)
 {
     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
     nsChromeRegistryContent* chromeRegistry =
         static_cast<nsChromeRegistryContent*>(registrySvc.get());
-    chromeRegistry->RegisterRemoteChrome(packages, resources, overrides, locale);
+    chromeRegistry->RegisterRemoteChrome(packages, resources, overrides,
+                                         locale, reset);
+    return true;
+}
+
+bool
+ContentChild::RecvRegisterChromeItem(const ChromeRegistryItem& item)
+{
+    nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
+    nsChromeRegistryContent* chromeRegistry =
+        static_cast<nsChromeRegistryContent*>(registrySvc.get());
+    switch (item.type()) {
+        case ChromeRegistryItem::TChromePackage:
+            chromeRegistry->RegisterPackage(item.get_ChromePackage());
+            break;
+
+        case ChromeRegistryItem::TOverrideMapping:
+            chromeRegistry->RegisterOverride(item.get_OverrideMapping());
+            break;
+
+        default:
+            MOZ_ASSERT(false, "bad chrome item");
+            return false;
+    }
+
     return true;
 }
 
 bool
 ContentChild::RecvSetOffline(const bool& offline)
 {
     nsCOMPtr<nsIIOService> io (do_GetIOService());
     NS_ASSERTION(io, "IO Service can not be null");
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -235,17 +235,19 @@ public:
                                     PAsmJSCacheEntryChild* aActor) MOZ_OVERRIDE;
 
     virtual PSpeechSynthesisChild* AllocPSpeechSynthesisChild() MOZ_OVERRIDE;
     virtual bool DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) MOZ_OVERRIDE;
 
     virtual bool RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
                                     const InfallibleTArray<ResourceMapping>& resources,
                                     const InfallibleTArray<OverrideMapping>& overrides,
-                                    const nsCString& locale) MOZ_OVERRIDE;
+                                    const nsCString& locale,
+                                    const bool& reset) MOZ_OVERRIDE;
+    virtual bool RecvRegisterChromeItem(const ChromeRegistryItem& item) MOZ_OVERRIDE;
 
     virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() MOZ_OVERRIDE;
     virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*) MOZ_OVERRIDE;
     virtual PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild() MOZ_OVERRIDE;
     virtual bool DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild*) MOZ_OVERRIDE;
 
     virtual bool RecvSetOffline(const bool& offline) MOZ_OVERRIDE;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -52,16 +52,22 @@ using struct mozilla::void_t from "ipc/I
 using mozilla::dom::asmjscache::OpenMode from "mozilla/dom/asmjscache/AsmJSCache.h";
 using mozilla::dom::asmjscache::WriteParams from "mozilla/dom/asmjscache/AsmJSCache.h";
 using mozilla::dom::AudioChannel from "mozilla/dom/AudioChannelBinding.h";
 using mozilla::dom::AudioChannelState from "AudioChannelCommon.h";
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
 using gfxIntSize from "nsSize.h";
 
+union ChromeRegistryItem
+{
+    ChromePackage;
+    OverrideMapping;
+};
+
 namespace mozilla {
 namespace dom {
 
 struct FontListEntry {
     nsString  familyName;
     nsString  faceName;
     nsCString filepath;
     uint16_t  weight;
@@ -376,17 +382,18 @@ child:
      */
     PCycleCollectWithLogs(bool dumpAllTraces,
                           FileDescriptor gcLog,
                           FileDescriptor ccLog);
 
     PTestShell();
 
     RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
-                   OverrideMapping[] overrides, nsCString locale);
+                   OverrideMapping[] overrides, nsCString locale, bool reset);
+    RegisterChromeItem(ChromeRegistryItem item);
 
     async SetOffline(bool offline);
 
     async NotifyVisited(URIParams uri);
 
     async SystemMemoryAvailable(uint64_t getterId, uint32_t memoryAvailable);
 
     PreferenceUpdate(PrefSetting pref);