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 "nsDownloader.h"
6 #include "nsIInputStream.h"
7 #include "nsIOutputStream.h"
8 #include "nsDirectoryServiceUtils.h"
9 #include "nsDirectoryServiceDefs.h"
10 #include "nsNetUtil.h"
11 #include "nsCRTGlue.h"
13 nsDownloader::~nsDownloader() {
14 if (mLocation
&& mLocationIsTemp
) {
15 // release the sink first since it may still hold an open file
16 // descriptor to mLocation. this needs to happen before the
17 // file can be removed otherwise the Remove call will fail.
23 nsresult rv
= mLocation
->Remove(false);
24 if (NS_FAILED(rv
)) NS_ERROR("unable to remove temp file");
28 NS_IMPL_ISUPPORTS(nsDownloader
, nsIDownloader
, nsIStreamListener
,
32 nsDownloader::Init(nsIDownloadObserver
* observer
, nsIFile
* location
) {
39 nsDownloader::OnStartRequest(nsIRequest
* request
) {
42 nsCOMPtr
<nsIFile
> location
;
43 rv
= NS_GetSpecialDirectory(NS_OS_TEMP_DIR
, getter_AddRefs(location
));
44 if (NS_FAILED(rv
)) return rv
;
47 NS_MakeRandomString(buf
, 8);
48 memcpy(buf
+ 8, ".tmp", 5);
49 rv
= location
->AppendNative(nsDependentCString(buf
, 12));
50 if (NS_FAILED(rv
)) return rv
;
52 rv
= location
->CreateUnique(nsIFile::NORMAL_FILE_TYPE
, 0600);
53 if (NS_FAILED(rv
)) return rv
;
55 location
.swap(mLocation
);
56 mLocationIsTemp
= true;
59 rv
= NS_NewLocalFileOutputStream(getter_AddRefs(mSink
), mLocation
);
60 if (NS_FAILED(rv
)) return rv
;
62 // we could wrap this output stream with a buffered output stream,
63 // but it shouldn't be necessary since we will be writing large
64 // chunks given to us via OnDataAvailable.
70 nsDownloader::OnStopRequest(nsIRequest
* request
, nsresult status
) {
76 mObserver
->OnDownloadComplete(this, request
, status
, mLocation
);
82 nsresult
nsDownloader::ConsumeData(nsIInputStream
* in
, void* closure
,
83 const char* fromRawSegment
,
84 uint32_t toOffset
, uint32_t count
,
85 uint32_t* writeCount
) {
86 nsDownloader
* self
= (nsDownloader
*)closure
;
87 if (self
->mSink
) return self
->mSink
->Write(fromRawSegment
, count
, writeCount
);
94 nsDownloader::OnDataAvailable(nsIRequest
* request
, nsIInputStream
* inStr
,
95 uint64_t sourceOffset
, uint32_t count
) {
97 return inStr
->ReadSegments(ConsumeData
, this, count
, &n
);