Backed out 2 changesets (bug 1943998) for causing wd failures @ phases.py CLOSED...
[gecko.git] / netwerk / base / nsDownloader.cpp
blobb6d3240226902b95732072988c071aacfe9f0b3e
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.
18 if (mSink) {
19 mSink->Close();
20 mSink = nullptr;
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,
29 nsIRequestObserver)
31 NS_IMETHODIMP
32 nsDownloader::Init(nsIDownloadObserver* observer, nsIFile* location) {
33 mObserver = observer;
34 mLocation = location;
35 return NS_OK;
38 NS_IMETHODIMP
39 nsDownloader::OnStartRequest(nsIRequest* request) {
40 nsresult rv;
41 if (!mLocation) {
42 nsCOMPtr<nsIFile> location;
43 rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(location));
44 if (NS_FAILED(rv)) return rv;
46 char buf[13];
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.
66 return NS_OK;
69 NS_IMETHODIMP
70 nsDownloader::OnStopRequest(nsIRequest* request, nsresult status) {
71 if (mSink) {
72 mSink->Close();
73 mSink = nullptr;
76 mObserver->OnDownloadComplete(this, request, status, mLocation);
77 mObserver = nullptr;
79 return NS_OK;
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);
89 *writeCount = count;
90 return NS_OK;
93 NS_IMETHODIMP
94 nsDownloader::OnDataAvailable(nsIRequest* request, nsIInputStream* inStr,
95 uint64_t sourceOffset, uint32_t count) {
96 uint32_t n;
97 return inStr->ReadSegments(ConsumeData, this, count, &n);