Bug 1440693 - Port 1434163 to C-C: nsIURI attributes are read-only now. r=aceman
authorJorg K <jorgk@jorgk.com>
Sun, 04 Mar 2018 12:12:07 +0100
changeset 31206 b6af191d5eaa5a01f39e88ba524a2527455c9b04
parent 31205 20758564d6cb90003a142f83df23e2697ca16b45
child 31207 43ead9ebb0357799820da297c73f7bf94c15c25b
push id383
push userclokep@gmail.com
push dateMon, 07 May 2018 21:52:48 +0000
reviewersaceman
bugs1440693, 1434163
Bug 1440693 - Port 1434163 to C-C: nsIURI attributes are read-only now. r=aceman
ldap/xpcom/src/nsLDAPURL.cpp
ldap/xpcom/src/nsLDAPURL.h
mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
mailnews/addrbook/src/nsAddbookUrl.cpp
mailnews/addrbook/src/nsAddbookUrl.h
mailnews/base/public/nsIMsgMailNewsUrl.idl
mailnews/base/src/nsMessengerContentHandler.cpp
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgMailNewsUrl.cpp
mailnews/base/util/nsMsgMailNewsUrl.h
mailnews/base/util/nsMsgUtils.cpp
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/src/nsMsgQuote.cpp
mailnews/compose/src/nsMsgSend.cpp
mailnews/compose/src/nsSmtpService.cpp
mailnews/compose/src/nsSmtpUrl.cpp
mailnews/compose/src/nsSmtpUrl.h
mailnews/imap/public/nsIImapService.idl
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapService.cpp
mailnews/imap/src/nsImapUrl.h
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsLocalUtils.cpp
mailnews/local/src/nsMailboxService.cpp
mailnews/local/src/nsPop3Service.cpp
mailnews/news/src/nsNNTPProtocol.cpp
mailnews/news/src/nsNewsFolder.cpp
mailnews/news/src/nsNntpService.cpp
--- a/ldap/xpcom/src/nsLDAPURL.cpp
+++ b/ldap/xpcom/src/nsLDAPURL.cpp
@@ -138,34 +138,35 @@ NS_IMETHODIMP
 nsLDAPURL::GetSpec(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetSpec(_retval);
 }
 
-nsresult
-nsLDAPURL::SetSpecInternal(const nsACString &aSpec)
+nsresult nsLDAPURL::SetSpecInternal(const nsACString &aSpec)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   // Cache the original spec in case we don't like what we've been passed and
   // need to reset ourselves.
   nsCString originalSpec;
   nsresult rv = mBaseURL->GetSpec(originalSpec);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = mBaseURL->SetSpecInternal(aSpec);
+  rv = NS_MutateURI(mBaseURL).SetSpec(aSpec).Finalize(mBaseURL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SetPathInternal(PromiseFlatCString(aSpec));
-  if (NS_FAILED(rv))
-    mBaseURL->SetSpecInternal(originalSpec);
+  if (NS_FAILED(rv)) {
+    nsresult rv2 = NS_MutateURI(mBaseURL).SetSpec(originalSpec).Finalize(mBaseURL);
+    NS_ENSURE_SUCCESS(rv2, rv2);
+  }
 
   return rv;
 }
 
 NS_IMETHODIMP nsLDAPURL::GetPrePath(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
@@ -176,151 +177,136 @@ NS_IMETHODIMP nsLDAPURL::GetPrePath(nsAC
 NS_IMETHODIMP nsLDAPURL::GetScheme(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetScheme(_retval);
 }
 
-NS_IMETHODIMP nsLDAPURL::SetScheme(const nsACString &aScheme)
+nsresult nsLDAPURL::SetScheme(const nsACString &aScheme)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   if (aScheme.Equals(LDAP_SCHEME, nsCaseInsensitiveCStringComparator()))
     mOptions &= !OPT_SECURE;
   else if (aScheme.Equals(LDAP_SSL_SCHEME,
                           nsCaseInsensitiveCStringComparator()))
     mOptions |= OPT_SECURE;
   else
     return NS_ERROR_MALFORMED_URI;
 
-  return mBaseURL->SetScheme(aScheme);
+  return NS_MutateURI(mBaseURL).SetScheme(aScheme).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetUserPass(nsACString &_retval)
 {
   _retval.Truncate();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetUserPass(const nsACString &aUserPass)
+nsresult nsLDAPURL::SetUserPass(const nsACString &aUserPass)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetUsername(nsACString &_retval)
 {
   _retval.Truncate();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetUsername(const nsACString &aUsername)
+nsresult nsLDAPURL::SetUsername(const nsACString &aUsername)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetPassword(nsACString &_retval)
 {
   _retval.Truncate();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetPassword(const nsACString &aPassword)
+nsresult nsLDAPURL::SetPassword(const nsACString &aPassword)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetHostPort(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetHostPort(_retval);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetHostPort(const nsACString &aHostPort)
+nsresult nsLDAPURL::SetHostPort(const nsACString &aHostPort)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
-  return mBaseURL->SetHostPort(aHostPort);
-}
-
-NS_IMETHODIMP
-nsLDAPURL::SetHostAndPort(const nsACString &aHostPort)
-{
-  if (!mBaseURL)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  return mBaseURL->SetHostAndPort(aHostPort);
+  return NS_MutateURI(mBaseURL).SetHostPort(aHostPort).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetHost(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetHost(_retval);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetHost(const nsACString &aHost)
+nsresult nsLDAPURL::SetHost(const nsACString &aHost)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
-  return mBaseURL->SetHost(aHost);
+  return NS_MutateURI(mBaseURL).SetHost(aHost).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetPort(int32_t *_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetPort(_retval);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetPort(int32_t aPort)
+nsresult nsLDAPURL::SetPort(int32_t aPort)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
-  return mBaseURL->SetPort(aPort);
+  return NS_MutateURI(mBaseURL).SetPort(aPort).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::GetPathQueryRef(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   return mBaseURL->GetPathQueryRef(_retval);
 }
 
-NS_IMETHODIMP nsLDAPURL::SetPathQueryRef(const nsACString &aPath)
+nsresult nsLDAPURL::SetPathQueryRef(const nsACString &aPath)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   nsresult rv = SetPathInternal(PromiseFlatCString(aPath));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return mBaseURL->SetPathQueryRef(aPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(aPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::GetAsciiSpec(nsACString &_retval)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   // XXX handle extra items?
@@ -459,17 +445,17 @@ NS_IMETHODIMP nsLDAPURL::SetDn(const nsA
 
   mDN.Assign(aDn);
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::GetAttributes(nsACString &aAttributes)
 {
   if (mAttributes.IsEmpty())
   {
     aAttributes.Truncate();
     return NS_OK;
@@ -505,17 +491,17 @@ NS_IMETHODIMP nsLDAPURL::SetAttributes(c
       mAttributes.Append(',');
   }
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 nsresult nsLDAPURL::SetAttributeArray(char** aAttributes)
 {
   mAttributes.Truncate();
 
   while (aAttributes && *aAttributes)
   {
@@ -560,17 +546,17 @@ NS_IMETHODIMP nsLDAPURL::AddAttribute(co
     mAttributes.Append(Substring(findAttribute, 1));
   }
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::RemoveAttribute(const nsACString &aAttribute)
 {
   if (!mBaseURL)
     return NS_ERROR_NOT_INITIALIZED;
 
   if (mAttributes.IsEmpty())
@@ -591,17 +577,17 @@ NS_IMETHODIMP nsLDAPURL::RemoveAttribute
     mAttributes.Cut(pos, findAttribute.Length() - 1);
   }
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::HasAttribute(const nsACString &aAttribute,
                                       bool *_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsAutoCString findAttribute(",");
@@ -631,17 +617,17 @@ NS_IMETHODIMP nsLDAPURL::SetScope(int32_
 
   mScope = aScope;
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::GetFilter(nsACString& _retval)
 {
     _retval.Assign(mFilter);
     return NS_OK;
 }
 NS_IMETHODIMP nsLDAPURL::SetFilter(const nsACString& aFilter)
@@ -654,17 +640,17 @@ NS_IMETHODIMP nsLDAPURL::SetFilter(const
   if (mFilter.IsEmpty())
     mFilter.AssignLiteral("(objectclass=*)");
 
   // Now get the current path
   nsCString newPath;
   GetPathInternal(newPath);
 
   // and update the base url
-  return mBaseURL->SetPathQueryRef(newPath);
+  return NS_MutateURI(mBaseURL).SetPathQueryRef(newPath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP nsLDAPURL::GetOptions(uint32_t *_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = mOptions;
   return NS_OK;
 }
@@ -678,19 +664,19 @@ NS_IMETHODIMP nsLDAPURL::SetOptions(uint
   mOptions = aOptions;
 
   if ((aOptions & OPT_SECURE) == OPT_SECURE)
     return SetScheme(LDAP_SSL_SCHEME);
 
   return SetScheme(LDAP_SCHEME);
 }
 
-NS_IMETHODIMP nsLDAPURL::SetRef(const nsACString &aRef)
+nsresult nsLDAPURL::SetRef(const nsACString &aRef)
 {
-  return mBaseURL->SetRef(aRef);
+  return NS_MutateURI(mBaseURL).SetRef(aRef).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetRef(nsACString &result)
 {
   return mBaseURL->GetRef(result);
 }
 
@@ -736,38 +722,35 @@ nsLDAPURL::GetHasRef(bool *result)
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetFilePath(nsACString &aFilePath)
 {
   return mBaseURL->GetFilePath(aFilePath);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetFilePath(const nsACString &aFilePath)
+nsresult nsLDAPURL::SetFilePath(const nsACString &aFilePath)
 {
-  return mBaseURL->SetFilePath(aFilePath);
+  return NS_MutateURI(mBaseURL).SetFilePath(aFilePath).Finalize(mBaseURL);
 }
 
 NS_IMETHODIMP
 nsLDAPURL::GetQuery(nsACString &aQuery)
 {
   return mBaseURL->GetQuery(aQuery);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetQuery(const nsACString &aQuery)
+nsresult nsLDAPURL::SetQuery(const nsACString &aQuery)
 {
-  return mBaseURL->SetQuery(aQuery);
+  return NS_MutateURI(mBaseURL).SetQuery(aQuery).Finalize(mBaseURL);
 }
 
-NS_IMETHODIMP
-nsLDAPURL::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
+nsresult nsLDAPURL::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
 {
-  return mBaseURL->SetQueryWithEncoding(aQuery, aEncoding);
+  return NS_MutateURI(mBaseURL).SetQueryWithEncoding(aQuery, aEncoding).Finalize(mBaseURL);
 }
 
 NS_IMPL_ISUPPORTS(nsLDAPURL::Mutator, nsIURISetters, nsIURIMutator)
 
 NS_IMETHODIMP
 nsLDAPURL::Mutate(nsIURIMutator** aMutator)
 {
   RefPtr<nsLDAPURL::Mutator> mutator = new nsLDAPURL::Mutator();
--- a/ldap/xpcom/src/nsLDAPURL.h
+++ b/ldap/xpcom/src/nsLDAPURL.h
@@ -34,16 +34,31 @@ class nsLDAPURL : public nsILDAPURL
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
   NS_DECL_NSILDAPURL
 
   nsLDAPURL();
 
+protected:
+  virtual nsresult SetSpecInternal(const nsACString &aSpec);
+  virtual nsresult SetScheme(const nsACString &aScheme);
+  virtual nsresult SetUserPass(const nsACString &aUserPass);
+  virtual nsresult SetUsername(const nsACString &aUsername);
+  virtual nsresult SetPassword(const nsACString &aPassword);
+  virtual nsresult SetHostPort(const nsACString &aHostPort);
+  virtual nsresult SetHost(const nsACString &aHost);
+  virtual nsresult SetPort(int32_t aPort);
+  virtual nsresult SetPathQueryRef(const nsACString &aPath);
+  virtual nsresult SetRef(const nsACString &aRef);
+  virtual nsresult SetFilePath(const nsACString &aFilePath);
+  virtual nsresult SetQuery(const nsACString &aQuery);
+  virtual nsresult SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding);
+
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<nsLDAPURL>
   {
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
@@ -60,26 +75,28 @@ public:
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
-      NS_ADDREF(*aMutator = this);
+      if (aMutator)
+        NS_ADDREF(*aMutator = this);
       return InitFromSpec(aSpec);
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsLDAPURL;
   };
+  friend BaseURIMutator<nsLDAPURL>;
 
 protected:
   enum RefHandlingEnum {
     eIgnoreRef,
     eHonorRef,
     eReplaceRef
   };
   virtual ~nsLDAPURL();
--- a/mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
+++ b/mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
@@ -55,23 +55,20 @@ NS_IMETHODIMP nsAddbookProtocolHandler::
 }
 
 NS_IMETHODIMP nsAddbookProtocolHandler::NewURI(const nsACString &aSpec,
                                                const char *aOriginCharset, // ignored
                                                nsIURI *aBaseURI,
                                                nsIURI **_retval)
 {
   nsresult rv;
-  nsCOMPtr<nsIAddbookUrl> addbookUrl = do_CreateInstance(NS_ADDBOOKURL_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = addbookUrl->SetSpecInternal(aSpec);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  nsCOMPtr<nsIURI> uri = do_QueryInterface(addbookUrl, &rv);
+  nsCOMPtr<nsIURI> uri;
+  rv = NS_MutateURI(new nsAddbookUrl::Mutator())
+         .SetSpec(aSpec)
+         .Finalize(uri);
   NS_ENSURE_SUCCESS(rv,rv);
 
   uri.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAddbookProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
--- a/mailnews/addrbook/src/nsAddbookUrl.cpp
+++ b/mailnews/addrbook/src/nsAddbookUrl.cpp
@@ -26,17 +26,17 @@ nsAddbookUrl::~nsAddbookUrl()
 {
 }
 
 NS_IMPL_ISUPPORTS(nsAddbookUrl, nsIAddbookUrl, nsIURI)
 
 nsresult
 nsAddbookUrl::SetSpecInternal(const nsACString &aSpec)
 {
-  nsresult rv = m_baseURL->SetSpecInternal(aSpec);
+  nsresult rv = NS_MutateURI(m_baseURL).SetSpec(aSpec).Finalize(m_baseURL);
   NS_ENSURE_SUCCESS(rv, rv);
   return ParseUrl();
 }
 
 nsresult nsAddbookUrl::ParseUrl()
 {
   nsAutoCString pathStr;
 
@@ -67,94 +67,90 @@ NS_IMETHODIMP nsAddbookUrl::GetPrePath(n
   return m_baseURL->GetPrePath(aPrePath);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetScheme(nsACString &aScheme)
 {
   return m_baseURL->GetScheme(aScheme);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetScheme(const nsACString &aScheme)
+nsresult nsAddbookUrl::SetScheme(const nsACString &aScheme)
 {
-  return m_baseURL->SetScheme(aScheme);
+  return NS_MutateURI(m_baseURL).SetScheme(aScheme).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetUserPass(nsACString &aUserPass)
 {
   return m_baseURL->GetUserPass(aUserPass);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetUserPass(const nsACString &aUserPass)
+nsresult nsAddbookUrl::SetUserPass(const nsACString &aUserPass)
 {
-  return m_baseURL->SetUserPass(aUserPass);
+  return NS_MutateURI(m_baseURL).SetUserPass(aUserPass).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetUsername(nsACString &aUsername)
 {
   return m_baseURL->GetUsername(aUsername);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetUsername(const nsACString &aUsername)
+nsresult nsAddbookUrl::SetUsername(const nsACString &aUsername)
 {
-  return m_baseURL->SetUsername(aUsername);
+  return NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetPassword(nsACString &aPassword)
 {
   return m_baseURL->GetPassword(aPassword);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetPassword(const nsACString &aPassword)
+nsresult nsAddbookUrl::SetPassword(const nsACString &aPassword)
 {
-  return m_baseURL->SetPassword(aPassword);
+  return NS_MutateURI(m_baseURL).SetPassword(aPassword).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetHostPort(nsACString &aHostPort)
 {
   return m_baseURL->GetHostPort(aHostPort);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetHostPort(const nsACString &aHostPort)
+nsresult nsAddbookUrl::SetHostPort(const nsACString &aHostPort)
 {
-  return m_baseURL->SetHostPort(aHostPort);
-}
-
-NS_IMETHODIMP nsAddbookUrl::SetHostAndPort(const nsACString &aHostPort)
-{
-  return m_baseURL->SetHostAndPort(aHostPort);
+  return NS_MutateURI(m_baseURL).SetHostPort(aHostPort).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetHost(nsACString &aHost)
 {
   return m_baseURL->GetHost(aHost);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetHost(const nsACString &aHost)
+nsresult nsAddbookUrl::SetHost(const nsACString &aHost)
 {
-  return m_baseURL->SetHost(aHost);
+  return NS_MutateURI(m_baseURL).SetHost(aHost).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetPort(int32_t *aPort)
 {
   return m_baseURL->GetPort(aPort);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetPort(int32_t aPort)
+nsresult nsAddbookUrl::SetPort(int32_t aPort)
 {
-  return m_baseURL->SetPort(aPort);
+  return NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetPathQueryRef(nsACString &aPath)
 {
   return m_baseURL->GetPathQueryRef(aPath);
 }
 
-NS_IMETHODIMP nsAddbookUrl::SetPathQueryRef(const nsACString &aPath)
+nsresult nsAddbookUrl::SetPathQueryRef(const nsACString &aPath)
 {
-  m_baseURL->SetPathQueryRef(aPath);
+  nsresult rv = NS_MutateURI(m_baseURL).SetPathQueryRef(aPath).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
   return ParseUrl();
 }
 
 NS_IMETHODIMP nsAddbookUrl::GetAsciiHost(nsACString &aHostA)
 {
   return m_baseURL->GetAsciiHost(aHostA);
 }
 
@@ -232,51 +228,48 @@ NS_IMETHODIMP nsAddbookUrl::Resolve(cons
 }
 
 NS_IMETHODIMP
 nsAddbookUrl::GetRef(nsACString &result)
 {
   return m_baseURL->GetRef(result);
 }
 
-NS_IMETHODIMP
-nsAddbookUrl::SetRef(const nsACString &aRef)
+nsresult nsAddbookUrl::SetRef(const nsACString &aRef)
 {
-  m_baseURL->SetRef(aRef);
+  nsresult rv = NS_MutateURI(m_baseURL).SetRef(aRef).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
   return ParseUrl();
 }
 
 NS_IMETHODIMP
 nsAddbookUrl::GetFilePath(nsACString &aFilePath)
 {
   return m_baseURL->GetFilePath(aFilePath);
 }
 
-NS_IMETHODIMP
-nsAddbookUrl::SetFilePath(const nsACString &aFilePath)
+nsresult nsAddbookUrl::SetFilePath(const nsACString &aFilePath)
 {
-  return m_baseURL->SetFilePath(aFilePath);
+  return NS_MutateURI(m_baseURL).SetFilePath(aFilePath).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP
 nsAddbookUrl::GetQuery(nsACString &aQuery)
 {
   return m_baseURL->GetQuery(aQuery);
 }
 
-NS_IMETHODIMP
-nsAddbookUrl::SetQuery(const nsACString &aQuery)
+nsresult nsAddbookUrl::SetQuery(const nsACString &aQuery)
 {
-  return m_baseURL->SetQuery(aQuery);
+  return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
 }
 
-NS_IMETHODIMP
-nsAddbookUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
+nsresult nsAddbookUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
 {
-  return m_baseURL->SetQueryWithEncoding(aQuery, aEncoding);
+  return NS_MutateURI(m_baseURL).SetQueryWithEncoding(aQuery, aEncoding).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsAddbookUrl::EqualsExceptRef(nsIURI *other, bool *_retval)
 {
   // The passed-in URI might be an nsMailtoUrl. Pass our inner URL to its
   // Equals method. The other nsMailtoUrl will then pass its inner URL to
   // to the Equals method of our inner URL. Other URIs will return false.
   if (other)
--- a/mailnews/addrbook/src/nsAddbookUrl.h
+++ b/mailnews/addrbook/src/nsAddbookUrl.h
@@ -15,16 +15,31 @@ class nsAddbookUrl : public nsIAddbookUr
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIURI
     NS_DECL_NSIADDBOOKURL
 
     nsAddbookUrl();
 
+protected:
+  virtual nsresult SetSpecInternal(const nsACString &aSpec);
+  virtual nsresult SetScheme(const nsACString &aScheme);
+  virtual nsresult SetUserPass(const nsACString &aUserPass);
+  virtual nsresult SetUsername(const nsACString &aUsername);
+  virtual nsresult SetPassword(const nsACString &aPassword);
+  virtual nsresult SetHostPort(const nsACString &aHostPort);
+  virtual nsresult SetHost(const nsACString &aHost);
+  virtual nsresult SetPort(int32_t aPort);
+  virtual nsresult SetPathQueryRef(const nsACString &aPath);
+  virtual nsresult SetRef(const nsACString &aRef);
+  virtual nsresult SetFilePath(const nsACString &aFilePath);
+  virtual nsresult SetQuery(const nsACString &aQuery);
+  virtual nsresult SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding);
+
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<nsAddbookUrl>
   {
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
@@ -41,26 +56,28 @@ public:
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
-      NS_ADDREF(*aMutator = this);
+      if (aMutator)
+        NS_ADDREF(*aMutator = this);
       return InitFromSpec(aSpec);
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsAddbookUrl;
   };
+  friend BaseURIMutator<nsAddbookUrl>;
 
 protected:
   enum RefHandlingEnum {
     eIgnoreRef,
     eHonorRef,
     eReplaceRef
   };
   virtual ~nsAddbookUrl();
--- a/mailnews/base/public/nsIMsgMailNewsUrl.idl
+++ b/mailnews/base/public/nsIMsgMailNewsUrl.idl
@@ -22,16 +22,19 @@ interface nsIMsgDBHdr;
 interface nsIDocShellLoadInfo;
 interface nsIDocShell;
 
 [scriptable, builtinclass, uuid(995455ba-5bb4-4643-8d70-2b877a2e1320)]
 interface nsIMsgMailNewsUrl : nsIURL {
   [noscript,notxpcom,nostdcall]
   nsresult setFileNameInternal(in ACString aFileName);
 
+  [noscript,notxpcom,nostdcall]
+  nsresult setSpecInternal(in ACString Spec);
+
   ///////////////////////////////////////////////////////////////////////////////
   // Eventually we'd like to push this type of functionality up into nsIURI.
   // The idea is to allow the "application" (the part of the code which wants to
   // run a url in order to perform some action) to register itself as a listener
   // on url. As a url listener, the app will be informed when the url begins to run
   // and when the url is finished.
   ////////////////////////////////////////////////////////////////////////////////
   void RegisterListener (in nsIUrlListener aUrlListener);
--- a/mailnews/base/src/nsMessengerContentHandler.cpp
+++ b/mailnews/base/src/nsMessengerContentHandler.cpp
@@ -10,16 +10,17 @@
 #include "nsIWindowWatcher.h"
 #include "nsIDocShell.h"
 #include "nsIWebNavigation.h"
 #include "nsIURL.h"
 #include "nsString.h"
 #include "nsMsgBaseCID.h"
 #include "plstr.h"
 #include "nsIURL.h"
+#include "nsIURIMutator.h"
 #include "nsServiceManagerUtils.h"
 
 nsMessengerContentHandler::nsMessengerContentHandler()
 {
 }
 
 /* the following macro actually implement addref, release and query interface for our component. */
 NS_IMPL_ISUPPORTS(nsMessengerContentHandler, nsIContentHandler)
@@ -50,17 +51,18 @@ NS_IMETHODIMP nsMessengerContentHandler:
         nsCOMPtr<nsIURL> aUrl = do_QueryInterface(aUri);
         if (aUrl)
         {
           nsAutoCString queryPart;
           aUrl->GetQuery(queryPart);
           queryPart.Replace(queryPart.Find("type=message/rfc822"),
                             sizeof("type=message/rfc822") - 1,
                             "type=application/x-message-display");
-          aUrl->SetQuery(queryPart);
+          rv = NS_MutateURI(aUrl).SetQuery(queryPart).Finalize(aUrl);
+          NS_ENSURE_SUCCESS(rv, rv);
           rv = OpenWindow(aUri);
         }
       }
     }
   }
 
   return rv;
 }
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -3184,17 +3184,18 @@ nsMsgDBFolder::parseURI(bool needServer)
       nsCString serverType;
       GetIncomingServerType(serverType);
       if (serverType.IsEmpty())
       {
         NS_WARNING("can't determine folder's server type");
         return NS_ERROR_FAILURE;
       }
 
-      url->SetScheme(serverType);
+      rv = NS_MutateURI(url).SetScheme(serverType).Finalize(url);
+      NS_ENSURE_SUCCESS(rv, rv);
       rv = accountManager->FindServerByURI(url, false,
                                       getter_AddRefs(server));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     mServer = do_GetWeakReference(server);
   } /* !mServer */
 
   // now try to find the local path for this folder
--- a/mailnews/base/util/nsMsgMailNewsUrl.cpp
+++ b/mailnews/base/util/nsMsgMailNewsUrl.cpp
@@ -212,30 +212,32 @@ NS_IMETHODIMP nsMsgMailNewsUrl::GetServe
   rv = GetScheme(scheme);
   if (NS_SUCCEEDED(rv))
   {
     if (scheme.EqualsLiteral("pop"))
       scheme.AssignLiteral("pop3");
     // we use "nntp" in the server list so translate it here.
     if (scheme.EqualsLiteral("news"))
       scheme.AssignLiteral("nntp");
-    url->SetScheme(scheme);
+    rv = NS_MutateURI(url).SetScheme(scheme).Finalize(url);
+    NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIMsgAccountManager> accountManager =
       do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) return rv;
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIMsgIncomingServer> server;
     rv = accountManager->FindServerByURI(url, false, aIncomingServer);
     if (!*aIncomingServer && scheme.EqualsLiteral("imap"))
     {
       // look for any imap server with this host name so clicking on
       // other users folder urls will work. We could override this method
       // for imap urls, or we could make caching of servers work and
       // just set the server in the imap code for this case.
-      url->SetUserPass(EmptyCString());
+      rv = NS_MutateURI(url).SetUserPass(EmptyCString()).Finalize(url);
+      NS_ENSURE_SUCCESS(rv, rv);
       rv = accountManager->FindServerByURI(url, false, aIncomingServer);
     }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgWindow(nsIMsgWindow **aMsgWindow)
@@ -413,17 +415,17 @@ nsresult nsMsgMailNewsUrl::SetSpecIntern
       mAttachmentFileName = start+FILENAME_PART_LEN;
       *end = '&';
     }
     else
       mAttachmentFileName = start+FILENAME_PART_LEN;
   }
 
   // Now, set the rest.
-  nsresult rv = m_baseURL->SetSpecInternal(aSpec);
+  nsresult rv = NS_MutateURI(m_baseURL).SetSpec(aSpec).Finalize(m_baseURL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Check whether the URL is in normalised form.
   nsCOMPtr <nsIMsgMessageUrl> msgUrl;
   QueryInterface(NS_GET_IID(nsIMsgMessageUrl), getter_AddRefs(msgUrl));
 
   nsAutoCString principalSpec;
   if (!msgUrl || NS_FAILED(msgUrl->GetPrincipalSpec(principalSpec))) {
@@ -440,96 +442,91 @@ NS_IMETHODIMP nsMsgMailNewsUrl::GetPrePa
   return m_baseURL->GetPrePath(aPrePath);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetScheme(nsACString &aScheme)
 {
   return m_baseURL->GetScheme(aScheme);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetScheme(const nsACString &aScheme)
+nsresult nsMsgMailNewsUrl::SetScheme(const nsACString &aScheme)
 {
-  return m_baseURL->SetScheme(aScheme);
+  return NS_MutateURI(m_baseURL).SetScheme(aScheme).Finalize(m_baseURL);
 }
 
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetUserPass(nsACString &aUserPass)
 {
   return m_baseURL->GetUserPass(aUserPass);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetUserPass(const nsACString &aUserPass)
+nsresult nsMsgMailNewsUrl::SetUserPass(const nsACString &aUserPass)
 {
-  return m_baseURL->SetUserPass(aUserPass);
+  return NS_MutateURI(m_baseURL).SetUserPass(aUserPass).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetUsername(nsACString &aUsername)
 {
   /* note:  this will return an escaped string */
   return m_baseURL->GetUsername(aUsername);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetUsername(const nsACString &aUsername)
+nsresult nsMsgMailNewsUrl::SetUsername(const nsACString &aUsername)
 {
-  return m_baseURL->SetUsername(aUsername);
+  return NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetPassword(nsACString &aPassword)
 {
   return m_baseURL->GetPassword(aPassword);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetPassword(const nsACString &aPassword)
+nsresult nsMsgMailNewsUrl::SetPassword(const nsACString &aPassword)
 {
-  return m_baseURL->SetPassword(aPassword);
+  return NS_MutateURI(m_baseURL).SetPassword(aPassword).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetHostPort(nsACString &aHostPort)
 {
   return m_baseURL->GetHostPort(aHostPort);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetHostPort(const nsACString &aHostPort)
+nsresult nsMsgMailNewsUrl::SetHostPort(const nsACString &aHostPort)
 {
-  return m_baseURL->SetHostPort(aHostPort);
-}
-
-NS_IMETHODIMP nsMsgMailNewsUrl::SetHostAndPort(const nsACString &aHostPort)
-{
-  return m_baseURL->SetHostAndPort(aHostPort);
+  return NS_MutateURI(m_baseURL).SetHostPort(aHostPort).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(nsACString &aHost)
 {
   return m_baseURL->GetHost(aHost);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetHost(const nsACString &aHost)
+nsresult nsMsgMailNewsUrl::SetHost(const nsACString &aHost)
 {
-  return m_baseURL->SetHost(aHost);
+  return NS_MutateURI(m_baseURL).SetHost(aHost).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetPort(int32_t *aPort)
 {
   return m_baseURL->GetPort(aPort);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetPort(int32_t aPort)
+nsresult nsMsgMailNewsUrl::SetPort(int32_t aPort)
 {
-  return m_baseURL->SetPort(aPort);
+  return NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetPathQueryRef(nsACString &aPath)
 {
   return m_baseURL->GetPathQueryRef(aPath);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetPathQueryRef(const nsACString &aPath)
+nsresult nsMsgMailNewsUrl::SetPathQueryRef(const nsACString &aPath)
 {
-  return m_baseURL->SetPathQueryRef(aPath);
+  return NS_MutateURI(m_baseURL).SetPathQueryRef(aPath).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiHost(nsACString &aHostA)
 {
     return m_baseURL->GetAsciiHost(aHostA);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiHostPort(nsACString &aHostPortA)
@@ -617,36 +614,38 @@ nsMsgMailNewsUrl::CloneInternal(uint32_t
 {
   nsresult rv;
   nsAutoCString urlSpec;
   nsCOMPtr<nsIIOService> ioService =
     mozilla::services::GetIOService();
   NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
   rv = GetSpec(urlSpec);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = ioService->NewURI(urlSpec, nullptr, nullptr, _retval);
+  nsCOMPtr<nsIURI> newUri;
+  rv = ioService->NewURI(urlSpec, nullptr, nullptr, getter_AddRefs(newUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // add the msg window to the cloned url
   nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindowWeak));
   if (msgWindow)
   {
-    nsCOMPtr<nsIMsgMailNewsUrl> msgMailNewsUrl = do_QueryInterface(*_retval, &rv);
+    nsCOMPtr<nsIMsgMailNewsUrl> msgMailNewsUrl = do_QueryInterface(newUri, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     msgMailNewsUrl->SetMsgWindow(msgWindow);
   }
 
   if (aRefHandlingMode == nsIMsgMailNewsUrl::REPLACE_REF) {
-    rv = (*_retval)->SetRef(newRef);
+    rv = NS_MutateURI(newUri).SetRef(newRef).Finalize(newUri);
     NS_ENSURE_SUCCESS(rv, rv);
   } else if (aRefHandlingMode == nsIMsgMailNewsUrl::IGNORE_REF) {
-    rv = (*_retval)->SetRef(EmptyCString());
+    rv = NS_MutateURI(newUri).SetRef(EmptyCString()).Finalize(newUri);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  newUri.forget(_retval);
   return rv;
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::Clone(nsIURI **_retval)
 {
   return CloneInternal(nsIMsgMailNewsUrl::HONOR_REF, EmptyCString(), _retval);
 }
 
@@ -740,45 +739,44 @@ nsresult nsMsgMailNewsUrl::SetFileNameIn
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetQuery(nsACString &aQuery)
 {
   return m_baseURL->GetQuery(aQuery);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetQuery(const nsACString &aQuery)
+nsresult nsMsgMailNewsUrl::SetQuery(const nsACString &aQuery)
 {
-  return m_baseURL->SetQuery(aQuery);
+  return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
 }
 
-NS_IMETHODIMP
-nsMsgMailNewsUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
+nsresult nsMsgMailNewsUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
 {
-  return m_baseURL->SetQueryWithEncoding(aQuery, aEncoding);
+  return NS_MutateURI(m_baseURL).SetQueryWithEncoding(aQuery, aEncoding).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetRef(nsACString &aRef)
 {
   return m_baseURL->GetRef(aRef);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetRef(const nsACString &aRef)
+nsresult nsMsgMailNewsUrl::SetRef(const nsACString &aRef)
 {
-  return m_baseURL->SetRef(aRef);
+  return NS_MutateURI(m_baseURL).SetRef(aRef).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetFilePath(nsACString &o_DirFile)
 {
   return m_baseURL->GetFilePath(o_DirFile);
 }
 
-NS_IMETHODIMP nsMsgMailNewsUrl::SetFilePath(const nsACString &i_DirFile)
+nsresult nsMsgMailNewsUrl::SetFilePath(const nsACString &i_DirFile)
 {
-  return m_baseURL->SetFilePath(i_DirFile);
+  return NS_MutateURI(m_baseURL).SetFilePath(i_DirFile).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetCommonBaseSpec(nsIURI *uri2, nsACString &result)
 {
   return m_baseURL->GetCommonBaseSpec(uri2, result);
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetRelativeSpec(nsIURI *uri2, nsACString &result)
--- a/mailnews/base/util/nsMsgMailNewsUrl.h
+++ b/mailnews/base/util/nsMsgMailNewsUrl.h
@@ -45,16 +45,30 @@ public:
     nsMsgMailNewsUrl();
 
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIMSGMAILNEWSURL
     NS_DECL_NSIURI
     NS_DECL_NSIURL
     NS_DECL_NSIURIWITHPRINCIPAL
 
+protected:
+  virtual nsresult SetScheme(const nsACString &aScheme);
+  virtual nsresult SetUserPass(const nsACString &aUserPass);
+  virtual nsresult SetUsername(const nsACString &aUsername);
+  virtual nsresult SetPassword(const nsACString &aPassword);
+  virtual nsresult SetHostPort(const nsACString &aHostPort);
+  virtual nsresult SetHost(const nsACString &aHost);
+  virtual nsresult SetPort(int32_t aPort);
+  virtual nsresult SetPathQueryRef(const nsACString &aPath);
+  virtual nsresult SetRef(const nsACString &aRef);
+  virtual nsresult SetFilePath(const nsACString &aFilePath);
+  virtual nsresult SetQuery(const nsACString &aQuery);
+  virtual nsresult SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding);
+
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<nsMsgMailNewsUrl>
   {
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
@@ -71,26 +85,28 @@ public:
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
-      NS_ADDREF(*aMutator = this);
+      if (aMutator)
+        NS_ADDREF(*aMutator = this);
       return InitFromSpec(aSpec);
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsMsgMailNewsUrl;
   };
+  friend BaseURIMutator<nsMsgMailNewsUrl>;
 
 protected:
   virtual ~nsMsgMailNewsUrl();
 
   nsCOMPtr<nsIURL> m_baseURL;
   nsCOMPtr<nsIPrincipal> m_principal;
   nsWeakPtr m_statusFeedbackWeak;
   nsWeakPtr m_msgWindowWeak;
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -73,16 +73,17 @@
 #include "nsIDocumentEncoder.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Services.h"
 #include "locale.h"
 #include "nsStringStream.h"
 #include "nsIInputStreamPump.h"
 #include "nsIInputStream.h"
 #include "nsIChannel.h"
+#include "nsIURIMutator.h"
 
 /* for logging to Error Console */
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 
 // Log an error string to the error console
 // (adapted from nsContentUtils::LogSimpleConsoleError).
 // Flag can indicate error, warning or info.
@@ -173,40 +174,43 @@ nsresult CreateStartupUrl(const char *ur
   if (!uri || !*uri || !aUrl) return rv;
   *aUrl = nullptr;
 
   // XXX fix this, so that base doesn't depend on imap, local or news.
   // we can't do NS_NewURI(uri, aUrl), because these are imap-message://, mailbox-message://, news-message:// uris.
   // I think we should do something like GetMessageServiceFromURI() to get the service, and then have the service create the
   // appropriate nsI*Url, and then QI to nsIURI, and return it.
   // see bug #110689
+  nsCOMPtr<nsIMsgMailNewsUrl> newUri;
   if (PL_strncasecmp(uri, "imap", 4) == 0)
   {
     nsCOMPtr<nsIImapUrl> imapUrl = do_CreateInstance(kImapUrlCID, &rv);
 
     if (NS_SUCCEEDED(rv) && imapUrl)
-      rv = imapUrl->QueryInterface(NS_GET_IID(nsIURI),
-      (void**) aUrl);
+      rv = imapUrl->QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(newUri));
+
+    // XXX Consider: NS_MutateURI(new nsImapUrl::Mutator()).SetSpec(nsDependentCString(uri)).Finalize(newUri);
   }
   else if (PL_strncasecmp(uri, "mailbox", 7) == 0)
   {
     nsCOMPtr<nsIMailboxUrl> mailboxUrl = do_CreateInstance(kCMailboxUrl, &rv);
     if (NS_SUCCEEDED(rv) && mailboxUrl)
-      rv = mailboxUrl->QueryInterface(NS_GET_IID(nsIURI),
-      (void**) aUrl);
+      rv = mailboxUrl->QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(newUri));
   }
   else if (PL_strncasecmp(uri, "news", 4) == 0)
   {
     nsCOMPtr<nsINntpUrl> nntpUrl = do_CreateInstance(kCNntpUrlCID, &rv);
     if (NS_SUCCEEDED(rv) && nntpUrl)
-      rv = nntpUrl->QueryInterface(NS_GET_IID(nsIURI),
-      (void**) aUrl);
+      rv = nntpUrl->QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(newUri));
   }
+
   if (*aUrl) // SetSpec can fail, for mailbox urls, but we still have a url.
-    (void)(*aUrl)->SetSpecInternal(nsDependentCString(uri));
+    (void)newUri->SetSpecInternal(nsDependentCString(uri));
+
+  newUri.forget(aUrl);
   return rv;
 }
 
 
 // Where should this live? It's a utility used to convert a string priority,
 //  e.g., "High, Low, Normal" to an enum.
 // Perhaps we should have an interface that groups together all these
 //  utilities...
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -45,16 +45,18 @@
 #include "nsContentCID.h"
 #include "nsISelection.h"
 #include "nsUTF8Utils.h"
 #include "mozilla/intl/LineBreaker.h"
 #include "mozilla/Services.h"
 #include "mimemoz2.h"
 #include "nsIArray.h"
 #include "nsArrayUtils.h"
+#include "nsIURIMutator.h"
+#include "mozilla/Unused.h"
 
 #ifdef MSGCOMP_TRACE_PERFORMANCE
 #include "mozilla/Logging.h"
 #include "nsIMsgHdr.h"
 #include "nsIMsgMessageService.h"
 #include "nsMsgUtils.h"
 #endif
 
@@ -1326,17 +1328,17 @@ nsMsgComposeService::RunMessageThroughMi
   if (fileUrl || PromiseFlatCString(aMsgURI).Find("&type=application/x-message-display") >= 0)
     rv = NS_NewURI(getter_AddRefs(url), mailboxUri);
   else
     rv = messageService->GetUrlForUri(PromiseFlatCString(aMsgURI).get(), getter_AddRefs(url), aMsgWindow);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // ignore errors here - it's not fatal, and in the case of mailbox messages,
   // we're always passing in an invalid spec...
-  (void)url->SetSpecInternal(mailboxUri);
+  mozilla::Unused << NS_MutateURI(url).SetSpec(mailboxUri).Finalize(url);
 
   // if we are forwarding a message and that message used a charset over ride
   // then use that over ride charset instead of the charset specified in the message
   nsCString mailCharset;
   if (aMsgWindow)
   {
     bool charsetOverride;
     if (NS_SUCCEEDED(aMsgWindow->GetCharsetOverride(&charsetOverride)) && charsetOverride)
--- a/mailnews/compose/src/nsMsgQuote.cpp
+++ b/mailnews/compose/src/nsMsgQuote.cpp
@@ -109,58 +109,55 @@ nsMsgQuote::QuoteMessage(const char *msg
     return NS_ERROR_INVALID_ARG;
 
   mQuoteHeaders = quoteHeaders;
   mStreamListener = aQuoteMsgStreamListener;
 
   nsAutoCString msgUri(msgURI);
   bool fileUrl = !strncmp(msgURI, "file:", 5);
   bool forwardedMessage = PL_strstr(msgURI, "&realtype=message/rfc822") != nullptr;
-  nsCOMPtr<nsIURI> aURL;
+  nsCOMPtr<nsIURI> newURI;
   if (fileUrl)
   {
     msgUri.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
     msgUri.AppendLiteral("?number=0");
-    rv = NS_NewURI(getter_AddRefs(aURL), msgUri);
-    nsCOMPtr<nsIMsgMessageUrl> mailUrl(do_QueryInterface(aURL));
+    rv = NS_NewURI(getter_AddRefs(newURI), msgUri);
+    nsCOMPtr<nsIMsgMessageUrl> mailUrl(do_QueryInterface(newURI));
     if (mailUrl)
       mailUrl->SetMessageHeader(aMsgHdr);
   }
   else if (forwardedMessage)
-    rv = NS_NewURI(getter_AddRefs(aURL), msgURI);
+    rv = NS_NewURI(getter_AddRefs(newURI), msgURI);
   else
   {
     nsCOMPtr <nsIMsgMessageService> msgService;
     rv = GetMessageServiceFromURI(nsDependentCString(msgURI), getter_AddRefs(msgService));
     if (NS_FAILED(rv)) return rv;
-    rv = msgService->GetUrlForUri(msgURI, getter_AddRefs(aURL), nullptr);
+    rv = msgService->GetUrlForUri(msgURI, getter_AddRefs(newURI), nullptr);
   }
   if (NS_FAILED(rv)) return rv;
 
-  nsCOMPtr <nsIURL> mailNewsUrl = do_QueryInterface(aURL, &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-
   nsAutoCString queryPart;
-  rv = mailNewsUrl->GetQuery(queryPart);
+  rv = newURI->GetQuery(queryPart);
   if (!queryPart.IsEmpty())
     queryPart.Append('&');
 
   if (headersOnly) /* We don't need to quote the message body but we still need to extract the headers */
     queryPart.AppendLiteral("header=only");
   else if (quoteHeaders)
     queryPart.AppendLiteral("header=quote");
   else
     queryPart.AppendLiteral("header=quotebody");
-  rv = mailNewsUrl->SetQuery(queryPart);
+  rv = NS_MutateURI(newURI).SetQuery(queryPart).Finalize(newURI);
   NS_ENSURE_SUCCESS(rv,rv);
 
   // if we were given a non empty charset, then use it
   if (aMsgCharSet && *aMsgCharSet)
   {
-    nsCOMPtr<nsIMsgI18NUrl> i18nUrl (do_QueryInterface(aURL));
+    nsCOMPtr<nsIMsgI18NUrl> i18nUrl (do_QueryInterface(newURI));
     if (i18nUrl)
       i18nUrl->SetCharsetOverRide(aMsgCharSet);
   }
 
   mQuoteListener = do_CreateInstance(NS_MSGQUOTELISTENER_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return rv;
   mQuoteListener->SetMsgQuote(this);
 
@@ -169,26 +166,26 @@ nsMsgQuote::QuoteMessage(const char *msg
   QueryInterface(NS_GET_IID(nsISupports), (void **) &supports);
   nsCOMPtr<nsISupports> quoteSupport = supports;
   NS_IF_RELEASE(supports);
 
   // now we want to create a necko channel for this url and we want to open it
   mQuoteChannel = nullptr;
   nsCOMPtr<nsIIOService> netService = mozilla::services::GetIOService();
   NS_ENSURE_TRUE(netService, NS_ERROR_UNEXPECTED);
-  rv = netService->NewChannelFromURI2(aURL,
+  rv = netService->NewChannelFromURI2(newURI,
                                       nullptr,
                                       nsContentUtils::GetSystemPrincipal(),
                                       nullptr,
                                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                                       nsIContentPolicy::TYPE_OTHER,
                                       getter_AddRefs(mQuoteChannel));
 
   if (NS_FAILED(rv)) return rv;
-  nsCOMPtr<nsISupports> ctxt = do_QueryInterface(aURL);
+  nsCOMPtr<nsISupports> ctxt = do_QueryInterface(newURI);
 
   nsCOMPtr<nsIStreamConverterService> streamConverterService =
            do_GetService("@mozilla.org/streamConverters;1", &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsCOMPtr<nsIStreamListener> convertedListener;
   rv = streamConverterService->AsyncConvertData("message/rfc822",
                                                 "application/vnd.mozilla.xul+xml",
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -2072,17 +2072,17 @@ nsMsgComposeAndSend::AddCompFieldLocalAt
                   if (!type.EqualsLiteral("multipart/appledouble"))  // can't do apple double on non-macs
 #endif
                   m_attachments[newLoc]->m_type = type;
                 }
 
                 //Then try using the url if we still haven't figured out the content type
                 if (m_attachments[newLoc]->m_type.IsEmpty())
                 {
-                  rv = fileUrl->SetSpecInternal(url);
+                  rv = NS_MutateURI(fileUrl).SetSpec(url).Finalize(fileUrl);
                   if (NS_SUCCEEDED(rv))
                   {
                     rv = fileUrl->GetFileExtension(fileExt);
                     if (NS_SUCCEEDED(rv) && !fileExt.IsEmpty()) {
                       nsAutoCString type;
                       mimeFinder->GetTypeFromExtension(fileExt, type);
   #ifndef XP_MACOSX
                     if (!type.EqualsLiteral("multipart/appledouble"))  // can't do apple double on non-macs
--- a/mailnews/compose/src/nsSmtpService.cpp
+++ b/mailnews/compose/src/nsSmtpService.cpp
@@ -42,17 +42,16 @@ typedef struct _findServerByKeyEntry {
 
 typedef struct _findServerByHostnameEntry {
     nsCString hostname;
     nsCString username;
     nsISmtpServer *server;
 } findServerByHostnameEntry;
 
 static NS_DEFINE_CID(kCSmtpUrlCID, NS_SMTPURL_CID);
-static NS_DEFINE_CID(kCMailtoUrlCID, NS_MAILTOURL_CID);
 
 // foward declarations...
 nsresult
 NS_MsgBuildSmtpUrl(nsIFile * aFilePath,
                    nsISmtpServer *aServer,
                    const char* aRecipients,
                    nsIMsgIdentity * aSenderIdentity,
                    const char * aSender,
@@ -168,20 +167,20 @@ nsresult NS_MsgBuildSmtpUrl(nsIFile * aF
 
   urlSpec.Append(smtpHostName);
   if (smtpHostName.FindChar(':') == -1)
   {
     urlSpec.Append(':');
     urlSpec.AppendInt(smtpPort);
   }
 
-  nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(smtpUrl, &rv));
+  nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl(do_QueryInterface(smtpUrl, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = url->SetSpecInternal(urlSpec);
+  rv = mailnewsurl->SetSpecInternal(urlSpec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   smtpUrl->SetSender(aSender);
   smtpUrl->SetRecipients(aRecipients);
   smtpUrl->SetRequestDSN(aRequestDSN);
   smtpUrl->SetPostMessageFile(aFilePath);
   smtpUrl->SetSenderIdentity(aSenderIdentity);
   if (aNotificationCallbacks)
@@ -200,19 +199,19 @@ nsresult NS_MsgBuildSmtpUrl(nsIFile * aF
     if (!smtpAuthPrompt)
       wwatch->GetNewAuthPrompter(0, getter_AddRefs(smtpAuthPrompt));
   }
 
   smtpUrl->SetPrompt(smtpPrompt);
   smtpUrl->SetAuthPrompt(smtpAuthPrompt);
 
   if (aUrlListener)
-    url->RegisterListener(aUrlListener);
+    mailnewsurl->RegisterListener(aUrlListener);
   if (aStatusFeedback)
-    url->SetStatusFeedback(aStatusFeedback);
+    mailnewsurl->SetStatusFeedback(aStatusFeedback);
 
   return CallQueryInterface(smtpUrl, aUrl);
 }
 
 nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl, nsISupports * aConsumer, nsIRequest ** aRequest)
 {
   NS_ENSURE_ARG_POINTER(aUrl);
 
@@ -294,35 +293,40 @@ NS_IMETHODIMP nsSmtpService::GetProtocol
 
 NS_IMETHODIMP nsSmtpService::NewURI(const nsACString &aSpec,
                                     const char *aOriginCharset,
                                     nsIURI *aBaseURI,
                                     nsIURI **_retval)
 {
   // get a new smtp url
   nsresult rv;
-  nsCOMPtr<nsIURI> mailtoUrl = do_CreateInstance(kCMailtoUrlCID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString utf8Spec;
   if (aOriginCharset)
   {
     nsCOMPtr<nsIUTF8ConverterService>
       utf8Converter(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv))
       rv = utf8Converter->ConvertURISpecToUTF8(aSpec, aOriginCharset, utf8Spec);
   }
 
   // utf8Spec is filled up only when aOriginCharset is specified and
   // the conversion is successful. Otherwise, fall back to aSpec.
-  if (aOriginCharset && NS_SUCCEEDED(rv))
-    rv = mailtoUrl->SetSpecInternal(utf8Spec);
-  else
-    rv = mailtoUrl->SetSpecInternal(aSpec);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIURI> mailtoUrl;
+  if (aOriginCharset && NS_SUCCEEDED(rv)) {
+    rv = NS_MutateURI(new nsMailtoUrl::Mutator())
+           .SetSpec(utf8Spec)
+           .Finalize(mailtoUrl);
+    NS_ENSURE_SUCCESS(rv, rv);
+  } else {
+    rv = NS_MutateURI(new nsMailtoUrl::Mutator())
+           .SetSpec(aSpec)
+           .Finalize(mailtoUrl);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   mailtoUrl.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsSmtpService::NewChannel(nsIURI *aURI, nsIChannel **_retval)
 {
   return NewChannel2(aURI, nullptr, _retval);
--- a/mailnews/compose/src/nsSmtpUrl.cpp
+++ b/mailnews/compose/src/nsSmtpUrl.cpp
@@ -260,17 +260,17 @@ nsresult nsMailtoUrl::ParseMailtoUrl(cha
     }
   }
 
   return NS_OK;
 }
 
 nsresult nsMailtoUrl::SetSpecInternal(const nsACString &aSpec)
 {
-  nsresult rv = m_baseURL->SetSpecInternal(aSpec);
+  nsresult rv = NS_MutateURI(m_baseURL).SetSpec(aSpec).Finalize(m_baseURL);
   NS_ENSURE_SUCCESS(rv, rv);
   return ParseUrl();
 }
 
 nsresult nsMailtoUrl::CleanupMailtoState()
 {
     m_ccPart = "";
     m_subjectPart = "";
@@ -395,102 +395,104 @@ NS_IMETHODIMP nsMailtoUrl::GetPrePath(ns
 	return m_baseURL->GetPrePath(aPrePath);
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetScheme(nsACString &aScheme)
 {
 	return m_baseURL->GetScheme(aScheme);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetScheme(const nsACString &aScheme)
+nsresult nsMailtoUrl::SetScheme(const nsACString &aScheme)
 {
-	m_baseURL->SetScheme(aScheme);
+  nsresult rv = NS_MutateURI(m_baseURL).SetScheme(aScheme).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetUserPass(nsACString &aUserPass)
 {
 	return m_baseURL->GetUserPass(aUserPass);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetUserPass(const nsACString &aUserPass)
+nsresult nsMailtoUrl::SetUserPass(const nsACString &aUserPass)
 {
-	m_baseURL->SetUserPass(aUserPass);
+  nsresult rv = NS_MutateURI(m_baseURL).SetUserPass(aUserPass).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetUsername(nsACString &aUsername)
 {
 	return m_baseURL->GetUsername(aUsername);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetUsername(const nsACString &aUsername)
+nsresult nsMailtoUrl::SetUsername(const nsACString &aUsername)
 {
-	m_baseURL->SetUsername(aUsername);
+  nsresult rv = NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetPassword(nsACString &aPassword)
 {
 	return m_baseURL->GetPassword(aPassword);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetPassword(const nsACString &aPassword)
+nsresult nsMailtoUrl::SetPassword(const nsACString &aPassword)
 {
-	m_baseURL->SetPassword(aPassword);
+  nsresult rv = NS_MutateURI(m_baseURL).SetPassword(aPassword).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetHostPort(nsACString &aHostPort)
 {
 	return m_baseURL->GetHost(aHostPort);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetHostPort(const nsACString &aHostPort)
+nsresult nsMailtoUrl::SetHostPort(const nsACString &aHostPort)
 {
-	m_baseURL->SetHost(aHostPort);
-	return ParseUrl();
-}
-
-NS_IMETHODIMP nsMailtoUrl::SetHostAndPort(const nsACString &aHostPort)
-{
-	m_baseURL->SetHostAndPort(aHostPort);
+  nsresult rv = NS_MutateURI(m_baseURL).SetHostPort(aHostPort).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetHost(nsACString &aHost)
 {
 	return m_baseURL->GetHost(aHost);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetHost(const nsACString &aHost)
+nsresult nsMailtoUrl::SetHost(const nsACString &aHost)
 {
-	m_baseURL->SetHost(aHost);
+  nsresult rv = NS_MutateURI(m_baseURL).SetHost(aHost).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetPort(int32_t *aPort)
 {
 	return m_baseURL->GetPort(aPort);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetPort(int32_t aPort)
+nsresult nsMailtoUrl::SetPort(int32_t aPort)
 {
-	m_baseURL->SetPort(aPort);
+  nsresult rv = NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetPathQueryRef(nsACString &aPath)
 {
 	return m_baseURL->GetPathQueryRef(aPath);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetPathQueryRef(const nsACString &aPath)
+nsresult nsMailtoUrl::SetPathQueryRef(const nsACString &aPath)
 {
-	m_baseURL->SetPathQueryRef(aPath);
+  nsresult rv = NS_MutateURI(m_baseURL).SetPathQueryRef(aPath).Finalize(m_baseURL);
+  NS_ENSURE_SUCCESS(rv, rv);
 	return ParseUrl();
 }
 
 NS_IMETHODIMP nsMailtoUrl::GetAsciiHost(nsACString &aHostA)
 {
 	return m_baseURL->GetAsciiHost(aHostA);
 }
 
@@ -562,19 +564,19 @@ nsMailtoUrl::CloneWithNewRef(const nsACS
   return CloneInternal(eReplaceRef, newRef, _retval);
 }
 
 NS_IMETHODIMP nsMailtoUrl::Resolve(const nsACString &relativePath, nsACString &result)
 {
   return m_baseURL->Resolve(relativePath, result);
 }
 
-NS_IMETHODIMP nsMailtoUrl::SetRef(const nsACString &aRef)
+nsresult nsMailtoUrl::SetRef(const nsACString &aRef)
 {
-  return m_baseURL->SetRef(aRef);
+  return NS_MutateURI(m_baseURL).SetRef(aRef).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP
 nsMailtoUrl::GetRef(nsACString &result)
 {
   return m_baseURL->GetRef(result);
 }
 
@@ -626,38 +628,35 @@ nsMailtoUrl::GetHasRef(bool *result)
 }
 
 NS_IMETHODIMP
 nsMailtoUrl::GetFilePath(nsACString &aFilePath)
 {
   return m_baseURL->GetFilePath(aFilePath);
 }
 
-NS_IMETHODIMP
-nsMailtoUrl::SetFilePath(const nsACString &aFilePath)
+nsresult nsMailtoUrl::SetFilePath(const nsACString &aFilePath)
 {
-  return m_baseURL->SetFilePath(aFilePath);
+  return NS_MutateURI(m_baseURL).SetFilePath(aFilePath).Finalize(m_baseURL);
 }
 
 NS_IMETHODIMP
 nsMailtoUrl::GetQuery(nsACString &aQuery)
 {
   return m_baseURL->GetQuery(aQuery);
 }
 
-NS_IMETHODIMP
-nsMailtoUrl::SetQuery(const nsACString &aQuery)
+nsresult nsMailtoUrl::SetQuery(const nsACString &aQuery)
 {
-  return m_baseURL->SetQuery(aQuery);
+  return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
 }
 
-NS_IMETHODIMP
-nsMailtoUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
+nsresult nsMailtoUrl::SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding)
 {
-  return m_baseURL->SetQueryWithEncoding(aQuery, aEncoding);
+  return NS_MutateURI(m_baseURL).SetQueryWithEncoding(aQuery, aEncoding).Finalize(m_baseURL);
 }
 
 NS_IMPL_ISUPPORTS(nsMailtoUrl::Mutator, nsIURISetters, nsIURIMutator)
 
 NS_IMETHODIMP
 nsMailtoUrl::Mutate(nsIURIMutator** aMutator)
 {
   RefPtr<nsMailtoUrl::Mutator> mutator = new nsMailtoUrl::Mutator();
--- a/mailnews/compose/src/nsSmtpUrl.h
+++ b/mailnews/compose/src/nsSmtpUrl.h
@@ -22,16 +22,31 @@ class nsMailtoUrl : public nsIMailtoUrl,
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIURI
     NS_DECL_NSIMAILTOURL
 
     nsMailtoUrl();
 
+protected:
+  virtual nsresult SetSpecInternal(const nsACString &aSpec);
+  virtual nsresult SetScheme(const nsACString &aScheme);
+  virtual nsresult SetUserPass(const nsACString &aUserPass);
+  virtual nsresult SetUsername(const nsACString &aUsername);
+  virtual nsresult SetPassword(const nsACString &aPassword);
+  virtual nsresult SetHostPort(const nsACString &aHostPort);
+  virtual nsresult SetHost(const nsACString &aHost);
+  virtual nsresult SetPort(int32_t aPort);
+  virtual nsresult SetPathQueryRef(const nsACString &aPath);
+  virtual nsresult SetRef(const nsACString &aRef);
+  virtual nsresult SetFilePath(const nsACString &aFilePath);
+  virtual nsresult SetQuery(const nsACString &aQuery);
+  virtual nsresult SetQueryWithEncoding(const nsACString &aQuery, const mozilla::Encoding* aEncoding);
+
 public:
   class Mutator
       : public nsIURIMutator
       , public BaseURIMutator<nsMailtoUrl>
   {
     NS_DECL_ISUPPORTS
     NS_FORWARD_SAFE_NSIURISETTERS_RET(mURI)
 
@@ -48,26 +63,28 @@ public:
     NS_IMETHOD Finalize(nsIURI** aURI) override
     {
       mURI.forget(aURI);
       return NS_OK;
     }
 
     NS_IMETHOD SetSpec(const nsACString & aSpec, nsIURIMutator** aMutator) override
     {
-      NS_ADDREF(*aMutator = this);
+      if (aMutator)
+        NS_ADDREF(*aMutator = this);
       return InitFromSpec(aSpec);
     }
 
     explicit Mutator() { }
   private:
     virtual ~Mutator() { }
 
     friend class nsMailtoUrl;
   };
+  friend BaseURIMutator<nsMailtoUrl>;
 
 protected:
   enum RefHandlingEnum {
     eIgnoreRef,
     eHonorRef,
     eReplaceRef
   };
   virtual ~nsMailtoUrl();
--- a/mailnews/imap/public/nsIImapService.idl
+++ b/mailnews/imap/public/nsIImapService.idl
@@ -16,16 +16,17 @@
 #include "nsIImapUrl.idl"
 
 interface nsIImapMessageSink;
 interface nsIUrlListener;
 interface nsIURI;
 interface nsIFile;
 interface nsIMsgFolder;
 interface nsIMsgWindow;
+interface nsIMsgMailNewsUrl;
 interface nsIImapIncomingServer;
 interface nsICacheStorage;
 
 [scriptable, uuid(aba44b3d-7a0f-4987-8794-96d2de66d966)]
 interface nsIImapService : nsISupports
 {
   // You can pass in null for the url listener and the url if you don't require either.....
   void selectFolder(in nsIMsgFolder aImapMailFolder,
@@ -43,17 +44,17 @@ interface nsIImapService : nsISupports
    * @param aMsgWindow          msg window url is running in, can be null
    *
    * @returns the url created to run the lite select in.
    */
   nsIURI liteSelectFolder(in nsIMsgFolder aImapMailFolder,
                           in nsIUrlListener aUrlListener,
                           in nsIMsgWindow aMsgWindow);
 
-  void addImapFetchToUrl(in nsIURI aURL,
+  void addImapFetchToUrl(in nsIMsgMailNewsUrl aURL,
                          in nsIMsgFolder aImapMailFolder,
                          in ACString aMessageIdentifierList,
                          in ACString aAdditionalHeader);
 
   void fetchMessage(in nsIImapUrl aUrl,
                     in nsImapState aImapAction,
                     in nsIMsgFolder aImapMailFolder,
                     in nsIImapMessageSink aImapMessageSink,
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -37,16 +37,17 @@
 #include "nsICopyMsgStreamListener.h"
 #include "nsTextFormatter.h"
 #include "nsIMsgHdr.h"
 #include "nsMsgI18N.h"
 // for the memory cache...
 #include "nsICacheEntry.h"
 #include "nsICacheStorage.h"
 #include "nsICacheEntryOpenCallback.h"
+#include "nsIURIMutator.h"
 
 #include "nsIPrompt.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsILoadInfo.h"
 #include "nsIMessengerWindowService.h"
 #include "nsIWindowMediator.h"
 #include "nsIWindowWatcher.h"
@@ -9301,20 +9302,18 @@ nsresult nsImapMockChannel::OpenCacheEnt
     cacheAccess = nsICacheStorage::OPEN_READONLY;
 
   // Use the uid validity as part of the cache key, so that if the uid validity
   // changes, we won't re-use the wrong cache entries.
   nsAutoCString extension;
   extension.AppendInt(uidValidity, 16);
 
   // Open a cache entry where the key is the potentially modified URL.
-  nsCOMPtr<nsIURI> newUri;
-  m_url->Clone(getter_AddRefs(newUri));
   nsAutoCString path;
-  newUri->GetPathQueryRef(path);
+  m_url->GetPathQueryRef(path);
 
   // First we need to "normalise" the URL by extracting ?part= and &filename.
   // The path should only contain: ?part=x.y&filename=file.ext
   // These are seen in the wild:
   // /;section=2?part=1.2&filename=A01.JPG
   // ?section=2?part=1.2&filename=A01.JPG&type=image/jpeg&filename=A01.JPG
   // ?part=1.2&type=image/jpeg&filename=IMG_C0030.jpg
   // ?header=quotebody&part=1.2&filename=lijbmghmkilicioj.png
@@ -9331,59 +9330,65 @@ nsresult nsImapMockChannel::OpenCacheEnt
   // Truncate path at either /; or ?
   int32_t ind = path.FindChar('?');
   if (ind != kNotFound)
     path.SetLength(ind);
   ind = path.Find("/;");
   if (ind != kNotFound)
     path.SetLength(ind);
 
+  nsCOMPtr<nsIURI> newUri;
   if (partQuery.IsEmpty())
   {
     // Not looking for a part. That's the easy part.
-    newUri->SetPathQueryRef(path);
+    rv = NS_MutateURI(m_url).SetPathQueryRef(path).Finalize(newUri);
+    NS_ENSURE_SUCCESS(rv, rv);
     return cacheStorage->AsyncOpenURI(newUri, extension, cacheAccess, this);
   }
 
   /**
    * Part processing (rest of this function).
    */
   if (mTryingToReadPart)
   {
     // If mTryingToReadPart is set, we are here for the second time.
     // We tried to read a part from the entire message but the meta data didn't
     // allow it. So we come back here.
     // Now request the part with its full URL.
     mTryingToReadPart = false;
 
     // Note that part extraction was already set the first time.
-    newUri->SetPathQueryRef(path + partQuery + filenameQuery);
+    rv = NS_MutateURI(m_url).SetPathQueryRef(path + partQuery + filenameQuery).Finalize(newUri);
+    NS_ENSURE_SUCCESS(rv, rv);
     return cacheStorage->AsyncOpenURI(newUri, extension, cacheAccess, this);
   }
 
   // First time processing. Set up part extraction.
   SetupPartExtractorListener(imapUrl, m_channelListener);
 
   // Check whether part is in the cache.
   bool exists = false;
-  newUri->SetPathQueryRef(path + partQuery + filenameQuery);
+  rv = NS_MutateURI(m_url).SetPathQueryRef(path + partQuery + filenameQuery).Finalize(newUri);
+  NS_ENSURE_SUCCESS(rv, rv);
   rv = cacheStorage->Exists(newUri, extension, &exists);
   NS_ENSURE_SUCCESS(rv, rv);
   if (exists) {
     return cacheStorage->AsyncOpenURI(newUri, extension, cacheAccess, this);
   }
 
   // Let's see whether we have the entire message instead.
-  newUri->SetPathQueryRef(path);
+  rv = NS_MutateURI(m_url).SetPathQueryRef(path).Finalize(newUri);
+  NS_ENSURE_SUCCESS(rv, rv);
   rv = cacheStorage->Exists(newUri, extension, &exists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!exists) {
     // The entire message is not in the cache. Request the part.
-    newUri->SetPathQueryRef(path + partQuery + filenameQuery);
+    rv = NS_MutateURI(m_url).SetPathQueryRef(path + partQuery + filenameQuery).Finalize(newUri);
+    NS_ENSURE_SUCCESS(rv, rv);
     return cacheStorage->AsyncOpenURI(newUri, extension, cacheAccess, this);
   }
 
   // This is where is gets complicated. The entire message is in the cache,
   // but we don't know whether it's suitable for use. Its meta data
   // might indicate that the message is incomplete.
   mTryingToReadPart = true;
   return cacheStorage->AsyncOpenURI(newUri, extension, cacheAccess, this);
--- a/mailnews/imap/src/nsImapService.cpp
+++ b/mailnews/imap/src/nsImapService.cpp
@@ -269,17 +269,17 @@ NS_IMETHODIMP nsImapService::GetUrlForUr
     urlSpec.AppendLiteral("fetch>UID>");
     urlSpec.Append(hierarchyDelimiter);
 
     nsAutoCString folderName;
     GetFolderName(folder, folderName);
     urlSpec.Append(folderName);
     urlSpec.Append('>');
     urlSpec.Append(msgKey);
-    rv = url->SetSpecInternal(urlSpec);
+    rv = mailnewsUrl->SetSpecInternal(urlSpec);
     imapUrl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::OpenAttachment(const char *aContentType,
                                             const char *aFileName,
@@ -350,23 +350,23 @@ NS_IMETHODIMP nsImapService::OpenAttachm
       GetFolderName(folder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(msgKey);
       urlSpec.Append(uriMimePart);
 
       if (!uriMimePart.IsEmpty())
       {
-        nsCOMPtr<nsIMsgMailNewsUrl> mailUrl (do_QueryInterface(imapUrl));
-        if (mailUrl)
+        nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl(do_QueryInterface(imapUrl));
+        if (mailnewsurl)
         {
-          rv = mailUrl->SetSpecInternal(urlSpec);
+          rv = mailnewsurl->SetSpecInternal(urlSpec);
           NS_ENSURE_SUCCESS(rv, rv);
           if (aFileName)
-            mailUrl->SetFileNameInternal(nsDependentCString(aFileName));
+            mailnewsurl->SetFileNameInternal(nsDependentCString(aFileName));
         }
         rv =  FetchMimePart(imapUrl, nsIImapUrl::nsImapOpenMimePart, folder, imapMessageSink,
                             nullptr, aDisplayConsumer, msgKey, uriMimePart);
       }
     } // if we got a message sink
   } // if we parsed the message uri
 
   return rv;
@@ -471,19 +471,19 @@ NS_IMETHODIMP nsImapService::DisplayMess
       nsCOMPtr<nsIImapUrl> imapUrl;
       nsAutoCString urlSpec;
       char hierarchyDelimiter = GetHierarchyDelimiter(folder);
       rv = CreateStartOfImapUrl(messageURI, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchyDelimiter);
       NS_ENSURE_SUCCESS(rv, rv);
       if (!mimePart.IsEmpty())
       {
         nsresult rv;
-        nsCOMPtr<nsIURI> url = do_QueryInterface(imapUrl);
-
-        rv = AddImapFetchToUrl(url, folder, msgKey + mimePart, EmptyCString());
+        nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
+
+        rv = AddImapFetchToUrl(mailnewsurl, folder, msgKey + mimePart, EmptyCString());
         NS_ENSURE_SUCCESS(rv, rv);
 
         return FetchMimePart(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
                              aURL, aDisplayConsumer, msgKey, mimePart);
       }
 
       nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
       nsCOMPtr<nsIMsgI18NUrl> i18nurl (do_QueryInterface(imapUrl));
@@ -598,17 +598,17 @@ nsresult nsImapService::FetchMimePart(ns
     NS_ENSURE_SUCCESS(rv, rv);
 
     // rhp: If we are displaying this message for the purpose of printing, we
     // need to append the header=print option.
     //
     if (mPrintingOperation)
       urlSpec.AppendLiteral("?header=print");
 
-    rv = url->SetSpecInternal(urlSpec);
+    rv = msgurl->SetSpecInternal(urlSpec);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = aImapUrl->SetImapAction(actionToUse /* nsIImapUrl::nsImapMsgFetch */);
     if (aImapMailFolder && aDisplayConsumer)
     {
       nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
       rv = aImapMailFolder->GetServer(getter_AddRefs(aMsgIncomingServer));
       if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
@@ -942,17 +942,17 @@ NS_IMETHODIMP nsImapService::SaveMessage
   }
   return rv;
 }
 
 /* fetching RFC822 messages */
 /* imap4://HOST>fetch><UID>>MAILBOXPATH>x */
 /*   'x' is the message UID */
 /* will set the 'SEEN' flag */
-NS_IMETHODIMP nsImapService::AddImapFetchToUrl(nsIURI *aUrl,
+NS_IMETHODIMP nsImapService::AddImapFetchToUrl(nsIMsgMailNewsUrl *aUrl,
                                                nsIMsgFolder *aImapMailFolder,
                                                const nsACString &aMessageIdentifierList,
                                                const nsACString &aAdditionalHeader)
 {
   NS_ENSURE_ARG_POINTER(aUrl);
 
   nsAutoCString urlSpec;
   nsresult rv = aUrl->GetSpec(urlSpec);
@@ -990,42 +990,42 @@ NS_IMETHODIMP nsImapService::FetchMessag
                                           const nsACString &aAdditionalHeader,
                                           nsIURI **aURL)
 {
   NS_ENSURE_ARG_POINTER(aImapUrl);
   NS_ENSURE_ARG_POINTER(aImapMailFolder);
   NS_ENSURE_ARG_POINTER(aImapMessage);
 
   nsresult rv;
-  nsCOMPtr<nsIURI> url = do_QueryInterface(aImapUrl);
-
-  rv = AddImapFetchToUrl(url, aImapMailFolder, messageIdentifierList, aAdditionalHeader);
+  nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(aImapUrl);
+
+  rv = AddImapFetchToUrl(mailnewsurl, aImapMailFolder, messageIdentifierList, aAdditionalHeader);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (WeAreOffline())
   {
     bool msgIsInCache = false;
     nsCOMPtr<nsIMsgMailNewsUrl> msgUrl(do_QueryInterface(aImapUrl));
     msgUrl->GetMsgIsInLocalCache(&msgIsInCache);
     if (!msgIsInCache)
-      IsMsgInMemCache(url, aImapMailFolder, &msgIsInCache);
+      IsMsgInMemCache(mailnewsurl, aImapMailFolder, &msgIsInCache);
 
     // Display the "offline" message if we didn't find it in the memory cache either
     if (!msgIsInCache)
     {
       nsCOMPtr<nsIMsgIncomingServer> server;
       rv = aImapMailFolder->GetServer(getter_AddRefs(server));
       if (server && aDisplayConsumer)
         rv = server->DisplayOfflineMsg(aMsgWindow);
       return rv;
     }
   }
 
   if (aURL)
-    NS_IF_ADDREF(*aURL = url);
+    mailnewsurl.forget(aURL);
 
   return GetMessageFromUrl(aImapUrl, aImapAction, aImapMailFolder, aImapMessage,
                            aMsgWindow, aDisplayConsumer, aConvertDataToText, aURL);
 }
 
 nsresult nsImapService::GetMessageFromUrl(nsIImapUrl *aImapUrl,
                                           nsImapAction aImapAction,
                                           nsIMsgFolder *aImapMailFolder,
@@ -1155,54 +1155,53 @@ NS_IMETHODIMP nsImapService::StreamMessa
     if (NS_SUCCEEDED(rv))
     {
       nsCOMPtr<nsIImapUrl> imapUrl;
       nsAutoCString urlSpec;
       char hierarchyDelimiter = GetHierarchyDelimiter(folder);
       rv = CreateStartOfImapUrl(nsDependentCString(aMessageURI), getter_AddRefs(imapUrl),
                                 folder, aUrlListener, urlSpec, hierarchyDelimiter);
       NS_ENSURE_SUCCESS(rv, rv);
-      nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
-      nsCOMPtr<nsIURI> url(do_QueryInterface(imapUrl));
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl(do_QueryInterface(imapUrl));
 
       // This option is used by the JS Mime Emitter, in case we want a cheap
       // streaming, for example, if we just want a quick look at some header,
       // without having to download all the attachments...
 
       uint32_t messageSize = 0;
       imapMessageSink->GetMessageSizeFromDB(msgKey.get(), &messageSize);
       nsAutoCString additionalHeader(aAdditionalHeader);
       bool fetchOnDemand =
         additionalHeader.Find("&fetchCompleteMessage=false") != kNotFound &&
           messageSize > (uint32_t) gMIMEOnDemandThreshold;
       imapUrl->SetFetchPartsOnDemand(fetchOnDemand);
 
       // We need to add the fetch command here for the cache lookup to behave correctly
-      rv = AddImapFetchToUrl(url, folder, msgKey, additionalHeader);
+      rv = AddImapFetchToUrl(mailnewsurl, folder, msgKey, additionalHeader);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
 
-      msgurl->SetMsgWindow(aMsgWindow);
-      rv = msgurl->GetServer(getter_AddRefs(aMsgIncomingServer));
+      mailnewsurl->SetMsgWindow(aMsgWindow);
+      rv = mailnewsurl->GetServer(getter_AddRefs(aMsgIncomingServer));
 
       // Try to check if the message is offline
       bool hasMsgOffline = false;
       folder->HasMsgOffline(key, &hasMsgOffline);
-      msgurl->SetMsgIsInLocalCache(hasMsgOffline);
+      mailnewsurl->SetMsgIsInLocalCache(hasMsgOffline);
       imapUrl->SetLocalFetchOnly(aLocalOnly);
 
       // If we don't have the message available locally, and we can't get it over
       // the network, return with an error
       if (aLocalOnly || WeAreOffline())
       {
         bool isMsgInMemCache = false;
         if (!hasMsgOffline)
         {
-          rv = IsMsgInMemCache(url, folder, &isMsgInMemCache);
+          rv = IsMsgInMemCache(mailnewsurl, folder, &isMsgInMemCache);
           NS_ENSURE_SUCCESS(rv, rv);
 
           if (!isMsgInMemCache)
             return NS_ERROR_FAILURE;
         }
       }
 
       bool shouldStoreMsgOffline = false;
@@ -1394,17 +1393,17 @@ NS_IMETHODIMP nsImapService::GetHeaders(
   nsCOMPtr<nsIImapUrl> imapUrl;
   nsAutoCString urlSpec;
   char hierarchyDelimiter = GetHierarchyDelimiter(aImapMailFolder);
 
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), aImapMailFolder,
                                      aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(imapUrl);
 
     rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
     if (NS_SUCCEEDED(rv))
     {
       urlSpec.AppendLiteral("/header>");
       urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
@@ -1412,17 +1411,17 @@ NS_IMETHODIMP nsImapService::GetHeaders(
       urlSpec.Append(char (hierarchyDelimiter));
 
       nsCString folderName;
 
       GetFolderName(aImapMailFolder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(messageIdentifierList);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsUrl->SetSpecInternal(urlSpec);
 
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
@@ -1449,31 +1448,31 @@ NS_IMETHODIMP nsImapService::GetBodyStar
     aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgPreview);
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(imapUrl);
 
       urlSpec.AppendLiteral("/previewBody>");
       urlSpec.Append(uidString);
       urlSpec.Append('>');
       urlSpec.Append(hierarchyDelimiter);
 
       nsCString folderName;
       GetFolderName(aImapMailFolder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(messageIdentifierList);
       urlSpec.Append('>');
       urlSpec.AppendInt(numBytes);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsUrl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 nsresult nsImapService::FolderCommand(nsIMsgFolder *imapMailFolder,
@@ -1490,30 +1489,29 @@ nsresult nsImapService::FolderCommand(ns
 
   char hierarchyDelimiter = GetHierarchyDelimiter(imapMailFolder);
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl),
                                      imapMailFolder, urlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = imapUrl->SetImapAction(imapAction);
     rv = SetImapUrlSink(imapMailFolder, imapUrl);
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
     nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
     if (mailnewsurl)
       mailnewsurl->SetMsgWindow(msgWindow);
 
     if (NS_SUCCEEDED(rv))
     {
       urlSpec.Append(aCommand);
       urlSpec.Append(hierarchyDelimiter);
 
       nsCString folderName;
       GetFolderName(imapMailFolder, folderName);
       urlSpec.Append(folderName);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP
@@ -1523,28 +1521,28 @@ nsImapService::VerifyLogon(nsIMsgFolder 
   nsCOMPtr<nsIImapUrl> imapUrl;
   nsAutoCString urlSpec;
 
   char delimiter = '/'; // shouldn't matter what is is.
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), aFolder,
                                      aUrlListener, urlSpec, delimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
     nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
     mailNewsUrl->SetSuppressErrorMsgs(true);
     mailNewsUrl->SetMsgWindow(aMsgWindow);
     rv = SetImapUrlSink(aFolder, imapUrl);
     urlSpec.AppendLiteral("/verifyLogon");
-    rv = uri->SetSpecInternal(urlSpec);
+    rv = mailnewsurl->SetSpecInternal(urlSpec);
     if (NS_SUCCEEDED(rv))
       rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, nullptr);
     if (aURL)
-      uri.forget(aURL);
+      mailnewsurl.forget(aURL);
   }
   return rv;
 }
 
 // Noop, used to update a folder (causes server to send changes).
 NS_IMETHODIMP nsImapService::Noop(nsIMsgFolder *aImapMailFolder,
                                   nsIUrlListener *aUrlListener,
                                   nsIURI **aURL)
@@ -1593,28 +1591,28 @@ NS_IMETHODIMP nsImapService::Biff(nsIMsg
   char hierarchyDelimiter = GetHierarchyDelimiter(aImapMailFolder);
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl),
     aImapMailFolder, aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = imapUrl->SetImapAction(nsIImapUrl::nsImapExpungeFolder);
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
     if (NS_SUCCEEDED(rv))
     {
       urlSpec.AppendLiteral("/Biff>");
       urlSpec.Append(hierarchyDelimiter);
 
       nsCString folderName;
       GetFolderName(aImapMailFolder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.AppendInt(uidHighWater);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::DeleteFolder(nsIMsgFolder *aImapMailFolder,
@@ -1660,29 +1658,29 @@ NS_IMETHODIMP nsImapService::DeleteMessa
     aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
       urlSpec.AppendLiteral("/deletemsg>");
       urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
       urlSpec.Append('>');
       urlSpec.Append(hierarchyDelimiter);
 
       nsCString folderName;
       GetFolderName(aImapMailFolder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(messageIdentifierList);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 // Delete all messages in a folder, used to empty trash
@@ -1757,32 +1755,32 @@ nsresult nsImapService::DiddleFlags(nsIM
                                      aImapMailFolder, aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
       urlSpec.Append('/');
       urlSpec.Append(howToDiddle);
       urlSpec.Append('>');
       urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
       urlSpec.Append('>');
       urlSpec.Append(hierarchyDelimiter);
       nsCString folderName;
       GetFolderName(aImapMailFolder, folderName);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(messageIdentifierList);
       urlSpec.Append('>');
       urlSpec.AppendInt(flags);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 nsresult nsImapService::SetImapUrlSink(nsIMsgFolder *aMsgFolder, nsIImapUrl *aImapUrl)
@@ -1830,23 +1828,21 @@ NS_IMETHODIMP nsImapService::DiscoverAll
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), aImapMailFolder,
                                      aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED (rv))
   {
     rv = SetImapUrlSink(aImapMailFolder, imapUrl);
 
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
       nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
-      if (mailnewsurl)
-        mailnewsurl->SetMsgWindow(aMsgWindow);
+      mailnewsurl->SetMsgWindow(aMsgWindow);
       urlSpec.AppendLiteral("/discoverallboxes");
       nsCOMPtr <nsIURI> url = do_QueryInterface(imapUrl, &rv);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::DiscoverAllAndSubscribedFolders(nsIMsgFolder *aImapMailFolder,
@@ -1861,19 +1857,19 @@ NS_IMETHODIMP nsImapService::DiscoverAll
   char hierarchyDelimiter = GetHierarchyDelimiter(aImapMailFolder);
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(aImapUrl), aImapMailFolder,
                                      aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && aImapUrl)
   {
     rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(aImapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(aImapUrl);
       urlSpec.AppendLiteral("/discoverallandsubscribedboxes");
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(aImapUrl, nullptr, aURL);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::DiscoverChildren(nsIMsgFolder *aImapMailFolder,
@@ -1891,21 +1887,21 @@ NS_IMETHODIMP nsImapService::DiscoverChi
                                      aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED (rv))
   {
     rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
     if (NS_SUCCEEDED(rv))
     {
       if (!folderPath.IsEmpty())
       {
-        nsCOMPtr<nsIURI> uri = do_QueryInterface(aImapUrl);
+        nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(aImapUrl);
         urlSpec.AppendLiteral("/discoverchildren>");
         urlSpec.Append(hierarchyDelimiter);
         urlSpec.Append(folderPath);
-        rv = uri->SetSpecInternal(urlSpec);
+        rv = mailnewsurl->SetSpecInternal(urlSpec);
 
         // Make sure the uri has the same hierarchy separator as the one in msg folder
         // obj if it's not kOnlineHierarchySeparatorUnknown (ie, '^').
         char uriDelimiter;
         nsresult rv1 = aImapUrl->GetOnlineSubDirSeparator(&uriDelimiter);
         if (NS_SUCCEEDED (rv1) && hierarchyDelimiter != kOnlineHierarchySeparatorUnknown &&
             uriDelimiter != hierarchyDelimiter)
           aImapUrl->SetOnlineSubDirSeparator(hierarchyDelimiter);
@@ -1959,20 +1955,18 @@ NS_IMETHODIMP nsImapService::OnlineMessa
 
   char hierarchyDelimiter = GetHierarchyDelimiter(aSrcFolder);
   rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), aSrcFolder, aUrlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv))
   {
     SetImapUrlSink(aSrcFolder, imapUrl);
     imapUrl->SetCopyState(copyState);
 
-    nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
-
-    msgurl->SetMsgWindow(aMsgWindow);
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl (do_QueryInterface(imapUrl));
+    mailnewsurl->SetMsgWindow(aMsgWindow);
 
     if (isMove)
       urlSpec.AppendLiteral("/onlinemove>");
     else
       urlSpec.AppendLiteral("/onlinecopy>");
     if (idsAreUids)
       urlSpec.Append(uidString);
     else
@@ -1986,17 +1980,17 @@ NS_IMETHODIMP nsImapService::OnlineMessa
     urlSpec.Append('>');
     urlSpec.Append(messageIds);
     urlSpec.Append('>');
     urlSpec.Append(hierarchyDelimiter);
     folderName.Adopt(strdup(""));
     GetFolderName(aDstFolder, folderName);
     urlSpec.Append(folderName);
 
-    rv = uri->SetSpecInternal(urlSpec);
+    rv = mailnewsurl->SetSpecInternal(urlSpec);
     if (NS_SUCCEEDED(rv))
       rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
   }
   return rv;
 }
 
 nsresult nsImapService::OfflineAppendFromFile(nsIFile *aFile,
                                               nsIURI *aUrl,
@@ -2151,17 +2145,17 @@ NS_IMETHODIMP nsImapService::AppendMessa
       // we get the loadGroup from msgWindow
       msgUrl->SetMsgWindow(aMsgWindow);
     }
 
     SetImapUrlSink(aDstFolder, imapUrl);
     imapUrl->SetMsgFile(aFile);
     imapUrl->SetCopyState(aCopyState);
 
-    nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
     if (inSelectedState)
       urlSpec.AppendLiteral("/appenddraftfromfile>");
     else
       urlSpec.AppendLiteral("/appendmsgfromfile>");
 
     urlSpec.Append(hierarchyDelimiter);
 
@@ -2176,21 +2170,21 @@ NS_IMETHODIMP nsImapService::AppendMessa
         urlSpec.Append(uidString);
       else
         urlSpec.Append(sequenceString);
       urlSpec.Append('>');
       if (!messageId.IsEmpty())
         urlSpec.Append(messageId);
     }
 
-    rv = uri->SetSpecInternal(urlSpec);
+    rv = mailnewsurl->SetSpecInternal(urlSpec);
     if (WeAreOffline())
     {
       // handle offline append to drafts or templates folder here.
-      return OfflineAppendFromFile(aFile, uri, aDstFolder, messageId, inSelectedState, aListener, aURL, aCopyState);
+      return OfflineAppendFromFile(aFile, mailnewsurl, aDstFolder, messageId, inSelectedState, aListener, aURL, aCopyState);
     }
     if (NS_SUCCEEDED(rv))
       rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, aURL);
   }
   return rv;
 }
 
 nsresult nsImapService::GetImapConnectionAndLoadUrl(nsIImapUrl *aImapUrl,
@@ -2257,29 +2251,29 @@ NS_IMETHODIMP nsImapService::MoveFolder(
     if (NS_SUCCEEDED(rv))
     {
       nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
       if (mailNewsUrl)
         mailNewsUrl->SetMsgWindow(msgWindow);
       char hierarchyDelimiter = kOnlineHierarchySeparatorUnknown;
       nsCString folderName;
 
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
       GetFolderName(srcFolder, folderName);
       urlSpec.AppendLiteral("/movefolderhierarchy>");
       urlSpec.Append(hierarchyDelimiter);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       GetFolderName(dstFolder, folderName);
       if (!folderName.IsEmpty())
       {
         urlSpec.Append(hierarchyDelimiter);
         urlSpec.Append(folderName);
       }
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
       {
         GetFolderName(srcFolder, folderName);
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
       }
     }
   }
   return rv;
@@ -2299,20 +2293,18 @@ NS_IMETHODIMP nsImapService::RenameLeaf(
   char hierarchyDelimiter = GetHierarchyDelimiter(srcFolder);
   nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), srcFolder,
                             urlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv))
   {
     rv = SetImapUrlSink(srcFolder, imapUrl);
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
       nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
-      if (mailNewsUrl)
-        mailNewsUrl->SetMsgWindow(msgWindow);
+      mailNewsUrl->SetMsgWindow(msgWindow);
       nsCString folderName;
       GetFolderName(srcFolder, folderName);
       urlSpec.AppendLiteral("/rename>");
       urlSpec.Append(hierarchyDelimiter);
       urlSpec.Append(folderName);
       urlSpec.Append('>');
       urlSpec.Append(hierarchyDelimiter);
       nsAutoCString cStrFolderName;
@@ -2329,21 +2321,21 @@ NS_IMETHODIMP nsImapService::RenameLeaf(
       CopyUTF16toMUTF7(PromiseFlatString(newLeafName), utfNewName);
       nsCString escapedNewName;
       MsgEscapeString(utfNewName, nsINetUtil::ESCAPE_URL_PATH, escapedNewName);
       nsCString escapedSlashName;
       rv = nsImapUrl::EscapeSlashes(escapedNewName.get(), getter_Copies(escapedSlashName));
       NS_ENSURE_SUCCESS(rv, rv);
       urlSpec.Append(escapedSlashName);
 
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailNewsUrl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
-    } // if (NS_SUCCEEDED(rv))
-  } // if (NS_SUCCEEDED(rv) && imapUrl)
+    }
+  }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::CreateFolder(nsIMsgFolder *parent,
                                           const nsAString &newFolderName,
                                           nsIUrlListener *urlListener,
                                           nsIURI **url)
 {
@@ -2356,17 +2348,17 @@ NS_IMETHODIMP nsImapService::CreateFolde
   char hierarchyDelimiter = GetHierarchyDelimiter(parent);
   rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), parent,
                             urlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = SetImapUrlSink(parent, imapUrl);
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
       nsCString folderName;
       GetFolderName(parent, folderName);
       urlSpec.AppendLiteral("/create>");
       urlSpec.Append(hierarchyDelimiter);
       if (!folderName.IsEmpty())
       {
         nsCString canonicalName;
@@ -2379,21 +2371,21 @@ NS_IMETHODIMP nsImapService::CreateFolde
 
       nsAutoCString utfNewName;
       rv = CopyUTF16toMUTF7(PromiseFlatString(newFolderName), utfNewName);
       NS_ENSURE_SUCCESS(rv, rv);
       nsCString escapedFolderName;
       MsgEscapeString(utfNewName, nsINetUtil::ESCAPE_URL_PATH, escapedFolderName);
       urlSpec.Append(escapedFolderName);
 
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
-    } // if (NS_SUCCEEDED(rv))
-  } // if (NS_SUCCEEDED(rv) && imapUrl)
+    }
+  }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::EnsureFolderExists(nsIMsgFolder *parent,
                                                 const nsAString &newFolderName,
                                                 nsIUrlListener *urlListener,
                                                 nsIURI **url)
 {
@@ -2405,38 +2397,38 @@ NS_IMETHODIMP nsImapService::EnsureFolde
 
   char hierarchyDelimiter = GetHierarchyDelimiter(parent);
   rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), parent, urlListener, urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = SetImapUrlSink(parent, imapUrl);
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
 
       nsCString folderName;
       GetFolderName(parent, folderName);
       urlSpec.AppendLiteral("/ensureExists>");
       urlSpec.Append(hierarchyDelimiter);
       if (!folderName.IsEmpty())
       {
         urlSpec.Append(folderName);
         urlSpec.Append(hierarchyDelimiter);
       }
       nsAutoCString utfNewName;
       CopyUTF16toMUTF7(PromiseFlatString(newFolderName), utfNewName);
       nsCString escapedFolderName;
       MsgEscapeString(utfNewName, nsINetUtil::ESCAPE_URL_PATH, escapedFolderName);
       urlSpec.Append(escapedFolderName);
 
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
-    } // if (NS_SUCCEEDED(rv))
-  } // if (NS_SUCCEEDED(rv) && imapUrl)
+    }
+  }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::ListFolder(nsIMsgFolder *aImapMailFolder,
                                         nsIUrlListener *aUrlListener,
                                         nsIURI **aURL)
 {
   NS_ENSURE_ARG_POINTER(aImapMailFolder);
@@ -2526,20 +2518,22 @@ nsresult nsImapService::GetServerFromUrl
   // "IMAP://userSharingFolder@server1/SharedFolderName"
   if (NS_FAILED(rv) || !aServer)
   {
     nsAutoCString turl;
     rv = mailnewsUrl->GetSpec(turl);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIURL> url;
-    rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID).SetSpec(turl).Finalize(url);
+    rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
+           .SetSpec(turl)
+           .SetUserPass(EmptyCString())
+           .Finalize(url);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    url->SetUserPass(EmptyCString());
     rv = accountManager->FindServerByURI(url, false, aServer);
     if (*aServer)
       aImapUrl->SetExternalLinkUrl(true);
   }
 
     // if we can't extract the imap server from this url then give up!!!
   NS_ENSURE_TRUE(*aServer, NS_ERROR_FAILURE);
   return rv;
@@ -3067,26 +3061,26 @@ nsresult nsImapService::ChangeFolderSubs
   char hierarchyDelimiter = GetHierarchyDelimiter(folder);
   rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(imapUrl), folder, urlListener,
                             urlSpec, hierarchyDelimiter);
   if (NS_SUCCEEDED(rv) && imapUrl)
   {
     rv = SetImapUrlSink(folder, imapUrl);
     if (NS_SUCCEEDED(rv))
     {
-      nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
+      nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
       urlSpec.Append(command);
       urlSpec.Append(hierarchyDelimiter);
       nsAutoCString utfFolderName;
       rv = CopyUTF16toMUTF7(PromiseFlatString(folderName), utfFolderName);
       NS_ENSURE_SUCCESS(rv, rv);
       nsCString escapedFolderName;
       MsgEscapeString(utfFolderName, nsINetUtil::ESCAPE_URL_PATH, escapedFolderName);
       urlSpec.Append(escapedFolderName);
-      rv = uri->SetSpecInternal(urlSpec);
+      rv = mailnewsurl->SetSpecInternal(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(imapUrl, nullptr, url);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP nsImapService::UnsubscribeFolder(nsIMsgFolder *aFolder,
--- a/mailnews/imap/src/nsImapUrl.h
+++ b/mailnews/imap/src/nsImapUrl.h
@@ -21,19 +21,20 @@
 #include "mozilla/Mutex.h"
 
 class nsImapUrl : public nsIImapUrl, public nsMsgMailNewsUrl, public nsIMsgMessageUrl, public nsIMsgI18NUrl
 {
 public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIURI override
+  // nsIMsgMailNewsUrl override
   nsresult SetSpecInternal(const nsACString &aSpec) override;
-  NS_IMETHOD SetQuery(const nsACString &aQuery) override;
+  nsresult SetQuery(const nsACString &aQuery) override;
+  // nsIURI override
   NS_IMETHOD CloneInternal(uint32_t aRefHandlingMode,
                            const nsACString& newRef, nsIURI **_retval) override;
 
   //////////////////////////////////////////////////////////////////////////////
   // we support the nsIImapUrl interface
   //////////////////////////////////////////////////////////////////////////////
   NS_DECL_NSIIMAPURL
 
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -3116,39 +3116,43 @@ nsMsgLocalMailFolder::GetIncomingServerT
 
     nsCOMPtr<nsIMsgAccountManager> accountManager =
              do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv))
       return rv;
 
     nsCOMPtr<nsIMsgIncomingServer> server;
     // try "none" first
-    url->SetScheme(NS_LITERAL_CSTRING("none"));
+    rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("none")).Finalize(url);
+    NS_ENSURE_SUCCESS(rv, rv);
     rv = accountManager->FindServerByURI(url, false, getter_AddRefs(server));
     if (NS_SUCCEEDED(rv) && server)
       mType.AssignLiteral("none");
     else
     {
       // next try "pop3"
-      url->SetScheme(NS_LITERAL_CSTRING("pop3"));
+      rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("pop3")).Finalize(url);
+      NS_ENSURE_SUCCESS(rv, rv);
       rv = accountManager->FindServerByURI(url, false, getter_AddRefs(server));
       if (NS_SUCCEEDED(rv) && server)
         mType.AssignLiteral("pop3");
       else
       {
         // next try "rss"
-        url->SetScheme(NS_LITERAL_CSTRING("rss"));
+        rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("rss")).Finalize(url);
+        NS_ENSURE_SUCCESS(rv, rv);
         rv = accountManager->FindServerByURI(url, false, getter_AddRefs(server));
         if (NS_SUCCEEDED(rv) && server)
           mType.AssignLiteral("rss");
         else
         {
 #ifdef HAVE_MOVEMAIL
           // next try "movemail"
-          url->SetScheme(NS_LITERAL_CSTRING("movemail"));
+          rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("movemail")).Finalize(url);
+          NS_ENSURE_SUCCESS(rv, rv);
           rv = accountManager->FindServerByURI(url, false, getter_AddRefs(server));
           if (NS_SUCCEEDED(rv) && server)
             mType.AssignLiteral("movemail");
 #endif /* HAVE_MOVEMAIL */
         }
       }
     }
   }
--- a/mailnews/local/src/nsLocalUtils.cpp
+++ b/mailnews/local/src/nsLocalUtils.cpp
@@ -38,61 +38,66 @@ nsGetMailboxServer(const char *uriStr, n
 
   // retrieve the AccountManager
   nsCOMPtr<nsIMsgAccountManager> accountManager =
     do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return rv;
 
   // find all local mail "no servers" matching the given hostname
   nsCOMPtr<nsIMsgIncomingServer> none_server;
-  url->SetScheme(NS_LITERAL_CSTRING("none"));
+  rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("none")).Finalize(url);
+  NS_ENSURE_SUCCESS(rv, rv);
   // No unescaping of username or hostname done here.
   // The unescaping is done inside of FindServerByURI
   rv = accountManager->FindServerByURI(url, false,
                                   getter_AddRefs(none_server));
   if (NS_SUCCEEDED(rv)) {
     none_server.forget(aResult);
     return rv;
   }
 
   // if that fails, look for the rss hosts matching the given hostname
   nsCOMPtr<nsIMsgIncomingServer> rss_server;
-  url->SetScheme(NS_LITERAL_CSTRING("rss"));
+  rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("rss")).Finalize(url);
+  NS_ENSURE_SUCCESS(rv, rv);
   rv = accountManager->FindServerByURI(url, false,
                                   getter_AddRefs(rss_server));
   if (NS_SUCCEEDED(rv))
   {
      rss_server.forget(aResult);
      return rv;
   }
 #ifdef HAVE_MOVEMAIL
   // find all movemail "servers" matching the given hostname
   nsCOMPtr<nsIMsgIncomingServer> movemail_server;
-  url->SetScheme(NS_LITERAL_CSTRING("movemail"));
+  rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("movemail")).Finalize(url);
+  NS_ENSURE_SUCCESS(rv, rv);
   rv = accountManager->FindServerByURI(url, false,
                                   getter_AddRefs(movemail_server));
   if (NS_SUCCEEDED(rv)) {
     movemail_server.forget(aResult);
     return rv;
   }
 #endif /* HAVE_MOVEMAIL */
 
   // if that fails, look for the pop hosts matching the given hostname
   nsCOMPtr<nsIMsgIncomingServer> server;
   if (NS_FAILED(rv))
   {
-    url->SetScheme(NS_LITERAL_CSTRING("pop3"));
+    rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("pop3")).Finalize(url);
+    NS_ENSURE_SUCCESS(rv, rv);
     rv = accountManager->FindServerByURI(url, false,
                                     getter_AddRefs(server));
 
     // if we can't find a pop server, maybe it's a local message
     // in an imap hierarchy. look for an imap server.
     if (NS_FAILED(rv))
     {
-      url->SetScheme(NS_LITERAL_CSTRING("imap"));
+      rv = NS_MutateURI(url).SetScheme(NS_LITERAL_CSTRING("imap")).Finalize(url);
+      NS_ENSURE_SUCCESS(rv, rv);
       rv = accountManager->FindServerByURI(url, false,
                                     getter_AddRefs(server));
     }
   }
   if (NS_SUCCEEDED(rv))
   {
     server.forget(aResult);
     return rv;
--- a/mailnews/local/src/nsMailboxService.cpp
+++ b/mailnews/local/src/nsMailboxService.cpp
@@ -543,17 +543,17 @@ NS_IMETHODIMP nsMailboxService::GetProto
 NS_IMETHODIMP nsMailboxService::NewURI(const nsACString &aSpec,
                                        const char *aOriginCharset,
                                        nsIURI *aBaseURI,
                                        nsIURI **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = 0;
   nsresult rv;
-  nsCOMPtr<nsIURI> aMsgUri = do_CreateInstance(NS_MAILBOXURL_CONTRACTID, &rv);
+  nsCOMPtr<nsIMsgMailNewsUrl> aMsgUri = do_CreateInstance(NS_MAILBOXURL_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   // SetSpec calls below may fail if the mailbox url is of the form
   // mailbox://<account>/<mailbox name>?... instead of
   // mailbox://<path to folder>?.... This is the case for pop3 download urls.
   // We know this, and the failure is harmless.
   if (aBaseURI)
   {
     nsAutoCString newSpec;
--- a/mailnews/local/src/nsPop3Service.cpp
+++ b/mailnews/local/src/nsPop3Service.cpp
@@ -212,30 +212,29 @@ nsresult nsPop3Service::BuildPop3Url(con
   pop3Sink->SetFolder(inbox);
 
   // now create a pop3 url and a protocol instance to run the url....
   nsCOMPtr<nsIPop3URL> pop3Url = do_CreateInstance(kPop3UrlCID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   pop3Url->SetPop3Sink(pop3Sink);
 
-  rv = CallQueryInterface(pop3Url, aUrl);
+  nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl;
+  rv = pop3Url->QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(mailnewsurl));
   NS_ENSURE_SUCCESS(rv,rv);
 
-  rv = (*aUrl)->SetSpecInternal(nsDependentCString(urlSpec));
+  rv = mailnewsurl->SetSpecInternal(nsDependentCString(urlSpec));
   NS_ENSURE_SUCCESS(rv,rv);
 
-  nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(pop3Url);
-  if (mailnewsurl)
-  {
-    if (aUrlListener)
-      mailnewsurl->RegisterListener(aUrlListener);
-    if (aMsgWindow)
-      mailnewsurl->SetMsgWindow(aMsgWindow);
-  }
+  if (aUrlListener)
+    mailnewsurl->RegisterListener(aUrlListener);
+  if (aMsgWindow)
+    mailnewsurl->SetMsgWindow(aMsgWindow);
+
+  mailnewsurl.forget(aUrl);
 
   return rv;
 }
 
 nsresult nsPop3Service::RunPopUrl(nsIMsgIncomingServer *aServer, nsIURI *aUrlToRun)
 {
 
   NS_ENSURE_ARG_POINTER(aServer);
@@ -380,45 +379,41 @@ NS_IMETHODIMP nsPop3Service::NewURI(cons
     nsCString username;
     server->GetHostName(hostname);
     server->GetUsername(username);
 
     int32_t port;
     server->GetPort(&port);
     if (port == -1) port = nsIPop3URL::DEFAULT_POP3_PORT;
 
-    // we need to escape the username because it may contain
-    // characters like / % or @
+    // We need to escape the username before calling SetUsername() because it may
+    // contain characters like / % or @. GetUsername() will unescape the username.
     nsCString escapedUsername;
     MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
 
     nsAutoCString popSpec("pop://");
     popSpec += escapedUsername;
     popSpec += "@";
     popSpec += hostname;
     popSpec += ":";
     popSpec.AppendInt(port);
     popSpec += "?";
     popSpec += uidl;
     nsCOMPtr<nsIUrlListener> urlListener = do_QueryInterface(folder, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    nsCOMPtr<nsIURI> newUri;
     rv = BuildPop3Url(popSpec.get(), folder, popServer,
-                      urlListener, _retval, nullptr);
+                      urlListener, getter_AddRefs(newUri), nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(*_retval, &rv);
-    if (NS_SUCCEEDED(rv))
-    {
-      // escape the username before we call SetUsername().  we do this because GetUsername()
-      // will unescape the username
-      mailnewsurl->SetUsername(escapedUsername);
-    }
+    rv = NS_MutateURI(newUri).SetUsername(escapedUsername).Finalize(newUri);
+    NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIPop3URL> popurl = do_QueryInterface(mailnewsurl, &rv);
+    nsCOMPtr<nsIPop3URL> popurl = do_QueryInterface(newUri, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString messageUri (aSpec);
     if (!strncmp(messageUri.get(), "mailbox:", 8))
       messageUri.Replace(0, 8, "mailbox-message:");
     offset = messageUri.Find("?number=");
     if (offset != kNotFound)
       messageUri.Replace(offset, 8, "#");
@@ -427,16 +422,17 @@ NS_IMETHODIMP nsPop3Service::NewURI(cons
       messageUri.SetLength(offset);
     popurl->SetMessageUri(messageUri.get());
     nsCOMPtr<nsIPop3Sink> pop3Sink;
     rv = popurl->GetPop3Sink(getter_AddRefs(pop3Sink));
     NS_ENSURE_SUCCESS(rv, rv);
 
     pop3Sink->SetBuildMessageUri(true);
 
+    newUri.forget(_retval);
     return NS_OK;
 }
 
 void nsPop3Service::AlertServerBusy(nsIMsgMailNewsUrl *url)
 {
   nsresult rv;
   nsCOMPtr<nsIStringBundleService> bundleService =
     mozilla::services::GetStringBundleService();
--- a/mailnews/news/src/nsNNTPProtocol.cpp
+++ b/mailnews/news/src/nsNNTPProtocol.cpp
@@ -26,16 +26,17 @@
 #include "prerror.h"
 #include "nsString.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Services.h"
 #include "mozilla/SlicedInputStream.h"
 #include "mozilla/mailnews/MimeHeaderParser.h"
 #include "nsContentUtils.h"
+#include "nsIURIMutator.h"
 
 #include "prprf.h"
 
 /* include event sink interfaces for news */
 
 #include "nsIMsgSearchSession.h"
 #include "nsIMsgSearchAdapter.h"
 #include "nsIMsgStatusFeedback.h"
@@ -342,17 +343,17 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize
     rv = server->GetPort(&port);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (port<=0) {
       port = (socketType == nsMsgSocketType::SSL) ?
              nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT;
     }
 
-    rv = m_url->SetPort(port);
+    rv = NS_MutateURI(m_url).SetPort(port).Finalize(m_url);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_PRECONDITION(m_url, "invalid URL passed into NNTP Protocol");
 
   m_runningURL = do_QueryInterface(m_url, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   SetIsBusy(true);
@@ -824,26 +825,27 @@ nsresult nsNNTPProtocol::OpenCacheEntry(
 
   // Open a cache entry with key = url, no extension.
   nsCOMPtr<nsIURI> uri;
   rv = mailnewsUrl->GetBaseURI(getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Truncate of the query part so we don't duplicate urls in the cache for
   // various message parts.
+  nsAutoCString path;
+  uri->GetPathQueryRef(path);
+  int32_t pos = path.FindChar('?');
   nsCOMPtr<nsIURI> newUri;
-  uri->Clone(getter_AddRefs(newUri));
-  nsAutoCString path;
-  newUri->GetPathQueryRef(path);
-  int32_t pos = path.FindChar('?');
   if (pos != kNotFound) {
     path.SetLength(pos);
-    newUri->SetPathQueryRef(path);
+    rv = NS_MutateURI(uri).SetPathQueryRef(path).Finalize(newUri);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
-  return cacheStorage->AsyncOpenURI(newUri, EmptyCString(), nsICacheStorage::OPEN_NORMALLY, this);
+  return cacheStorage->AsyncOpenURI(newUri ? newUri : uri, EmptyCString(),
+                                    nsICacheStorage::OPEN_NORMALLY, this);
 }
 
 NS_IMETHODIMP nsNNTPProtocol::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
 {
   nsresult rv;
   nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningURL, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
--- a/mailnews/news/src/nsNewsFolder.cpp
+++ b/mailnews/news/src/nsNewsFolder.cpp
@@ -61,16 +61,17 @@
 #include "nsILoginManager.h"
 #include "nsIPromptService.h"
 #include "nsEmbedCID.h"
 #include "nsIDOMWindow.h"
 #include "mozilla/Services.h"
 #include "nsAutoPtr.h"
 #include "nsIInputStream.h"
 #include "nsMemory.h"
+#include "nsIURIMutator.h"
 
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
 
 // ###tw  This really ought to be the most
 // efficient file reading size for the current
 // operating system.
 #define NEWSRC_FILE_BUFFER_SIZE 1024
 
@@ -1082,42 +1083,41 @@ NS_IMETHODIMP nsMsgNewsFolder::SetGroupP
   mGroupPassword = aGroupPassword;
   return NS_OK;
 }
 
 nsresult nsMsgNewsFolder::CreateNewsgroupUrlForSignon(const char *ref,
     nsAString &result)
 {
   nsresult rv;
-  nsCOMPtr<nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
 
   nsCOMPtr<nsIMsgIncomingServer> server;
   rv = GetServer(getter_AddRefs(server));
   if (NS_FAILED(rv)) return rv;
 
   nsCOMPtr<nsINntpIncomingServer> nntpServer;
   rv = GetNntpServer(getter_AddRefs(nntpServer));
   if (NS_FAILED(rv)) return rv;
 
   bool singleSignon = true;
   rv = nntpServer->GetSingleSignon(&singleSignon);
 
+  nsCOMPtr<nsIURL> url;
   if (singleSignon)
   {
     nsCString serverURI;
     rv = server->GetServerURI(serverURI);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = url->SetSpecInternal(serverURI);
+    rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID).SetSpec(serverURI).Finalize(url);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else
   {
-    rv = url->SetSpecInternal(mURI);
+    rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID).SetSpec(mURI).Finalize(url);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   int32_t port = 0;
   rv = url->GetPort(&port);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (port <= 0)
@@ -1130,25 +1130,25 @@ nsresult nsMsgNewsFolder::CreateNewsgrou
     nsresult rv = server->GetSocketType(&socketType);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Only set this for ssl newsgroups as for non-ssl connections, we don't
     // need to specify the port as it is the default for the protocol and
     // password manager "blanks" those out.
     if (socketType == nsMsgSocketType::SSL)
     {
-      rv = url->SetPort(nsINntpUrl::DEFAULT_NNTPS_PORT);
+      rv = NS_MutateURI(url).SetPort(nsINntpUrl::DEFAULT_NNTPS_PORT).Finalize(url);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   nsCString rawResult;
   if (ref)
   {
-    rv = url->SetRef(nsDependentCString(ref));
+    rv = NS_MutateURI(url).SetRef(nsDependentCString(ref)).Finalize(url);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = url->GetSpec(rawResult);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else
   {
     // If the url doesn't have a path, make sure we don't get a '/' on the end
--- a/mailnews/news/src/nsNntpService.cpp
+++ b/mailnews/news/src/nsNntpService.cpp
@@ -48,16 +48,18 @@
 #include "nsIWindowWatcher.h"
 #include "nsICommandLine.h"
 #include "nsIMsgMailNewsUrl.h"
 #include "nsIMsgMailSession.h"
 #include "nsISupportsPrimitives.h"
 #include "nsArrayUtils.h"
 #include "nsIStreamListener.h"
 #include "nsIInputStream.h"
+#include "nsIURIMutator.h"
+
 #include "../../base/src/MailnewsLoadContextInfo.h"
 
 #undef GetPort  // XXX Windows!
 #undef SetPort  // XXX Windows!
 
 #define PREF_MAIL_ROOT_NNTP   "mail.root.nntp"        // old - for backward compatibility only
 #define PREF_MAIL_ROOT_NNTP_REL   "mail.root.nntp-rel"
 
@@ -227,20 +229,17 @@ nsNntpService::DisplayMessage(const char
   nsNewsAction action = nsINntpUrl::ActionFetchArticle;
   if (mOpenAttachmentOperation)
     action = nsINntpUrl::ActionFetchPart;
 
   nsCOMPtr<nsIURI> url;
   rv = ConstructNntpUrl(urlStr.get(), aUrlListener, aMsgWindow, aMessageURI, action, getter_AddRefs(url));
   NS_ENSURE_SUCCESS(rv,rv);
 
-  nsCOMPtr <nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(url,&rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  nsCOMPtr<nsIMsgI18NUrl> i18nurl = do_QueryInterface(msgUrl,&rv);
+  nsCOMPtr<nsIMsgI18NUrl> i18nurl = do_QueryInterface(url, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   i18nurl->SetCharsetOverRide(aCharsetOverride);
 
   bool shouldStoreMsgOffline = false;
 
   if (folder)
   {
@@ -262,17 +261,17 @@ nsNntpService::DisplayMessage(const char
         int32_t socketType;
         rv = server->GetSocketType(&socketType);
         NS_ENSURE_SUCCESS(rv, rv);
 
         port = (socketType == nsMsgSocketType::SSL) ?
                nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT;
       }
 
-      rv = url->SetPort(port);
+      rv = NS_MutateURI(url).SetPort(port).Finalize(url);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
 
     // Look for the message in the offline cache
     bool hasMsgOffline = false;
     folder->HasMsgOffline(key, &hasMsgOffline);
@@ -283,17 +282,19 @@ nsNntpService::DisplayMessage(const char
       rv = IsMsgInMemCache(url, folder, &hasMsgOffline);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // If the message is not found in either, then we might need to return
     if (!hasMsgOffline && WeAreOffline())
       return server->DisplayOfflineMsg(aMsgWindow);
 
-    msgUrl->SetMsgIsInLocalCache(hasMsgOffline);
+    nsCOMPtr <nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(url,&rv);
+    NS_ENSURE_SUCCESS(rv,rv);
+    mailnewsurl->SetMsgIsInLocalCache(hasMsgOffline);
 
     nsCOMPtr<nsIMsgNewsFolder> newsFolder(do_QueryInterface(folder, &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline);
   }
 
   rv = GetMessageFromUrl(url, aMsgWindow, aDisplayConsumer);
   if (aURL)
@@ -1204,24 +1205,25 @@ NS_IMETHODIMP nsNntpService::GetProtocol
 
 NS_IMETHODIMP nsNntpService::NewURI(const nsACString &aSpec,
                                     const char *aCharset, // ignored
                                     nsIURI *aBaseURI,
                                     nsIURI **_retval)
 {
     nsresult rv;
 
-    nsCOMPtr<nsIURI> nntpUri = do_CreateInstance(NS_NNTPURL_CONTRACTID, &rv);
+    nsCOMPtr<nsIMsgMailNewsUrl> nntpUri = do_CreateInstance(NS_NNTPURL_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     if (aBaseURI)
     {
       nsAutoCString newSpec;
       aBaseURI->Resolve(aSpec, newSpec);
       rv = nntpUri->SetSpecInternal(newSpec);
+      // XXX Consider: rv = NS_MutateURI(new nsNntpUrl::Mutator()).SetSpec(newSpec).Finalize(nntpUri);
     }
     else
     {
       rv = nntpUri->SetSpecInternal(aSpec);
     }
     NS_ENSURE_SUCCESS(rv,rv);
 
     nntpUri.forget(_retval);
@@ -1423,40 +1425,44 @@ nsNntpService::StreamMessage(const char 
     nsCOMPtr<nsIURI> url;
     rv = ConstructNntpUrl(urlStr.get(), aUrlListener, aMsgWindow, aURIString.get(),
                           action, getter_AddRefs(url));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aLocalOnly || WeAreOffline())
     {
       // Check in the offline cache, then in the mem cache
-      nsCOMPtr<nsIMsgMailNewsUrl> msgUrl(do_QueryInterface(url, &rv));
       bool hasMsgOffline = false;
       folder->HasMsgOffline(key, &hasMsgOffline);
       if (!hasMsgOffline)
       {
         nsCOMPtr<nsIMsgIncomingServer> server;
         rv = folder->GetServer(getter_AddRefs(server));
         NS_ENSURE_SUCCESS(rv, rv);
 
         int32_t socketType;
         rv = server->GetSocketType(&socketType);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        url->SetPort((socketType == nsMsgSocketType::SSL) ?
-                     nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT);
+        rv = NS_MutateURI(url)
+               .SetPort(socketType == nsMsgSocketType::SSL ?
+                          nsINntpUrl::DEFAULT_NNTPS_PORT :
+                          nsINntpUrl::DEFAULT_NNTP_PORT)
+               .Finalize(url);
+        NS_ENSURE_SUCCESS(rv, rv);
 
         rv = IsMsgInMemCache(url, folder, &hasMsgOffline);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       // Return with an error if we didn't find it in the memory cache either
       if (!hasMsgOffline)
         return NS_ERROR_FAILURE;
 
+      nsCOMPtr<nsIMsgMailNewsUrl> msgUrl(do_QueryInterface(url, &rv));
       msgUrl->SetMsgIsInLocalCache(true);
     }
 
     rv = GetMessageFromUrl(url, aMsgWindow, aConsumer);
     if (aURL)
       url.forget(aURL);
     return rv;
 }
@@ -1504,27 +1510,30 @@ NS_IMETHODIMP nsNntpService::IsMsgInMemC
 {
   NS_ENSURE_ARG_POINTER(aUrl);
   *aResult = false;
   nsresult rv;
 
   if (mCacheStorage)
   {
     // NNTP urls are truncated at the query part when used as cache keys.
-    nsCOMPtr <nsIURI> newUri;
-    aUrl->Clone(getter_AddRefs(newUri));
     nsAutoCString path;
-    newUri->GetPathQueryRef(path);
+    aUrl->GetPathQueryRef(path);
     int32_t pos = path.FindChar('?');
+    nsCOMPtr<nsIURI> newUri;
     if (pos != kNotFound) {
       path.SetLength(pos);
-      newUri->SetPathQueryRef(path);
+      rv = NS_MutateURI(aUrl).SetPathQueryRef(path).Finalize(newUri);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
     bool exists;
-    rv = mCacheStorage->Exists(newUri, EmptyCString(), &exists);
+    if (newUri)
+      rv = mCacheStorage->Exists(newUri, EmptyCString(), &exists);
+    else
+      rv = mCacheStorage->Exists(aUrl, EmptyCString(), &exists);
     if (NS_SUCCEEDED(rv) && exists) {
       *aResult = true;
     }
   }
 
   return NS_OK;
 }