dom/file/FileHelper.cpp

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:918fa8e942dc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "FileHelper.h"
8
9 #include "nsIFileStorage.h"
10
11 #include "nsError.h"
12 #include "nsProxyRelease.h"
13
14 #include "FileHandle.h"
15 #include "FileRequest.h"
16 #include "FileService.h"
17 #include "nsIRequest.h"
18 #include "nsThreadUtils.h"
19
20 USING_FILE_NAMESPACE
21
22 namespace {
23
24 LockedFile* gCurrentLockedFile = nullptr;
25
26 } // anonymous namespace
27
28 FileHelper::FileHelper(LockedFile* aLockedFile,
29 FileRequest* aFileRequest)
30 : mFileStorage(aLockedFile->mFileHandle->mFileStorage),
31 mLockedFile(aLockedFile),
32 mFileRequest(aFileRequest),
33 mResultCode(NS_OK),
34 mFinished(false)
35 {
36 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
37 }
38
39 FileHelper::~FileHelper()
40 {
41 NS_ASSERTION(!mFileStorage && !mLockedFile && !mFileRequest && !mListener &&
42 !mRequest, "Should have cleared this!");
43 }
44
45 NS_IMPL_ISUPPORTS(FileHelper, nsIRequestObserver)
46
47 nsresult
48 FileHelper::Enqueue()
49 {
50 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
51
52 FileService* service = FileService::GetOrCreate();
53 NS_ENSURE_TRUE(service, NS_ERROR_FAILURE);
54
55 nsresult rv = service->Enqueue(mLockedFile, this);
56 NS_ENSURE_SUCCESS(rv, rv);
57
58 if (mLockedFile) {
59 mLockedFile->OnNewRequest();
60 }
61
62 return NS_OK;
63 }
64
65 nsresult
66 FileHelper::AsyncRun(FileHelperListener* aListener)
67 {
68 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
69
70 // Assign the listener early, so we can use it synchronously if the code
71 // below fails.
72 mListener = aListener;
73
74 nsresult rv;
75
76 nsCOMPtr<nsISupports> stream;
77 if (mLockedFile->mRequestMode == LockedFile::PARALLEL) {
78 rv = mLockedFile->CreateParallelStream(getter_AddRefs(stream));
79 }
80 else {
81 rv = mLockedFile->GetOrCreateStream(getter_AddRefs(stream));
82 }
83
84 if (NS_SUCCEEDED(rv)) {
85 NS_ASSERTION(stream, "This should never be null!");
86
87 rv = DoAsyncRun(stream);
88 }
89
90 if (NS_FAILED(rv)) {
91 mResultCode = NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
92 Finish();
93 }
94
95 return NS_OK;
96 }
97
98 NS_IMETHODIMP
99 FileHelper::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt)
100 {
101 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
102
103 return NS_OK;
104 }
105
106 NS_IMETHODIMP
107 FileHelper::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
108 nsresult aStatus)
109 {
110 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
111
112 if (NS_FAILED(aStatus)) {
113 if (aStatus == NS_ERROR_FILE_NO_DEVICE_SPACE) {
114 mResultCode = NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR;
115 }
116 else {
117 mResultCode = NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
118 }
119 }
120
121 Finish();
122
123 return NS_OK;
124 }
125
126 void
127 FileHelper::OnStreamProgress(uint64_t aProgress, uint64_t aProgressMax)
128 {
129 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
130
131 if (mLockedFile->IsAborted()) {
132 NS_ASSERTION(mRequest, "Should have a request!\n");
133
134 nsresult rv = mRequest->Cancel(NS_BINDING_ABORTED);
135 if (NS_FAILED(rv)) {
136 NS_WARNING("Failed to cancel the request!");
137 }
138
139 return;
140 }
141
142 if (mFileRequest) {
143 mFileRequest->OnProgress(aProgress, aProgressMax);
144 }
145 }
146
147 // static
148 LockedFile*
149 FileHelper::GetCurrentLockedFile()
150 {
151 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
152
153 return gCurrentLockedFile;
154 }
155
156 nsresult
157 FileHelper::GetSuccessResult(JSContext* aCx,
158 JS::MutableHandle<JS::Value> aVal)
159 {
160 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
161
162 aVal.setUndefined();
163 return NS_OK;
164 }
165
166 void
167 FileHelper::ReleaseObjects()
168 {
169 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
170
171 mFileStorage = nullptr;
172 mLockedFile = nullptr;
173 mFileRequest = nullptr;
174 mListener = nullptr;
175 mRequest = nullptr;
176 }
177
178 void
179 FileHelper::Finish()
180 {
181 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
182
183 if (mFinished) {
184 return;
185 }
186
187 mFinished = true;
188
189 if (mLockedFile->IsAborted()) {
190 // Always fire a "error" event with ABORT_ERR if the transaction was
191 // aborted, even if the request succeeded or failed with another error.
192 mResultCode = NS_ERROR_DOM_FILEHANDLE_ABORT_ERR;
193 }
194
195 LockedFile* oldLockedFile = gCurrentLockedFile;
196 gCurrentLockedFile = mLockedFile;
197
198 if (mFileRequest) {
199 nsresult rv = mFileRequest->NotifyHelperCompleted(this);
200 if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
201 mResultCode = rv;
202 }
203 }
204
205 NS_ASSERTION(gCurrentLockedFile == mLockedFile, "Should be unchanged!");
206 gCurrentLockedFile = oldLockedFile;
207
208 mLockedFile->OnRequestFinished();
209
210 mListener->OnFileHelperComplete(this);
211
212 ReleaseObjects();
213
214 NS_ASSERTION(!(mFileStorage || mLockedFile || mFileRequest || mListener ||
215 mRequest), "Subclass didn't call FileHelper::ReleaseObjects!");
216
217 }
218
219 void
220 FileHelper::OnStreamClose()
221 {
222 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
223 Finish();
224 }
225
226 void
227 FileHelper::OnStreamDestroy()
228 {
229 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
230 Finish();
231 }

mercurial