/src/mozilla-central/netwerk/base/nsDownloader.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
15 | 0 | if (mLocation && mLocationIsTemp) { |
16 | 0 | // release the sink first since it may still hold an open file |
17 | 0 | // descriptor to mLocation. this needs to happen before the |
18 | 0 | // file can be removed otherwise the Remove call will fail. |
19 | 0 | if (mSink) { |
20 | 0 | mSink->Close(); |
21 | 0 | mSink = nullptr; |
22 | 0 | } |
23 | 0 |
|
24 | 0 | nsresult rv = mLocation->Remove(false); |
25 | 0 | if (NS_FAILED(rv)) |
26 | 0 | NS_ERROR("unable to remove temp file"); |
27 | 0 | } |
28 | 0 | } |
29 | | |
30 | | NS_IMPL_ISUPPORTS(nsDownloader, |
31 | | nsIDownloader, |
32 | | nsIStreamListener, |
33 | | nsIRequestObserver) |
34 | | |
35 | | NS_IMETHODIMP |
36 | | nsDownloader::Init(nsIDownloadObserver *observer, nsIFile *location) |
37 | 0 | { |
38 | 0 | mObserver = observer; |
39 | 0 | mLocation = location; |
40 | 0 | return NS_OK; |
41 | 0 | } |
42 | | |
43 | | NS_IMETHODIMP |
44 | | nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt) |
45 | 0 | { |
46 | 0 | nsresult rv; |
47 | 0 | if (!mLocation) { |
48 | 0 | nsCOMPtr<nsIFile> location; |
49 | 0 | rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(location)); |
50 | 0 | if (NS_FAILED(rv)) return rv; |
51 | 0 | |
52 | 0 | char buf[13]; |
53 | 0 | NS_MakeRandomString(buf, 8); |
54 | 0 | memcpy(buf+8, ".tmp", 5); |
55 | 0 | rv = location->AppendNative(nsDependentCString(buf, 12)); |
56 | 0 | if (NS_FAILED(rv)) return rv; |
57 | 0 | |
58 | 0 | rv = location->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); |
59 | 0 | if (NS_FAILED(rv)) return rv; |
60 | 0 | |
61 | 0 | location.swap(mLocation); |
62 | 0 | mLocationIsTemp = true; |
63 | 0 | } |
64 | 0 |
|
65 | 0 | rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation); |
66 | 0 | if (NS_FAILED(rv)) return rv; |
67 | 0 | |
68 | 0 | // we could wrap this output stream with a buffered output stream, |
69 | 0 | // but it shouldn't be necessary since we will be writing large |
70 | 0 | // chunks given to us via OnDataAvailable. |
71 | 0 | |
72 | 0 | return NS_OK; |
73 | 0 | } |
74 | | |
75 | | NS_IMETHODIMP |
76 | | nsDownloader::OnStopRequest(nsIRequest *request, |
77 | | nsISupports *ctxt, |
78 | | nsresult status) |
79 | 0 | { |
80 | 0 | if (mSink) { |
81 | 0 | mSink->Close(); |
82 | 0 | mSink = nullptr; |
83 | 0 | } |
84 | 0 |
|
85 | 0 | mObserver->OnDownloadComplete(this, request, ctxt, status, mLocation); |
86 | 0 | mObserver = nullptr; |
87 | 0 |
|
88 | 0 | return NS_OK; |
89 | 0 | } |
90 | | |
91 | | nsresult |
92 | | nsDownloader::ConsumeData(nsIInputStream* in, |
93 | | void* closure, |
94 | | const char* fromRawSegment, |
95 | | uint32_t toOffset, |
96 | | uint32_t count, |
97 | | uint32_t *writeCount) |
98 | 0 | { |
99 | 0 | nsDownloader *self = (nsDownloader *) closure; |
100 | 0 | if (self->mSink) |
101 | 0 | return self->mSink->Write(fromRawSegment, count, writeCount); |
102 | 0 | |
103 | 0 | *writeCount = count; |
104 | 0 | return NS_OK; |
105 | 0 | } |
106 | | |
107 | | NS_IMETHODIMP |
108 | | nsDownloader::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, |
109 | | nsIInputStream *inStr, |
110 | | uint64_t sourceOffset, uint32_t count) |
111 | 0 | { |
112 | 0 | uint32_t n; |
113 | 0 | return inStr->ReadSegments(ConsumeData, this, count, &n); |
114 | 0 | } |