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