Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include "mozilla/Mutex.h" |
michael@0 | 6 | #include "nsTransportUtils.h" |
michael@0 | 7 | #include "nsITransport.h" |
michael@0 | 8 | #include "nsProxyRelease.h" |
michael@0 | 9 | #include "nsThreadUtils.h" |
michael@0 | 10 | #include "nsAutoPtr.h" |
michael@0 | 11 | #include "nsCOMPtr.h" |
michael@0 | 12 | |
michael@0 | 13 | using namespace mozilla; |
michael@0 | 14 | |
michael@0 | 15 | //----------------------------------------------------------------------------- |
michael@0 | 16 | |
michael@0 | 17 | class nsTransportStatusEvent; |
michael@0 | 18 | |
michael@0 | 19 | class nsTransportEventSinkProxy : public nsITransportEventSink |
michael@0 | 20 | { |
michael@0 | 21 | public: |
michael@0 | 22 | NS_DECL_THREADSAFE_ISUPPORTS |
michael@0 | 23 | NS_DECL_NSITRANSPORTEVENTSINK |
michael@0 | 24 | |
michael@0 | 25 | nsTransportEventSinkProxy(nsITransportEventSink *sink, |
michael@0 | 26 | nsIEventTarget *target, |
michael@0 | 27 | bool coalesceAll) |
michael@0 | 28 | : mSink(sink) |
michael@0 | 29 | , mTarget(target) |
michael@0 | 30 | , mLock("nsTransportEventSinkProxy.mLock") |
michael@0 | 31 | , mLastEvent(nullptr) |
michael@0 | 32 | , mCoalesceAll(coalesceAll) |
michael@0 | 33 | { |
michael@0 | 34 | NS_ADDREF(mSink); |
michael@0 | 35 | } |
michael@0 | 36 | |
michael@0 | 37 | virtual ~nsTransportEventSinkProxy() |
michael@0 | 38 | { |
michael@0 | 39 | // our reference to mSink could be the last, so be sure to release |
michael@0 | 40 | // it on the target thread. otherwise, we could get into trouble. |
michael@0 | 41 | NS_ProxyRelease(mTarget, mSink); |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | nsITransportEventSink *mSink; |
michael@0 | 45 | nsCOMPtr<nsIEventTarget> mTarget; |
michael@0 | 46 | Mutex mLock; |
michael@0 | 47 | nsTransportStatusEvent *mLastEvent; |
michael@0 | 48 | bool mCoalesceAll; |
michael@0 | 49 | }; |
michael@0 | 50 | |
michael@0 | 51 | class nsTransportStatusEvent : public nsRunnable |
michael@0 | 52 | { |
michael@0 | 53 | public: |
michael@0 | 54 | nsTransportStatusEvent(nsTransportEventSinkProxy *proxy, |
michael@0 | 55 | nsITransport *transport, |
michael@0 | 56 | nsresult status, |
michael@0 | 57 | uint64_t progress, |
michael@0 | 58 | uint64_t progressMax) |
michael@0 | 59 | : mProxy(proxy) |
michael@0 | 60 | , mTransport(transport) |
michael@0 | 61 | , mStatus(status) |
michael@0 | 62 | , mProgress(progress) |
michael@0 | 63 | , mProgressMax(progressMax) |
michael@0 | 64 | {} |
michael@0 | 65 | |
michael@0 | 66 | ~nsTransportStatusEvent() {} |
michael@0 | 67 | |
michael@0 | 68 | NS_IMETHOD Run() |
michael@0 | 69 | { |
michael@0 | 70 | // since this event is being handled, we need to clear the proxy's ref. |
michael@0 | 71 | // if not coalescing all, then last event may not equal self! |
michael@0 | 72 | { |
michael@0 | 73 | MutexAutoLock lock(mProxy->mLock); |
michael@0 | 74 | if (mProxy->mLastEvent == this) |
michael@0 | 75 | mProxy->mLastEvent = nullptr; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress, |
michael@0 | 79 | mProgressMax); |
michael@0 | 80 | return NS_OK; |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | nsRefPtr<nsTransportEventSinkProxy> mProxy; |
michael@0 | 84 | |
michael@0 | 85 | // parameters to OnTransportStatus |
michael@0 | 86 | nsCOMPtr<nsITransport> mTransport; |
michael@0 | 87 | nsresult mStatus; |
michael@0 | 88 | uint64_t mProgress; |
michael@0 | 89 | uint64_t mProgressMax; |
michael@0 | 90 | }; |
michael@0 | 91 | |
michael@0 | 92 | NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy, nsITransportEventSink) |
michael@0 | 93 | |
michael@0 | 94 | NS_IMETHODIMP |
michael@0 | 95 | nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport, |
michael@0 | 96 | nsresult status, |
michael@0 | 97 | uint64_t progress, |
michael@0 | 98 | uint64_t progressMax) |
michael@0 | 99 | { |
michael@0 | 100 | nsresult rv = NS_OK; |
michael@0 | 101 | nsRefPtr<nsTransportStatusEvent> event; |
michael@0 | 102 | { |
michael@0 | 103 | MutexAutoLock lock(mLock); |
michael@0 | 104 | |
michael@0 | 105 | // try to coalesce events! ;-) |
michael@0 | 106 | if (mLastEvent && (mCoalesceAll || mLastEvent->mStatus == status)) { |
michael@0 | 107 | mLastEvent->mStatus = status; |
michael@0 | 108 | mLastEvent->mProgress = progress; |
michael@0 | 109 | mLastEvent->mProgressMax = progressMax; |
michael@0 | 110 | } |
michael@0 | 111 | else { |
michael@0 | 112 | event = new nsTransportStatusEvent(this, transport, status, |
michael@0 | 113 | progress, progressMax); |
michael@0 | 114 | if (!event) |
michael@0 | 115 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 116 | mLastEvent = event; // weak ref |
michael@0 | 117 | } |
michael@0 | 118 | } |
michael@0 | 119 | if (event) { |
michael@0 | 120 | rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); |
michael@0 | 121 | if (NS_FAILED(rv)) { |
michael@0 | 122 | NS_WARNING("unable to post transport status event"); |
michael@0 | 123 | |
michael@0 | 124 | MutexAutoLock lock(mLock); // cleanup.. don't reference anymore! |
michael@0 | 125 | mLastEvent = nullptr; |
michael@0 | 126 | } |
michael@0 | 127 | } |
michael@0 | 128 | return rv; |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | //----------------------------------------------------------------------------- |
michael@0 | 132 | |
michael@0 | 133 | nsresult |
michael@0 | 134 | net_NewTransportEventSinkProxy(nsITransportEventSink **result, |
michael@0 | 135 | nsITransportEventSink *sink, |
michael@0 | 136 | nsIEventTarget *target, |
michael@0 | 137 | bool coalesceAll) |
michael@0 | 138 | { |
michael@0 | 139 | *result = new nsTransportEventSinkProxy(sink, target, coalesceAll); |
michael@0 | 140 | if (!*result) |
michael@0 | 141 | return NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 142 | NS_ADDREF(*result); |
michael@0 | 143 | return NS_OK; |
michael@0 | 144 | } |