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"
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
{
21 NS_DECL_THREADSAFE_ISUPPORTS
22 NS_DECL_NSITRANSPORTEVENTSINK
24 nsTransportEventSinkProxy(nsITransportEventSink
* sink
, nsIEventTarget
* target
)
27 mLock("nsTransportEventSinkProxy.mLock"),
33 virtual ~nsTransportEventSinkProxy() {
34 // our reference to mSink could be the last, so be sure to release
35 // it on the target thread. otherwise, we could get into trouble.
36 NS_ProxyRelease("nsTransportEventSinkProxy::mSink", mTarget
,
41 nsITransportEventSink
* mSink
;
42 nsCOMPtr
<nsIEventTarget
> mTarget
;
43 Mutex mLock MOZ_UNANNOTATED
;
44 nsTransportStatusEvent
* mLastEvent
;
47 class nsTransportStatusEvent
: public Runnable
{
49 nsTransportStatusEvent(nsTransportEventSinkProxy
* proxy
,
50 nsITransport
* transport
, nsresult status
,
51 int64_t progress
, int64_t progressMax
)
52 : Runnable("nsTransportStatusEvent"),
54 mTransport(transport
),
57 mProgressMax(progressMax
) {}
59 ~nsTransportStatusEvent() {
60 auto ReleaseTransport
= [transport(std::move(mTransport
))]() mutable {};
61 if (!net::OnSocketThread()) {
62 net::gSocketTransportService
->Dispatch(NS_NewRunnableFunction(
63 "nsHttpConnection::~nsHttpConnection", std::move(ReleaseTransport
)));
67 NS_IMETHOD
Run() override
{
68 // since this event is being handled, we need to clear the proxy's ref.
69 // if not coalescing all, then last event may not equal self!
71 MutexAutoLock
lock(mProxy
->mLock
);
72 if (mProxy
->mLastEvent
== this) mProxy
->mLastEvent
= nullptr;
75 mProxy
->mSink
->OnTransportStatus(mTransport
, mStatus
, mProgress
,
80 RefPtr
<nsTransportEventSinkProxy
> mProxy
;
82 // parameters to OnTransportStatus
83 nsCOMPtr
<nsITransport
> mTransport
;
89 NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy
, nsITransportEventSink
)
92 nsTransportEventSinkProxy::OnTransportStatus(nsITransport
* transport
,
93 nsresult status
, int64_t progress
,
94 int64_t progressMax
) {
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
;
106 event
= new nsTransportStatusEvent(this, transport
, status
, progress
,
108 if (!event
) rv
= NS_ERROR_OUT_OF_MEMORY
;
109 mLastEvent
= event
; // weak ref
113 rv
= mTarget
->Dispatch(event
, NS_DISPATCH_NORMAL
);
115 NS_WARNING("unable to post transport status event");
117 MutexAutoLock
lock(mLock
); // cleanup.. don't reference anymore!
118 mLastEvent
= nullptr;
124 //-----------------------------------------------------------------------------
126 nsresult
net_NewTransportEventSinkProxy(nsITransportEventSink
** result
,
127 nsITransportEventSink
* sink
,
128 nsIEventTarget
* target
) {
129 RefPtr
<nsTransportEventSinkProxy
> res
=
130 new nsTransportEventSinkProxy(sink
, target
);