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