Bug 1448330 - Make nsIURI.clone a private method r=mayhemer
authorValentin Gosu <valentin.gosu@gmail.com>
Thu, 14 Jun 2018 13:05:43 +0200
changeset 423109 110e4b10e2eaca929de9ec715da66fe26d52445f
parent 423108 7eab423d6991f0b239071a32e11d3c0ea8d9c7c7
child 423110 30ef0ff424054f15fb9dee7203cd73eac30f9c9e
push id34163
push usercsabou@mozilla.com
push dateThu, 21 Jun 2018 01:14:46 +0000
treeherdermozilla-central@e09fbaee1456 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1448330
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1448330 - Make nsIURI.clone a private method r=mayhemer MozReview-Commit-ID: 1efpeaEPaXP
browser/base/content/browser-safebrowsing.js
browser/modules/BlockedSiteContent.jsm
caps/NullPrincipalURI.cpp
caps/NullPrincipalURI.h
docshell/base/nsDocShell.cpp
dom/base/Link.cpp
dom/base/Link.h
dom/base/Location.cpp
dom/html/HTMLFormElement.cpp
dom/jsurl/nsJSProtocolHandler.cpp
dom/webbrowserpersist/nsWebBrowserPersist.cpp
dom/xbl/nsXBLPrototypeBinding.cpp
image/decoders/icon/nsIconURI.cpp
image/decoders/icon/nsIconURI.h
layout/generic/nsImageFrame.cpp
layout/style/nsCSSValue.cpp
modules/libjar/nsJARChannel.cpp
modules/libjar/nsJARURI.cpp
modules/libjar/nsJARURI.h
netwerk/base/nsIURI.idl
netwerk/base/nsSimpleNestedURI.cpp
netwerk/base/nsSimpleURI.cpp
netwerk/base/nsSimpleURI.h
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/protocol/about/nsAboutProtocolHandler.cpp
netwerk/protocol/res/SubstitutingProtocolHandler.h
netwerk/test/unit/test_URIs.js
netwerk/test/unit/test_URIs2.js
netwerk/test/unit/test_bug396389.js
toolkit/components/places/nsFaviconService.cpp
toolkit/modules/RemoteWebProgress.jsm
uriloader/prefetch/OfflineCacheUpdateParent.cpp
--- a/browser/base/content/browser-safebrowsing.js
+++ b/browser/base/content/browser-safebrowsing.js
@@ -54,17 +54,17 @@ var gSafeBrowsing = {
    *        Information about the reasons for blocking the resource.
    *        In the case false positive, it may contain SafeBrowsing
    *        matching list and provider of the list
    * @return String the report phishing URL.
    */
   getReportURL(name, info) {
     let reportInfo = info;
     if (!reportInfo) {
-      let pageUri = gBrowser.currentURI.clone();
+      let pageUri = gBrowser.currentURI;
 
       // Remove the query to avoid including potentially sensitive data
       if (pageUri instanceof Ci.nsIURL) {
         pageUri = pageUri.mutate()
                          .setQuery("")
                          .finalize();
       }
 
--- a/browser/modules/BlockedSiteContent.jsm
+++ b/browser/modules/BlockedSiteContent.jsm
@@ -14,17 +14,17 @@ ChromeUtils.defineModuleGetter(this, "Sa
 function getSiteBlockedErrorDetails(docShell) {
   let blockedInfo = {};
   if (docShell.failedChannel) {
     let classifiedChannel = docShell.failedChannel.
                             QueryInterface(Ci.nsIClassifiedChannel);
     if (classifiedChannel) {
       let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
 
-      let reportUri = httpChannel.URI.clone();
+      let reportUri = httpChannel.URI;
 
       // Remove the query to avoid leaking sensitive data
       if (reportUri instanceof Ci.nsIURL) {
         reportUri = reportUri.mutate()
                              .setQuery("")
                              .finalize();
       }
 
--- a/caps/NullPrincipalURI.cpp
+++ b/caps/NullPrincipalURI.cpp
@@ -276,17 +276,17 @@ NullPrincipalURI::GetUserPass(nsACString
 }
 
 nsresult
 NullPrincipalURI::SetUserPass(const nsACString& aUserPass)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP
+nsresult
 NullPrincipalURI::Clone(nsIURI** _newURI)
 {
   nsCOMPtr<nsIURI> uri = new NullPrincipalURI(*this);
   uri.forget(_newURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/caps/NullPrincipalURI.h
+++ b/caps/NullPrincipalURI.h
@@ -51,16 +51,17 @@ private:
   NullPrincipalURI(const NullPrincipalURI& aOther);
 
   ~NullPrincipalURI() {}
 
   nsresult Init();
 
   nsAutoCStringN<NSID_LENGTH> mPath;
 
+  nsresult Clone(nsIURI** aURI);
   nsresult SetSpecInternal(const nsACString &input);
   nsresult SetScheme(const nsACString &input);
   nsresult SetUserPass(const nsACString &input);
   nsresult SetUsername(const nsACString &input);
   nsresult SetPassword(const nsACString &input);
   nsresult SetHostPort(const nsACString &aValue);
   nsresult SetHost(const nsACString &input);
   nsresult SetPort(int32_t port);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13471,42 +13471,33 @@ nsDocShell::OnLinkClickSync(nsIContent* 
   if (anchor) {
     anchor->GetType(typeHint);
     NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
     nsAutoCString type, dummy;
     NS_ParseRequestContentType(utf8Hint, type, dummy);
     CopyUTF8toUTF16(type, typeHint);
   }
 
-  // Clone the URI now, in case a content policy or something messes
-  // with it under InternalLoad; we do _not_ want to change the URI
-  // our caller passed in.
-  nsCOMPtr<nsIURI> clonedURI;
-  aURI->Clone(getter_AddRefs(clonedURI));
-  if (!clonedURI) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   // if the triggeringPrincipal is not passed explicitly, then we
   // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
   nsCOMPtr<nsIPrincipal> triggeringPrincipal =
     aTriggeringPrincipal ? aTriggeringPrincipal
                          : aContent->NodePrincipal();
 
   // Link click (or form submission) can be triggered inside an onload handler,
   // and we don't want to add history entry in this case.
   bool inOnLoadHandler = false;
   GetIsExecutingOnLoadHandler(&inOnLoadHandler);
   uint32_t loadType = inOnLoadHandler ? LOAD_NORMAL_REPLACE : LOAD_LINK;
 
   if (aIsUserTriggered) {
     flags |= INTERNAL_LOAD_FLAGS_IS_USER_TRIGGERED;
   }
 
-  nsresult rv = InternalLoad(clonedURI,                 // New URI
+  nsresult rv = InternalLoad(aURI,                      // New URI
                              nullptr,                   // Original URI
                              Nothing(),                 // Let the protocol handler assign it
                              false,                     // LoadReplace
                              referer,                   // Referer URI
                              refererPolicy,             // Referer policy
                              triggeringPrincipal,
                              aContent->NodePrincipal(),
                              flags,
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -854,29 +854,16 @@ Link::UnregisterFromHistory()
       NS_ASSERTION(NS_SUCCEEDED(rv), "This should only fail if we misuse the API!");
       if (NS_SUCCEEDED(rv)) {
         mRegistered = false;
       }
     }
   }
 }
 
-already_AddRefed<nsIURI>
-Link::GetURIToMutate()
-{
-  MOZ_ASSERT(false, "TODO: REMOVE THIS METHOD");
-  nsCOMPtr<nsIURI> uri(GetURI());
-  if (!uri) {
-    return nullptr;
-  }
-  nsCOMPtr<nsIURI> clone;
-  (void)uri->Clone(getter_AddRefs(clone));
-  return clone.forget();
-}
-
 void
 Link::SetHrefAttribute(nsIURI *aURI)
 {
   NS_ASSERTION(aURI, "Null URI is illegal!");
 
   // if we change this code to not reserialize we need to do something smarter
   // in SetProtocol because changing the protocol of an URI can change the
   // "nature" of the nsIURL/nsIURI implementation.
--- a/dom/base/Link.h
+++ b/dom/base/Link.h
@@ -165,17 +165,16 @@ protected:
 
 private:
   /**
    * Unregisters from History so this node no longer gets notifications about
    * changes to visitedness.
    */
   void UnregisterFromHistory();
 
-  already_AddRefed<nsIURI> GetURIToMutate();
   void SetHrefAttribute(nsIURI *aURI);
 
   void GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
                                      nsContentPolicyType& aPolicyType,
                                      nsString& aMimeType,
                                      nsAString& aMedia);
 
   mutable nsCOMPtr<nsIURI> mCachedURI;
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -216,17 +216,18 @@ Location::GetWritableURI(nsIURI** aURI, 
   nsCOMPtr<nsIURI> uri;
 
   nsresult rv = GetURI(getter_AddRefs(uri));
   if (NS_FAILED(rv) || !uri) {
     return rv;
   }
 
   if (!aNewRef) {
-    return uri->Clone(aURI);
+    uri.forget(aURI);
+    return NS_OK;
   }
 
   return uri->CloneWithNewRef(*aNewRef, aURI);
 }
 
 nsresult
 Location::SetURI(nsIURI* aURI, bool aReplace)
 {
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -1665,18 +1665,17 @@ HTMLFormElement::GetActionURL(nsIURI** a
   if (action.IsEmpty()) {
     nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(document));
     if (!htmlDoc) {
       // Must be a XML, XUL or other non-HTML document type
       // so do nothing.
       return NS_OK;
     }
 
-    rv = docURI->Clone(getter_AddRefs(actionURL));
-    NS_ENSURE_SUCCESS(rv, rv);
+    actionURL = docURI;
   } else {
     nsCOMPtr<nsIURI> baseURL = GetBaseURI();
     NS_ASSERTION(baseURL, "No Base URL found in Form Submit!\n");
     if (!baseURL) {
       return NS_OK; // No base URL -> exit early, see Bug 30721
     }
     rv = NS_NewURI(getter_AddRefs(actionURL), action, nullptr, baseURL);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -1371,26 +1371,17 @@ nsJSURI::Deserialize(const mozilla::ipc:
     return true;
 }
 
 // nsSimpleURI methods:
 /* virtual */ mozilla::net::nsSimpleURI*
 nsJSURI::StartClone(mozilla::net::nsSimpleURI::RefHandlingEnum refHandlingMode,
                     const nsACString& newRef)
 {
-    nsCOMPtr<nsIURI> baseClone;
-    if (mBaseURI) {
-      // Note: We preserve ref on *base* URI, regardless of ref handling mode.
-      nsresult rv = mBaseURI->Clone(getter_AddRefs(baseClone));
-      if (NS_FAILED(rv)) {
-        return nullptr;
-      }
-    }
-
-    nsJSURI* url = new nsJSURI(baseClone);
+    nsJSURI* url = new nsJSURI(mBaseURI);
     SetRefOnClone(url, refHandlingMode, newRef);
     return url;
 }
 
 // Queries this list of interfaces. If none match, it queries mURI.
 NS_IMPL_NSIURIMUTATOR_ISUPPORTS(nsJSURI::Mutator,
                                 nsIURISetters,
                                 nsIURIMutator,
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -614,21 +614,17 @@ nsWebBrowserPersist::SerializeNextFile()
             nsCOMPtr<nsIURI> uri;
             rv = NS_NewURI(getter_AddRefs(uri), iter.Key(),
                            data->mCharset.get());
             if (NS_WARN_IF(NS_FAILED(rv))) {
                 break;
             }
 
             // Make a URI to save the data to.
-            nsCOMPtr<nsIURI> fileAsURI;
-            rv = data->mDataPath->Clone(getter_AddRefs(fileAsURI));
-            if (NS_WARN_IF(NS_FAILED(rv))) {
-                break;
-            }
+            nsCOMPtr<nsIURI> fileAsURI = data->mDataPath;
             rv = AppendPathToURI(fileAsURI, data->mFilename, fileAsURI);
             if (NS_WARN_IF(NS_FAILED(rv))) {
                 break;
             }
 
             // The Referrer Policy doesn't matter here since the referrer is
             // nullptr.
             rv = SaveURIInternal(uri, 0, nullptr,
@@ -2523,21 +2519,19 @@ nsWebBrowserPersist::URIData::GetLocalUR
 {
     aSpecOut.SetIsVoid(true);
     if (!mNeedsFixup) {
         return NS_OK;
     }
     nsresult rv;
     nsCOMPtr<nsIURI> fileAsURI;
     if (mFile) {
-        rv = mFile->Clone(getter_AddRefs(fileAsURI));
-        NS_ENSURE_SUCCESS(rv, rv);
+        fileAsURI = mFile;
     } else {
-        rv = mDataPath->Clone(getter_AddRefs(fileAsURI));
-        NS_ENSURE_SUCCESS(rv, rv);
+        fileAsURI = mDataPath;
         rv = AppendPathToURI(fileAsURI, mFilename, fileAsURI);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // remove username/password if present
     Unused << NS_MutateURI(fileAsURI)
                 .SetUserPass(EmptyCString())
                 .Finalize(fileAsURI);
@@ -2650,26 +2644,22 @@ nsWebBrowserPersist::SaveSubframeContent
         aData->mSubFrameExt.Assign(char16_t('.'));
         aData->mSubFrameExt.Append(ext);
     }
 
     nsString filenameWithExt = aData->mFilename;
     filenameWithExt.Append(aData->mSubFrameExt);
 
     // Work out the path for the subframe
-    nsCOMPtr<nsIURI> frameURI;
-    rv = mCurrentDataPath->Clone(getter_AddRefs(frameURI));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIURI> frameURI = mCurrentDataPath;
     rv = AppendPathToURI(frameURI, filenameWithExt, frameURI);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Work out the path for the subframe data
-    nsCOMPtr<nsIURI> frameDataURI;
-    rv = mCurrentDataPath->Clone(getter_AddRefs(frameDataURI));
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIURI> frameDataURI = mCurrentDataPath;
     nsAutoString newFrameDataPath(aData->mFilename);
 
     // Append _data
     newFrameDataPath.AppendLiteral("_data");
     rv = AppendPathToURI(frameDataURI, newFrameDataPath, frameDataURI);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Make frame document & data path conformant and unique
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -131,25 +131,24 @@ nsXBLPrototypeBinding::Init(const nsACSt
                             bool aFirstBinding)
 {
   nsresult rv;
   nsCOMPtr<nsIURI> bindingURI = aInfo->DocumentURI();
 
   // The binding URI might be an immutable URI (e.g. for about: URIs). In that case,
   // we'll fail in SetRef below, but that doesn't matter much for now.
   if (aFirstBinding) {
-    rv = bindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
-    NS_ENSURE_SUCCESS(rv, rv);
+    mAlternateBindingURI = bindingURI;
   }
   rv = NS_MutateURI(bindingURI)
         .SetRef(aID)
         .Finalize(mBindingURI);
   if (NS_FAILED(rv)) {
     // If SetRef failed, mBindingURI should be a clone.
-    bindingURI->Clone(getter_AddRefs(mBindingURI));
+    mBindingURI = bindingURI;
   }
 
   mXBLDocInfoWeak = aInfo;
 
   // aElement will be null when reading from the cache, but the element will
   // still be set later.
   if (aElement) {
     SetBindingElement(aElement);
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -504,41 +504,37 @@ nsMozIconURI::SchemeIs(const char* aSche
   if (!aScheme) {
     return NS_ERROR_INVALID_ARG;
   }
 
   *aEquals = PL_strcasecmp("moz-icon", aScheme) ? false : true;
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 nsMozIconURI::Clone(nsIURI** result)
 {
+  nsresult rv;
   nsCOMPtr<nsIURL> newIconURL;
   if (mIconURL) {
-    nsCOMPtr<nsIURI> newURI;
-    nsresult rv = mIconURL->Clone(getter_AddRefs(newURI));
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-    newIconURL = do_QueryInterface(newURI, &rv);
+    newIconURL = do_QueryInterface(mIconURL, &rv);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
-  nsMozIconURI* uri = new nsMozIconURI();
+  RefPtr<nsMozIconURI> uri = new nsMozIconURI();
   newIconURL.swap(uri->mIconURL);
   uri->mSize = mSize;
   uri->mContentType = mContentType;
   uri->mFileName = mFileName;
   uri->mStockIcon = mStockIcon;
   uri->mIconSize = mIconSize;
   uri->mIconState = mIconState;
-  NS_ADDREF(*result = uri);
+  uri.forget(result);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMozIconURI::CloneIgnoringRef(nsIURI** result)
 {
   // GetRef/SetRef not supported by nsMozIconURI, so
--- a/image/decoders/icon/nsIconURI.h
+++ b/image/decoders/icon/nsIconURI.h
@@ -42,16 +42,17 @@ protected:
                        // given a filename with an extension
   nsCString mStockIcon;
   int32_t mIconSize;   // -1 if not specified, otherwise index into
                        // kSizeStrings
   int32_t mIconState;  // -1 if not specified, otherwise index into
                        // kStateStrings
 
 private:
+  nsresult Clone(nsIURI** aURI);
   nsresult SetSpecInternal(const nsACString &input);
   nsresult SetScheme(const nsACString &input);
   nsresult SetUserPass(const nsACString &input);
   nsresult SetUsername(const nsACString &input);
   nsresult SetPassword(const nsACString &input);
   nsresult SetHostPort(const nsACString &aValue);
   nsresult SetHost(const nsACString &input);
   nsresult SetPort(int32_t port);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1945,17 +1945,17 @@ nsImageFrame::GetAnchorHREFTargetAndNode
 
   // Walk up the content tree, looking for an nsIDOMAnchorElement
   for (nsIContent* content = mContent->GetParent();
        content; content = content->GetParent()) {
     nsCOMPtr<dom::Link> link(do_QueryInterface(content));
     if (link) {
       nsCOMPtr<nsIURI> href = content->GetHrefURI();
       if (href) {
-        href->Clone(aHref);
+        href.forget(aHref);
       }
       status = (*aHref != nullptr);
 
       RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(content);
       if (anchor) {
         anchor->GetTarget(aTarget);
       }
       NS_ADDREF(*aNode = content);
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1304,19 +1304,20 @@ css::URLValueData::ResolveLocalRef(nsIUR
 
   if (result && IsLocalRef()) {
     nsCString ref;
     mURI->GetRef(ref);
 
     nsresult rv = NS_MutateURI(aURI)
                     .SetRef(ref)
                     .Finalize(result);
+
     if (NS_FAILED(rv)) {
-      // If setting the ref failed, just return a clone.
-      aURI->Clone(getter_AddRefs(result));
+      // If setting the ref failed, just return the original URI.
+      result = aURI;
     }
   }
 
   return result.forget();
 }
 
 already_AddRefed<nsIURI>
 css::URLValueData::ResolveLocalRef(nsIContent* aContent) const
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -459,51 +459,39 @@ nsJARChannel::OpenLocalFile()
     }
 
     nsCOMPtr<nsIFile> clonedFile;
     rv = mJarFile->Clone(getter_AddRefs(clonedFile));
     if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
     }
 
-    // clone mJarURI
-    nsCOMPtr<nsIURI> clonedURI;
-    rv = mJarURI->Clone(getter_AddRefs(clonedURI));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-    }
-    nsCOMPtr<nsIJARURI> clonedJarURI = do_QueryInterface(clonedURI, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-    }
+    nsCOMPtr<nsIJARURI> localJARURI = mJarURI;
 
     nsAutoCString jarEntry(mJarEntry);
     nsAutoCString innerJarEntry(mInnerJarEntry);
 
     RefPtr<nsJARChannel> self = this;
     return mWorker->Dispatch(
             NS_NewRunnableFunction("nsJARChannel::OpenLocalFile",
                                    [self,
                                    jarCache,
                                    clonedFile,
-                                   clonedJarURI,
+                                   localJARURI,
                                    jarEntry,
                                    innerJarEntry] () mutable {
 
         RefPtr<nsJARInputThunk> input;
         nsresult rv = CreateLocalJarInput(jarCache,
                                           clonedFile,
                                           innerJarEntry,
-                                          clonedJarURI,
+                                          localJARURI,
                                           jarEntry,
                                           getter_AddRefs(input));
 
-        NS_ReleaseOnMainThreadSystemGroup("nsJARChannel::clonedJarURI",
-                                          clonedJarURI.forget());
-
         nsCOMPtr<nsIRunnable> target;
         if (NS_SUCCEEDED(rv)) {
             target = NewRunnableMethod<RefPtr<nsJARInputThunk>, bool>(
                 "nsJARChannel::ContinueOpenLocalFile",
                 self,
                 &nsJARChannel::ContinueOpenLocalFile,
                 input,
                 false);
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -585,17 +585,17 @@ nsJARURI::SchemeIs(const char *i_Scheme,
     if (*i_Scheme == 'j' || *i_Scheme == 'J') {
         *o_Equals = PL_strcasecmp("jar", i_Scheme) ? false : true;
     } else {
         *o_Equals = false;
     }
     return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 nsJARURI::Clone(nsIURI **result)
 {
     nsresult rv;
 
     nsCOMPtr<nsIJARURI> uri;
     rv = CloneWithJARFileInternal(mJARFile, eHonorRef, getter_AddRefs(uri));
     if (NS_FAILED(rv)) return rv;
 
@@ -905,40 +905,35 @@ nsJARURI::CloneWithJARFileInternal(nsIUR
                                    nsJARURI::RefHandlingEnum refHandlingMode,
                                    const nsACString& newRef,
                                    nsIJARURI **result)
 {
     if (!jarFile) {
         return NS_ERROR_INVALID_ARG;
     }
 
-    nsresult rv;
-
-    nsCOMPtr<nsIURI> newJARFile;
-    rv = jarFile->Clone(getter_AddRefs(newJARFile));
-    if (NS_FAILED(rv)) return rv;
-
+    nsresult rv = NS_OK;
+    nsCOMPtr<nsIURI> newJARFile = jarFile;
     nsCOMPtr<nsIURI> newJAREntryURI;
     if (refHandlingMode == eHonorRef) {
-      rv = mJAREntry->Clone(getter_AddRefs(newJAREntryURI));
+      newJAREntryURI = mJAREntry;
     } else if (refHandlingMode == eReplaceRef) {
       rv = mJAREntry->CloneWithNewRef(newRef, getter_AddRefs(newJAREntryURI));
     } else {
       rv = mJAREntry->CloneIgnoringRef(getter_AddRefs(newJAREntryURI));
     }
     if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
     NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
 
-    nsJARURI* uri = new nsJARURI();
-    NS_ADDREF(uri);
+    RefPtr<nsJARURI> uri = new nsJARURI();
     uri->mJARFile = newJARFile;
     uri->mJAREntry = newJAREntry;
-    *result = uri;
+    uri.forget(result);
 
     return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP
 nsJARURI::GetInnerURI(nsIURI **aURI)
--- a/modules/libjar/nsJARURI.h
+++ b/modules/libjar/nsJARURI.h
@@ -94,16 +94,17 @@ protected:
                                       nsIJARURI **result);
     nsCOMPtr<nsIURI> mJARFile;
     // mJarEntry stored as a URL so that we can easily access things
     // like extensions, refs, etc.
     nsCOMPtr<nsIURL> mJAREntry;
     nsCString        mCharsetHint;
 
 private:
+    nsresult Clone(nsIURI** aURI);
     nsresult SetSpecInternal(const nsACString &input);
     nsresult SetScheme(const nsACString &input);
     nsresult SetUserPass(const nsACString &input);
     nsresult SetUsername(const nsACString &input);
     nsresult SetPassword(const nsACString &input);
     nsresult SetHostPort(const nsACString &aValue);
     nsresult SetHost(const nsACString &input);
     nsresult SetPort(int32_t port);
--- a/netwerk/base/nsIURI.idl
+++ b/netwerk/base/nsIURI.idl
@@ -177,21 +177,16 @@ interface nsIURI : nsISupports
     /**
      * An optimization to do scheme checks without requiring the users of nsIURI
      * to GetScheme, thereby saving extra allocating and freeing. Returns true if
      * the schemes match (case ignored).
      */
     boolean schemeIs(in string scheme);
 
     /**
-     * Clones the current URI.
-     */
-    nsIURI clone();
-
-    /**
      * This method resolves a relative string into an absolute URI string,
      * using this URI as the base. 
      *
      * NOTE: some implementations may have no concept of a relative URI.
      */
     AUTF8String resolve(in AUTF8String relativePath);
 
 
--- a/netwerk/base/nsSimpleNestedURI.cpp
+++ b/netwerk/base/nsSimpleNestedURI.cpp
@@ -203,19 +203,19 @@ nsSimpleNestedURI::EqualsInternal(nsIURI
 
 /* virtual */ nsSimpleURI*
 nsSimpleNestedURI::StartClone(nsSimpleURI::RefHandlingEnum refHandlingMode,
                               const nsACString& newRef)
 {
     NS_ENSURE_TRUE(mInnerURI, nullptr);
 
     nsCOMPtr<nsIURI> innerClone;
-    nsresult rv;
+    nsresult rv = NS_OK;
     if (refHandlingMode == eHonorRef) {
-        rv = mInnerURI->Clone(getter_AddRefs(innerClone));
+        innerClone = mInnerURI;
     } else if (refHandlingMode == eReplaceRef) {
         rv = mInnerURI->CloneWithNewRef(newRef, getter_AddRefs(innerClone));
     } else {
         rv = mInnerURI->CloneIgnoringRef(getter_AddRefs(innerClone));
     }
 
     if (NS_FAILED(rv)) {
         return nullptr;
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -622,17 +622,17 @@ nsSimpleURI::SetRefOnClone(nsSimpleURI* 
     if (refHandlingMode == eHonorRef) {
         url->mRef = mRef;
         url->mIsRefValid = mIsRefValid;
     } else if (refHandlingMode == eReplaceRef) {
         url->SetRef(newRef);
     }
 }
 
-NS_IMETHODIMP
+nsresult
 nsSimpleURI::Clone(nsIURI** result)
 {
     return CloneInternal(eHonorRef, EmptyCString(), result);
 }
 
 NS_IMETHODIMP
 nsSimpleURI::CloneIgnoringRef(nsIURI** result)
 {
--- a/netwerk/base/nsSimpleURI.h
+++ b/netwerk/base/nsSimpleURI.h
@@ -66,16 +66,17 @@ public:
 protected:
     // enum used in a few places to specify how .ref attribute should be handled
     enum RefHandlingEnum {
         eIgnoreRef,
         eHonorRef,
         eReplaceRef
     };
 
+    virtual nsresult Clone(nsIURI** aURI);
     virtual nsresult SetSpecInternal(const nsACString &input);
     virtual nsresult SetScheme(const nsACString &input);
     virtual nsresult SetUserPass(const nsACString &input);
     nsresult SetUsername(const nsACString &input);
     virtual nsresult SetPassword(const nsACString &input);
     virtual nsresult SetHostPort(const nsACString &aValue);
     virtual nsresult SetHost(const nsACString &input);
     virtual nsresult SetPort(int32_t port);
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -2268,17 +2268,17 @@ nsStandardURL::SchemeIs(const char *sche
 
 /* virtual */ nsStandardURL*
 nsStandardURL::StartClone()
 {
     nsStandardURL *clone = new nsStandardURL();
     return clone;
 }
 
-NS_IMETHODIMP
+nsresult
 nsStandardURL::Clone(nsIURI **result)
 {
     return CloneInternal(eHonorRef, EmptyCString(), result);
 }
 
 
 NS_IMETHODIMP
 nsStandardURL::CloneIgnoringRef(nsIURI **result)
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -158,16 +158,17 @@ protected:
                          bool copyCached = false);
 
     // Helper for subclass implementation of GetFile().  Subclasses that map
     // URIs to files in a special way should implement this method.  It should
     // ensure that our mFile is initialized, if it's possible.
     // returns NS_ERROR_NO_INTERFACE if the url does not map to a file
     virtual nsresult EnsureFile();
 
+    virtual nsresult Clone(nsIURI** aURI);
     virtual nsresult SetSpecInternal(const nsACString &input);
     virtual nsresult SetScheme(const nsACString &input);
     virtual nsresult SetUserPass(const nsACString &input);
     virtual nsresult SetUsername(const nsACString &input);
     virtual nsresult SetPassword(const nsACString &input);
     virtual nsresult SetHostPort(const nsACString &aValue);
     virtual nsresult SetHost(const nsACString &input);
     virtual nsresult SetPort(int32_t port);
--- a/netwerk/protocol/about/nsAboutProtocolHandler.cpp
+++ b/netwerk/protocol/about/nsAboutProtocolHandler.cpp
@@ -420,19 +420,19 @@ nsNestedAboutURI::StartClone(nsSimpleURI
                              const nsACString& aNewRef)
 {
     // Sadly, we can't make use of nsSimpleNestedURI::StartClone here.
     // However, this function is expected to exactly match that function,
     // aside from the "new ns***URI()" call.
     NS_ENSURE_TRUE(mInnerURI, nullptr);
 
     nsCOMPtr<nsIURI> innerClone;
-    nsresult rv;
+    nsresult rv = NS_OK;
     if (aRefHandlingMode == eHonorRef) {
-        rv = mInnerURI->Clone(getter_AddRefs(innerClone));
+        innerClone = mInnerURI;
     } else if (aRefHandlingMode == eReplaceRef) {
         rv = mInnerURI->CloneWithNewRef(aNewRef, getter_AddRefs(innerClone));
     } else {
         rv = mInnerURI->CloneIgnoringRef(getter_AddRefs(innerClone));
     }
 
     if (NS_FAILED(rv)) {
         return nullptr;
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.h
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.h
@@ -122,16 +122,17 @@ class SubstitutingURL : public nsStandar
 public:
   virtual nsStandardURL* StartClone() override;
   virtual MOZ_MUST_USE nsresult EnsureFile() override;
   NS_IMETHOD GetClassIDNoAlloc(nsCID *aCID) override;
 
 private:
   explicit SubstitutingURL() : nsStandardURL(true) {}
   explicit SubstitutingURL(bool aSupportsFileURL) : nsStandardURL(true) { MOZ_ASSERT(aSupportsFileURL); }
+  virtual nsresult Clone(nsIURI** aURI) override { return nsStandardURL::Clone(aURI); }
 
 public:
   class Mutator
     : public TemplatedMutator<SubstitutingURL>
   {
     NS_DECL_ISUPPORTS
   public:
     explicit Mutator() = default;
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -333,17 +333,17 @@ function do_test_uri_basic(aTest) {
     }
     do_info("relURI.pathQueryRef = " + relURI.pathQueryRef + ", was " + URI.pathQueryRef);
     URI = relURI;
     do_info("URI.pathQueryRef now = " + URI.pathQueryRef);
   }
 
   // Sanity-check
   do_info("testing " + aTest.spec + " equals a clone of itself");
-  do_check_uri_eq(URI, URI.clone());
+  do_check_uri_eq(URI, URI.mutate().finalize());
   do_check_uri_eqExceptRef(URI, URI.cloneIgnoringRef());
   do_info("testing " + aTest.spec + " instanceof nsIURL");
   Assert.equal(URI instanceof Ci.nsIURL, aTest.nsIURL);
   do_info("testing " + aTest.spec + " instanceof nsINestedURI");
   Assert.equal(URI instanceof Ci.nsINestedURI,
                aTest.nsINestedURI);
 
   do_info("testing that " + aTest.spec + " throws or returns false " +
@@ -399,17 +399,17 @@ function do_test_uri_with_hash_suffix(aT
       return;
     }
   } else {
     testURI = NetUtil.newURI(aTest.spec + aSuffix);
   }
 
   do_info("testing " + aTest.spec + " with '" + aSuffix + "' appended " +
            "equals a clone of itself");
-  do_check_uri_eq(testURI, testURI.clone());
+  do_check_uri_eq(testURI, testURI.mutate().finalize());
 
   do_info("testing " + aTest.spec +
           " doesn't equal self with '" + aSuffix + "' appended");
 
   Assert.ok(!origURI.equals(testURI));
 
   do_info("testing " + aTest.spec +
           " is equalExceptRef to self with '" + aSuffix + "' appended");
--- a/netwerk/test/unit/test_URIs2.js
+++ b/netwerk/test/unit/test_URIs2.js
@@ -442,17 +442,17 @@ function do_test_uri_basic(aTest) {
     }
     do_info("relURI.pathQueryRef = " + relURI.pathQueryRef + ", was " + URI.pathQueryRef);
     URI = relURI;
     do_info("URI.pathQueryRef now = " + URI.pathQueryRef);
   }
 
   // Sanity-check
   do_info("testing " + aTest.spec + " equals a clone of itself");
-  do_check_uri_eq(URI, URI.clone());
+  do_check_uri_eq(URI, URI.mutate().finalize());
   do_check_uri_eqExceptRef(URI, URI.cloneIgnoringRef());
   do_info("testing " + aTest.spec + " instanceof nsIURL");
   Assert.equal(URI instanceof Ci.nsIURL, aTest.nsIURL);
   do_info("testing " + aTest.spec + " instanceof nsINestedURI");
   Assert.equal(URI instanceof Ci.nsINestedURI,
                aTest.nsINestedURI);
 
   do_info("testing that " + aTest.spec + " throws or returns false " +
@@ -508,17 +508,17 @@ function do_test_uri_with_hash_suffix(aT
       return;
     }
   } else {
     testURI = NetUtil.newURI(aTest.spec + aSuffix);
   }
 
   do_info("testing " + aTest.spec + " with '" + aSuffix + "' appended " +
            "equals a clone of itself");
-  do_check_uri_eq(testURI, testURI.clone());
+  do_check_uri_eq(testURI, testURI.mutate().finalize());
 
   do_info("testing " + aTest.spec +
           " doesn't equal self with '" + aSuffix + "' appended");
 
   Assert.ok(!origURI.equals(testURI));
 
   do_info("testing " + aTest.spec +
           " is equalExceptRef to self with '" + aSuffix + "' appended");
--- a/netwerk/test/unit/test_bug396389.js
+++ b/netwerk/test/unit/test_bug396389.js
@@ -27,17 +27,17 @@ var prefData =
 
 function run_test() {
   var ios = Cc["@mozilla.org/network/io-service;1"].
     getService(Ci.nsIIOService);
 
   var uri1 = ios.newURI("file:///");
   Assert.ok(uri1 instanceof Ci.nsIFileURL);
 
-  var uri2 = uri1.clone();
+  var uri2 = uri1.mutate().finalize();
   Assert.ok(uri2 instanceof Ci.nsIFileURL);
   Assert.ok(uri1.equals(uri2));
 
   var uri3 = round_trip(uri1);
   Assert.ok(uri3 instanceof Ci.nsIFileURL);
   Assert.ok(uri1.equals(uri3));
 
   // Make sure our prefs are set such that this test actually means something
--- a/toolkit/components/places/nsFaviconService.cpp
+++ b/toolkit/components/places/nsFaviconService.cpp
@@ -259,17 +259,20 @@ nsFaviconService::GetDefaultFavicon(nsIU
   NS_ENSURE_ARG_POINTER(_retval);
 
   // not found, use default
   if (!mDefaultIcon) {
     nsresult rv = NS_NewURI(getter_AddRefs(mDefaultIcon),
                             NS_LITERAL_CSTRING(FAVICON_DEFAULT_URL));
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  return mDefaultIcon->Clone(_retval);
+
+  nsCOMPtr<nsIURI> uri = mDefaultIcon;
+  uri.forget(_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFaviconService::GetDefaultFaviconMimeType(nsACString& _retval)
 {
   _retval = NS_LITERAL_CSTRING(FAVICON_DEFAULT_MIMETYPE);
   return NS_OK;
 }
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -15,18 +15,18 @@ function RemoteWebProgressRequest(spec, 
   this._originalURI = Services.io.newURI(originalSpec);
   this._requestCPOW = requestCPOW;
   this._matchedList = matchedList;
 }
 
 RemoteWebProgressRequest.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIChannel, Ci.nsIClassifiedChannel]),
 
-  get URI() { return this._uri.clone(); },
-  get originalURI() { return this._originalURI.clone(); },
+  get URI() { return this._uri; },
+  get originalURI() { return this._originalURI; },
   get matchedList() { return this._matchedList; }
 };
 
 function RemoteWebProgress(aManager, aIsTopLevel) {
   this.wrappedJSObject = this;
 
   this._manager = aManager;
 
--- a/uriloader/prefetch/OfflineCacheUpdateParent.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateParent.cpp
@@ -136,19 +136,17 @@ OfflineCacheUpdateParent::Schedule(const
 
         rv = update->Schedule();
         NS_ENSURE_SUCCESS(rv, rv);
     } else {
         update->AddObserver(this, false);
     }
 
     if (stickDocument) {
-        nsCOMPtr<nsIURI> stickURI;
-        documentURI->Clone(getter_AddRefs(stickURI));
-        update->StickDocument(stickURI);
+        update->StickDocument(documentURI);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 OfflineCacheUpdateParent::UpdateStateChanged(nsIOfflineCacheUpdate* aUpdate, uint32_t state)
 {