Bug 1532324 - Remove manual NS_RELEASE from netwerk/* r=JuniorHsu
authorValentin Gosu <valentin.gosu@gmail.com>
Tue, 05 Mar 2019 18:43:02 +0000
changeset 520326 077c740cc12037cf93b673e8786c2ae96f03e4c0
parent 520325 b6e605718832c9bec3bb18933f3da8a286843efa
child 520327 5571dfe818985e3a66159c79a83d3547bbd3619e
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJuniorHsu
bugs1532324
milestone67.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 1532324 - Remove manual NS_RELEASE from netwerk/* r=JuniorHsu Differential Revision: https://phabricator.services.mozilla.com/D22005
netwerk/base/BackgroundFileSaver.cpp
netwerk/base/nsAsyncStreamCopier.cpp
netwerk/base/nsBufferedStreams.cpp
netwerk/base/nsBufferedStreams.h
netwerk/base/nsIOService.cpp
netwerk/base/nsIncrementalDownload.cpp
netwerk/base/nsIncrementalStreamLoader.cpp
netwerk/base/nsLoadGroup.cpp
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/base/nsStreamLoader.cpp
netwerk/build/nsNetModule.cpp
netwerk/cache/nsCacheEntryDescriptor.cpp
netwerk/cache/nsCacheEntryDescriptor.h
netwerk/cache/nsCacheService.cpp
netwerk/cache2/CacheObserver.cpp
netwerk/cache2/CacheObserver.h
netwerk/protocol/about/nsAboutBlank.cpp
netwerk/protocol/about/nsAboutCache.cpp
netwerk/protocol/data/nsDataHandler.cpp
netwerk/protocol/file/nsFileProtocolHandler.cpp
netwerk/protocol/ftp/nsFTPChannel.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.h
netwerk/protocol/viewsource/nsViewSourceHandler.cpp
--- a/netwerk/base/BackgroundFileSaver.cpp
+++ b/netwerk/base/BackgroundFileSaver.cpp
@@ -304,37 +304,36 @@ nsresult BackgroundFileSaver::GetWorkerT
   mWorkerThreadAttentionRequested = true;
 
   return NS_OK;
 }
 
 // Called on the worker thread.
 // static
 void BackgroundFileSaver::AsyncCopyCallback(void *aClosure, nsresult aStatus) {
-  BackgroundFileSaver *self = (BackgroundFileSaver *)aClosure;
+  // We called NS_ADDREF_THIS when NS_AsyncCopy started, to keep the object
+  // alive even if other references disappeared.  At the end of this method,
+  // we've finished using the object and can safely release our reference.
+  RefPtr<BackgroundFileSaver> self =
+      dont_AddRef((BackgroundFileSaver *)aClosure);
   {
     MutexAutoLock lock(self->mLock);
 
     // Now that the copy was interrupted or terminated, any notification from
     // the control thread requires an event to be posted to the worker thread.
     self->mAsyncCopyContext = nullptr;
 
     // When detecting failures, ignore the status code we use to interrupt.
     if (NS_FAILED(aStatus) && aStatus != NS_ERROR_ABORT &&
         NS_SUCCEEDED(self->mStatus)) {
       self->mStatus = aStatus;
     }
   }
 
   (void)self->ProcessAttention();
-
-  // We called NS_ADDREF_THIS when NS_AsyncCopy started, to keep the object
-  // alive even if other references disappeared.  At this point, we've finished
-  // using the object and can safely release our reference.
-  NS_RELEASE(self);
 }
 
 // Called on the worker thread.
 nsresult BackgroundFileSaver::ProcessAttention() {
   nsresult rv;
 
   // This function is called whenever the attention of the worker thread has
   // been requested.  This may happen in these cases:
--- a/netwerk/base/nsAsyncStreamCopier.cpp
+++ b/netwerk/base/nsAsyncStreamCopier.cpp
@@ -112,19 +112,20 @@ void nsAsyncStreamCopier::Complete(nsres
   if (observer) {
     LOG(("  calling OnStopRequest [status=%" PRIx32 "]\n",
          static_cast<uint32_t>(status)));
     observer->OnStopRequest(AsRequest(), status);
   }
 }
 
 void nsAsyncStreamCopier::OnAsyncCopyComplete(void *closure, nsresult status) {
-  nsAsyncStreamCopier *self = (nsAsyncStreamCopier *)closure;
+  // AddRef'd in AsyncCopy. Will be released at the end of the method.
+  RefPtr<nsAsyncStreamCopier> self =
+      dont_AddRef((nsAsyncStreamCopier *)closure);
   self->Complete(status);
-  NS_RELEASE(self);  // addref'd in AsyncCopy
 }
 
 //-----------------------------------------------------------------------------
 // nsISupports
 
 // We cannot use simply NS_IMPL_ISUPPORTSx as both
 // nsIAsyncStreamCopier and nsIAsyncStreamCopier2 implement nsIRequest
 
@@ -359,22 +360,24 @@ nsAsyncStreamCopier::AsyncCopy(nsIReques
 
 // Launch async copy.
 // All errors are reported through the observer.
 void nsAsyncStreamCopier::AsyncCopyInternal() {
   MOZ_ASSERT(mMode == NS_ASYNCCOPY_VIA_READSEGMENTS ||
              mMode == NS_ASYNCCOPY_VIA_WRITESEGMENTS);
 
   nsresult rv;
-  // we want to receive progress notifications; release happens in
+  // We want to receive progress notifications; release happens in
   // OnAsyncCopyComplete.
-  NS_ADDREF_THIS();
+  RefPtr<nsAsyncStreamCopier> self = this;
   {
     MutexAutoLock lock(mLock);
     rv = NS_AsyncCopy(mSource, mSink, mTarget, mMode, mChunkSize,
                       OnAsyncCopyComplete, this, mCloseSource, mCloseSink,
                       getter_AddRefs(mCopierCtx));
   }
   if (NS_FAILED(rv)) {
-    NS_RELEASE_THIS();
     Cancel(rv);
+    return;  // release self
   }
+
+  Unused << self.forget();  // Will be released in OnAsyncCopyComplete
 }
--- a/netwerk/base/nsBufferedStreams.cpp
+++ b/netwerk/base/nsBufferedStreams.cpp
@@ -55,33 +55,33 @@ nsBufferedStream::nsBufferedStream()
       mBufferDisabled(false),
       mEOF(false),
       mGetBufferCount(0) {}
 
 nsBufferedStream::~nsBufferedStream() { Close(); }
 
 NS_IMPL_ISUPPORTS(nsBufferedStream, nsITellableStream, nsISeekableStream)
 
-nsresult nsBufferedStream::Init(nsISupports* stream, uint32_t bufferSize) {
-  NS_ASSERTION(stream, "need to supply a stream");
+nsresult nsBufferedStream::Init(nsISupports* aStream, uint32_t bufferSize) {
+  NS_ASSERTION(aStream, "need to supply a stream");
   NS_ASSERTION(mStream == nullptr, "already inited");
-  mStream = stream;
-  NS_IF_ADDREF(mStream);
+  mStream = aStream;  // we keep a reference until nsBufferedStream::Close
   mBufferSize = bufferSize;
   mBufferStartOffset = 0;
   mCursor = 0;
   mBuffer = new (mozilla::fallible) char[bufferSize];
   if (mBuffer == nullptr) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 nsresult nsBufferedStream::Close() {
-  NS_IF_RELEASE(mStream);
+  // Drop the reference from nsBufferedStream::Init()
+  mStream = nullptr;
   if (mBuffer) {
     delete[] mBuffer;
     mBuffer = nullptr;
     mBufferSize = 0;
     mBufferStartOffset = 0;
     mCursor = 0;
     mFillPoint = 0;
   }
@@ -255,18 +255,18 @@ nsBufferedStream::SetEOF() {
   if (NS_SUCCEEDED(rv)) {
     mEOF = true;
   }
 
   return rv;
 }
 
 nsresult nsBufferedStream::GetData(nsISupports** aResult) {
-  nsCOMPtr<nsISupports> rv(mStream);
-  *aResult = rv.forget().take();
+  nsCOMPtr<nsISupports> stream(mStream);
+  stream.forget(aResult);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsBufferedInputStream
 
 NS_IMPL_ADDREF_INHERITED(nsBufferedInputStream, nsBufferedStream)
 NS_IMPL_RELEASE_INHERITED(nsBufferedInputStream, nsBufferedStream)
@@ -305,24 +305,18 @@ nsBufferedInputStream::nsBufferedInputSt
       mIsCloneableInputStream(false),
       mIsInputStreamLength(false),
       mIsAsyncInputStreamLength(false) {}
 
 nsresult nsBufferedInputStream::Create(nsISupports* aOuter, REFNSIID aIID,
                                        void** aResult) {
   NS_ENSURE_NO_AGGREGATION(aOuter);
 
-  nsBufferedInputStream* stream = new nsBufferedInputStream();
-  if (stream == nullptr) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  NS_ADDREF(stream);
-  nsresult rv = stream->QueryInterface(aIID, aResult);
-  NS_RELEASE(stream);
-  return rv;
+  RefPtr<nsBufferedInputStream> stream = new nsBufferedInputStream();
+  return stream->QueryInterface(aIID, aResult);
 }
 
 NS_IMETHODIMP
 nsBufferedInputStream::Init(nsIInputStream* stream, uint32_t bufferSize) {
   nsresult rv = nsBufferedStream::Init(stream, bufferSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   {
@@ -360,17 +354,16 @@ nsBufferedInputStream::Close() {
     rv1 = Source()->Close();
 #ifdef DEBUG
     if (NS_FAILED(rv1)) {
       NS_WARNING(
           "(debug) Error: Source()->Close() returned error (rv1) in "
           "bsBuffedInputStream::Close().");
     };
 #endif
-    NS_RELEASE(mStream);
   }
 
   rv2 = nsBufferedStream::Close();
 
 #ifdef DEBUG
   if (NS_FAILED(rv2)) {
     NS_WARNING(
         "(debug) Error: nsBufferedStream::Close() returned error (rv2) within "
@@ -579,18 +572,18 @@ nsBufferedInputStream::EnableBuffering()
 }
 
 NS_IMETHODIMP
 nsBufferedInputStream::GetUnbufferedStream(nsISupports** aStream) {
   // Empty the buffer so subsequent i/o trumps any buffered data.
   mBufferStartOffset += mCursor;
   mFillPoint = mCursor = 0;
 
-  *aStream = mStream;
-  NS_IF_ADDREF(*aStream);
+  nsCOMPtr<nsISupports> stream = mStream;
+  stream.forget(aStream);
   return NS_OK;
 }
 
 void nsBufferedInputStream::Serialize(InputStreamParams& aParams,
                                       FileDescriptorArray& aFileDescriptors,
                                       bool aDelayedStart, uint32_t aMaxSize,
                                       uint32_t* aSizeUsed,
                                       mozilla::dom::ContentChild* aManager) {
@@ -727,17 +720,17 @@ nsBufferedInputStream::OnInputStreamRead
   return callback->OnInputStreamReady(this);
 }
 
 NS_IMETHODIMP
 nsBufferedInputStream::GetData(nsIInputStream** aResult) {
   nsCOMPtr<nsISupports> stream;
   nsBufferedStream::GetData(getter_AddRefs(stream));
   nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(stream);
-  *aResult = inputStream.forget().take();
+  inputStream.forget(aResult);
   return NS_OK;
 }
 
 // nsICloneableInputStream interface
 
 NS_IMETHODIMP
 nsBufferedInputStream::GetCloneable(bool* aCloneable) {
   *aCloneable = false;
@@ -841,24 +834,18 @@ NS_INTERFACE_MAP_BEGIN(nsBufferedOutputS
   NS_INTERFACE_MAP_ENTRY(nsIBufferedOutputStream)
   NS_INTERFACE_MAP_ENTRY(nsIStreamBufferAccess)
 NS_INTERFACE_MAP_END_INHERITING(nsBufferedStream)
 
 nsresult nsBufferedOutputStream::Create(nsISupports* aOuter, REFNSIID aIID,
                                         void** aResult) {
   NS_ENSURE_NO_AGGREGATION(aOuter);
 
-  nsBufferedOutputStream* stream = new nsBufferedOutputStream();
-  if (stream == nullptr) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  NS_ADDREF(stream);
-  nsresult rv = stream->QueryInterface(aIID, aResult);
-  NS_RELEASE(stream);
-  return rv;
+  RefPtr<nsBufferedOutputStream> stream = new nsBufferedOutputStream();
+  return stream->QueryInterface(aIID, aResult);
 }
 
 NS_IMETHODIMP
 nsBufferedOutputStream::Init(nsIOutputStream* stream, uint32_t bufferSize) {
   // QI stream to an nsISafeOutputStream, to see if we should support it
   mSafeStream = do_QueryInterface(stream);
 
   return nsBufferedStream::Init(stream, bufferSize);
@@ -885,17 +872,16 @@ nsBufferedOutputStream::Close() {
     rv2 = Sink()->Close();
 #ifdef DEBUG
     if (NS_FAILED(rv2)) {
       NS_WARNING(
           "(debug) Sink->Close() inside nsBufferedOutputStream::Close() "
           "returned error (rv2).");
     }
 #endif
-    NS_RELEASE(mStream);
   }
   rv3 = nsBufferedStream::Close();
 
 #ifdef DEBUG
   if (NS_FAILED(rv3)) {
     NS_WARNING(
         "(debug) nsBufferedStream:Close() inside "
         "nsBufferedOutputStream::Close() returned error (rv3).");
@@ -1169,24 +1155,24 @@ nsBufferedOutputStream::GetUnbufferedStr
   // Empty the buffer so subsequent i/o trumps any buffered data.
   if (mFillPoint) {
     nsresult rv = Flush();
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
-  *aStream = mStream;
-  NS_IF_ADDREF(*aStream);
+  nsCOMPtr<nsISupports> stream = mStream;
+  stream.forget(aStream);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBufferedOutputStream::GetData(nsIOutputStream** aResult) {
   nsCOMPtr<nsISupports> stream;
   nsBufferedStream::GetData(getter_AddRefs(stream));
   nsCOMPtr<nsIOutputStream> outputStream = do_QueryInterface(stream);
-  *aResult = outputStream.forget().take();
+  outputStream.forget(aResult);
   return NS_OK;
 }
 #undef METER
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/netwerk/base/nsBufferedStreams.h
+++ b/netwerk/base/nsBufferedStreams.h
@@ -49,17 +49,17 @@ class nsBufferedStream : public nsISeeka
   // output streams, and is relative to mBufferStartOffset.
   uint32_t mCursor;
 
   // mFillPoint is the amount available in the buffer for input streams,
   // or the high watermark of bytes written into the buffer, and therefore
   // is relative to mBufferStartOffset.
   uint32_t mFillPoint;
 
-  nsISupports* mStream;  // cast to appropriate subclass
+  nsCOMPtr<nsISupports> mStream;  // cast to appropriate subclass
 
   bool mBufferDisabled;
   bool mEOF;  // True if mStream is at EOF
   uint8_t mGetBufferCount;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -85,17 +85,17 @@ class nsBufferedInputStream final : publ
   NS_DECL_NSIINPUTSTREAMLENGTH
   NS_DECL_NSIASYNCINPUTSTREAMLENGTH
   NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
 
   nsBufferedInputStream();
 
   static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
-  nsIInputStream* Source() { return (nsIInputStream*)mStream; }
+  nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); }
 
  protected:
   virtual ~nsBufferedInputStream() = default;
 
   template <typename M>
   void SerializeInternal(mozilla::ipc::InputStreamParams& aParams,
                          FileDescriptorArray& aFileDescriptors,
                          bool aDelayedStart, uint32_t aMaxSize,
@@ -131,17 +131,17 @@ class nsBufferedOutputStream : public ns
   NS_DECL_NSISAFEOUTPUTSTREAM
   NS_DECL_NSIBUFFEREDOUTPUTSTREAM
   NS_DECL_NSISTREAMBUFFERACCESS
 
   nsBufferedOutputStream() : nsBufferedStream() {}
 
   static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
-  nsIOutputStream* Sink() { return (nsIOutputStream*)mStream; }
+  nsIOutputStream* Sink() { return (nsIOutputStream*)mStream.get(); }
 
  protected:
   virtual ~nsBufferedOutputStream() { nsBufferedOutputStream::Close(); }
 
   NS_IMETHOD Fill() override { return NS_OK; }  // no-op for output streams
 
   nsCOMPtr<nsISafeOutputStream> mSafeStream;  // QI'd from mStream
 };
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -710,20 +710,19 @@ nsIOService::GetProtocolHandler(const ch
     // protocol handler.
 
     rv =
         CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-gio", result);
     if (NS_SUCCEEDED(rv)) {
       nsAutoCString spec(scheme);
       spec.Append(':');
 
-      nsIURI *uri;
-      rv = (*result)->NewURI(spec, nullptr, nullptr, &uri);
+      nsCOMPtr<nsIURI> uri;
+      rv = (*result)->NewURI(spec, nullptr, nullptr, getter_AddRefs(uri));
       if (NS_SUCCEEDED(rv)) {
-        NS_RELEASE(uri);
         return rv;
       }
 
       NS_RELEASE(*result);
     }
 #endif
   }
 
--- a/netwerk/base/nsIncrementalDownload.cpp
+++ b/netwerk/base/nsIncrementalDownload.cpp
@@ -396,23 +396,25 @@ nsIncrementalDownload::Init(nsIURI *uri,
 
   if (chunkSize > 0) mChunkSize = chunkSize;
   if (interval >= 0) mInterval = interval;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIncrementalDownload::GetURI(nsIURI **result) {
-  NS_IF_ADDREF(*result = mURI);
+  nsCOMPtr<nsIURI> uri = mURI;
+  uri.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIncrementalDownload::GetFinalURI(nsIURI **result) {
-  NS_IF_ADDREF(*result = mFinalURI);
+  nsCOMPtr<nsIURI> uri = mFinalURI;
+  uri.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIncrementalDownload::GetDestination(nsIFile **result) {
   if (!mDest) {
     *result = nullptr;
     return NS_OK;
@@ -821,16 +823,11 @@ nsIncrementalDownload::OnRedirectVerifyC
   mNewRedirectChannel = nullptr;
   return NS_OK;
 }
 
 extern nsresult net_NewIncrementalDownload(nsISupports *outer, const nsIID &iid,
                                            void **result) {
   if (outer) return NS_ERROR_NO_AGGREGATION;
 
-  nsIncrementalDownload *d = new nsIncrementalDownload();
-  if (!d) return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(d);
-  nsresult rv = d->QueryInterface(iid, result);
-  NS_RELEASE(d);
-  return rv;
+  RefPtr<nsIncrementalDownload> d = new nsIncrementalDownload();
+  return d->QueryInterface(iid, result);
 }
--- a/netwerk/base/nsIncrementalStreamLoader.cpp
+++ b/netwerk/base/nsIncrementalStreamLoader.cpp
@@ -20,22 +20,18 @@ nsIncrementalStreamLoader::Init(nsIIncre
   mObserver = observer;
   return NS_OK;
 }
 
 nsresult nsIncrementalStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID,
                                            void **aResult) {
   if (aOuter) return NS_ERROR_NO_AGGREGATION;
 
-  nsIncrementalStreamLoader *it = new nsIncrementalStreamLoader();
-  if (it == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(it);
-  nsresult rv = it->QueryInterface(aIID, aResult);
-  NS_RELEASE(it);
-  return rv;
+  RefPtr<nsIncrementalStreamLoader> it = new nsIncrementalStreamLoader();
+  return it->QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ISUPPORTS(nsIncrementalStreamLoader, nsIIncrementalStreamLoader,
                   nsIRequestObserver, nsIStreamListener,
                   nsIThreadRetargetableStreamListener)
 
 NS_IMETHODIMP
 nsIncrementalStreamLoader::GetNumBytesRead(uint32_t *aNumBytes) {
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -191,48 +191,45 @@ nsLoadGroup::Cancel(nsresult status) {
   // Set the flag indicating that the loadgroup is being canceled...  This
   // prevents any new channels from being added during the operation.
   //
   mIsCanceling = true;
 
   nsresult firstError = NS_OK;
 
   while (count > 0) {
-    nsIRequest *request = requests.ElementAt(--count);
+    nsCOMPtr<nsIRequest> request = dont_AddRef(requests.ElementAt(--count));
 
     NS_ASSERTION(request, "NULL request found in list.");
 
     if (!mRequests.Search(request)) {
       // |request| was removed already
-      NS_RELEASE(request);
       continue;
     }
 
     if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
       nsAutoCString nameStr;
       request->GetName(nameStr);
-      LOG(("LOADGROUP [%p]: Canceling request %p %s.\n", this, request,
+      LOG(("LOADGROUP [%p]: Canceling request %p %s.\n", this, request.get(),
            nameStr.get()));
     }
 
     //
     // Remove the request from the load group...  This may cause
     // the OnStopRequest notification to fire...
     //
     // XXX: What should the context be?
     //
     (void)RemoveRequest(request, nullptr, status);
 
     // Cancel the request...
     rv = request->Cancel(status);
 
     // Remember the first failure and return it...
     if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) firstError = rv;
-
-    NS_RELEASE(request);
   }
 
   if (mRequestContext) {
     Unused << mRequestContext->CancelTailPendingRequests(status);
   }
 
 #if defined(DEBUG)
   NS_ASSERTION(mRequests.EntryCount() == 0, "Request list is not empty.");
@@ -257,35 +254,33 @@ nsLoadGroup::Suspend() {
   }
 
   firstError = NS_OK;
   //
   // Operate the elements from back to front so that if items get
   // get removed from the list it won't affect our iteration
   //
   while (count > 0) {
-    nsIRequest *request = requests.ElementAt(--count);
+    nsCOMPtr<nsIRequest> request = dont_AddRef(requests.ElementAt(--count));
 
     NS_ASSERTION(request, "NULL request found in list.");
     if (!request) continue;
 
     if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
       nsAutoCString nameStr;
       request->GetName(nameStr);
-      LOG(("LOADGROUP [%p]: Suspending request %p %s.\n", this, request,
+      LOG(("LOADGROUP [%p]: Suspending request %p %s.\n", this, request.get(),
            nameStr.get()));
     }
 
     // Suspend the request...
     rv = request->Suspend();
 
     // Remember the first failure and return it...
     if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) firstError = rv;
-
-    NS_RELEASE(request);
   }
 
   return firstError;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::Resume() {
   nsresult rv, firstError;
@@ -298,35 +293,33 @@ nsLoadGroup::Resume() {
   }
 
   firstError = NS_OK;
   //
   // Operate the elements from back to front so that if items get
   // get removed from the list it won't affect our iteration
   //
   while (count > 0) {
-    nsIRequest *request = requests.ElementAt(--count);
+    nsCOMPtr<nsIRequest> request = dont_AddRef(requests.ElementAt(--count));
 
     NS_ASSERTION(request, "NULL request found in list.");
     if (!request) continue;
 
     if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
       nsAutoCString nameStr;
       request->GetName(nameStr);
-      LOG(("LOADGROUP [%p]: Resuming request %p %s.\n", this, request,
+      LOG(("LOADGROUP [%p]: Resuming request %p %s.\n", this, request.get(),
            nameStr.get()));
     }
 
     // Resume the request...
     rv = request->Resume();
 
     // Remember the first failure and return it...
     if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) firstError = rv;
-
-    NS_RELEASE(request);
   }
 
   return firstError;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::GetLoadFlags(uint32_t *aLoadFlags) {
   *aLoadFlags = mLoadFlags;
@@ -336,34 +329,34 @@ nsLoadGroup::GetLoadFlags(uint32_t *aLoa
 NS_IMETHODIMP
 nsLoadGroup::SetLoadFlags(uint32_t aLoadFlags) {
   mLoadFlags = aLoadFlags;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::GetLoadGroup(nsILoadGroup **loadGroup) {
-  *loadGroup = mLoadGroup;
-  NS_IF_ADDREF(*loadGroup);
+  nsCOMPtr<nsILoadGroup> result = mLoadGroup;
+  result.forget(loadGroup);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::SetLoadGroup(nsILoadGroup *loadGroup) {
   mLoadGroup = loadGroup;
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsILoadGroup methods:
 
 NS_IMETHODIMP
 nsLoadGroup::GetDefaultLoadRequest(nsIRequest **aRequest) {
-  *aRequest = mDefaultLoadRequest;
-  NS_IF_ADDREF(*aRequest);
+  nsCOMPtr<nsIRequest> result = mDefaultLoadRequest;
+  result.forget(aRequest);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest) {
   LOG(("nsLoadGroup::SetDefaultLoadRequest this=%p default-request=%p", this,
        aRequest));
 
@@ -606,32 +599,31 @@ NS_IMETHODIMP
 nsLoadGroup::SetGroupObserver(nsIRequestObserver *aObserver) {
   mObserver = do_GetWeakReference(aObserver);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::GetGroupObserver(nsIRequestObserver **aResult) {
   nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
-  *aResult = observer;
-  NS_IF_ADDREF(*aResult);
+  observer.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::GetActiveCount(uint32_t *aResult) {
   *aResult = mForegroundCount;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks) {
   NS_ENSURE_ARG_POINTER(aCallbacks);
-  *aCallbacks = mCallbacks;
-  NS_IF_ADDREF(*aCallbacks);
+  nsCOMPtr<nsIInterfaceRequestor> callbacks = mCallbacks;
+  callbacks.forget(aCallbacks);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks) {
   mCallbacks = aCallbacks;
   return NS_OK;
 }
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -44,17 +44,17 @@ using namespace mozilla::ipc;
 namespace mozilla {
 namespace net {
 
 static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID);
 static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
 
 // This will always be initialized and destroyed on the main thread, but
 // can be safely used on other threads.
-nsIIDNService *nsStandardURL::gIDN = nullptr;
+StaticRefPtr<nsIIDNService> nsStandardURL::gIDN;
 
 // This value will only be updated on the main thread once. Worker threads
 // may race when reading this values, but that's OK because in the worst
 // case we will just dispatch a noop runnable to the main thread.
 bool nsStandardURL::gInitialized = false;
 
 const char nsStandardURL::gHostLimitDigits[] = {'/', '\\', '?', '#', 0};
 bool nsStandardURL::gPunycodeHost = true;
@@ -263,29 +263,29 @@ void nsStandardURL::InitGlobalObjects() 
   }
 
   gInitialized = true;
 
   Preferences::AddBoolVarCache(&gPunycodeHost,
                                "network.standard-url.punycode-host", true);
   nsCOMPtr<nsIIDNService> serv(do_GetService(NS_IDNSERVICE_CONTRACTID));
   if (serv) {
-    NS_ADDREF(gIDN = serv.get());
+    gIDN = serv;
   }
   MOZ_DIAGNOSTIC_ASSERT(gIDN);
 
   // Make sure nsURLHelper::InitGlobals() gets called on the main thread
   nsCOMPtr<nsIURLParser> parser = net_GetStdURLParser();
   MOZ_DIAGNOSTIC_ASSERT(parser);
   Unused << parser;
 }
 
 void nsStandardURL::ShutdownGlobalObjects() {
   MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
-  NS_IF_RELEASE(gIDN);
+  gIDN = nullptr;
 
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
   if (gInitialized) {
     // This instanciates a dummy class, and will trigger the class
     // destructor when libxul is unloaded. This is equivalent to atexit(),
     // but gracefully handles dlclose().
     StaticMutexAutoLock lock(gAllURLsMutex);
     static DumpLeakedURLs d;
@@ -2460,26 +2460,25 @@ nsStandardURL::GetCommonBaseSpec(nsIURI 
   // if uri's are equal, then return uri as is
   bool isEquals = false;
   if (NS_SUCCEEDED(Equals(uri2, &isEquals)) && isEquals)
     return GetSpec(aResult);
 
   aResult.Truncate();
 
   // check pre-path; if they don't match, then return empty string
-  nsStandardURL *stdurl2;
-  nsresult rv = uri2->QueryInterface(kThisImplCID, (void **)&stdurl2);
+  RefPtr<nsStandardURL> stdurl2;
+  nsresult rv = uri2->QueryInterface(kThisImplCID, getter_AddRefs(stdurl2));
   isEquals = NS_SUCCEEDED(rv) &&
              SegmentIs(mScheme, stdurl2->mSpec.get(), stdurl2->mScheme) &&
              SegmentIs(mHost, stdurl2->mSpec.get(), stdurl2->mHost) &&
              SegmentIs(mUsername, stdurl2->mSpec.get(), stdurl2->mUsername) &&
              SegmentIs(mPassword, stdurl2->mSpec.get(), stdurl2->mPassword) &&
              (Port() == stdurl2->Port());
   if (!isEquals) {
-    if (NS_SUCCEEDED(rv)) NS_RELEASE(stdurl2);
     return NS_OK;
   }
 
   // scan for first mismatched character
   const char *thisIndex, *thatIndex, *startCharPos;
   startCharPos = mSpec.get() + mDirectory.mPos;
   thisIndex = startCharPos;
   thatIndex = stdurl2->mSpec.get() + mDirectory.mPos;
@@ -2491,41 +2490,38 @@ nsStandardURL::GetCommonBaseSpec(nsIURI 
   // backup to just after previous slash so we grab an appropriate path
   // segment such as a directory (not partial segments)
   // todo:  also check for file matches which include '?' and '#'
   while ((thisIndex != startCharPos) && (*(thisIndex - 1) != '/')) thisIndex--;
 
   // grab spec from beginning to thisIndex
   aResult = Substring(mSpec, mScheme.mPos, thisIndex - mSpec.get());
 
-  NS_RELEASE(stdurl2);
   return rv;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetRelativeSpec(nsIURI *uri2, nsACString &aResult) {
   NS_ENSURE_ARG_POINTER(uri2);
 
   aResult.Truncate();
 
   // if uri's are equal, then return empty string
   bool isEquals = false;
   if (NS_SUCCEEDED(Equals(uri2, &isEquals)) && isEquals) return NS_OK;
 
-  nsStandardURL *stdurl2;
-  nsresult rv = uri2->QueryInterface(kThisImplCID, (void **)&stdurl2);
+  RefPtr<nsStandardURL> stdurl2;
+  nsresult rv = uri2->QueryInterface(kThisImplCID, getter_AddRefs(stdurl2));
   isEquals = NS_SUCCEEDED(rv) &&
              SegmentIs(mScheme, stdurl2->mSpec.get(), stdurl2->mScheme) &&
              SegmentIs(mHost, stdurl2->mSpec.get(), stdurl2->mHost) &&
              SegmentIs(mUsername, stdurl2->mSpec.get(), stdurl2->mUsername) &&
              SegmentIs(mPassword, stdurl2->mSpec.get(), stdurl2->mPassword) &&
              (Port() == stdurl2->Port());
   if (!isEquals) {
-    if (NS_SUCCEEDED(rv)) NS_RELEASE(stdurl2);
-
     return uri2->GetSpec(aResult);
   }
 
   // scan for first mismatched character
   const char *thisIndex, *thatIndex, *startCharPos;
   startCharPos = mSpec.get() + mDirectory.mPos;
   thisIndex = startCharPos;
   thatIndex = stdurl2->mSpec.get() + mDirectory.mPos;
@@ -2543,17 +2539,16 @@ nsStandardURL::GetRelativeSpec(nsIURI *u
     // look for end of first segment
     while ((*thisIndex == *thatIndex) && *thisIndex && (*thisIndex != '/')) {
       thisIndex++;
       thatIndex++;
     }
 
     // if we didn't match through the first segment, return absolute path
     if ((*thisIndex != '/') || (*thatIndex != '/')) {
-      NS_RELEASE(stdurl2);
       return uri2->GetSpec(aResult);
     }
   }
 #endif
 
   while ((*thisIndex == *thatIndex) && *thisIndex) {
     thisIndex++;
     thatIndex++;
@@ -2571,17 +2566,16 @@ nsStandardURL::GetRelativeSpec(nsIURI *u
     if (*thisIndex == '/') aResult.AppendLiteral("../");
   }
 
   // grab spec from thisIndex to end
   uint32_t startPos = stdurl2->mScheme.mPos + thatIndex - stdurl2->mSpec.get();
   aResult.Append(
       Substring(stdurl2->mSpec, startPos, stdurl2->mSpec.Length() - startPos));
 
-  NS_RELEASE(stdurl2);
   return rv;
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL::nsIURL
 //----------------------------------------------------------------------------
 
 // result may contain unescaped UTF-8 characters
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -293,19 +293,18 @@ class nsStandardURL : public nsIFileURL,
   enum { eEncoding_Unknown, eEncoding_ASCII, eEncoding_UTF8 };
 
   uint32_t mURLType : 2;          // nsIStandardURL::URLTYPE_xxx
   uint32_t mSupportsFileURL : 1;  // QI to nsIFileURL?
   uint32_t mCheckedIfHostA : 1;   // If set to true, it means either that
                                   // mDisplayHost has a been initialized, or
                                   // that the hostname is not punycode
 
-  // global objects.  don't use COMPtr as its destructor will cause a
-  // coredump if we leak it.
-  static nsIIDNService *gIDN;
+  // global objects.
+  static StaticRefPtr<nsIIDNService> gIDN;
   static const char gHostLimitDigits[];
   static bool gInitialized;
   static bool gPunycodeHost;
 
  public:
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
   void PrintSpec() const { printf("  %s\n", mSpec.get()); }
 #endif
--- a/netwerk/base/nsStreamLoader.cpp
+++ b/netwerk/base/nsStreamLoader.cpp
@@ -24,36 +24,33 @@ nsStreamLoader::Init(nsIStreamLoaderObse
   mRequestObserver = aRequestObserver;
   return NS_OK;
 }
 
 nsresult nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) {
   if (aOuter) return NS_ERROR_NO_AGGREGATION;
 
-  nsStreamLoader *it = new nsStreamLoader();
-  if (it == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(it);
-  nsresult rv = it->QueryInterface(aIID, aResult);
-  NS_RELEASE(it);
-  return rv;
+  RefPtr<nsStreamLoader> it = new nsStreamLoader();
+  return it->QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader, nsIRequestObserver,
                   nsIStreamListener, nsIThreadRetargetableStreamListener)
 
 NS_IMETHODIMP
 nsStreamLoader::GetNumBytesRead(uint32_t *aNumBytes) {
   *aNumBytes = mData.length();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStreamLoader::GetRequest(nsIRequest **aRequest) {
-  NS_IF_ADDREF(*aRequest = mRequest);
+  nsCOMPtr<nsIRequest> req = mRequest;
+  req.forget(aRequest);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStreamLoader::OnStartRequest(nsIRequest *request) {
   nsCOMPtr<nsIChannel> chan(do_QueryInterface(request));
   if (chan) {
     int64_t contentLength = -1;
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -98,28 +98,25 @@ static BaseWebSocketChannel* WebSocketCh
   return new WebSocketChannel;
 }
 
 #define WEB_SOCKET_HANDLER_CONSTRUCTOR(type, secure)             \
   nsresult type##Constructor(nsISupports* aOuter, REFNSIID aIID, \
                              void** aResult) {                   \
     nsresult rv;                                                 \
                                                                  \
-    BaseWebSocketChannel* inst;                                  \
+    RefPtr<BaseWebSocketChannel> inst;                           \
                                                                  \
     *aResult = nullptr;                                          \
     if (nullptr != aOuter) {                                     \
       rv = NS_ERROR_NO_AGGREGATION;                              \
       return rv;                                                 \
     }                                                            \
     inst = WebSocketChannelConstructor(secure);                  \
-    NS_ADDREF(inst);                                             \
-    rv = inst->QueryInterface(aIID, aResult);                    \
-    NS_RELEASE(inst);                                            \
-    return rv;                                                   \
+    return inst->QueryInterface(aIID, aResult);                  \
   }
 
 WEB_SOCKET_HANDLER_CONSTRUCTOR(WebSocketChannel, false)
 WEB_SOCKET_HANDLER_CONSTRUCTOR(WebSocketSSLChannel, true)
 #undef WEB_SOCKET_HANDLER_CONSTRUCTOR
 }  // namespace net
 }  // namespace mozilla
 
@@ -176,170 +173,145 @@ nsresult CreateNewStreamConvServiceFacto
                                            void** aResult) {
   if (!aResult) {
     return NS_ERROR_INVALID_POINTER;
   }
   if (aOuter) {
     *aResult = nullptr;
     return NS_ERROR_NO_AGGREGATION;
   }
-  nsStreamConverterService* inst = nullptr;
-  nsresult rv = NS_NewStreamConv(&inst);
+  RefPtr<nsStreamConverterService> inst;
+  nsresult rv = NS_NewStreamConv(getter_AddRefs(inst));
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
     return rv;
   }
   rv = inst->QueryInterface(aIID, aResult);
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
   }
-  NS_RELEASE(inst); /* get rid of extra refcnt */
   return rv;
 }
 
 nsresult CreateNewFTPDirListingConv(nsISupports* aOuter, REFNSIID aIID,
                                     void** aResult) {
   if (!aResult) {
     return NS_ERROR_INVALID_POINTER;
   }
   if (aOuter) {
     *aResult = nullptr;
     return NS_ERROR_NO_AGGREGATION;
   }
-  nsFTPDirListingConv* inst = nullptr;
-  nsresult rv = NS_NewFTPDirListingConv(&inst);
+  RefPtr<nsFTPDirListingConv> inst;
+  nsresult rv = NS_NewFTPDirListingConv(getter_AddRefs(inst));
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
     return rv;
   }
   rv = inst->QueryInterface(aIID, aResult);
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
   }
-  NS_RELEASE(inst); /* get rid of extra refcnt */
   return rv;
 }
 
 nsresult CreateNewMultiMixedConvFactory(nsISupports* aOuter, REFNSIID aIID,
                                         void** aResult) {
   if (!aResult) {
     return NS_ERROR_INVALID_POINTER;
   }
   if (aOuter) {
     *aResult = nullptr;
     return NS_ERROR_NO_AGGREGATION;
   }
-  nsMultiMixedConv* inst = nullptr;
-  nsresult rv = NS_NewMultiMixedConv(&inst);
+  RefPtr<nsMultiMixedConv> inst;
+  nsresult rv = NS_NewMultiMixedConv(getter_AddRefs(inst));
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
     return rv;
   }
   rv = inst->QueryInterface(aIID, aResult);
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
   }
-  NS_RELEASE(inst); /* get rid of extra refcnt */
   return rv;
 }
 
 nsresult CreateNewTXTToHTMLConvFactory(nsISupports* aOuter, REFNSIID aIID,
                                        void** aResult) {
   if (!aResult) {
     return NS_ERROR_INVALID_POINTER;
   }
   if (aOuter) {
     *aResult = nullptr;
     return NS_ERROR_NO_AGGREGATION;
   }
-  mozTXTToHTMLConv* inst = nullptr;
-  nsresult rv = MOZ_NewTXTToHTMLConv(&inst);
+  RefPtr<mozTXTToHTMLConv> inst;
+  nsresult rv = MOZ_NewTXTToHTMLConv(getter_AddRefs(inst));
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
     return rv;
   }
   rv = inst->QueryInterface(aIID, aResult);
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
   }
-  NS_RELEASE(inst); /* get rid of extra refcnt */
   return rv;
 }
 
 nsresult CreateNewHTTPCompressConvFactory(nsISupports* aOuter, REFNSIID aIID,
                                           void** aResult) {
   if (!aResult) {
     return NS_ERROR_INVALID_POINTER;
   }
   if (aOuter) {
     *aResult = nullptr;
     return NS_ERROR_NO_AGGREGATION;
   }
-  mozilla::net::nsHTTPCompressConv* inst = nullptr;
-  nsresult rv = NS_NewHTTPCompressConv(&inst);
+  RefPtr<mozilla::net::nsHTTPCompressConv> inst;
+  nsresult rv = NS_NewHTTPCompressConv(getter_AddRefs(inst));
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
     return rv;
   }
   rv = inst->QueryInterface(aIID, aResult);
   if (NS_FAILED(rv)) {
     *aResult = nullptr;
   }
-  NS_RELEASE(inst); /* get rid of extra refcnt */
   return rv;
 }
 
 nsresult CreateNewUnknownDecoderFactory(nsISupports* aOuter, REFNSIID aIID,
                                         void** aResult) {
-  nsresult rv;
-
   if (!aResult) {
     return NS_ERROR_NULL_POINTER;
   }
   *aResult = nullptr;
 
   if (aOuter) {
     return NS_ERROR_NO_AGGREGATION;
   }
 
-  nsUnknownDecoder* inst;
-
-  inst = new nsUnknownDecoder();
-  if (!inst) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  NS_ADDREF(inst);
-  rv = inst->QueryInterface(aIID, aResult);
-  NS_RELEASE(inst);
-
-  return rv;
+  RefPtr<nsUnknownDecoder> inst = new nsUnknownDecoder();
+  return inst->QueryInterface(aIID, aResult);
 }
 
 nsresult CreateNewBinaryDetectorFactory(nsISupports* aOuter, REFNSIID aIID,
                                         void** aResult) {
-  nsresult rv;
-
   if (!aResult) {
     return NS_ERROR_NULL_POINTER;
   }
   *aResult = nullptr;
 
   if (aOuter) {
     return NS_ERROR_NO_AGGREGATION;
   }
 
-  auto* inst = new nsBinaryDetector();
-  if (!inst) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  NS_ADDREF(inst);
-  rv = inst->QueryInterface(aIID, aResult);
-  NS_RELEASE(inst);
-
-  return rv;
+  RefPtr<nsBinaryDetector> inst = new nsBinaryDetector();
+  return inst->QueryInterface(aIID, aResult);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Module implementation for the net library
 
 // Net module startup hook
 nsresult nsNetStartup() {
   mozilla::net::nsStandardURL::InitGlobalObjects();
--- a/netwerk/cache/nsCacheEntryDescriptor.cpp
+++ b/netwerk/cache/nsCacheEntryDescriptor.cpp
@@ -76,33 +76,31 @@ nsCacheEntryDescriptor::nsCacheEntryDesc
     : mCacheEntry(entry),
       mAccessGranted(accessGranted),
       mOutputWrapper(nullptr),
       mLock("nsCacheEntryDescriptor.mLock"),
       mAsyncDoomPending(false),
       mDoomedOnClose(false),
       mClosingDescriptor(false) {
   PR_INIT_CLIST(this);
-  NS_ADDREF(nsCacheService::GlobalInstance());  // ensure it lives for the
-                                                // lifetime of the descriptor
+  // We need to make sure the cache service lives for the entire lifetime
+  // of the descriptor
+  mCacheService = nsCacheService::GlobalInstance();
 }
 
 nsCacheEntryDescriptor::~nsCacheEntryDescriptor() {
   // No need to close if the cache entry has already been severed.  This
   // helps avoid a shutdown assertion (bug 285519) that is caused when
   // consumers end up holding onto these objects past xpcom-shutdown.  It's
   // okay for them to do that because the cache service calls our Close
   // method during xpcom-shutdown, so we don't need to complain about it.
   if (mCacheEntry) Close();
 
   NS_ASSERTION(mInputWrappers.IsEmpty(), "We have still some input wrapper!");
   NS_ASSERTION(!mOutputWrapper, "We have still an output wrapper!");
-
-  nsCacheService *service = nsCacheService::GlobalInstance();
-  NS_RELEASE(service);
 }
 
 NS_IMETHODIMP
 nsCacheEntryDescriptor::GetClientID(nsACString &aClientID) {
   nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHEENTRYDESCRIPTOR_GETCLIENTID));
   if (!mCacheEntry) {
     aClientID.Truncate();
     return NS_ERROR_NOT_AVAILABLE;
@@ -280,17 +278,17 @@ nsCacheEntryDescriptor::SetDataSize(uint
   return rv;
 }
 
 NS_IMETHODIMP
 nsCacheEntryDescriptor::OpenInputStream(uint32_t offset,
                                         nsIInputStream **result) {
   NS_ENSURE_ARG_POINTER(result);
 
-  nsInputStreamWrapper *cacheInput = nullptr;
+  RefPtr<nsInputStreamWrapper> cacheInput;
   {
     nsCacheServiceAutoLock lock(
         LOCK_TELEM(NSCACHEENTRYDESCRIPTOR_OPENINPUTSTREAM));
     if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
     if (!mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
 
     // Don't open any new stream when closing descriptor or clearing entries
     if (mClosingDescriptor || nsCacheService::GetClearingEntries())
@@ -307,26 +305,26 @@ nsCacheEntryDescriptor::OpenInputStream(
     } else {
       cacheInput = new nsInputStreamWrapper(this, offset);
     }
     if (!cacheInput) return NS_ERROR_OUT_OF_MEMORY;
 
     mInputWrappers.AppendElement(cacheInput);
   }
 
-  NS_ADDREF(*result = cacheInput);
+  cacheInput.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCacheEntryDescriptor::OpenOutputStream(uint32_t offset,
                                          nsIOutputStream **result) {
   NS_ENSURE_ARG_POINTER(result);
 
-  nsOutputStreamWrapper *cacheOutput = nullptr;
+  RefPtr<nsOutputStreamWrapper> cacheOutput;
   {
     nsCacheServiceAutoLock lock(
         LOCK_TELEM(NSCACHEENTRYDESCRIPTOR_OPENOUTPUTSTREAM));
     if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
     if (!mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
 
     // Don't open any new stream when closing descriptor or clearing entries
     if (mClosingDescriptor || nsCacheService::GetClearingEntries())
@@ -348,17 +346,17 @@ nsCacheEntryDescriptor::OpenOutputStream
       }
       cacheOutput = new nsOutputStreamWrapper(this, offset);
     }
     if (!cacheOutput) return NS_ERROR_OUT_OF_MEMORY;
 
     mOutputWrapper = cacheOutput;
   }
 
-  NS_ADDREF(*result = cacheOutput);
+  cacheOutput.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCacheEntryDescriptor::GetCacheElement(nsISupports **result) {
   NS_ENSURE_ARG_POINTER(result);
   nsCacheServiceAutoLock lock(
       LOCK_TELEM(NSCACHEENTRYDESCRIPTOR_GETCACHEELEMENT));
--- a/netwerk/cache/nsCacheEntryDescriptor.h
+++ b/netwerk/cache/nsCacheEntryDescriptor.h
@@ -200,16 +200,18 @@ class nsCacheEntryDescriptor final : pub
     nsresult InitZstream();
     nsresult WriteBuffer();
   };
 
  private:
   /**
    * nsCacheEntryDescriptor data members
    */
+
+  nsCOMPtr<nsICacheServiceInternal> mCacheService;
   nsCacheEntry* mCacheEntry;  // we are a child of the entry
   nsCacheAccessMode mAccessGranted;
   nsTArray<nsInputStreamWrapper*> mInputWrappers;
   nsOutputStreamWrapper* mOutputWrapper;
   mozilla::Mutex mLock;
   bool mAsyncDoomPending;
   bool mDoomedOnClose;
   bool mClosingDescriptor;
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
@@ -637,25 +637,21 @@ void nsCacheService::Shutdown() {
 }
 
 nsresult nsCacheService::Create(nsISupports *aOuter, const nsIID &aIID,
                                 void **aResult) {
   nsresult rv;
 
   if (aOuter != nullptr) return NS_ERROR_NO_AGGREGATION;
 
-  nsCacheService *cacheService = new nsCacheService();
-  if (cacheService == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(cacheService);
+  RefPtr<nsCacheService> cacheService = new nsCacheService();
   rv = cacheService->Init();
   if (NS_SUCCEEDED(rv)) {
     rv = cacheService->QueryInterface(aIID, aResult);
   }
-  NS_RELEASE(cacheService);
   return rv;
 }
 
 NS_IMETHODIMP
 nsCacheService::CreateSession(const char *clientID,
                               nsCacheStoragePolicy storagePolicy,
                               bool streamBased, nsICacheSession **result) {
   *result = nullptr;
@@ -915,33 +911,32 @@ nsresult nsCacheService::CreateCustomOff
   if (MOZ_LOG_TEST(gCacheLog, LogLevel::Info)) {
     CACHE_LOG_INFO(("Creating custom offline device, %s, %d",
                     aProfileDir->HumanReadablePath().get(), aQuota));
   }
 
   if (!mInitialized) return NS_ERROR_NOT_AVAILABLE;
   if (!mEnableOfflineDevice) return NS_ERROR_NOT_AVAILABLE;
 
-  *aDevice = new nsOfflineCacheDevice;
-
-  NS_ADDREF(*aDevice);
+  RefPtr<nsOfflineCacheDevice> device = new nsOfflineCacheDevice();
 
   // set the preferences
-  (*aDevice)->SetCacheParentDirectory(aProfileDir);
-  (*aDevice)->SetCapacity(aQuota);
+  device->SetCacheParentDirectory(aProfileDir);
+  device->SetCapacity(aQuota);
 
-  nsresult rv = (*aDevice)->InitWithSqlite(mStorageService);
+  nsresult rv = device->InitWithSqlite(mStorageService);
   if (NS_FAILED(rv)) {
     CACHE_LOG_DEBUG(("OfflineDevice->InitWithSqlite() failed (0x%.8" PRIx32
                      ")\n",
                      static_cast<uint32_t>(rv)));
     CACHE_LOG_DEBUG(("    - disabling offline cache for this session.\n"));
+    device = nullptr;
+  }
 
-    NS_RELEASE(*aDevice);
-  }
+  device.forget(aDevice);
   return rv;
 }
 
 nsresult nsCacheService::RemoveCustomOfflineDevice(
     nsOfflineCacheDevice *aDevice) {
   nsCOMPtr<nsIFile> profileDir = aDevice->BaseDirectory();
   if (!profileDir) return NS_ERROR_UNEXPECTED;
 
--- a/netwerk/cache2/CacheObserver.cpp
+++ b/netwerk/cache2/CacheObserver.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/net/NeckoCommon.h"
 #include "prsystem.h"
 #include <time.h>
 #include <math.h>
 
 namespace mozilla {
 namespace net {
 
-CacheObserver* CacheObserver::sSelf = nullptr;
+StaticRefPtr<CacheObserver> CacheObserver::sSelf;
 
 static float const kDefaultHalfLifeHours = 24.0F;  // 24 hours
 float CacheObserver::sHalfLifeHours = kDefaultHalfLifeHours;
 
 static bool const kDefaultUseDiskCache = true;
 bool CacheObserver::sUseDiskCache = kDefaultUseDiskCache;
 
 static bool const kDefaultUseMemoryCache = true;
@@ -108,17 +108,16 @@ nsresult CacheObserver::Init() {
   }
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs) {
     return NS_ERROR_UNEXPECTED;
   }
 
   sSelf = new CacheObserver();
-  NS_ADDREF(sSelf);
 
   obs->AddObserver(sSelf, "prefservice:after-app-defaults", true);
   obs->AddObserver(sSelf, "profile-do-change", true);
   obs->AddObserver(sSelf, "browser-delayed-startup-finished", true);
   obs->AddObserver(sSelf, "profile-before-change", true);
   obs->AddObserver(sSelf, "xpcom-shutdown", true);
   obs->AddObserver(sSelf, "last-pb-context-exited", true);
   obs->AddObserver(sSelf, "clear-origin-attributes-data", true);
@@ -128,17 +127,17 @@ nsresult CacheObserver::Init() {
 }
 
 // static
 nsresult CacheObserver::Shutdown() {
   if (!sSelf) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  NS_RELEASE(sSelf);
+  sSelf = nullptr;
   return NS_OK;
 }
 
 void CacheObserver::AttachToPreferences() {
   mozilla::Preferences::AddBoolVarCache(
       &sUseDiskCache, "browser.cache.disk.enable", kDefaultUseDiskCache);
   mozilla::Preferences::AddBoolVarCache(
       &sUseMemoryCache, "browser.cache.memory.enable", kDefaultUseMemoryCache);
@@ -248,18 +247,18 @@ void CacheObserver::SetDiskCacheCapacity
   if (!sSelf) {
     return;
   }
 
   if (NS_IsMainThread()) {
     sSelf->StoreDiskCacheCapacity();
   } else {
     nsCOMPtr<nsIRunnable> event =
-        NewRunnableMethod("net::CacheObserver::StoreDiskCacheCapacity", sSelf,
-                          &CacheObserver::StoreDiskCacheCapacity);
+        NewRunnableMethod("net::CacheObserver::StoreDiskCacheCapacity",
+                          sSelf.get(), &CacheObserver::StoreDiskCacheCapacity);
     NS_DispatchToMainThread(event);
   }
 }
 
 void CacheObserver::StoreDiskCacheCapacity() {
   mozilla::Preferences::SetInt("browser.cache.disk.capacity",
                                sDiskCacheCapacity);
 }
@@ -271,18 +270,18 @@ void CacheObserver::SetCacheFSReported()
   if (!sSelf) {
     return;
   }
 
   if (NS_IsMainThread()) {
     sSelf->StoreCacheFSReported();
   } else {
     nsCOMPtr<nsIRunnable> event =
-        NewRunnableMethod("net::CacheObserver::StoreCacheFSReported", sSelf,
-                          &CacheObserver::StoreCacheFSReported);
+        NewRunnableMethod("net::CacheObserver::StoreCacheFSReported",
+                          sSelf.get(), &CacheObserver::StoreCacheFSReported);
     NS_DispatchToMainThread(event);
   }
 }
 
 void CacheObserver::StoreCacheFSReported() {
   mozilla::Preferences::SetInt("browser.cache.disk.filesystem_reported",
                                sCacheFSReported);
 }
@@ -294,18 +293,18 @@ void CacheObserver::SetHashStatsReported
   if (!sSelf) {
     return;
   }
 
   if (NS_IsMainThread()) {
     sSelf->StoreHashStatsReported();
   } else {
     nsCOMPtr<nsIRunnable> event =
-        NewRunnableMethod("net::CacheObserver::StoreHashStatsReported", sSelf,
-                          &CacheObserver::StoreHashStatsReported);
+        NewRunnableMethod("net::CacheObserver::StoreHashStatsReported",
+                          sSelf.get(), &CacheObserver::StoreHashStatsReported);
     NS_DispatchToMainThread(event);
   }
 }
 
 void CacheObserver::StoreHashStatsReported() {
   mozilla::Preferences::SetInt("browser.cache.disk.hashstats_reported",
                                sHashStatsReported);
 }
--- a/netwerk/cache2/CacheObserver.h
+++ b/netwerk/cache2/CacheObserver.h
@@ -77,17 +77,17 @@ class CacheObserver : public nsIObserver
   static uint32_t MaxShutdownIOLag() { return sMaxShutdownIOLag; }
   static bool IsPastShutdownIOLag();
 
   static bool ShuttingDown() {
     return sShutdownDemandedTime != PR_INTERVAL_NO_TIMEOUT;
   }
 
  private:
-  static CacheObserver* sSelf;
+  static StaticRefPtr<CacheObserver> sSelf;
 
   void StoreDiskCacheCapacity();
   void StoreCacheFSReported();
   void StoreHashStatsReported();
   void AttachToPreferences();
 
   static bool sUseMemoryCache;
   static bool sUseDiskCache;
--- a/netwerk/protocol/about/nsAboutBlank.cpp
+++ b/netwerk/protocol/about/nsAboutBlank.cpp
@@ -35,17 +35,13 @@ nsAboutBlank::GetURIFlags(nsIURI* aURI, 
             nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
             nsIAboutModule::MAKE_LINKABLE |
             nsIAboutModule::HIDE_FROM_ABOUTABOUT;
   return NS_OK;
 }
 
 nsresult nsAboutBlank::Create(nsISupports* aOuter, REFNSIID aIID,
                               void** aResult) {
-  nsAboutBlank* about = new nsAboutBlank();
-  if (about == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(about);
-  nsresult rv = about->QueryInterface(aIID, aResult);
-  NS_RELEASE(about);
-  return rv;
+  RefPtr<nsAboutBlank> about = new nsAboutBlank();
+  return about->QueryInterface(aIID, aResult);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/netwerk/protocol/about/nsAboutCache.cpp
+++ b/netwerk/protocol/about/nsAboutCache.cpp
@@ -547,17 +547,13 @@ NS_IMETHODIMP
 nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result) {
   *result = nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT;
   return NS_OK;
 }
 
 // static
 nsresult nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID,
                               void **aResult) {
-  nsAboutCache *about = new nsAboutCache();
-  if (about == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(about);
-  nsresult rv = about->QueryInterface(aIID, aResult);
-  NS_RELEASE(about);
-  return rv;
+  RefPtr<nsAboutCache> about = new nsAboutCache();
+  return about->QueryInterface(aIID, aResult);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/netwerk/protocol/data/nsDataHandler.cpp
+++ b/netwerk/protocol/data/nsDataHandler.cpp
@@ -14,22 +14,18 @@
 #include "mozilla/dom/MimeType.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS(nsDataHandler, nsIProtocolHandler, nsISupportsWeakReference)
 
 nsresult nsDataHandler::Create(nsISupports* aOuter, const nsIID& aIID,
                                void** aResult) {
-  nsDataHandler* ph = new nsDataHandler();
-  if (ph == nullptr) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(ph);
-  nsresult rv = ph->QueryInterface(aIID, aResult);
-  NS_RELEASE(ph);
-  return rv;
+  RefPtr<nsDataHandler> ph = new nsDataHandler();
+  return ph->QueryInterface(aIID, aResult);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIProtocolHandler methods:
 
 NS_IMETHODIMP
 nsDataHandler::GetScheme(nsACString& result) {
   result.AssignLiteral("data");
@@ -92,38 +88,35 @@ nsDataHandler::NewURI(const nsACString& 
   uri.forget(result);
   return rv;
 }
 
 NS_IMETHODIMP
 nsDataHandler::NewChannel(nsIURI* uri, nsILoadInfo* aLoadInfo,
                           nsIChannel** result) {
   NS_ENSURE_ARG_POINTER(uri);
-  nsDataChannel* channel;
+  RefPtr<nsDataChannel> channel;
   if (XRE_IsParentProcess()) {
     channel = new nsDataChannel(uri);
   } else {
     channel = new mozilla::net::DataChannelChild(uri);
   }
-  NS_ADDREF(channel);
 
   nsresult rv = channel->Init();
   if (NS_FAILED(rv)) {
-    NS_RELEASE(channel);
     return rv;
   }
 
   // set the loadInfo on the new channel
   rv = channel->SetLoadInfo(aLoadInfo);
   if (NS_FAILED(rv)) {
-    NS_RELEASE(channel);
     return rv;
   }
 
-  *result = channel;
+  channel.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDataHandler::AllowPort(int32_t port, const char* scheme, bool* _retval) {
   // don't override anything.
   *_retval = false;
   return NS_OK;
--- a/netwerk/protocol/file/nsFileProtocolHandler.cpp
+++ b/netwerk/protocol/file/nsFileProtocolHandler.cpp
@@ -163,41 +163,37 @@ nsFileProtocolHandler::NewURI(const nsAC
       .Finalize(result);
 }
 
 NS_IMETHODIMP
 nsFileProtocolHandler::NewChannel(nsIURI *uri, nsILoadInfo *aLoadInfo,
                                   nsIChannel **result) {
   nsresult rv;
 
-  nsFileChannel *chan;
+  RefPtr<nsFileChannel> chan;
   if (IsNeckoChild()) {
     chan = new mozilla::net::FileChannelChild(uri);
   } else {
     chan = new nsFileChannel(uri);
   }
-  if (!chan) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(chan);
 
   // set the loadInfo on the new channel ; must do this
   // before calling Init() on it, since it needs the load
   // info be already set.
   rv = chan->SetLoadInfo(aLoadInfo);
   if (NS_FAILED(rv)) {
-    NS_RELEASE(chan);
     return rv;
   }
 
   rv = chan->Init();
   if (NS_FAILED(rv)) {
-    NS_RELEASE(chan);
     return rv;
   }
 
-  *result = chan;
+  chan.forget(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFileProtocolHandler::AllowPort(int32_t port, const char *scheme,
                                  bool *result) {
   // don't override anything.
   *result = false;
--- a/netwerk/protocol/ftp/nsFTPChannel.cpp
+++ b/netwerk/protocol/ftp/nsFTPChannel.cpp
@@ -40,20 +40,20 @@ nsFtpChannel::SetUploadStream(nsIInputSt
   mUploadStream = stream;
 
   // NOTE: contentLength is intentionally ignored here.
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsFtpChannel::GetUploadStream(nsIInputStream **stream) {
-  NS_ENSURE_ARG_POINTER(stream);
-  *stream = mUploadStream;
-  NS_IF_ADDREF(*stream);
+nsFtpChannel::GetUploadStream(nsIInputStream **aStream) {
+  NS_ENSURE_ARG_POINTER(aStream);
+  nsCOMPtr<nsIInputStream> stream = mUploadStream;
+  stream.forget(aStream);
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString &aEntityID) {
   NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
@@ -69,38 +69,35 @@ nsFtpChannel::GetEntityID(nsACString &en
 
   entityID = mEntityID;
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 nsFtpChannel::GetProxyInfo(nsIProxyInfo **aProxyInfo) {
-  *aProxyInfo = ProxyInfo();
-  NS_IF_ADDREF(*aProxyInfo);
+  nsCOMPtr<nsIProxyInfo> info = ProxyInfo();
+  info.forget(aProxyInfo);
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
 nsresult nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
                                          nsIChannel **channel) {
   if (!async) return NS_ERROR_NOT_IMPLEMENTED;
 
-  nsFtpState *state = new nsFtpState();
-  if (!state) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(state);
+  RefPtr<nsFtpState> state = new nsFtpState();
 
   nsresult rv = state->Init(this);
   if (NS_FAILED(rv)) {
-    NS_RELEASE(state);
     return rv;
   }
 
-  *result = state;
+  state.forget(result);
   return NS_OK;
 }
 
 bool nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg) {
   nsAutoCString host;
   URI()->GetHost(host);
   CopyUTF8toUTF16(host, statusArg);
   return true;
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -89,27 +89,26 @@ nsFtpState::nsFtpState()
       mUseUTF8(false),
       mControlStatus(NS_OK),
       mDeferredCallbackPending(false) {
   this->mServerAddress.raw.family = 0;
   this->mServerAddress.inet = {};
   LOG_INFO(("FTP:(%p) nsFtpState created", this));
 
   // make sure handler stays around
-  NS_ADDREF(gFtpHandler);
+  mHandler = gFtpHandler;
 }
 
 nsFtpState::~nsFtpState() {
   LOG_INFO(("FTP:(%p) nsFtpState destroyed", this));
 
   if (mProxyRequest) mProxyRequest->Cancel(NS_ERROR_FAILURE);
 
   // release reference to handler
-  nsFtpProtocolHandler *handler = gFtpHandler;
-  NS_RELEASE(handler);
+  mHandler = nullptr;
 }
 
 // nsIInputStreamCallback implementation
 NS_IMETHODIMP
 nsFtpState::OnInputStreamReady(nsIAsyncInputStream *aInStream) {
   LOG(("FTP:(%p) data stream ready\n", this));
 
   // We are receiving a notification from our data stream, so just forward it
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.h
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.h
@@ -177,16 +177,18 @@ class nsFtpState final : public nsBaseCo
    * there.  This method is initially called (indirectly) from the channel's
    * AsyncOpen implementation.
    */
   void Connect();
 
   ///////////////////////////////////
   // Private members
 
+  nsCOMPtr<nsIProxiedProtocolHandler> mHandler;  // Ref to gFtpHandler
+
   // ****** state machine vars
   FTP_STATE mState;        // the current state
   FTP_STATE mNextState;    // the next state
   bool mKeepRunning;       // thread event loop boolean
   int32_t mResponseCode;   // the last command response code
   nsCString mResponseMsg;  // the last command response text
 
   // ****** channel/transport/stream vars
--- a/netwerk/protocol/viewsource/nsViewSourceHandler.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceHandler.cpp
@@ -100,34 +100,30 @@ nsViewSourceHandler::NewURI(const nsACSt
   uri.swap(*aResult);
   return rv;
 }
 
 NS_IMETHODIMP
 nsViewSourceHandler::NewChannel(nsIURI *uri, nsILoadInfo *aLoadInfo,
                                 nsIChannel **result) {
   NS_ENSURE_ARG_POINTER(uri);
-  nsViewSourceChannel *channel = new nsViewSourceChannel();
-  if (!channel) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(channel);
+  RefPtr<nsViewSourceChannel> channel = new nsViewSourceChannel();
 
   nsresult rv = channel->Init(uri);
   if (NS_FAILED(rv)) {
-    NS_RELEASE(channel);
     return rv;
   }
 
   // set the loadInfo on the new channel
   rv = channel->SetLoadInfo(aLoadInfo);
   if (NS_FAILED(rv)) {
-    NS_RELEASE(channel);
     return rv;
   }
 
-  *result = static_cast<nsIViewSourceChannel *>(channel);
+  *result = channel.forget().downcast<nsIViewSourceChannel>().take();
   return NS_OK;
 }
 
 nsresult nsViewSourceHandler::NewSrcdocChannel(nsIURI *aURI, nsIURI *aBaseURI,
                                                const nsAString &aSrcdoc,
                                                nsILoadInfo *aLoadInfo,
                                                nsIChannel **outChannel) {
   NS_ENSURE_ARG_POINTER(aURI);