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 196074 f4bbd83d67e09ee189c0cfa6615a53ec5bc9e2c8
parent 196073 3a3c113c0da7e2ad3280672c2da8ab236dc47f0e
child 196075 eacefc24c9592817b1167886780b3f246f68f9c9
push id46787
push usermrbkap@mozilla.com
push dateFri, 25 Jul 2014 20:18:24 +0000
treeherdermozilla-inbound@f4bbd83d67e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs687194
milestone34.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 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);