Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / filesystem / FileSystemTaskBase.cpp
blob34cfd8f0182685bdb3c89205e7d13259a4e67518
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 "mozilla/dom/FileSystemTaskBase.h"
9 #include "nsNetCID.h"
10 #include "mozilla/dom/File.h"
11 #include "mozilla/dom/FileSystemBase.h"
12 #include "mozilla/dom/FileSystemRequestParent.h"
13 #include "mozilla/dom/FileSystemUtils.h"
14 #include "mozilla/dom/Promise.h"
15 #include "mozilla/ipc/BackgroundChild.h"
16 #include "mozilla/ipc/BackgroundParent.h"
17 #include "mozilla/ipc/PBackgroundChild.h"
18 #include "mozilla/Unused.h"
19 #include "nsProxyRelease.h"
21 namespace mozilla::dom {
23 namespace {
25 nsresult FileSystemErrorFromNsError(const nsresult& aErrorValue) {
26 uint16_t module = NS_ERROR_GET_MODULE(aErrorValue);
27 if (module == NS_ERROR_MODULE_DOM_FILESYSTEM ||
28 module == NS_ERROR_MODULE_DOM_FILE || module == NS_ERROR_MODULE_DOM) {
29 return aErrorValue;
32 switch (aErrorValue) {
33 case NS_OK:
34 return NS_OK;
36 case NS_ERROR_FILE_INVALID_PATH:
37 case NS_ERROR_FILE_UNRECOGNIZED_PATH:
38 return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
40 case NS_ERROR_FILE_DESTINATION_NOT_DIR:
41 return NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR;
43 case NS_ERROR_FILE_ACCESS_DENIED:
44 case NS_ERROR_FILE_DIR_NOT_EMPTY:
45 return NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
47 case NS_ERROR_FILE_NOT_FOUND:
48 case NS_ERROR_NOT_AVAILABLE:
49 return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
51 case NS_ERROR_FILE_ALREADY_EXISTS:
52 return NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR;
54 case NS_ERROR_FILE_NOT_DIRECTORY:
55 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
57 case NS_ERROR_UNEXPECTED:
58 default:
59 return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
63 nsresult DispatchToIOThread(nsIRunnable* aRunnable) {
64 MOZ_ASSERT(aRunnable);
66 nsCOMPtr<nsIEventTarget> target =
67 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
68 MOZ_ASSERT(target);
70 return target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
73 } // anonymous namespace
75 /**
76 * FileSystemTaskBase class
79 FileSystemTaskChildBase::FileSystemTaskChildBase(nsIGlobalObject* aGlobalObject,
80 FileSystemBase* aFileSystem)
81 : mErrorValue(NS_OK),
82 mFileSystem(aFileSystem),
83 mGlobalObject(aGlobalObject) {
84 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
85 aFileSystem->AssertIsOnOwningThread();
86 MOZ_ASSERT(aGlobalObject);
89 FileSystemTaskChildBase::~FileSystemTaskChildBase() {
90 mFileSystem->AssertIsOnOwningThread();
93 FileSystemBase* FileSystemTaskChildBase::GetFileSystem() const {
94 mFileSystem->AssertIsOnOwningThread();
95 return mFileSystem.get();
98 void FileSystemTaskChildBase::Start() {
99 mFileSystem->AssertIsOnOwningThread();
101 mozilla::ipc::PBackgroundChild* actor =
102 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
103 if (NS_WARN_IF(!actor)) {
104 // We are probably shutting down.
105 return;
108 nsAutoString serialization;
109 mFileSystem->SerializeDOMPath(serialization);
111 ErrorResult rv;
112 FileSystemParams params = GetRequestParams(serialization, rv);
113 if (NS_WARN_IF(rv.Failed())) {
114 rv.SuppressException();
115 return;
118 actor->SendPFileSystemRequestConstructor(this, params);
121 void FileSystemTaskChildBase::SetRequestResult(
122 const FileSystemResponseValue& aValue) {
123 mFileSystem->AssertIsOnOwningThread();
125 if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) {
126 FileSystemErrorResponse r = aValue;
127 mErrorValue = r.error();
128 } else {
129 ErrorResult rv;
130 SetSuccessRequestResult(aValue, rv);
131 mErrorValue = rv.StealNSResult();
135 mozilla::ipc::IPCResult FileSystemTaskChildBase::Recv__delete__(
136 const FileSystemResponseValue& aValue) {
137 mFileSystem->AssertIsOnOwningThread();
139 SetRequestResult(aValue);
140 HandlerCallback();
141 return IPC_OK();
144 void FileSystemTaskChildBase::SetError(const nsresult& aErrorValue) {
145 mErrorValue = FileSystemErrorFromNsError(aErrorValue);
149 * FileSystemTaskParentBase class
152 FileSystemTaskParentBase::FileSystemTaskParentBase(
153 FileSystemBase* aFileSystem, const FileSystemParams& aParam,
154 FileSystemRequestParent* aParent)
155 : Runnable("dom::FileSystemTaskParentBase"),
156 mErrorValue(NS_OK),
157 mFileSystem(aFileSystem),
158 mRequestParent(aParent),
159 mBackgroundEventTarget(GetCurrentSerialEventTarget()) {
160 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
161 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
162 MOZ_ASSERT(aParent);
163 MOZ_ASSERT(mBackgroundEventTarget);
164 mozilla::ipc::AssertIsOnBackgroundThread();
167 FileSystemTaskParentBase::~FileSystemTaskParentBase() {
168 // This task can be released on different threads because we dispatch it (as
169 // runnable) to main-thread, I/O and then back to the PBackground thread.
170 NS_ProxyRelease("FileSystemTaskParentBase::mFileSystem",
171 mBackgroundEventTarget, mFileSystem.forget());
172 NS_ProxyRelease("FileSystemTaskParentBase::mRequestParent",
173 mBackgroundEventTarget, mRequestParent.forget());
176 void FileSystemTaskParentBase::Start() {
177 mozilla::ipc::AssertIsOnBackgroundThread();
178 mFileSystem->AssertIsOnOwningThread();
180 DebugOnly<nsresult> rv = DispatchToIOThread(this);
181 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchToIOThread failed");
184 void FileSystemTaskParentBase::HandleResult() {
185 mozilla::ipc::AssertIsOnBackgroundThread();
186 mFileSystem->AssertIsOnOwningThread();
188 if (mFileSystem->IsShutdown()) {
189 return;
192 MOZ_ASSERT(mRequestParent);
193 (void)mRequestParent->Send__delete__(mRequestParent, GetRequestResult());
196 FileSystemResponseValue FileSystemTaskParentBase::GetRequestResult() const {
197 mozilla::ipc::AssertIsOnBackgroundThread();
198 mFileSystem->AssertIsOnOwningThread();
200 if (HasError()) {
201 return FileSystemErrorResponse(mErrorValue);
204 ErrorResult rv;
205 FileSystemResponseValue value = GetSuccessRequestResult(rv);
206 if (NS_WARN_IF(rv.Failed())) {
207 return FileSystemErrorResponse(rv.StealNSResult());
210 return value;
213 void FileSystemTaskParentBase::SetError(const nsresult& aErrorValue) {
214 mErrorValue = FileSystemErrorFromNsError(aErrorValue);
217 NS_IMETHODIMP
218 FileSystemTaskParentBase::Run() {
219 // This method can run in 2 different threads. Here why:
220 // 1. We are are on the I/O thread and we call IOWork().
221 // 2. After step 1, it returns back to the PBackground thread.
223 // Run I/O thread tasks
224 if (!mozilla::ipc::IsOnBackgroundThread()) {
225 nsresult rv = IOWork();
226 if (NS_WARN_IF(NS_FAILED(rv))) {
227 SetError(rv);
230 // Let's go back to PBackground thread to finish the work.
231 rv = mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
232 if (NS_WARN_IF(NS_FAILED(rv))) {
233 return rv;
236 return NS_OK;
239 // If we are here, it's because the I/O work has been done and we have to
240 // handle the result back via IPC.
241 mozilla::ipc::AssertIsOnBackgroundThread();
242 HandleResult();
243 return NS_OK;
246 } // namespace mozilla::dom