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") {}
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
,
38 nsCOMPtr
<nsITransportEventSink
> mSink
;
39 nsCOMPtr
<nsIEventTarget
> mTarget
;
40 Mutex mLock MOZ_UNANNOTATED
;
41 RefPtr
<nsTransportStatusEvent
> mLastEvent
;
44 class nsTransportStatusEvent
: public Runnable
{
46 nsTransportStatusEvent(nsTransportEventSinkProxy
* proxy
,
47 nsITransport
* transport
, nsresult status
,
48 int64_t progress
, int64_t progressMax
)
49 : Runnable("nsTransportStatusEvent"),
51 mTransport(transport
),
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
,
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
);