nsDownloader.cpp (2926B)
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/. */ 4 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" 12 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; 21 } 22 23 nsresult rv = mLocation->Remove(false); 24 if (NS_FAILED(rv)) NS_ERROR("unable to remove temp file"); 25 } 26 } 27 28 NS_IMPL_ISUPPORTS(nsDownloader, nsIDownloader, nsIStreamListener, 29 nsIRequestObserver) 30 31 NS_IMETHODIMP 32 nsDownloader::Init(nsIDownloadObserver* observer, nsIFile* location) { 33 mObserver = observer; 34 mLocation = location; 35 return NS_OK; 36 } 37 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; 45 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; 51 52 rv = location->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); 53 if (NS_FAILED(rv)) return rv; 54 55 location.swap(mLocation); 56 mLocationIsTemp = true; 57 } 58 59 rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation); 60 if (NS_FAILED(rv)) return rv; 61 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. 65 66 return NS_OK; 67 } 68 69 NS_IMETHODIMP 70 nsDownloader::OnStopRequest(nsIRequest* request, nsresult status) { 71 if (mSink) { 72 mSink->Close(); 73 mSink = nullptr; 74 } 75 76 mObserver->OnDownloadComplete(this, request, status, mLocation); 77 mObserver = nullptr; 78 79 return NS_OK; 80 } 81 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); 88 89 *writeCount = count; 90 return NS_OK; 91 } 92 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); 98 }