1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Mozilla.
15 : *
16 : * The Initial Developer of the Original Code is IBM Corporation.
17 : * Portions created by IBM Corporation are Copyright (C) 2003
18 : * IBM Corporation. All Rights Reserved.
19 : *
20 : * Contributor(s):
21 : * IBM Corp.
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPL"), or
25 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : #include "mozilla/Mutex.h"
38 : #include "nsTransportUtils.h"
39 : #include "nsITransport.h"
40 : #include "nsProxyRelease.h"
41 : #include "nsThreadUtils.h"
42 : #include "nsAutoPtr.h"
43 : #include "nsCOMPtr.h"
44 :
45 : using namespace mozilla;
46 :
47 : //-----------------------------------------------------------------------------
48 :
49 : class nsTransportStatusEvent;
50 :
51 : class nsTransportEventSinkProxy : public nsITransportEventSink
52 : {
53 : public:
54 : NS_DECL_ISUPPORTS
55 : NS_DECL_NSITRANSPORTEVENTSINK
56 :
57 3007 : nsTransportEventSinkProxy(nsITransportEventSink *sink,
58 : nsIEventTarget *target,
59 : bool coalesceAll)
60 : : mSink(sink)
61 : , mTarget(target)
62 : , mLock("nsTransportEventSinkProxy.mLock")
63 : , mLastEvent(nsnull)
64 3007 : , mCoalesceAll(coalesceAll)
65 : {
66 3007 : NS_ADDREF(mSink);
67 3007 : }
68 :
69 5990 : virtual ~nsTransportEventSinkProxy()
70 5990 : {
71 : // our reference to mSink could be the last, so be sure to release
72 : // it on the target thread. otherwise, we could get into trouble.
73 2995 : NS_ProxyRelease(mTarget, mSink);
74 11980 : }
75 :
76 : nsITransportEventSink *mSink;
77 : nsCOMPtr<nsIEventTarget> mTarget;
78 : Mutex mLock;
79 : nsTransportStatusEvent *mLastEvent;
80 : bool mCoalesceAll;
81 : };
82 :
83 : class nsTransportStatusEvent : public nsRunnable
84 : {
85 : public:
86 3893 : nsTransportStatusEvent(nsTransportEventSinkProxy *proxy,
87 : nsITransport *transport,
88 : nsresult status,
89 : PRUint64 progress,
90 : PRUint64 progressMax)
91 : : mProxy(proxy)
92 : , mTransport(transport)
93 : , mStatus(status)
94 : , mProgress(progress)
95 3893 : , mProgressMax(progressMax)
96 3893 : {}
97 :
98 15572 : ~nsTransportStatusEvent() {}
99 :
100 3893 : NS_IMETHOD Run()
101 : {
102 : // since this event is being handled, we need to clear the proxy's ref.
103 : // if not coalescing all, then last event may not equal self!
104 : {
105 7786 : MutexAutoLock lock(mProxy->mLock);
106 3893 : if (mProxy->mLastEvent == this)
107 3861 : mProxy->mLastEvent = nsnull;
108 : }
109 :
110 3893 : mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress,
111 3893 : mProgressMax);
112 3893 : return nsnull;
113 : }
114 :
115 : nsRefPtr<nsTransportEventSinkProxy> mProxy;
116 :
117 : // parameters to OnTransportStatus
118 : nsCOMPtr<nsITransport> mTransport;
119 : nsresult mStatus;
120 : PRUint64 mProgress;
121 : PRUint64 mProgressMax;
122 : };
123 :
124 22809 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsTransportEventSinkProxy, nsITransportEventSink)
125 :
126 : NS_IMETHODIMP
127 15010 : nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport,
128 : nsresult status,
129 : PRUint64 progress,
130 : PRUint64 progressMax)
131 : {
132 15010 : nsresult rv = NS_OK;
133 30020 : nsRefPtr<nsTransportStatusEvent> event;
134 : {
135 30020 : MutexAutoLock lock(mLock);
136 :
137 : // try to coalesce events! ;-)
138 15010 : if (mLastEvent && (mCoalesceAll || mLastEvent->mStatus == status)) {
139 11117 : mLastEvent->mStatus = status;
140 11117 : mLastEvent->mProgress = progress;
141 11117 : mLastEvent->mProgressMax = progressMax;
142 : }
143 : else {
144 : event = new nsTransportStatusEvent(this, transport, status,
145 3893 : progress, progressMax);
146 3893 : if (!event)
147 0 : rv = NS_ERROR_OUT_OF_MEMORY;
148 3893 : mLastEvent = event; // weak ref
149 : }
150 : }
151 15010 : if (event) {
152 3893 : rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
153 3893 : if (NS_FAILED(rv)) {
154 0 : NS_WARNING("unable to post transport status event");
155 :
156 0 : MutexAutoLock lock(mLock); // cleanup.. don't reference anymore!
157 0 : mLastEvent = nsnull;
158 : }
159 : }
160 15010 : return rv;
161 : }
162 :
163 : //-----------------------------------------------------------------------------
164 :
165 : nsresult
166 3007 : net_NewTransportEventSinkProxy(nsITransportEventSink **result,
167 : nsITransportEventSink *sink,
168 : nsIEventTarget *target,
169 : bool coalesceAll)
170 : {
171 3007 : *result = new nsTransportEventSinkProxy(sink, target, coalesceAll);
172 3007 : if (!*result)
173 0 : return NS_ERROR_OUT_OF_MEMORY;
174 3007 : NS_ADDREF(*result);
175 3007 : return NS_OK;
176 : }
|