Bug 1442239 - Make URI deserialization (nsISerializable.read) happen via nsIURIMutator only r=mayhemer
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 19 Mar 2018 20:22:32 +0100
changeset 408890 61aa0247279aaacf8e0aedf47281f15de8952258
parent 408889 abbc5dc0409eb1a2871e2fbd782bf4b9f28f9693
child 408891 377b62a130e78fa57d0311b2887cbabeffea6823
push id33664
push usershindli@mozilla.com
push dateTue, 20 Mar 2018 10:10:08 +0000
treeherdermozilla-central@70fe801fb934 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1442239
milestone61.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 1442239 - Make URI deserialization (nsISerializable.read) happen via nsIURIMutator only r=mayhemer * Deserialization now only happens via a mutator * The CID for URI implementations actually returns the nsIURIMutator for each class * The QueryInterface of mutators implementing nsISerializable will now act as a finalizer if passed the IID of an interface implemented by the URI it holds MozReview-Commit-ID: H5MUJOEkpia
caps/NullPrincipalURI.h
dom/file/nsHostObjectURI.cpp
dom/file/nsHostObjectURI.h
dom/jsurl/nsJSProtocolHandler.cpp
dom/jsurl/nsJSProtocolHandler.h
image/decoders/icon/nsIconURI.h
layout/build/nsLayoutModule.cpp
modules/libjar/nsJARFactory.cpp
modules/libjar/nsJARURI.cpp
modules/libjar/nsJARURI.h
netwerk/base/nsIURIMutator.idl
netwerk/base/nsSimpleNestedURI.cpp
netwerk/base/nsSimpleNestedURI.h
netwerk/base/nsSimpleURI.cpp
netwerk/base/nsSimpleURI.h
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/build/nsNetCID.h
netwerk/build/nsNetModule.cpp
netwerk/protocol/about/nsAboutProtocolHandler.cpp
netwerk/protocol/about/nsAboutProtocolHandler.h
netwerk/protocol/res/SubstitutingProtocolHandler.cpp
netwerk/test/unit/test_uri_mutator.js
widget/tests/unit/test_taskbar_jumplistitems.js
--- a/caps/NullPrincipalURI.h
+++ b/caps/NullPrincipalURI.h
@@ -79,21 +79,16 @@ public:
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
     NS_IMETHOD Deserialize(const mozilla::ipc::URIParams& aParams) override
     {
       return InitFromIPCParams(aParams);
     }
 
-    NS_IMETHOD Read(nsIObjectInputStream* aStream) override
-    {
-      return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
--- a/dom/file/nsHostObjectURI.cpp
+++ b/dom/file/nsHostObjectURI.cpp
@@ -70,17 +70,17 @@ nsHostObjectURI::GetPrincipalUri(nsIURI*
   return NS_OK;
 }
 
 // nsISerializable methods:
 
 NS_IMETHODIMP
 nsHostObjectURI::Read(nsIObjectInputStream* aStream)
 {
-  nsresult rv = mozilla::net::nsSimpleURI::Read(aStream);
+  nsresult rv = mozilla::net::nsSimpleURI::ReadPrivate(aStream);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISupports> supports;
   rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mPrincipal = do_QueryInterface(supports, &rv);
   return rv;
@@ -225,17 +225,23 @@ nsHostObjectURI::EqualsInternal(nsIURI* 
     // Both of us have mPrincipals. Compare them.
     return mPrincipal->Equals(otherUri->mPrincipal, aResult);
   }
   // else, at least one of us lacks a principal; only equal if *both* lack it.
   *aResult = (!mPrincipal && !otherUri->mPrincipal);
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS(nsHostObjectURI::Mutator, nsIURISetters, nsIURIMutator, nsIBlobURIMutator, nsIPrincipalURIMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsHostObjectURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsIBlobURIMutator,
+                                nsIPrincipalURIMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsHostObjectURI::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsHostObjectURI::Mutator> mutator = new nsHostObjectURI::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
--- a/dom/file/nsHostObjectURI.h
+++ b/dom/file/nsHostObjectURI.h
@@ -80,21 +80,34 @@ protected:
   bool Deserialize(const mozilla::ipc::URIParams&);
 
 public:
   class Mutator final
     : public nsIURIMutator
     , public BaseURIMutator<nsHostObjectURI>
     , public nsIBlobURIMutator
     , public nsIPrincipalURIMutator
+    , public nsISerializable
   {
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
     NS_DEFINE_NSIMUTATOR_COMMON
 
+    NS_IMETHOD
+    Write(nsIObjectOutputStream *aOutputStream) override
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    MOZ_MUST_USE NS_IMETHOD
+    Read(nsIObjectInputStream* aStream) override
+    {
+        return InitFromInputStream(aStream);
+    }
+
     MOZ_MUST_USE NS_IMETHOD
     SetBlobImpl(mozilla::dom::BlobImpl *aBlobImpl) override
     {
         if (!mURI) {
             return NS_ERROR_NULL_POINTER;
         }
         mURI->mBlobImpl = aBlobImpl;
         return NS_OK;
@@ -119,9 +132,13 @@ public:
 
   friend BaseURIMutator<nsHostObjectURI>;
 };
 
 #define NS_HOSTOBJECTURI_CID \
 { 0xf5475c51, 0x59a7, 0x4757, \
   { 0xb3, 0xd9, 0xe2, 0x11, 0xa9, 0x41, 0x08, 0x72 } }
 
+#define NS_HOSTOBJECTURIMUTATOR_CID \
+{ 0xbbe50ef2, 0x80eb, 0x469d, \
+  { 0xb7, 0x0d, 0x02, 0x85, 0x82, 0x75, 0x38, 0x9f } }
+
 #endif /* nsHostObjectURI_h */
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -1278,19 +1278,26 @@ NS_INTERFACE_MAP_BEGIN(nsJSURI)
       return NS_NOINTERFACE;
   }
   else
 NS_INTERFACE_MAP_END_INHERITING(mozilla::net::nsSimpleURI)
 
 // nsISerializable methods:
 
 NS_IMETHODIMP
-nsJSURI::Read(nsIObjectInputStream* aStream)
+nsJSURI::Read(nsIObjectInputStream *aStream)
 {
-    nsresult rv = mozilla::net::nsSimpleURI::Read(aStream);
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsJSURI::ReadPrivate(nsIObjectInputStream *aStream)
+{
+    nsresult rv = mozilla::net::nsSimpleURI::ReadPrivate(aStream);
     if (NS_FAILED(rv)) return rv;
 
     bool haveBase;
     rv = aStream->ReadBoolean(&haveBase);
     if (NS_FAILED(rv)) return rv;
 
     if (haveBase) {
         nsCOMPtr<nsISupports> supports;
@@ -1375,17 +1382,21 @@ nsJSURI::StartClone(mozilla::net::nsSimp
       }
     }
 
     nsJSURI* url = new nsJSURI(baseClone);
     SetRefOnClone(url, refHandlingMode, newRef);
     return url;
 }
 
-NS_IMPL_ISUPPORTS(nsJSURI::Mutator, nsIURISetters, nsIURIMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsJSURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsJSURI::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsJSURI::Mutator> mutator = new nsJSURI::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
--- a/dom/jsurl/nsJSProtocolHandler.h
+++ b/dom/jsurl/nsJSProtocolHandler.h
@@ -26,16 +26,24 @@
 #define NS_JSURI_CID                                 \
 { /* 58f089ee-512a-42d2-a935-d0c874128930 */         \
     0x58f089ee,                                      \
     0x512a,                                          \
     0x42d2,                                          \
     {0xa9, 0x35, 0xd0, 0xc8, 0x74, 0x12, 0x89, 0x30} \
 }
 
+#define NS_JSURIMUTATOR_CID                          \
+{ /* 574ce83e-fe9f-4095-b85c-7909abbf7c37 */         \
+    0x574ce83e,                                      \
+    0xfe9f,                                          \
+    0x4095,                                          \
+    {0xb8, 0x5c, 0x79, 0x09, 0xab, 0xbf, 0x7c, 0x37} \
+}
+
 #define NS_JSPROTOCOLHANDLER_CONTRACTID \
     NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "javascript"
 
 
 class nsJSProtocolHandler : public nsIProtocolHandler
 {
 public:
     NS_DECL_ISUPPORTS
@@ -98,29 +106,43 @@ public:
 
 protected:
     virtual ~nsJSURI() {}
 
     virtual nsresult EqualsInternal(nsIURI* other,
                                     RefHandlingEnum refHandlingMode,
                                     bool* result) override;
     bool Deserialize(const mozilla::ipc::URIParams&);
+    nsresult ReadPrivate(nsIObjectInputStream *aStream);
 
 private:
     nsCOMPtr<nsIURI> mBaseURI;
 
 public:
     class Mutator final
         : public nsIURIMutator
         , public BaseURIMutator<nsJSURI>
+        , public nsISerializable
     {
         NS_DECL_ISUPPORTS
         NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
+        MOZ_MUST_USE NS_IMETHOD
+        Read(nsIObjectInputStream* aStream) override
+        {
+            return InitFromInputStream(aStream);
+        }
+
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsJSURI;
     };
 
     friend BaseURIMutator<nsJSURI>;
--- a/image/decoders/icon/nsIconURI.h
+++ b/image/decoders/icon/nsIconURI.h
@@ -72,21 +72,16 @@ public:
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
     NS_IMETHOD Deserialize(const mozilla::ipc::URIParams& aParams) override
     {
       return InitFromIPCParams(aParams);
     }
 
-    NS_IMETHOD Read(nsIObjectInputStream* aStream) override
-    {
-      return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -215,17 +215,18 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(HTMLEdito
 #define PRESENTATION_TCP_SESSION_TRANSPORT_CID \
 { 0xc9d023f4, 0x6228, 0x4c07, { 0x8b, 0x1d, 0x9c, 0x19, 0x57, 0x3f, 0xaa, 0x27 } }
 
 already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
+typedef nsHostObjectURI::Mutator nsHostObjectURIMutator;
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURIMutator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMParser)
 NS_GENERIC_FACTORY_CONSTRUCTOR(LocalStorageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(SessionStorageManager)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService,
                                          DOMRequestService::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManagerService,
                                          QuotaManagerService::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ServiceWorkerManager,
@@ -429,17 +430,18 @@ MAKE_CTOR(CreateChildMessageManager,    
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy)
 MAKE_CTOR(CreatePluginDocument,           nsIDocument,                 NS_NewPluginDocument)
 MAKE_CTOR(CreateVideoDocument,            nsIDocument,                 NS_NewVideoDocument)
 MAKE_CTOR(CreateFocusManager,             nsIFocusManager,      NS_NewFocusManager)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init)
 
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSURI)
+typedef nsJSURI::Mutator nsJSURIMutator;
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSURIMutator)
 
 // views are not refcounted, so this is the same as
 // NS_GENERIC_FACTORY_CONSTRUCTOR without the NS_ADDREF/NS_RELEASE
 #define NS_GENERIC_FACTORY_CONSTRUCTOR_NOREFS(_InstanceClass)                 \
 static nsresult                                                               \
 _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,               \
                             void **aResult)                                   \
 {                                                                             \
@@ -568,25 +570,27 @@ NS_DEFINE_NAMED_CID(NS_NODATAPROTOCOLCON
 NS_DEFINE_NAMED_CID(NS_XULCONTROLLERS_CID);
 #ifdef MOZ_XUL
 NS_DEFINE_NAMED_CID(NS_XULSORTSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_XULDOCUMENT_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_CONTENT_DOCUMENT_LOADER_FACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_JSPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_JSURI_CID);
+NS_DEFINE_NAMED_CID(NS_JSURIMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_WINDOWCOMMANDTABLE_CID);
 NS_DEFINE_NAMED_CID(NS_WINDOWCONTROLLER_CID);
 NS_DEFINE_NAMED_CID(NS_PLUGINDOCLOADERFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_PLUGINDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_VIDEODOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_STYLESHEETSERVICE_CID);
 NS_DEFINE_NAMED_CID(TRANSFORMIIX_NODESET_CID);
 NS_DEFINE_NAMED_CID(NS_XMLSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
+NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURIMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_DOMPARSER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSESSIONSTORAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMLOCALSTORAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
 NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
 NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID);
 NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID);
 NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID);
@@ -814,26 +818,28 @@ static const mozilla::Module::CIDEntry k
   { &kNS_NODATAPROTOCOLCONTENTPOLICY_CID, false, nullptr, nsNoDataProtocolContentPolicyConstructor },
   { &kNS_XULCONTROLLERS_CID, false, nullptr, NS_NewXULControllers },
 #ifdef MOZ_XUL
   { &kNS_XULSORTSERVICE_CID, false, nullptr, CreateXULSortService },
   { &kNS_XULDOCUMENT_CID, false, nullptr, CreateXULDocument },
 #endif
   { &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID, false, nullptr, CreateContentDLF },
   { &kNS_JSPROTOCOLHANDLER_CID, false, nullptr, nsJSProtocolHandler::Create },
-  { &kNS_JSURI_CID, false, nullptr, nsJSURIConstructor },
+  { &kNS_JSURI_CID, false, nullptr, nsJSURIMutatorConstructor }, // do_CreateInstance returns mutator
+  { &kNS_JSURIMUTATOR_CID, false, nullptr, nsJSURIMutatorConstructor },
   { &kNS_WINDOWCOMMANDTABLE_CID, false, nullptr, CreateWindowCommandTableConstructor },
   { &kNS_WINDOWCONTROLLER_CID, false, nullptr, CreateWindowControllerWithSingletonCommandTable },
   { &kNS_PLUGINDOCLOADERFACTORY_CID, false, nullptr, CreateContentDLF },
   { &kNS_PLUGINDOCUMENT_CID, false, nullptr, CreatePluginDocument },
   { &kNS_VIDEODOCUMENT_CID, false, nullptr, CreateVideoDocument },
   { &kNS_STYLESHEETSERVICE_CID, false, nullptr, nsStyleSheetServiceConstructor },
   { &kTRANSFORMIIX_NODESET_CID, false, nullptr, txNodeSetAdaptorConstructor },
   { &kNS_XMLSERIALIZER_CID, false, nullptr, nsDOMSerializerConstructor },
-  { &kNS_HOSTOBJECTURI_CID, false, nullptr, nsHostObjectURIConstructor },
+  { &kNS_HOSTOBJECTURI_CID, false, nullptr, nsHostObjectURIMutatorConstructor }, // do_CreateInstance returns mutator
+  { &kNS_HOSTOBJECTURIMUTATOR_CID, false, nullptr, nsHostObjectURIMutatorConstructor },
   { &kNS_DOMPARSER_CID, false, nullptr, DOMParserConstructor },
   { &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, nullptr, SessionStorageManagerConstructor },
   { &kNS_DOMLOCALSTORAGEMANAGER_CID, false, nullptr, LocalStorageManagerConstructor },
   { &kNS_TEXTEDITOR_CID, false, nullptr, TextEditorConstructor },
   { &kDOMREQUEST_SERVICE_CID, false, nullptr, DOMRequestServiceConstructor },
   { &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor },
   { &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor },
   { &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor },
--- a/modules/libjar/nsJARFactory.cpp
+++ b/modules/libjar/nsJARFactory.cpp
@@ -15,32 +15,31 @@
 #include "nsJARProtocolHandler.h"
 #include "nsJARURI.h"
 #include "nsJAR.h"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJAR)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsZipReaderCache)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsJARProtocolHandler,
                                          nsJARProtocolHandler::GetSingleton)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsJARURI)
 
 typedef nsJARURI::Mutator nsJARURIMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJARURIMutator)
 
 NS_DEFINE_NAMED_CID(NS_ZIPREADER_CID);
 NS_DEFINE_NAMED_CID(NS_ZIPREADERCACHE_CID);
 NS_DEFINE_NAMED_CID(NS_JARPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_JARURI_CID);
 NS_DEFINE_NAMED_CID(NS_JARURIMUTATOR_CID);
 
 static const mozilla::Module::CIDEntry kJARCIDs[] = {
     { &kNS_ZIPREADER_CID, false, nullptr, nsJARConstructor },
     { &kNS_ZIPREADERCACHE_CID, false, nullptr, nsZipReaderCacheConstructor },
     { &kNS_JARPROTOCOLHANDLER_CID, false, nullptr, nsJARProtocolHandlerConstructor },
-    { &kNS_JARURI_CID, false, nullptr, nsJARURIConstructor },
+    { &kNS_JARURI_CID, false, nullptr, nsJARURIMutatorConstructor }, // do_CreateInstance returns mutator
     { &kNS_JARURIMUTATOR_CID, false, nullptr, nsJARURIMutatorConstructor },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kJARContracts[] = {
     { "@mozilla.org/libjar/zip-reader;1", &kNS_ZIPREADER_CID },
     { "@mozilla.org/libjar/zip-reader-cache;1", &kNS_ZIPREADERCACHE_CID },
     { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar", &kNS_JARPROTOCOLHANDLER_CID },
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -102,17 +102,24 @@ nsJARURI::CreateEntryURL(const nsACStrin
                                 spec, charset, nullptr, nullptr))
         .Finalize(url);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISerializable methods:
 
 NS_IMETHODIMP
-nsJARURI::Read(nsIObjectInputStream* aInputStream)
+nsJARURI::Read(nsIObjectInputStream *aStream)
+{
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsJARURI::ReadPrivate(nsIObjectInputStream *aInputStream)
 {
     nsresult rv;
 
     nsCOMPtr<nsISupports> supports;
     rv = aInputStream->ReadObject(true, getter_AddRefs(supports));
     NS_ENSURE_SUCCESS(rv, rv);
 
     mJARFile = do_QueryInterface(supports, &rv);
@@ -251,17 +258,22 @@ nsJARURI::GetHasRef(bool *result)
 }
 
 nsresult
 nsJARURI::SetSpecInternal(const nsACString& aSpec)
 {
     return SetSpecWithBase(aSpec, nullptr);
 }
 
-NS_IMPL_ISUPPORTS(nsJARURI::Mutator, nsIURISetters, nsIURIMutator, nsIURLMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsJARURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsIURLMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsJARURI::Mutator::SetFileName(const nsACString& aFileName, nsIURIMutator** aMutator)
 {
     if (!mURI) {
         return NS_ERROR_NULL_POINTER;
     }
     if (aMutator) {
--- a/modules/libjar/nsJARURI.h
+++ b/modules/libjar/nsJARURI.h
@@ -109,32 +109,46 @@ private:
     nsresult SetHost(const nsACString &input);
     nsresult SetPort(int32_t port);
     nsresult SetPathQueryRef(const nsACString &input);
     nsresult SetRef(const nsACString &input);
     nsresult SetFilePath(const nsACString &input);
     nsresult SetQuery(const nsACString &input);
     nsresult SetQueryWithEncoding(const nsACString &input, const Encoding* encoding);
     bool Deserialize(const mozilla::ipc::URIParams&);
+    nsresult ReadPrivate(nsIObjectInputStream *aStream);
 
     nsresult SetFileNameInternal(const nsACString& fileName);
     nsresult SetFileBaseNameInternal(const nsACString& fileBaseName);
     nsresult SetFileExtensionInternal(const nsACString& fileExtension);
 
 public:
     class Mutator final
         : public nsIURIMutator
         , public BaseURIMutator<nsJARURI>
         , public nsIURLMutator
+        , public nsISerializable
     {
         NS_DECL_ISUPPORTS
         NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
         NS_DECL_NSIURLMUTATOR
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
+        MOZ_MUST_USE NS_IMETHOD
+        Read(nsIObjectInputStream* aStream) override
+        {
+            return InitFromInputStream(aStream);
+        }
+
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsJARURI;
     };
 
     friend BaseURIMutator<nsJARURI>;
--- a/netwerk/base/nsIURIMutator.idl
+++ b/netwerk/base/nsIURIMutator.idl
@@ -41,17 +41,17 @@ protected:
     }
     mURI = static_cast<T*>(clone.get());
     return NS_OK;
   }
 
   MOZ_MUST_USE nsresult InitFromInputStream(nsIObjectInputStream* aStream)
   {
     RefPtr<T> uri = new T();
-    nsresult rv = uri->Read(aStream);
+    nsresult rv = uri->ReadPrivate(aStream);
     if (NS_FAILED(rv)) {
       return rv;
     }
     mURI = uri.forget();
     return NS_OK;
   }
 
   MOZ_MUST_USE nsresult InitFromIPCParams(const mozilla::ipc::URIParams& aParams)
@@ -93,33 +93,60 @@ protected:
 #define NS_DEFINE_NSIMUTATOR_COMMON                                           \
   MOZ_MUST_USE NS_IMETHOD                                                     \
   Deserialize(const mozilla::ipc::URIParams& aParams) override                \
   {                                                                           \
     return InitFromIPCParams(aParams);                                        \
   }                                                                           \
                                                                               \
   MOZ_MUST_USE NS_IMETHOD                                                     \
-  Read(nsIObjectInputStream* aStream) override                                \
-  {                                                                           \
-    return InitFromInputStream(aStream);                                      \
-  }                                                                           \
-                                                                              \
-  MOZ_MUST_USE NS_IMETHOD                                                     \
   Finalize(nsIURI** aURI) override                                            \
   {                                                                           \
     mURI.forget(aURI); return NS_OK;                                          \
   }                                                                           \
                                                                               \
   MOZ_MUST_USE NS_IMETHOD                                                     \
   SetSpec(const nsACString& aSpec, nsIURIMutator** aMutator) override         \
   {                                                                           \
     if (aMutator) NS_ADDREF(*aMutator = this);                                \
     return InitFromSpec(aSpec);                                               \
   }                                                                           \
+
+// Implements AddRef, Release and QueryInterface for the mutator
+#define NS_IMPL_NSIURIMUTATOR_ISUPPORTS(aClass, ...)                          \
+  NS_IMPL_ADDREF(aClass)                                                      \
+  NS_IMPL_RELEASE(aClass)                                                     \
+  NS_IMPL_NSIURIMUTATOR_QUERY_INTERFACE(aClass, __VA_ARGS__)                  \
+
+// The list of interfaces is queried and an AddRef-ed pointer is returned if
+// there is a match. Otherwise, we call QueryInterface on mURI and return.
+// The reason for this specialized QueryInterface implementation is that we
+// we want to be able to instantiate the mutator for a given CID of a
+// nsIURI implementation, call nsISerializable.Read() on the mutator to
+// deserialize the URI then QueryInterface the mutator to an nsIURI interface.
+// See bug 1442239.
+// If you QueryInterface a mutator to an interface of the URI
+// implementation this is similar to calling Finalize.
+#define NS_IMPL_NSIURIMUTATOR_QUERY_INTERFACE(aClass, ...)                    \
+  static_assert(MOZ_ARG_COUNT(__VA_ARGS__) > 0,                               \
+                "Need more arguments");                                       \
+  NS_INTERFACE_MAP_BEGIN(aClass)                                              \
+    nsCOMPtr<nsIURI> uri;                                                     \
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIMutator)              \
+    MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__))                   \
+    if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {                              \
+      foundInterface = nullptr;                                               \
+    } else                                                                    \
+    if (mURI &&                                                               \
+        NS_SUCCEEDED(mURI->QueryInterface(aIID, getter_AddRefs(uri)))) {      \
+        mURI = nullptr;                                                       \
+        foundInterface = uri.get();                                           \
+    } else                                                                    \
+  NS_INTERFACE_MAP_END                                                        \
+
 %}
 
 [ptr] native Encoding(const mozilla::Encoding);
 [ref] native const_URIParams_ref(const mozilla::ipc::URIParams);
 
 [scriptable, builtinclass, uuid(1fc53257-898b-4c5e-b69c-05bc84b4cd8f)]
 interface nsIURISetSpec : nsISupports
 {
@@ -248,24 +275,16 @@ interface nsIURISetters : nsIURISetSpec
   }                                                                           \
 
 %}
 
 [scriptable, builtinclass, uuid(4d1f3103-1c44-4dcd-b717-5d22a697a7d9)]
 interface nsIURIMutator : nsIURISetters
 {
   /**
-   * Initializes the URI by reading from the input stream.
-   * The input stream must contain the serialization of the same object type.
-   * See nsISerializable.
-   */
-  [must_use]
-  void read(in nsIObjectInputStream aInputStream);
-
-  /**
    * Initalizes the URI by reading IPC URIParams.
    * See nsIIPCSerializableURI.
    */
   [noscript, notxpcom, must_use]
   nsresult deserialize(in const_URIParams_ref aParams);
 
   /**
    * Finishes changing or constructing the URI and returns an immutable URI.
--- a/netwerk/base/nsSimpleNestedURI.cpp
+++ b/netwerk/base/nsSimpleNestedURI.cpp
@@ -23,19 +23,26 @@ nsSimpleNestedURI::nsSimpleNestedURI(nsI
 {
     NS_ASSERTION(innerURI, "Must have inner URI");
     NS_TryToSetImmutable(innerURI);
 }
 
 // nsISerializable
 
 NS_IMETHODIMP
-nsSimpleNestedURI::Read(nsIObjectInputStream* aStream)
+nsSimpleNestedURI::Read(nsIObjectInputStream *aStream)
 {
-    nsresult rv = nsSimpleURI::Read(aStream);
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSimpleNestedURI::ReadPrivate(nsIObjectInputStream *aStream)
+{
+    nsresult rv = nsSimpleURI::ReadPrivate(aStream);
     if (NS_FAILED(rv)) return rv;
 
     NS_ASSERTION(!mMutable, "How did that happen?");
 
     nsCOMPtr<nsISupports> supports;
     rv = aStream->ReadObject(true, getter_AddRefs(supports));
     if (NS_FAILED(rv)) return rv;
 
@@ -181,17 +188,21 @@ NS_IMETHODIMP
 nsSimpleNestedURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
 {
     static NS_DEFINE_CID(kSimpleNestedURICID, NS_SIMPLENESTEDURI_CID);
 
     *aClassIDNoAlloc = kSimpleNestedURICID;
     return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS(nsSimpleNestedURI::Mutator, nsIURISetters, nsIURIMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsSimpleNestedURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsSimpleNestedURI::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsSimpleNestedURI::Mutator> mutator = new nsSimpleNestedURI::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
--- a/netwerk/base/nsSimpleNestedURI.h
+++ b/netwerk/base/nsSimpleNestedURI.h
@@ -66,35 +66,43 @@ public:
     // Override the nsIClassInfo method GetClassIDNoAlloc to make sure our
     // nsISerializable impl works right.
     NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) override;
 
 protected:
     nsCOMPtr<nsIURI> mInnerURI;
 
     bool Deserialize(const mozilla::ipc::URIParams&);
+    nsresult ReadPrivate(nsIObjectInputStream *stream);
 
 public:
     class Mutator final
         : public nsIURIMutator
         , public BaseURIMutator<nsSimpleNestedURI>
+        , public nsISerializable
     {
         NS_DECL_ISUPPORTS
         NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         MOZ_MUST_USE NS_IMETHOD
         Deserialize(const mozilla::ipc::URIParams& aParams) override
         {
             return InitFromIPCParams(aParams);
         }
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
         MOZ_MUST_USE NS_IMETHOD
         Read(nsIObjectInputStream* aStream) override
         {
             return InitFromInputStream(aStream);
         }
 
         MOZ_MUST_USE NS_IMETHOD
         Finalize(nsIURI** aURI) override
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -70,17 +70,24 @@ NS_INTERFACE_TABLE_TO_MAP_SEGUE
   else
   NS_INTERFACE_MAP_ENTRY(nsISizeOf)
 NS_INTERFACE_MAP_END
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISerializable methods:
 
 NS_IMETHODIMP
-nsSimpleURI::Read(nsIObjectInputStream* aStream)
+nsSimpleURI::Read(nsIObjectInputStream *aStream)
+{
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSimpleURI::ReadPrivate(nsIObjectInputStream *aStream)
 {
     nsresult rv;
 
     bool isMutable;
     rv = aStream->ReadBoolean(&isMutable);
     if (NS_FAILED(rv)) return rv;
     mMutable = isMutable;
 
@@ -872,18 +879,21 @@ nsSimpleURI::SetQuery(const nsACString& 
 
 nsresult
 nsSimpleURI::SetQueryWithEncoding(const nsACString& aQuery,
                                   const Encoding* aEncoding)
 {
     return SetQuery(aQuery);
 }
 
-NS_IMPL_ISUPPORTS(nsSimpleURI::Mutator, nsIURISetters, nsIURIMutator)
-
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsSimpleURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsSimpleURI::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsSimpleURI::Mutator> mutator = new nsSimpleURI::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
--- a/netwerk/base/nsSimpleURI.h
+++ b/netwerk/base/nsSimpleURI.h
@@ -83,16 +83,17 @@ protected:
     virtual nsresult SetHostPort(const nsACString &aValue);
     virtual nsresult SetHost(const nsACString &input);
     virtual nsresult SetPort(int32_t port);
     virtual nsresult SetPathQueryRef(const nsACString &input);
     virtual nsresult SetRef(const nsACString &input);
     virtual nsresult SetFilePath(const nsACString &input);
     virtual nsresult SetQuery(const nsACString &input);
     virtual nsresult SetQueryWithEncoding(const nsACString &input, const Encoding* encoding);
+    nsresult ReadPrivate(nsIObjectInputStream *stream);
 
     // Helper to share code between Equals methods.
     virtual nsresult EqualsInternal(nsIURI* other,
                                     RefHandlingEnum refHandlingMode,
                                     bool* result);
 
     // Helper to be used by inherited classes who want to test
     // equality given an assumed nsSimpleURI.  This must NOT check
@@ -127,21 +128,34 @@ protected:
     bool mIsRefValid; // To distinguish between empty-ref and no-ref.
     bool mIsQueryValid; // To distinguish between empty-query and no-query.
 
 
 public:
     class Mutator final
         : public nsIURIMutator
         , public BaseURIMutator<nsSimpleURI>
+        , public nsISerializable
     {
         NS_DECL_ISUPPORTS
         NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
         NS_DEFINE_NSIMUTATOR_COMMON
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
+        MOZ_MUST_USE NS_IMETHOD
+        Read(nsIObjectInputStream* aStream) override
+        {
+            return InitFromInputStream(aStream);
+        }
+
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         friend class nsSimpleURI;
     };
 
     friend BaseURIMutator<nsSimpleURI>;
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -2214,22 +2214,24 @@ nsStandardURL::SetPathQueryRef(const nsA
         mExtension.mLen = -1;
         mQuery.mLen = -1;
         mRef.mLen = -1;
     }
     return NS_OK;
 }
 
 // When updating this also update SubstitutingURL::Mutator
-NS_IMPL_ISUPPORTS(nsStandardURL::Mutator,
-                  nsIURISetters,
-                  nsIURIMutator,
-                  nsIStandardURLMutator,
-                  nsIURLMutator,
-                  nsIFileURLMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsStandardURL::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsIStandardURLMutator,
+                                nsIURLMutator,
+                                nsIFileURLMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsStandardURL::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsStandardURL::Mutator> mutator = new nsStandardURL::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
@@ -3382,16 +3384,23 @@ nsStandardURL::SetMutable(bool value)
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsISerializable
 //----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsStandardURL::Read(nsIObjectInputStream *stream)
 {
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsStandardURL::ReadPrivate(nsIObjectInputStream *stream)
+{
     NS_PRECONDITION(mDisplayHost.IsEmpty(), "Shouldn't have cached unicode host");
     NS_PRECONDITION(mSpecEncoding == eEncoding_Unknown,
                     "Shouldn't have spec encoding here");
 
     nsresult rv;
 
     uint32_t urlType;
     rv = stream->Read32(&urlType);
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -189,16 +189,17 @@ protected:
     virtual nsresult SetHost(const nsACString &input);
     virtual nsresult SetPort(int32_t port);
     virtual nsresult SetPathQueryRef(const nsACString &input);
     virtual nsresult SetRef(const nsACString &input);
     virtual nsresult SetFilePath(const nsACString &input);
     virtual nsresult SetQuery(const nsACString &input);
     virtual nsresult SetQueryWithEncoding(const nsACString &input, const Encoding* encoding);
     bool Deserialize(const mozilla::ipc::URIParams&);
+    nsresult ReadPrivate(nsIObjectInputStream *stream);
 
 private:
     nsresult Init(uint32_t urlType, int32_t defaultPort, const nsACString &spec,
                   const char *charset, nsIURI *baseURI);
     nsresult SetDefaultPort(int32_t aNewDefaultPort);
     nsresult SetFile(nsIFile *file);
 
     nsresult SetFileNameInternal(const nsACString &input);
@@ -342,25 +343,33 @@ public:
     // the same code for SubstitutingURL (which extends nsStandardURL)
     template<class T>
     class TemplatedMutator
         : public nsIURIMutator
         , public BaseURIMutator<T>
         , public nsIStandardURLMutator
         , public nsIURLMutator
         , public nsIFileURLMutator
+        , public nsISerializable
     {
         NS_FORWARD_SAFE_NSIURISETTERS_RET(BaseURIMutator<T>::mURI)
 
         MOZ_MUST_USE NS_IMETHOD
         Deserialize(const mozilla::ipc::URIParams& aParams) override
         {
             return BaseURIMutator<T>::InitFromIPCParams(aParams);
         }
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            NS_NOTREACHED("Use nsIURIMutator.read() instead");
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
         MOZ_MUST_USE NS_IMETHOD
         Read(nsIObjectInputStream* aStream) override
         {
             return BaseURIMutator<T>::InitFromInputStream(aStream);
         }
 
         MOZ_MUST_USE NS_IMETHOD
         Finalize(nsIURI** aURI) override
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -96,26 +96,42 @@
 #define NS_SIMPLENESTEDURI_CID                           \
 { /* 56388dad-287b-4240-a785-85c394012503 */             \
      0x56388dad,                                         \
      0x287b,                                             \
      0x4240,                                             \
      { 0xa7, 0x85, 0x85, 0xc3, 0x94, 0x01, 0x25, 0x03 }  \
 }
 
+#define NS_SIMPLENESTEDURIMUTATOR_CID                    \
+{ /* 9c4e9d49-ce64-4ca3-acef-3075c5e5aba7 */             \
+     0x9c4e9d49,                                         \
+     0xce64,                                             \
+     0x4ca3,                                             \
+     { 0xac, 0xef, 0x30, 0x75, 0xc5, 0xe5, 0xab, 0xa7 }  \
+}
+
 // component inheriting from the nested simple URI component and also
 // carrying along its base URI
 #define NS_NESTEDABOUTURI_CID                            \
 { /* 2f277c00-0eaf-4ddb-b936-41326ba48aae */             \
      0x2f277c00,                                         \
      0x0eaf,                                             \
      0x4ddb,                                             \
      { 0xb9, 0x36, 0x41, 0x32, 0x6b, 0xa4, 0x8a, 0xae }  \
 }
 
+#define NS_NESTEDABOUTURIMUTATOR_CID                     \
+{ /* b0054ef3-b096-483d-8242-4ee36b7b2115 */             \
+     0xb0054ef3,                                         \
+     0xb096,                                             \
+     0x483d,                                             \
+     { 0x82, 0x42, 0x4e, 0xe3, 0x6b, 0x7b, 0x21, 0x15 }  \
+}
+
 // component implementing nsIStandardURL, nsIURI, nsIURL, nsISerializable,
 // and nsIClassInfo.
 #define NS_STANDARDURL_CONTRACTID \
     "@mozilla.org/network/standard-url;1"
 #define NS_STANDARDURL_CID                           \
 { /* de9472d0-8034-11d3-9399-00104ba0fd40 */         \
     0xde9472d0,                                      \
     0x8034,                                          \
@@ -691,16 +707,23 @@
 
 #define NS_SUBSTITUTINGURL_CID                       \
 { 0xdea9657c,                                        \
   0x18cf,                                            \
   0x4984,                                            \
   { 0xbd, 0xe9, 0xcc, 0xef, 0x5d, 0x8a, 0xb4, 0x73 } \
 }
 
+#define NS_SUBSTITUTINGURLMUTATOR_CID                \
+{ 0xb3cfeb91,                                        \
+  0x332a,                                            \
+  0x46c9,                                            \
+  { 0xad, 0x97, 0x93, 0xff, 0x39, 0x84, 0x14, 0x94 } \
+}
+
 /******************************************************************************
  * netwerk/protocol/file/ classes
  */
 
 #define NS_FILEPROTOCOLHANDLER_CID                   \
 { /* fbc81170-1f69-11d3-9344-00104ba0fd40 */         \
     0xfbc81170,                                      \
     0x1f69,                                          \
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -217,20 +217,20 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWifiMon
 // protocols
 ///////////////////////////////////////////////////////////////////////////////
 
 // about:blank is mandatory
 #include "nsAboutProtocolHandler.h"
 #include "nsAboutBlank.h"
 typedef mozilla::net::nsAboutProtocolHandler nsAboutProtocolHandler;
 typedef mozilla::net::nsSafeAboutProtocolHandler nsSafeAboutProtocolHandler;
-typedef mozilla::net::nsNestedAboutURI nsNestedAboutURI;
+typedef mozilla::net::nsNestedAboutURI::Mutator nsNestedAboutURIMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAboutProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafeAboutProtocolHandler)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsNestedAboutURI)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsNestedAboutURIMutator)
 
 // about
 #include "nsAboutCache.h"
 #include "nsAboutCacheEntry.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAboutCacheEntry)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsApplicationCacheService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsApplicationCacheNamespace)
@@ -289,22 +289,23 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Name
 } // namespace net
 } // namespace mozilla
 #endif
 
 // resource
 #include "nsResProtocolHandler.h"
 #include "ExtensionProtocolHandler.h"
 #include "SubstitutingProtocolHandler.h"
+typedef mozilla::net::SubstitutingURL::Mutator SubstitutingURLMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsResProtocolHandler, Init)
 
 namespace mozilla {
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ExtensionProtocolHandler,
     ExtensionProtocolHandler::GetSingleton)
-NS_GENERIC_FACTORY_CONSTRUCTOR(SubstitutingURL)
+NS_GENERIC_FACTORY_CONSTRUCTOR(SubstitutingURLMutator)
 } // namespace mozilla
 
 #include "nsViewSourceHandler.h"
 typedef mozilla::net::nsViewSourceHandler nsViewSourceHandler;
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsViewSourceHandler)
 
 #include "nsDataHandler.h"
 
@@ -358,27 +359,23 @@ WEB_SOCKET_HANDLER_CONSTRUCTOR(WebSocket
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "nsURLParsers.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoAuthURLParser)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAuthURLParser)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStdURLParser)
 
 #include "nsStandardURL.h"
-typedef mozilla::net::nsStandardURL nsStandardURL;
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandardURL)
 typedef mozilla::net::nsStandardURL::Mutator nsStandardURLMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandardURLMutator)
-typedef mozilla::net::nsSimpleURI nsSimpleURI;
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleURI)
 typedef mozilla::net::nsSimpleURI::Mutator nsSimpleURIMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleURIMutator)
 
-typedef mozilla::net::nsSimpleNestedURI nsSimpleNestedURI;
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleNestedURI)
+typedef mozilla::net::nsSimpleNestedURI::Mutator nsSimpleNestedURIMutator;
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleNestedURIMutator)
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "nsIDNService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsIDNService, Init)
 
 ///////////////////////////////////////////////////////////////////////////////
 #if defined(XP_WIN)
@@ -641,17 +638,17 @@ static nsresult nsNetStartup()
 {
     return NS_OK;
 }
 
 // Net module shutdown hook
 static void nsNetShutdown()
 {
     // Release the url parser that the stdurl is holding.
-    nsStandardURL::ShutdownGlobalObjects();
+    mozilla::net::nsStandardURL::ShutdownGlobalObjects();
 
     // Release global state used by the URL helper module.
     net_ShutdownURLHelper();
 #ifdef XP_MACOSX
     net_ShutdownURLHelperOSX();
 #endif
 
     // Release DNS service reference.
@@ -676,16 +673,17 @@ NS_DEFINE_NAMED_CID(NS_TLSSERVERSOCKET_C
 NS_DEFINE_NAMED_CID(NS_UDPSOCKET_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKETPROVIDERSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_DNSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_IDNSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_EFFECTIVETLDSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLEURI_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLEURIMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_SIMPLENESTEDURI_CID);
+NS_DEFINE_NAMED_CID(NS_SIMPLENESTEDURIMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_ASYNCSTREAMCOPIER_CID);
 NS_DEFINE_NAMED_CID(NS_INPUTSTREAMPUMP_CID);
 NS_DEFINE_NAMED_CID(NS_INPUTSTREAMCHANNEL_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_INCREMENTALSTREAMLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_UNICHARSTREAMLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_DOWNLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID);
@@ -737,20 +735,22 @@ NS_DEFINE_NAMED_CID(NS_HTTPAUTHMANAGER_C
 NS_DEFINE_NAMED_CID(NS_HTTPCHANNELAUTHPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_HTTPACTIVITYDISTRIBUTOR_CID);
 NS_DEFINE_NAMED_CID(NS_THROTTLEQUEUE_CID);
 NS_DEFINE_NAMED_CID(NS_BACKGROUNDCHANNELREGISTRAR_CID);
 NS_DEFINE_NAMED_CID(NS_FTPPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_RESPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_EXTENSIONPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_SUBSTITUTINGURL_CID);
+NS_DEFINE_NAMED_CID(NS_SUBSTITUTINGURLMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_ABOUTPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_SAFEABOUTPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_ABOUT_BLANK_MODULE_CID);
 NS_DEFINE_NAMED_CID(NS_NESTEDABOUTURI_CID);
+NS_DEFINE_NAMED_CID(NS_NESTEDABOUTURIMUTATOR_CID);
 NS_DEFINE_NAMED_CID(NS_ABOUT_CACHE_MODULE_CID);
 NS_DEFINE_NAMED_CID(NS_ABOUT_CACHE_ENTRY_MODULE_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKSSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKS4SOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_UDPSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_CACHESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHENAMESPACE_CID);
@@ -793,19 +793,20 @@ static const mozilla::Module::CIDEntry k
     { &kNS_SOCKETTRANSPORTSERVICE_CID, false, nullptr, nsSocketTransportServiceConstructor },
     { &kNS_SERVERSOCKET_CID, false, nullptr, nsServerSocketConstructor },
     { &kNS_TLSSERVERSOCKET_CID, false, nullptr, TLSServerSocketConstructor },
     { &kNS_UDPSOCKET_CID, false, nullptr, nsUDPSocketConstructor },
     { &kNS_SOCKETPROVIDERSERVICE_CID, false, nullptr, nsSocketProviderService::Create },
     { &kNS_DNSSERVICE_CID, false, nullptr, nsIDNSServiceConstructor },
     { &kNS_IDNSERVICE_CID, false, nullptr, nsIDNServiceConstructor },
     { &kNS_EFFECTIVETLDSERVICE_CID, false, nullptr, nsEffectiveTLDServiceConstructor },
-    { &kNS_SIMPLEURI_CID, false, nullptr, nsSimpleURIConstructor },
+    { &kNS_SIMPLEURI_CID, false, nullptr, nsSimpleURIMutatorConstructor }, // do_CreateInstance returns mutator
     { &kNS_SIMPLEURIMUTATOR_CID, false, nullptr, nsSimpleURIMutatorConstructor },
-    { &kNS_SIMPLENESTEDURI_CID, false, nullptr, nsSimpleNestedURIConstructor },
+    { &kNS_SIMPLENESTEDURI_CID, false, nullptr, nsSimpleNestedURIMutatorConstructor }, // do_CreateInstance returns mutator
+    { &kNS_SIMPLENESTEDURIMUTATOR_CID, false, nullptr, nsSimpleNestedURIMutatorConstructor },
     { &kNS_ASYNCSTREAMCOPIER_CID, false, nullptr, nsAsyncStreamCopierConstructor },
     { &kNS_INPUTSTREAMPUMP_CID, false, nullptr, nsInputStreamPumpConstructor },
     { &kNS_INPUTSTREAMCHANNEL_CID, false, nullptr, nsInputStreamChannelConstructor },
     { &kNS_STREAMLOADER_CID, false, nullptr, mozilla::net::nsStreamLoader::Create },
     { &kNS_INCREMENTALSTREAMLOADER_CID, false, nullptr, nsIncrementalStreamLoader::Create },
     { &kNS_UNICHARSTREAMLOADER_CID, false, nullptr, nsUnicharStreamLoader::Create },
     { &kNS_DOWNLOADER_CID, false, nullptr, nsDownloaderConstructor },
     { &kNS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID, false, nullptr,
@@ -821,17 +822,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_LOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsFileOutputStream::Create },
     { &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsAtomicFileOutputStreamConstructor },
     { &kNS_SAFELOCALFILEOUTPUTSTREAM_CID, false, nullptr, nsSafeFileOutputStreamConstructor },
     { &kNS_LOCALFILESTREAM_CID, false, nullptr, nsFileStreamConstructor },
     { &kNS_INCREMENTALDOWNLOAD_CID, false, nullptr, net_NewIncrementalDownload },
     { &kNS_STDURLPARSER_CID, false, nullptr, nsStdURLParserConstructor },
     { &kNS_NOAUTHURLPARSER_CID, false, nullptr, nsNoAuthURLParserConstructor },
     { &kNS_AUTHURLPARSER_CID, false, nullptr, nsAuthURLParserConstructor },
-    { &kNS_STANDARDURL_CID, false, nullptr, nsStandardURLConstructor },
+    { &kNS_STANDARDURL_CID, false, nullptr, nsStandardURLMutatorConstructor }, // do_CreateInstance returns mutator
     { &kNS_STANDARDURLMUTATOR_CID, false, nullptr, nsStandardURLMutatorConstructor },
     { &kNS_ARRAYBUFFERINPUTSTREAM_CID, false, nullptr, ArrayBufferInputStreamConstructor },
     { &kNS_BUFFEREDINPUTSTREAM_CID, false, nullptr, nsBufferedInputStream::Create },
     { &kNS_BUFFEREDOUTPUTSTREAM_CID, false, nullptr, nsBufferedOutputStream::Create },
     { &kNS_MIMEINPUTSTREAM_CID, false, nullptr, nsMIMEInputStreamConstructor },
     { &kNS_PROTOCOLPROXYSERVICE_CID, true, nullptr, nsProtocolProxyServiceConstructor },
     { &kNS_STREAMCONVERTERSERVICE_CID, false, nullptr, CreateNewStreamConvServiceFactory },
 #if defined (XP_WIN)
@@ -858,21 +859,23 @@ static const mozilla::Module::CIDEntry k
     { &kNS_HTTPAUTHMANAGER_CID, false, nullptr, mozilla::net::nsHttpAuthManagerConstructor },
     { &kNS_HTTPCHANNELAUTHPROVIDER_CID, false, nullptr, mozilla::net::nsHttpChannelAuthProviderConstructor },
     { &kNS_HTTPACTIVITYDISTRIBUTOR_CID, false, nullptr, mozilla::net::nsHttpActivityDistributorConstructor },
     { &kNS_THROTTLEQUEUE_CID, false, nullptr, mozilla::net::ThrottleQueueConstructor },
     { &kNS_BACKGROUNDCHANNELREGISTRAR_CID, false, nullptr, mozilla::net::BackgroundChannelRegistrarConstructor },
     { &kNS_FTPPROTOCOLHANDLER_CID, false, nullptr, nsFtpProtocolHandlerConstructor },
     { &kNS_RESPROTOCOLHANDLER_CID, false, nullptr, nsResProtocolHandlerConstructor },
     { &kNS_EXTENSIONPROTOCOLHANDLER_CID, false, nullptr, mozilla::ExtensionProtocolHandlerConstructor },
-    { &kNS_SUBSTITUTINGURL_CID, false, nullptr, mozilla::SubstitutingURLConstructor },
+    { &kNS_SUBSTITUTINGURL_CID, false, nullptr, mozilla::SubstitutingURLMutatorConstructor }, // do_CreateInstance returns mutator
+    { &kNS_SUBSTITUTINGURLMUTATOR_CID, false, nullptr, mozilla::SubstitutingURLMutatorConstructor },
     { &kNS_ABOUTPROTOCOLHANDLER_CID, false, nullptr, nsAboutProtocolHandlerConstructor },
     { &kNS_SAFEABOUTPROTOCOLHANDLER_CID, false, nullptr, nsSafeAboutProtocolHandlerConstructor },
     { &kNS_ABOUT_BLANK_MODULE_CID, false, nullptr, nsAboutBlank::Create },
-    { &kNS_NESTEDABOUTURI_CID, false, nullptr, nsNestedAboutURIConstructor },
+    { &kNS_NESTEDABOUTURI_CID, false, nullptr, nsNestedAboutURIMutatorConstructor }, // do_CreateInstance returns mutator
+    { &kNS_NESTEDABOUTURIMUTATOR_CID, false, nullptr, nsNestedAboutURIMutatorConstructor },
     { &kNS_ABOUT_CACHE_MODULE_CID, false, nullptr, nsAboutCache::Create },
     { &kNS_ABOUT_CACHE_ENTRY_MODULE_CID, false, nullptr, nsAboutCacheEntryConstructor },
     { &kNS_SOCKSSOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV5 },
     { &kNS_SOCKS4SOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV4 },
     { &kNS_UDPSOCKETPROVIDER_CID, false, nullptr, nsUDPSocketProviderConstructor },
     { &kNS_CACHESERVICE_CID, false, nullptr, nsCacheService::Create },
     { &kNS_APPLICATIONCACHESERVICE_CID, false, nullptr, nsApplicationCacheServiceConstructor },
     { &kNS_APPLICATIONCACHENAMESPACE_CID, false, nullptr, nsApplicationCacheNamespaceConstructor },
@@ -920,17 +923,16 @@ static const mozilla::Module::ContractID
     { NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &kNS_SOCKETTRANSPORTSERVICE_CID },
     { NS_SERVERSOCKET_CONTRACTID, &kNS_SERVERSOCKET_CID },
     { NS_TLSSERVERSOCKET_CONTRACTID, &kNS_TLSSERVERSOCKET_CID },
     { NS_UDPSOCKET_CONTRACTID, &kNS_UDPSOCKET_CID },
     { NS_SOCKETPROVIDERSERVICE_CONTRACTID, &kNS_SOCKETPROVIDERSERVICE_CID },
     { NS_DNSSERVICE_CONTRACTID, &kNS_DNSSERVICE_CID },
     { NS_IDNSERVICE_CONTRACTID, &kNS_IDNSERVICE_CID },
     { NS_EFFECTIVETLDSERVICE_CONTRACTID, &kNS_EFFECTIVETLDSERVICE_CID },
-    { NS_SIMPLEURI_CONTRACTID, &kNS_SIMPLEURI_CID },
     { NS_SIMPLEURIMUTATOR_CONTRACTID, &kNS_SIMPLEURIMUTATOR_CID },
     { NS_ASYNCSTREAMCOPIER_CONTRACTID, &kNS_ASYNCSTREAMCOPIER_CID },
     { NS_INPUTSTREAMPUMP_CONTRACTID, &kNS_INPUTSTREAMPUMP_CID },
     { NS_INPUTSTREAMCHANNEL_CONTRACTID, &kNS_INPUTSTREAMCHANNEL_CID },
     { NS_STREAMLOADER_CONTRACTID, &kNS_STREAMLOADER_CID },
     { NS_INCREMENTALSTREAMLOADER_CONTRACTID, &kNS_INCREMENTALSTREAMLOADER_CID },
     { NS_UNICHARSTREAMLOADER_CONTRACTID, &kNS_UNICHARSTREAMLOADER_CID },
     { NS_DOWNLOADER_CONTRACTID, &kNS_DOWNLOADER_CID },
@@ -945,17 +947,16 @@ static const mozilla::Module::ContractID
     { NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_LOCALFILEOUTPUTSTREAM_CID },
     { NS_ATOMICLOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_ATOMICLOCALFILEOUTPUTSTREAM_CID },
     { NS_SAFELOCALFILEOUTPUTSTREAM_CONTRACTID, &kNS_SAFELOCALFILEOUTPUTSTREAM_CID },
     { NS_LOCALFILESTREAM_CONTRACTID, &kNS_LOCALFILESTREAM_CID },
     { NS_INCREMENTALDOWNLOAD_CONTRACTID, &kNS_INCREMENTALDOWNLOAD_CID },
     { NS_STDURLPARSER_CONTRACTID, &kNS_STDURLPARSER_CID },
     { NS_NOAUTHURLPARSER_CONTRACTID, &kNS_NOAUTHURLPARSER_CID },
     { NS_AUTHURLPARSER_CONTRACTID, &kNS_AUTHURLPARSER_CID },
-    { NS_STANDARDURL_CONTRACTID, &kNS_STANDARDURL_CID },
     { NS_STANDARDURLMUTATOR_CONTRACTID, &kNS_STANDARDURLMUTATOR_CID },
     { NS_ARRAYBUFFERINPUTSTREAM_CONTRACTID, &kNS_ARRAYBUFFERINPUTSTREAM_CID },
     { NS_BUFFEREDINPUTSTREAM_CONTRACTID, &kNS_BUFFEREDINPUTSTREAM_CID },
     { NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &kNS_BUFFEREDOUTPUTSTREAM_CID },
     { NS_MIMEINPUTSTREAM_CONTRACTID, &kNS_MIMEINPUTSTREAM_CID },
     { NS_PROTOCOLPROXYSERVICE_CONTRACTID, &kNS_PROTOCOLPROXYSERVICE_CID },
     { NS_STREAMCONVERTERSERVICE_CONTRACTID, &kNS_STREAMCONVERTERSERVICE_CID },
 #if defined(XP_WIN)
--- a/netwerk/protocol/about/nsAboutProtocolHandler.cpp
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
@@ -355,20 +355,28 @@ nsSafeAboutProtocolHandler::AllowPort(in
 // nsNestedAboutURI implementation
 NS_INTERFACE_MAP_BEGIN(nsNestedAboutURI)
   if (aIID.Equals(kNestedAboutURICID))
       foundInterface = static_cast<nsIURI*>(this);
   else
 NS_INTERFACE_MAP_END_INHERITING(nsSimpleNestedURI)
 
 // nsISerializable
+
 NS_IMETHODIMP
-nsNestedAboutURI::Read(nsIObjectInputStream* aStream)
+nsNestedAboutURI::Read(nsIObjectInputStream *aStream)
 {
-    nsresult rv = nsSimpleNestedURI::Read(aStream);
+    NS_NOTREACHED("Use nsIURIMutator.read() instead");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsNestedAboutURI::ReadPrivate(nsIObjectInputStream *aStream)
+{
+    nsresult rv = nsSimpleNestedURI::ReadPrivate(aStream);
     if (NS_FAILED(rv)) return rv;
 
     bool haveBase;
     rv = aStream->ReadBoolean(&haveBase);
     if (NS_FAILED(rv)) return rv;
 
     if (haveBase) {
         nsCOMPtr<nsISupports> supports;
@@ -434,17 +442,21 @@ nsNestedAboutURI::StartClone(nsSimpleURI
 
     nsNestedAboutURI* url = new nsNestedAboutURI(innerClone, mBaseURI);
     SetRefOnClone(url, aRefHandlingMode, aNewRef);
     url->SetMutable(false);
 
     return url;
 }
 
-NS_IMPL_ISUPPORTS(nsNestedAboutURI::Mutator, nsIURISetters, nsIURIMutator)
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsNestedAboutURI::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsISerializable)
 
 NS_IMETHODIMP
 nsNestedAboutURI::Mutate(nsIURIMutator** aMutator)
 {
     RefPtr<nsNestedAboutURI::Mutator> mutator = new nsNestedAboutURI::Mutator();
     nsresult rv = mutator->InitFromURI(this);
     if (NS_FAILED(rv)) {
         return rv;
--- a/netwerk/protocol/about/nsAboutProtocolHandler.h
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.h
@@ -82,35 +82,43 @@ public:
     NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) override;
 
     nsIURI* GetBaseURI() const {
         return mBaseURI;
     }
 
 protected:
     nsCOMPtr<nsIURI> mBaseURI;
+    nsresult ReadPrivate(nsIObjectInputStream *stream);
 
 public:
     class Mutator final
         : public nsIURIMutator
         , public BaseURIMutator<nsNestedAboutURI>
+        , public nsISerializable
     {
         NS_DECL_ISUPPORTS
         NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
         explicit Mutator() { }
     private:
         virtual ~Mutator() { }
 
         MOZ_MUST_USE NS_IMETHOD
         Deserialize(const mozilla::ipc::URIParams& aParams) override
         {
             return InitFromIPCParams(aParams);
         }
 
+        NS_IMETHOD
+        Write(nsIObjectOutputStream *aOutputStream) override
+        {
+            return NS_ERROR_NOT_IMPLEMENTED;
+        }
+
         MOZ_MUST_USE NS_IMETHOD
         Read(nsIObjectInputStream* aStream) override
         {
             return InitFromInputStream(aStream);
         }
 
         MOZ_MUST_USE NS_IMETHOD
         Finalize(nsIURI** aURI) override
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
@@ -27,22 +27,25 @@ namespace net {
 static LazyLogModule gResLog("nsResProtocol");
 
 static NS_DEFINE_CID(kSubstitutingURLCID, NS_SUBSTITUTINGURL_CID);
 
 //---------------------------------------------------------------------------------
 // SubstitutingURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
 //---------------------------------------------------------------------------------
 
-NS_IMPL_ISUPPORTS(SubstitutingURL::Mutator,
-                  nsIURISetters,
-                  nsIURIMutator,
-                  nsIStandardURLMutator,
-                  nsIURLMutator,
-                  nsIFileURLMutator)
+// The list of interfaces should be in sync with nsStandardURL
+// Queries this list of interfaces. If none match, it queries mURI.
+NS_IMPL_NSIURIMUTATOR_ISUPPORTS(SubstitutingURL::Mutator,
+                                nsIURISetters,
+                                nsIURIMutator,
+                                nsIStandardURLMutator,
+                                nsIURLMutator,
+                                nsIFileURLMutator,
+                                nsISerializable)
 
 nsresult
 SubstitutingURL::EnsureFile()
 {
   nsAutoCString ourScheme;
   nsresult rv = GetScheme(ourScheme);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/netwerk/test/unit/test_uri_mutator.js
+++ b/netwerk/test/unit/test_uri_mutator.js
@@ -16,8 +16,27 @@ add_task(async function test_simple_sett
   let uri = standardMutator()
               .setSpec("http://example.com/")
               .setQuery("hello")
               .setRef("bla")
               .setScheme("ftp")
               .finalize();
   equal(uri.spec, "ftp://example.com/?hello#bla");
 });
+
+add_task(async function test_qi_behaviour() {
+  let uri = standardMutator()
+              .setSpec("http://example.com/")
+              .QueryInterface(Ci.nsIURI);
+  equal(uri.spec, "http://example.com/");
+
+  Assert.throws(() => { uri = standardMutator().QueryInterface(Ci.nsIURI); },
+                /NS_NOINTERFACE/,
+                "mutator doesn't QI if it holds no URI");
+
+  let mutator = standardMutator()
+                  .setSpec("http://example.com/path");
+  uri = mutator.QueryInterface(Ci.nsIURI);
+  equal(uri.spec, "http://example.com/path");
+  Assert.throws(() => { uri = mutator.QueryInterface(Ci.nsIURI); },
+                /NS_NOINTERFACE/,
+                "Second QueryInterface should fail");
+});
--- a/widget/tests/unit/test_taskbar_jumplistitems.js
+++ b/widget/tests/unit/test_taskbar_jumplistitems.js
@@ -96,21 +96,16 @@ function test_hashes()
   link.uri = uri1;
   Assert.equal(link.uriHash, "QGLmWuwuTozr3tOfXSf5mg==");
   uri1 = uri1.mutate().setSpec("http://www.123.com/test/").finalize();
   link.uri = uri1;
   Assert.equal(link.uriHash, "AG87Ls+GmaUYSUJFETRr3Q==");
   uri1 = uri1.mutate().setSpec("https://www.123.com/").finalize();
   link.uri = uri1;
   Assert.equal(link.uriHash, "iSx6UH1a9enVPzUA9JZ42g==");
-
-  var uri3 = Cc["@mozilla.org/network/simple-uri;1"]
-            .createInstance(Ci.nsIURI);
-  link.uri = uri3;
-  Assert.equal(link.uriHash, "hTrpDwNRMkvXPqYV5kh1Fw==");
 }
 
 function test_links()
 {
   // links:
   var link1 = Cc["@mozilla.org/windows-jumplistlink;1"]
              .createInstance(Ci.nsIJumpListLink);
   var link2 = Cc["@mozilla.org/windows-jumplistlink;1"]