/src/mozilla-central/dom/filesystem/GetFileOrDirectoryTask.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=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 "GetFileOrDirectoryTask.h" |
8 | | |
9 | | #include "js/Value.h" |
10 | | #include "mozilla/dom/FileBlobImpl.h" |
11 | | #include "mozilla/dom/FileSystemBase.h" |
12 | | #include "mozilla/dom/FileSystemUtils.h" |
13 | | #include "mozilla/dom/PFileSystemParams.h" |
14 | | #include "mozilla/dom/Promise.h" |
15 | | #include "mozilla/dom/IPCBlobUtils.h" |
16 | | #include "nsIFile.h" |
17 | | #include "nsString.h" |
18 | | |
19 | | namespace mozilla { |
20 | | namespace dom { |
21 | | |
22 | | /** |
23 | | * GetFileOrDirectoryTaskChild |
24 | | */ |
25 | | |
26 | | /* static */ already_AddRefed<GetFileOrDirectoryTaskChild> |
27 | | GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem, |
28 | | nsIFile* aTargetPath, |
29 | | ErrorResult& aRv) |
30 | 0 | { |
31 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
32 | 0 | MOZ_ASSERT(aFileSystem); |
33 | 0 |
|
34 | 0 | nsCOMPtr<nsIGlobalObject> globalObject = |
35 | 0 | do_QueryInterface(aFileSystem->GetParentObject()); |
36 | 0 | if (NS_WARN_IF(!globalObject)) { |
37 | 0 | aRv.Throw(NS_ERROR_FAILURE); |
38 | 0 | return nullptr; |
39 | 0 | } |
40 | 0 | |
41 | 0 | RefPtr<GetFileOrDirectoryTaskChild> task = |
42 | 0 | new GetFileOrDirectoryTaskChild(globalObject, aFileSystem, aTargetPath); |
43 | 0 |
|
44 | 0 | // aTargetPath can be null. In this case SetError will be called. |
45 | 0 |
|
46 | 0 | task->mPromise = Promise::Create(globalObject, aRv); |
47 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
48 | 0 | return nullptr; |
49 | 0 | } |
50 | 0 | |
51 | 0 | return task.forget(); |
52 | 0 | } |
53 | | |
54 | | GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(nsIGlobalObject* aGlobalObject, |
55 | | FileSystemBase* aFileSystem, |
56 | | nsIFile* aTargetPath) |
57 | | : FileSystemTaskChildBase(aGlobalObject, aFileSystem) |
58 | | , mTargetPath(aTargetPath) |
59 | 0 | { |
60 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
61 | 0 | MOZ_ASSERT(aFileSystem); |
62 | 0 | } |
63 | | |
64 | | GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild() |
65 | 0 | { |
66 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
67 | 0 | } |
68 | | |
69 | | already_AddRefed<Promise> |
70 | | GetFileOrDirectoryTaskChild::GetPromise() |
71 | 0 | { |
72 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
73 | 0 | return RefPtr<Promise>(mPromise).forget(); |
74 | 0 | } |
75 | | |
76 | | FileSystemParams |
77 | | GetFileOrDirectoryTaskChild::GetRequestParams(const nsString& aSerializedDOMPath, |
78 | | ErrorResult& aRv) const |
79 | 0 | { |
80 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
81 | 0 |
|
82 | 0 | nsAutoString path; |
83 | 0 | aRv = mTargetPath->GetPath(path); |
84 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
85 | 0 | return FileSystemGetFileOrDirectoryParams(); |
86 | 0 | } |
87 | 0 | |
88 | 0 | return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path); |
89 | 0 | } |
90 | | |
91 | | void |
92 | | GetFileOrDirectoryTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue, |
93 | | ErrorResult& aRv) |
94 | 0 | { |
95 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
96 | 0 | switch (aValue.type()) { |
97 | 0 | case FileSystemResponseValue::TFileSystemFileResponse: { |
98 | 0 | FileSystemFileResponse r = aValue; |
99 | 0 |
|
100 | 0 | RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(r.blob()); |
101 | 0 | MOZ_ASSERT(blobImpl); |
102 | 0 |
|
103 | 0 | mResultFile = File::Create(mFileSystem->GetParentObject(), blobImpl); |
104 | 0 | MOZ_ASSERT(mResultFile); |
105 | 0 | break; |
106 | 0 | } |
107 | 0 | case FileSystemResponseValue::TFileSystemDirectoryResponse: { |
108 | 0 | FileSystemDirectoryResponse r = aValue; |
109 | 0 |
|
110 | 0 | nsCOMPtr<nsIFile> file; |
111 | 0 | aRv = NS_NewLocalFile(r.realPath(), true, getter_AddRefs(file)); |
112 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
113 | 0 | return; |
114 | 0 | } |
115 | 0 | |
116 | 0 | mResultDirectory = Directory::Create(mFileSystem->GetParentObject(), |
117 | 0 | file, mFileSystem); |
118 | 0 | MOZ_ASSERT(mResultDirectory); |
119 | 0 | break; |
120 | 0 | } |
121 | 0 | default: { |
122 | 0 | MOZ_CRASH("not reached"); |
123 | 0 | break; |
124 | 0 | } |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | | void |
129 | | GetFileOrDirectoryTaskChild::HandlerCallback() |
130 | 0 | { |
131 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
132 | 0 | if (mFileSystem->IsShutdown()) { |
133 | 0 | mPromise = nullptr; |
134 | 0 | return; |
135 | 0 | } |
136 | 0 | |
137 | 0 | if (HasError()) { |
138 | 0 | mPromise->MaybeReject(mErrorValue); |
139 | 0 | mPromise = nullptr; |
140 | 0 | return; |
141 | 0 | } |
142 | 0 | |
143 | 0 | if (mResultDirectory) { |
144 | 0 | mPromise->MaybeResolve(mResultDirectory); |
145 | 0 | mResultDirectory = nullptr; |
146 | 0 | mPromise = nullptr; |
147 | 0 | return; |
148 | 0 | } |
149 | 0 | |
150 | 0 | MOZ_ASSERT(mResultFile); |
151 | 0 | mPromise->MaybeResolve(mResultFile); |
152 | 0 | mResultFile = nullptr; |
153 | 0 | mPromise = nullptr; |
154 | 0 | } |
155 | | |
156 | | /** |
157 | | * GetFileOrDirectoryTaskParent |
158 | | */ |
159 | | |
160 | | /* static */ already_AddRefed<GetFileOrDirectoryTaskParent> |
161 | | GetFileOrDirectoryTaskParent::Create(FileSystemBase* aFileSystem, |
162 | | const FileSystemGetFileOrDirectoryParams& aParam, |
163 | | FileSystemRequestParent* aParent, |
164 | | ErrorResult& aRv) |
165 | 0 | { |
166 | 0 | MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); |
167 | 0 | AssertIsOnBackgroundThread(); |
168 | 0 | MOZ_ASSERT(aFileSystem); |
169 | 0 |
|
170 | 0 | RefPtr<GetFileOrDirectoryTaskParent> task = |
171 | 0 | new GetFileOrDirectoryTaskParent(aFileSystem, aParam, aParent); |
172 | 0 |
|
173 | 0 | aRv = NS_NewLocalFile(aParam.realPath(), true, |
174 | 0 | getter_AddRefs(task->mTargetPath)); |
175 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
176 | 0 | return nullptr; |
177 | 0 | } |
178 | 0 | |
179 | 0 | return task.forget(); |
180 | 0 | } |
181 | | |
182 | | GetFileOrDirectoryTaskParent::GetFileOrDirectoryTaskParent(FileSystemBase* aFileSystem, |
183 | | const FileSystemGetFileOrDirectoryParams& aParam, |
184 | | FileSystemRequestParent* aParent) |
185 | | : FileSystemTaskParentBase(aFileSystem, aParam, aParent) |
186 | | , mIsDirectory(false) |
187 | 0 | { |
188 | 0 | MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); |
189 | 0 | AssertIsOnBackgroundThread(); |
190 | 0 | MOZ_ASSERT(aFileSystem); |
191 | 0 | } |
192 | | |
193 | | FileSystemResponseValue |
194 | | GetFileOrDirectoryTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const |
195 | 0 | { |
196 | 0 | AssertIsOnBackgroundThread(); |
197 | 0 |
|
198 | 0 | nsAutoString path; |
199 | 0 | aRv = mTargetPath->GetPath(path); |
200 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
201 | 0 | return FileSystemDirectoryResponse(); |
202 | 0 | } |
203 | 0 | |
204 | 0 | if (mIsDirectory) { |
205 | 0 | return FileSystemDirectoryResponse(path); |
206 | 0 | } |
207 | 0 | |
208 | 0 | RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mTargetPath); |
209 | 0 |
|
210 | 0 | IPCBlob ipcBlob; |
211 | 0 | aRv = IPCBlobUtils::Serialize(blobImpl, mRequestParent->Manager(), ipcBlob); |
212 | 0 | if (NS_WARN_IF(aRv.Failed())) { |
213 | 0 | return FileSystemDirectoryResponse(); |
214 | 0 | } |
215 | 0 | |
216 | 0 | return FileSystemFileResponse(ipcBlob); |
217 | 0 | } |
218 | | |
219 | | nsresult |
220 | | GetFileOrDirectoryTaskParent::IOWork() |
221 | 0 | { |
222 | 0 | MOZ_ASSERT(XRE_IsParentProcess(), |
223 | 0 | "Only call from parent process!"); |
224 | 0 | MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!"); |
225 | 0 |
|
226 | 0 | if (mFileSystem->IsShutdown()) { |
227 | 0 | return NS_ERROR_FAILURE; |
228 | 0 | } |
229 | 0 | |
230 | 0 | // Whether we want to get the root directory. |
231 | 0 | bool exists; |
232 | 0 | nsresult rv = mTargetPath->Exists(&exists); |
233 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
234 | 0 | return rv; |
235 | 0 | } |
236 | 0 | |
237 | 0 | if (!exists) { |
238 | 0 | if (!mFileSystem->ShouldCreateDirectory()) { |
239 | 0 | return NS_ERROR_DOM_FILE_NOT_FOUND_ERR; |
240 | 0 | } |
241 | 0 | |
242 | 0 | rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777); |
243 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
244 | 0 | return rv; |
245 | 0 | } |
246 | 0 | } |
247 | 0 | |
248 | 0 | // Get isDirectory. |
249 | 0 | rv = mTargetPath->IsDirectory(&mIsDirectory); |
250 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
251 | 0 | return rv; |
252 | 0 | } |
253 | 0 | |
254 | 0 | if (mIsDirectory) { |
255 | 0 | return NS_OK; |
256 | 0 | } |
257 | 0 | |
258 | 0 | bool isFile; |
259 | 0 | // Get isFile |
260 | 0 | rv = mTargetPath->IsFile(&isFile); |
261 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
262 | 0 | return rv; |
263 | 0 | } |
264 | 0 | |
265 | 0 | if (!isFile) { |
266 | 0 | // Neither directory or file. |
267 | 0 | return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR; |
268 | 0 | } |
269 | 0 | |
270 | 0 | if (!mFileSystem->IsSafeFile(mTargetPath)) { |
271 | 0 | return NS_ERROR_DOM_SECURITY_ERR; |
272 | 0 | } |
273 | 0 | |
274 | 0 | return NS_OK; |
275 | 0 | } |
276 | | |
277 | | nsresult |
278 | | GetFileOrDirectoryTaskParent::GetTargetPath(nsAString& aPath) const |
279 | 0 | { |
280 | 0 | return mTargetPath->GetPath(aPath); |
281 | 0 | } |
282 | | |
283 | | } // namespace dom |
284 | | } // namespace mozilla |