Bug 1448330 - Make nsIURI.clone a private method r=mayhemer draft
authorValentin Gosu <valentin.gosu@gmail.com>
Thu, 14 Jun 2018 13:05:43 +0200
changeset 807321 e660f1e5bcae9b7119bc5b37713691069272b375
parent 806884 75a32b57132f8cba42779555662a057a0416a313
push id113087
push uservalentin.gosu@gmail.com
push dateThu, 14 Jun 2018 11:06:57 +0000
reviewersmayhemer
bugs1448330
milestone62.0a1
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
@@ -13534,42 +13534,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
@@ -130,25 +130,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
@@ -327,17 +327,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 " +
@@ -393,17 +393,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)
 {