1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsDownloader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,113 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsDownloader.h" 1.9 +#include "nsIInputStream.h" 1.10 +#include "nsDirectoryServiceUtils.h" 1.11 +#include "nsDirectoryServiceDefs.h" 1.12 +#include "nsNetUtil.h" 1.13 +#include "nsCRTGlue.h" 1.14 + 1.15 +nsDownloader::~nsDownloader() 1.16 +{ 1.17 + if (mLocation && mLocationIsTemp) { 1.18 + // release the sink first since it may still hold an open file 1.19 + // descriptor to mLocation. this needs to happen before the 1.20 + // file can be removed otherwise the Remove call will fail. 1.21 + if (mSink) { 1.22 + mSink->Close(); 1.23 + mSink = nullptr; 1.24 + } 1.25 + 1.26 + nsresult rv = mLocation->Remove(false); 1.27 + if (NS_FAILED(rv)) 1.28 + NS_ERROR("unable to remove temp file"); 1.29 + } 1.30 +} 1.31 + 1.32 +NS_IMPL_ISUPPORTS(nsDownloader, 1.33 + nsIDownloader, 1.34 + nsIStreamListener, 1.35 + nsIRequestObserver) 1.36 + 1.37 +NS_IMETHODIMP 1.38 +nsDownloader::Init(nsIDownloadObserver *observer, nsIFile *location) 1.39 +{ 1.40 + mObserver = observer; 1.41 + mLocation = location; 1.42 + return NS_OK; 1.43 +} 1.44 + 1.45 +NS_IMETHODIMP 1.46 +nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt) 1.47 +{ 1.48 + nsresult rv; 1.49 + if (!mLocation) { 1.50 + nsCOMPtr<nsIFile> location; 1.51 + rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(location)); 1.52 + if (NS_FAILED(rv)) return rv; 1.53 + 1.54 + char buf[13]; 1.55 + NS_MakeRandomString(buf, 8); 1.56 + memcpy(buf+8, ".tmp", 5); 1.57 + rv = location->AppendNative(nsDependentCString(buf, 12)); 1.58 + if (NS_FAILED(rv)) return rv; 1.59 + 1.60 + rv = location->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); 1.61 + if (NS_FAILED(rv)) return rv; 1.62 + 1.63 + location.swap(mLocation); 1.64 + mLocationIsTemp = true; 1.65 + } 1.66 + 1.67 + rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation); 1.68 + if (NS_FAILED(rv)) return rv; 1.69 + 1.70 + // we could wrap this output stream with a buffered output stream, 1.71 + // but it shouldn't be necessary since we will be writing large 1.72 + // chunks given to us via OnDataAvailable. 1.73 + 1.74 + return NS_OK; 1.75 +} 1.76 + 1.77 +NS_IMETHODIMP 1.78 +nsDownloader::OnStopRequest(nsIRequest *request, 1.79 + nsISupports *ctxt, 1.80 + nsresult status) 1.81 +{ 1.82 + if (mSink) { 1.83 + mSink->Close(); 1.84 + mSink = nullptr; 1.85 + } 1.86 + 1.87 + mObserver->OnDownloadComplete(this, request, ctxt, status, mLocation); 1.88 + mObserver = nullptr; 1.89 + 1.90 + return NS_OK; 1.91 +} 1.92 + 1.93 +NS_METHOD 1.94 +nsDownloader::ConsumeData(nsIInputStream* in, 1.95 + void* closure, 1.96 + const char* fromRawSegment, 1.97 + uint32_t toOffset, 1.98 + uint32_t count, 1.99 + uint32_t *writeCount) 1.100 +{ 1.101 + nsDownloader *self = (nsDownloader *) closure; 1.102 + if (self->mSink) 1.103 + return self->mSink->Write(fromRawSegment, count, writeCount); 1.104 + 1.105 + *writeCount = count; 1.106 + return NS_OK; 1.107 +} 1.108 + 1.109 +NS_IMETHODIMP 1.110 +nsDownloader::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, 1.111 + nsIInputStream *inStr, 1.112 + uint64_t sourceOffset, uint32_t count) 1.113 +{ 1.114 + uint32_t n; 1.115 + return inStr->ReadSegments(ConsumeData, this, count, &n); 1.116 +}