From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- netwerk/base/nsTransportUtils.cpp | 133 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 netwerk/base/nsTransportUtils.cpp (limited to 'netwerk/base/nsTransportUtils.cpp') diff --git a/netwerk/base/nsTransportUtils.cpp b/netwerk/base/nsTransportUtils.cpp new file mode 100644 index 0000000000..df53ead198 --- /dev/null +++ b/netwerk/base/nsTransportUtils.cpp @@ -0,0 +1,133 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Mutex.h" +#include "nsCOMPtr.h" +#include "nsITransport.h" +#include "nsProxyRelease.h" +#include "nsSocketTransportService2.h" +#include "nsThreadUtils.h" +#include "nsTransportUtils.h" + +using namespace mozilla; + +//----------------------------------------------------------------------------- + +class nsTransportStatusEvent; + +class nsTransportEventSinkProxy : public nsITransportEventSink { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITRANSPORTEVENTSINK + + nsTransportEventSinkProxy(nsITransportEventSink* sink, nsIEventTarget* target) + : mSink(sink), + mTarget(target), + mLock("nsTransportEventSinkProxy.mLock"), + mLastEvent(nullptr) { + NS_ADDREF(mSink); + } + + private: + virtual ~nsTransportEventSinkProxy() { + // our reference to mSink could be the last, so be sure to release + // it on the target thread. otherwise, we could get into trouble. + NS_ProxyRelease("nsTransportEventSinkProxy::mSink", mTarget, + dont_AddRef(mSink)); + } + + public: + nsITransportEventSink* mSink; + nsCOMPtr mTarget; + Mutex mLock MOZ_UNANNOTATED; + nsTransportStatusEvent* mLastEvent; +}; + +class nsTransportStatusEvent : public Runnable { + public: + nsTransportStatusEvent(nsTransportEventSinkProxy* proxy, + nsITransport* transport, nsresult status, + int64_t progress, int64_t progressMax) + : Runnable("nsTransportStatusEvent"), + mProxy(proxy), + mTransport(transport), + mStatus(status), + mProgress(progress), + mProgressMax(progressMax) {} + + ~nsTransportStatusEvent() { + auto ReleaseTransport = [transport(std::move(mTransport))]() mutable {}; + if (!net::OnSocketThread()) { + net::gSocketTransportService->Dispatch(NS_NewRunnableFunction( + "nsHttpConnection::~nsHttpConnection", std::move(ReleaseTransport))); + } + } + + NS_IMETHOD Run() override { + // since this event is being handled, we need to clear the proxy's ref. + // if not coalescing all, then last event may not equal self! + { + MutexAutoLock lock(mProxy->mLock); + if (mProxy->mLastEvent == this) mProxy->mLastEvent = nullptr; + } + + mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress, + mProgressMax); + return NS_OK; + } + + RefPtr mProxy; + + // parameters to OnTransportStatus + nsCOMPtr mTransport; + nsresult mStatus; + int64_t mProgress; + int64_t mProgressMax; +}; + +NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy, nsITransportEventSink) + +NS_IMETHODIMP +nsTransportEventSinkProxy::OnTransportStatus(nsITransport* transport, + nsresult status, int64_t progress, + int64_t progressMax) { + nsresult rv = NS_OK; + RefPtr event; + { + MutexAutoLock lock(mLock); + + // try to coalesce events! ;-) + if (mLastEvent && (mLastEvent->mStatus == status)) { + mLastEvent->mStatus = status; + mLastEvent->mProgress = progress; + mLastEvent->mProgressMax = progressMax; + } else { + event = new nsTransportStatusEvent(this, transport, status, progress, + progressMax); + if (!event) rv = NS_ERROR_OUT_OF_MEMORY; + mLastEvent = event; // weak ref + } + } + if (event) { + rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("unable to post transport status event"); + + MutexAutoLock lock(mLock); // cleanup.. don't reference anymore! + mLastEvent = nullptr; + } + } + return rv; +} + +//----------------------------------------------------------------------------- + +nsresult net_NewTransportEventSinkProxy(nsITransportEventSink** result, + nsITransportEventSink* sink, + nsIEventTarget* target) { + RefPtr res = + new nsTransportEventSinkProxy(sink, target); + res.forget(result); + return NS_OK; +} -- cgit v1.2.3