1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is Mozilla.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2002
19 * the Initial Developer. All Rights Reserved.
22 * Darin Fisher <darin@netscape.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsAsyncStreamCopier.h"
39 #include "nsIEventTarget.h"
40 #include "nsStreamUtils.h"
41 #include "nsNetSegmentUtils.h"
42 #include "nsNetUtil.h"
43 #include "nsAutoLock.h"
46 #if defined(PR_LOGGING)
48 // NSPR_LOG_MODULES=nsStreamCopier:5
50 static PRLogModuleInfo
*gStreamCopierLog
= nsnull
;
52 #define LOG(args) PR_LOG(gStreamCopierLog, PR_LOG_DEBUG, args)
54 //-----------------------------------------------------------------------------
56 nsAsyncStreamCopier::nsAsyncStreamCopier()
58 , mMode(NS_ASYNCCOPY_VIA_READSEGMENTS
)
59 , mChunkSize(NET_DEFAULT_SEGMENT_SIZE
)
61 , mIsPending(PR_FALSE
)
63 #if defined(PR_LOGGING)
64 if (!gStreamCopierLog
)
65 gStreamCopierLog
= PR_NewLogModule("nsStreamCopier");
67 LOG(("Creating nsAsyncStreamCopier @%x\n", this));
70 nsAsyncStreamCopier::~nsAsyncStreamCopier()
72 LOG(("Destroying nsAsyncStreamCopier @%x\n", this));
74 PR_DestroyLock(mLock
);
78 nsAsyncStreamCopier::IsComplete(nsresult
*status
)
80 nsAutoLock
lock(mLock
);
87 nsAsyncStreamCopier::Complete(nsresult status
)
89 LOG(("nsAsyncStreamCopier::Complete [this=%x status=%x]\n", this, status
));
91 nsCOMPtr
<nsIRequestObserver
> observer
;
92 nsCOMPtr
<nsISupports
> ctx
;
94 nsAutoLock
lock(mLock
);
96 mIsPending
= PR_FALSE
;
99 // setup OnStopRequest callback and release references...
100 observer
= mObserver
;
101 ctx
= mObserverContext
;
103 mObserverContext
= nsnull
;
108 LOG((" calling OnStopRequest [status=%x]\n", status
));
109 observer
->OnStopRequest(this, ctx
, status
);
114 nsAsyncStreamCopier::OnAsyncCopyComplete(void *closure
, nsresult status
)
116 nsAsyncStreamCopier
*self
= (nsAsyncStreamCopier
*) closure
;
117 self
->Complete(status
);
118 NS_RELEASE(self
); // addref'd in AsyncCopy
121 //-----------------------------------------------------------------------------
124 NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncStreamCopier
,
126 nsIAsyncStreamCopier
)
128 //-----------------------------------------------------------------------------
132 nsAsyncStreamCopier::GetName(nsACString
&name
)
139 nsAsyncStreamCopier::IsPending(PRBool
*result
)
141 *result
= !IsComplete();
146 nsAsyncStreamCopier::GetStatus(nsresult
*status
)
153 nsAsyncStreamCopier::Cancel(nsresult status
)
158 if (NS_SUCCEEDED(status
)) {
159 NS_WARNING("cancel with non-failure status code");
160 status
= NS_BASE_STREAM_CLOSED
;
163 nsCOMPtr
<nsIAsyncInputStream
> asyncSource
= do_QueryInterface(mSource
);
165 asyncSource
->CloseWithStatus(status
);
169 nsCOMPtr
<nsIAsyncOutputStream
> asyncSink
= do_QueryInterface(mSink
);
171 asyncSink
->CloseWithStatus(status
);
179 nsAsyncStreamCopier::Suspend()
181 NS_NOTREACHED("nsAsyncStreamCopier::Suspend");
182 return NS_ERROR_NOT_IMPLEMENTED
;
186 nsAsyncStreamCopier::Resume()
188 NS_NOTREACHED("nsAsyncStreamCopier::Resume");
189 return NS_ERROR_NOT_IMPLEMENTED
;
193 nsAsyncStreamCopier::GetLoadFlags(nsLoadFlags
*aLoadFlags
)
195 *aLoadFlags
= LOAD_NORMAL
;
200 nsAsyncStreamCopier::SetLoadFlags(nsLoadFlags aLoadFlags
)
206 nsAsyncStreamCopier::GetLoadGroup(nsILoadGroup
**aLoadGroup
)
208 *aLoadGroup
= nsnull
;
213 nsAsyncStreamCopier::SetLoadGroup(nsILoadGroup
*aLoadGroup
)
218 //-----------------------------------------------------------------------------
219 // nsIAsyncStreamCopier
222 nsAsyncStreamCopier::Init(nsIInputStream
*source
,
223 nsIOutputStream
*sink
,
224 nsIEventTarget
*target
,
225 PRBool sourceBuffered
,
229 NS_ASSERTION(sourceBuffered
|| sinkBuffered
, "at least one stream must be buffered");
231 NS_ASSERTION(!mLock
, "already initialized");
232 mLock
= PR_NewLock();
234 return NS_ERROR_OUT_OF_MEMORY
;
237 chunkSize
= NET_DEFAULT_SEGMENT_SIZE
;
238 mChunkSize
= chunkSize
;
243 mMode
= sourceBuffered
? NS_ASYNCCOPY_VIA_READSEGMENTS
244 : NS_ASYNCCOPY_VIA_WRITESEGMENTS
;
249 mTarget
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
, &rv
);
250 if (NS_FAILED(rv
)) return rv
;
256 nsAsyncStreamCopier::AsyncCopy(nsIRequestObserver
*observer
, nsISupports
*ctx
)
258 LOG(("nsAsyncStreamCopier::AsyncCopy [this=%x observer=%x]\n", this, observer
));
260 NS_ASSERTION(mSource
&& mSink
, "not initialized");
264 // build proxy for observer events
265 rv
= NS_NewRequestObserverProxy(getter_AddRefs(mObserver
), observer
);
266 if (NS_FAILED(rv
)) return rv
;
269 // from this point forward, AsyncCopy is going to return NS_OK. any errors
270 // will be reported via OnStopRequest.
271 mIsPending
= PR_TRUE
;
273 mObserverContext
= ctx
;
275 rv
= mObserver
->OnStartRequest(this, mObserverContext
);
280 // we want to receive progress notifications; release happens in
281 // OnAsyncCopyComplete.
283 rv
= NS_AsyncCopy(mSource
, mSink
, mTarget
, mMode
, mChunkSize
,
284 OnAsyncCopyComplete
, this);