Backed out changeset 8aaffdf63d09 (bug 1920575) for causing bc failures on browser_si...
[gecko.git] / netwerk / base / nsTransportUtils.cpp
blob242907da08581e5fe89e827789071fa4c5409acd
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/Mutex.h"
6 #include "nsCOMPtr.h"
7 #include "nsITransport.h"
8 #include "nsProxyRelease.h"
9 #include "nsSocketTransportService2.h"
10 #include "nsThreadUtils.h"
11 #include "nsTransportUtils.h"
13 using namespace mozilla;
15 //-----------------------------------------------------------------------------
17 class nsTransportStatusEvent;
19 class nsTransportEventSinkProxy : public nsITransportEventSink {
20 public:
21 NS_DECL_THREADSAFE_ISUPPORTS
22 NS_DECL_NSITRANSPORTEVENTSINK
24 nsTransportEventSinkProxy(nsITransportEventSink* sink, nsIEventTarget* target)
25 : mSink(sink),
26 mTarget(target),
27 mLock("nsTransportEventSinkProxy.mLock") {}
29 private:
30 virtual ~nsTransportEventSinkProxy() {
31 // our reference to mSink could be the last, so be sure to release
32 // it on the target thread. otherwise, we could get into trouble.
33 NS_ProxyRelease("nsTransportEventSinkProxy::mSink", mTarget,
34 mSink.forget());
37 public:
38 nsCOMPtr<nsITransportEventSink> mSink;
39 nsCOMPtr<nsIEventTarget> mTarget;
40 Mutex mLock MOZ_UNANNOTATED;
41 RefPtr<nsTransportStatusEvent> mLastEvent;
44 class nsTransportStatusEvent : public Runnable {
45 public:
46 nsTransportStatusEvent(nsTransportEventSinkProxy* proxy,
47 nsITransport* transport, nsresult status,
48 int64_t progress, int64_t progressMax)
49 : Runnable("nsTransportStatusEvent"),
50 mProxy(proxy),
51 mTransport(transport),
52 mStatus(status),
53 mProgress(progress),
54 mProgressMax(progressMax) {}
56 ~nsTransportStatusEvent() {
57 auto ReleaseTransport = [transport(std::move(mTransport))]() mutable {};
58 if (!net::OnSocketThread()) {
59 net::gSocketTransportService->Dispatch(NS_NewRunnableFunction(
60 "nsHttpConnection::~nsHttpConnection", std::move(ReleaseTransport)));
64 NS_IMETHOD Run() override {
65 // since this event is being handled, we need to clear the proxy's ref.
66 // if not coalescing all, then last event may not equal self!
68 MutexAutoLock lock(mProxy->mLock);
69 if (mProxy->mLastEvent == this) {
70 mProxy->mLastEvent = nullptr;
74 mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress,
75 mProgressMax);
76 mProxy = nullptr;
77 return NS_OK;
80 RefPtr<nsTransportEventSinkProxy> mProxy;
82 // parameters to OnTransportStatus
83 nsCOMPtr<nsITransport> mTransport;
84 nsresult mStatus;
85 int64_t mProgress;
86 int64_t mProgressMax;
89 NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy, nsITransportEventSink)
91 NS_IMETHODIMP
92 nsTransportEventSinkProxy::OnTransportStatus(nsITransport* transport,
93 nsresult status, int64_t progress,
94 int64_t progressMax) {
95 nsresult rv = NS_OK;
96 RefPtr<nsTransportStatusEvent> event;
98 MutexAutoLock lock(mLock);
100 // try to coalesce events! ;-)
101 if (mLastEvent && (mLastEvent->mStatus == status)) {
102 mLastEvent->mStatus = status;
103 mLastEvent->mProgress = progress;
104 mLastEvent->mProgressMax = progressMax;
105 } else {
106 event = new nsTransportStatusEvent(this, transport, status, progress,
107 progressMax);
108 if (!event) rv = NS_ERROR_OUT_OF_MEMORY;
109 mLastEvent = event; // weak ref
112 if (event) {
113 rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
114 if (NS_FAILED(rv)) {
115 NS_WARNING("unable to post transport status event");
117 MutexAutoLock lock(mLock); // cleanup.. don't reference anymore!
118 mLastEvent = nullptr;
121 return rv;
124 //-----------------------------------------------------------------------------
126 nsresult net_NewTransportEventSinkProxy(nsITransportEventSink** result,
127 nsITransportEventSink* sink,
128 nsIEventTarget* target) {
129 RefPtr<nsTransportEventSinkProxy> res =
130 new nsTransportEventSinkProxy(sink, target);
131 res.forget(result);
132 return NS_OK;