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/. */
7 #include "GetFileOrDirectoryTask.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 "mozilla/ipc/BackgroundParent.h"
20 namespace mozilla::dom
{
23 * GetFileOrDirectoryTaskChild
27 already_AddRefed
<GetFileOrDirectoryTaskChild
>
28 GetFileOrDirectoryTaskChild::Create(FileSystemBase
* aFileSystem
,
29 nsIFile
* aTargetPath
, ErrorResult
& aRv
) {
30 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
31 MOZ_ASSERT(aFileSystem
);
33 nsCOMPtr
<nsIGlobalObject
> globalObject
= aFileSystem
->GetParentObject();
34 if (NS_WARN_IF(!globalObject
)) {
35 aRv
.Throw(NS_ERROR_FAILURE
);
39 RefPtr
<GetFileOrDirectoryTaskChild
> task
=
40 new GetFileOrDirectoryTaskChild(globalObject
, aFileSystem
, aTargetPath
);
42 // aTargetPath can be null. In this case SetError will be called.
44 task
->mPromise
= Promise::Create(globalObject
, aRv
);
45 if (NS_WARN_IF(aRv
.Failed())) {
52 GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(
53 nsIGlobalObject
* aGlobalObject
, FileSystemBase
* aFileSystem
,
55 : FileSystemTaskChildBase(aGlobalObject
, aFileSystem
),
56 mTargetPath(aTargetPath
) {
57 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
58 MOZ_ASSERT(aFileSystem
);
61 GetFileOrDirectoryTaskChild::~GetFileOrDirectoryTaskChild() {
62 MOZ_ASSERT(NS_IsMainThread());
65 already_AddRefed
<Promise
> GetFileOrDirectoryTaskChild::GetPromise() {
66 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
67 return RefPtr
<Promise
>(mPromise
).forget();
70 FileSystemParams
GetFileOrDirectoryTaskChild::GetRequestParams(
71 const nsString
& aSerializedDOMPath
, ErrorResult
& aRv
) const {
72 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
75 aRv
= mTargetPath
->GetPath(path
);
76 if (NS_WARN_IF(aRv
.Failed())) {
77 return FileSystemGetFileOrDirectoryParams();
80 return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath
, path
);
83 void GetFileOrDirectoryTaskChild::SetSuccessRequestResult(
84 const FileSystemResponseValue
& aValue
, ErrorResult
& aRv
) {
85 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
86 switch (aValue
.type()) {
87 case FileSystemResponseValue::TFileSystemFileResponse
: {
88 FileSystemFileResponse r
= aValue
;
90 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(r
.blob());
93 nsCOMPtr
<nsIGlobalObject
> globalObject
= mFileSystem
->GetParentObject();
94 MOZ_ASSERT(globalObject
);
96 mResultFile
= File::Create(globalObject
, blobImpl
);
97 if (NS_WARN_IF(!mResultFile
)) {
98 aRv
.Throw(NS_ERROR_FAILURE
);
102 case FileSystemResponseValue::TFileSystemDirectoryResponse
: {
103 FileSystemDirectoryResponse r
= aValue
;
105 nsCOMPtr
<nsIFile
> file
;
106 aRv
= NS_NewLocalFile(r
.realPath(), true, getter_AddRefs(file
));
107 if (NS_WARN_IF(aRv
.Failed())) {
112 Directory::Create(mFileSystem
->GetParentObject(), file
, mFileSystem
);
113 MOZ_ASSERT(mResultDirectory
);
117 MOZ_CRASH("not reached");
123 void GetFileOrDirectoryTaskChild::HandlerCallback() {
124 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
125 if (mFileSystem
->IsShutdown()) {
131 mPromise
->MaybeReject(mErrorValue
);
136 if (mResultDirectory
) {
137 mPromise
->MaybeResolve(mResultDirectory
);
138 mResultDirectory
= nullptr;
143 MOZ_ASSERT(mResultFile
);
144 mPromise
->MaybeResolve(mResultFile
);
145 mResultFile
= nullptr;
150 * GetFileOrDirectoryTaskParent
154 already_AddRefed
<GetFileOrDirectoryTaskParent
>
155 GetFileOrDirectoryTaskParent::Create(
156 FileSystemBase
* aFileSystem
,
157 const FileSystemGetFileOrDirectoryParams
& aParam
,
158 FileSystemRequestParent
* aParent
, ErrorResult
& aRv
) {
159 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
160 mozilla::ipc::AssertIsOnBackgroundThread();
161 MOZ_ASSERT(aFileSystem
);
163 RefPtr
<GetFileOrDirectoryTaskParent
> task
=
164 new GetFileOrDirectoryTaskParent(aFileSystem
, aParam
, aParent
);
166 aRv
= NS_NewLocalFile(aParam
.realPath(), true,
167 getter_AddRefs(task
->mTargetPath
));
168 if (NS_WARN_IF(aRv
.Failed())) {
172 return task
.forget();
175 GetFileOrDirectoryTaskParent::GetFileOrDirectoryTaskParent(
176 FileSystemBase
* aFileSystem
,
177 const FileSystemGetFileOrDirectoryParams
& aParam
,
178 FileSystemRequestParent
* aParent
)
179 : FileSystemTaskParentBase(aFileSystem
, aParam
, aParent
),
180 mIsDirectory(false) {
181 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
182 mozilla::ipc::AssertIsOnBackgroundThread();
183 MOZ_ASSERT(aFileSystem
);
186 FileSystemResponseValue
GetFileOrDirectoryTaskParent::GetSuccessRequestResult(
187 ErrorResult
& aRv
) const {
188 mozilla::ipc::AssertIsOnBackgroundThread();
191 aRv
= mTargetPath
->GetPath(path
);
192 if (NS_WARN_IF(aRv
.Failed())) {
193 return FileSystemDirectoryResponse();
197 return FileSystemDirectoryResponse(path
);
200 RefPtr
<BlobImpl
> blobImpl
= new FileBlobImpl(mTargetPath
);
203 aRv
= IPCBlobUtils::Serialize(blobImpl
, ipcBlob
);
204 if (NS_WARN_IF(aRv
.Failed())) {
205 return FileSystemDirectoryResponse();
208 return FileSystemFileResponse(ipcBlob
);
211 nsresult
GetFileOrDirectoryTaskParent::IOWork() {
212 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
213 MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
215 if (mFileSystem
->IsShutdown()) {
216 return NS_ERROR_FAILURE
;
219 // Whether we want to get the root directory.
221 nsresult rv
= mTargetPath
->Exists(&exists
);
222 if (NS_WARN_IF(NS_FAILED(rv
))) {
227 if (!mFileSystem
->ShouldCreateDirectory()) {
228 return NS_ERROR_DOM_FILE_NOT_FOUND_ERR
;
231 rv
= mTargetPath
->Create(nsIFile::DIRECTORY_TYPE
, 0777);
232 if (NS_WARN_IF(NS_FAILED(rv
))) {
238 rv
= mTargetPath
->IsDirectory(&mIsDirectory
);
239 if (NS_WARN_IF(NS_FAILED(rv
))) {
249 rv
= mTargetPath
->IsFile(&isFile
);
250 if (NS_WARN_IF(NS_FAILED(rv
))) {
255 // Neither directory or file.
256 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR
;
259 if (!mFileSystem
->IsSafeFile(mTargetPath
)) {
260 return NS_ERROR_DOM_SECURITY_ERR
;
266 nsresult
GetFileOrDirectoryTaskParent::GetTargetPath(nsAString
& aPath
) const {
267 return mTargetPath
->GetPath(aPath
);
270 } // namespace mozilla::dom