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 "GetFilesTask.h"
9 #include "HTMLSplitOnSpacesTokenizer.h"
11 #include "mozilla/dom/BlobImpl.h"
12 #include "mozilla/dom/File.h"
13 #include "mozilla/dom/FileSystemBase.h"
14 #include "mozilla/dom/FileSystemUtils.h"
15 #include "mozilla/dom/IPCBlobUtils.h"
16 #include "mozilla/dom/PFileSystemParams.h"
17 #include "mozilla/dom/Promise.h"
18 #include "mozilla/ipc/BackgroundParent.h"
22 namespace mozilla::dom
{
29 already_AddRefed
<GetFilesTaskChild
> GetFilesTaskChild::Create(
30 FileSystemBase
* aFileSystem
, Directory
* aDirectory
, nsIFile
* aTargetPath
,
31 bool aRecursiveFlag
, ErrorResult
& aRv
) {
32 MOZ_ASSERT(aFileSystem
);
33 MOZ_ASSERT(aDirectory
);
34 aFileSystem
->AssertIsOnOwningThread();
36 nsCOMPtr
<nsIGlobalObject
> globalObject
= aFileSystem
->GetParentObject();
37 if (NS_WARN_IF(!globalObject
)) {
38 aRv
.Throw(NS_ERROR_FAILURE
);
42 RefPtr
<GetFilesTaskChild
> task
= new GetFilesTaskChild(
43 globalObject
, aFileSystem
, aDirectory
, aTargetPath
, aRecursiveFlag
);
45 // aTargetPath can be null. In this case SetError will be called.
47 task
->mPromise
= Promise::Create(globalObject
, aRv
);
48 if (NS_WARN_IF(aRv
.Failed())) {
55 GetFilesTaskChild::GetFilesTaskChild(nsIGlobalObject
* aGlobalObject
,
56 FileSystemBase
* aFileSystem
,
57 Directory
* aDirectory
,
58 nsIFile
* aTargetPath
, bool aRecursiveFlag
)
59 : FileSystemTaskChildBase(aGlobalObject
, aFileSystem
),
60 mDirectory(aDirectory
),
61 mTargetPath(aTargetPath
),
62 mRecursiveFlag(aRecursiveFlag
) {
63 MOZ_ASSERT(aFileSystem
);
64 MOZ_ASSERT(aDirectory
);
65 aFileSystem
->AssertIsOnOwningThread();
68 GetFilesTaskChild::~GetFilesTaskChild() {
69 mFileSystem
->AssertIsOnOwningThread();
72 already_AddRefed
<Promise
> GetFilesTaskChild::GetPromise() {
73 mFileSystem
->AssertIsOnOwningThread();
74 return RefPtr
<Promise
>(mPromise
).forget();
77 FileSystemParams
GetFilesTaskChild::GetRequestParams(
78 const nsString
& aSerializedDOMPath
, ErrorResult
& aRv
) const {
79 mFileSystem
->AssertIsOnOwningThread();
82 aRv
= mTargetPath
->GetPath(path
);
83 if (NS_WARN_IF(aRv
.Failed())) {
84 return FileSystemGetFilesParams();
88 mDirectory
->GetPath(domPath
, aRv
);
89 if (NS_WARN_IF(aRv
.Failed())) {
90 return FileSystemGetFilesParams();
93 return FileSystemGetFilesParams(aSerializedDOMPath
, path
, domPath
,
97 void GetFilesTaskChild::SetSuccessRequestResult(
98 const FileSystemResponseValue
& aValue
, ErrorResult
& aRv
) {
99 mFileSystem
->AssertIsOnOwningThread();
100 MOZ_ASSERT(aValue
.type() ==
101 FileSystemResponseValue::TFileSystemFilesResponse
);
103 FileSystemFilesResponse r
= aValue
;
105 if (!mTargetData
.SetLength(r
.data().Length(), mozilla::fallible_t())) {
106 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
110 nsCOMPtr
<nsIGlobalObject
> globalObject
= mFileSystem
->GetParentObject();
111 MOZ_ASSERT(globalObject
);
113 for (uint32_t i
= 0; i
< r
.data().Length(); ++i
) {
114 const FileSystemFileResponse
& data
= r
.data()[i
];
115 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(data
.blob());
116 MOZ_ASSERT(blobImpl
);
118 mTargetData
[i
] = File::Create(globalObject
, blobImpl
);
119 if (NS_WARN_IF(!mTargetData
[i
])) {
120 aRv
.Throw(NS_ERROR_FAILURE
);
126 void GetFilesTaskChild::HandlerCallback() {
127 mFileSystem
->AssertIsOnOwningThread();
128 if (mFileSystem
->IsShutdown()) {
134 mPromise
->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR
);
139 mPromise
->MaybeResolve(mTargetData
);
148 already_AddRefed
<GetFilesTaskParent
> GetFilesTaskParent::Create(
149 FileSystemBase
* aFileSystem
, const FileSystemGetFilesParams
& aParam
,
150 FileSystemRequestParent
* aParent
, ErrorResult
& aRv
) {
151 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
152 mozilla::ipc::AssertIsOnBackgroundThread();
153 MOZ_ASSERT(aFileSystem
);
155 RefPtr
<GetFilesTaskParent
> task
=
156 new GetFilesTaskParent(aFileSystem
, aParam
, aParent
);
158 aRv
= NS_NewLocalFile(aParam
.realPath(), true,
159 getter_AddRefs(task
->mTargetPath
));
160 if (NS_WARN_IF(aRv
.Failed())) {
164 return task
.forget();
167 GetFilesTaskParent::GetFilesTaskParent(FileSystemBase
* aFileSystem
,
168 const FileSystemGetFilesParams
& aParam
,
169 FileSystemRequestParent
* aParent
)
170 : FileSystemTaskParentBase(aFileSystem
, aParam
, aParent
),
171 GetFilesHelperBase(aParam
.recursiveFlag()),
172 mDirectoryDOMPath(aParam
.domPath()) {
173 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
174 mozilla::ipc::AssertIsOnBackgroundThread();
175 MOZ_ASSERT(aFileSystem
);
178 FileSystemResponseValue
GetFilesTaskParent::GetSuccessRequestResult(
179 ErrorResult
& aRv
) const {
180 mozilla::ipc::AssertIsOnBackgroundThread();
182 FallibleTArray
<FileSystemFileResponse
> inputs
;
183 if (!inputs
.SetLength(mTargetBlobImplArray
.Length(), mozilla::fallible_t())) {
184 FileSystemFilesResponse response
;
185 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
189 for (unsigned i
= 0; i
< mTargetBlobImplArray
.Length(); i
++) {
191 aRv
= IPCBlobUtils::Serialize(mTargetBlobImplArray
[i
], ipcBlob
);
192 if (NS_WARN_IF(aRv
.Failed())) {
193 FileSystemFilesResponse response
;
197 inputs
[i
] = FileSystemFileResponse(ipcBlob
);
200 FileSystemFilesResponse response
;
201 response
.data() = std::move(inputs
);
205 nsresult
GetFilesTaskParent::IOWork() {
206 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
207 MOZ_ASSERT(!NS_IsMainThread(), "Only call on I/O thread!");
209 if (mFileSystem
->IsShutdown()) {
210 return NS_ERROR_FAILURE
;
214 nsresult rv
= mTargetPath
->Exists(&exists
);
215 if (NS_WARN_IF(NS_FAILED(rv
))) {
224 rv
= mTargetPath
->IsDirectory(&isDir
);
225 if (NS_WARN_IF(NS_FAILED(rv
))) {
230 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR
;
234 rv
= ExploreDirectory(mDirectoryDOMPath
, mTargetPath
);
235 if (NS_WARN_IF(NS_FAILED(rv
))) {
242 nsresult
GetFilesTaskParent::GetTargetPath(nsAString
& aPath
) const {
243 return mTargetPath
->GetPath(aPath
);
246 } // namespace mozilla::dom