Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / dom / filesystem / FileSystemTaskBase.cpp
blob388e9ea1e205b41174ad9db804faa465094d6cd7
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 {
22 namespace dom {
24 namespace {
26 nsresult FileSystemErrorFromNsError(const nsresult& aErrorValue) {
27 uint16_t module = NS_ERROR_GET_MODULE(aErrorValue);
28 if (module == NS_ERROR_MODULE_DOM_FILESYSTEM ||
29 module == NS_ERROR_MODULE_DOM_FILE || module == NS_ERROR_MODULE_DOM) {
30 return aErrorValue;
33 switch (aErrorValue) {
34 case NS_OK:
35 return NS_OK;
37 case NS_ERROR_FILE_INVALID_PATH:
38 case NS_ERROR_FILE_UNRECOGNIZED_PATH:
39 return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
41 case NS_ERROR_FILE_DESTINATION_NOT_DIR:
42 return NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR;
44 case NS_ERROR_FILE_ACCESS_DENIED:
45 case NS_ERROR_FILE_DIR_NOT_EMPTY:
46 return NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
48 case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST:
49 case NS_ERROR_NOT_AVAILABLE:
50 return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
52 case NS_ERROR_FILE_ALREADY_EXISTS:
53 return NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR;
55 case NS_ERROR_FILE_NOT_DIRECTORY:
56 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
58 case NS_ERROR_UNEXPECTED:
59 default:
60 return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
64 nsresult DispatchToIOThread(nsIRunnable* aRunnable) {
65 MOZ_ASSERT(aRunnable);
67 nsCOMPtr<nsIEventTarget> target =
68 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
69 MOZ_ASSERT(target);
71 return target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
74 // This runnable is used when an error value is set before doing any real
75 // operation on the I/O thread. In this case we skip all and we directly
76 // communicate the error.
77 class ErrorRunnable final : public CancelableRunnable {
78 public:
79 explicit ErrorRunnable(FileSystemTaskChildBase* aTask)
80 : CancelableRunnable("ErrorRunnable"), mTask(aTask) {
81 MOZ_ASSERT(aTask);
84 NS_IMETHOD
85 Run() override {
86 MOZ_ASSERT(NS_IsMainThread());
87 MOZ_ASSERT(mTask->HasError());
89 mTask->HandlerCallback();
90 return NS_OK;
93 private:
94 RefPtr<FileSystemTaskChildBase> mTask;
97 } // anonymous namespace
99 /**
100 * FileSystemTaskBase class
103 FileSystemTaskChildBase::FileSystemTaskChildBase(nsIGlobalObject* aGlobalObject,
104 FileSystemBase* aFileSystem)
105 : mErrorValue(NS_OK),
106 mFileSystem(aFileSystem),
107 mGlobalObject(aGlobalObject) {
108 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
109 aFileSystem->AssertIsOnOwningThread();
110 MOZ_ASSERT(aGlobalObject);
113 FileSystemTaskChildBase::~FileSystemTaskChildBase() {
114 mFileSystem->AssertIsOnOwningThread();
117 FileSystemBase* FileSystemTaskChildBase::GetFileSystem() const {
118 mFileSystem->AssertIsOnOwningThread();
119 return mFileSystem.get();
122 void FileSystemTaskChildBase::Start() {
123 mFileSystem->AssertIsOnOwningThread();
125 mozilla::ipc::PBackgroundChild* actor =
126 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
127 if (NS_WARN_IF(!actor)) {
128 // We are probably shutting down.
129 return;
132 nsAutoString serialization;
133 mFileSystem->SerializeDOMPath(serialization);
135 ErrorResult rv;
136 FileSystemParams params = GetRequestParams(serialization, rv);
137 if (NS_WARN_IF(rv.Failed())) {
138 rv.SuppressException();
139 return;
142 // Retain a reference so the task object isn't deleted without IPDL's
143 // knowledge. The reference will be released by
144 // mozilla::ipc::BackgroundChildImpl::DeallocPFileSystemRequestChild.
145 NS_ADDREF_THIS();
147 if (NS_IsMainThread()) {
148 nsIEventTarget* target = mGlobalObject->EventTargetFor(TaskCategory::Other);
149 MOZ_ASSERT(target);
151 actor->SetEventTargetForActor(this, target);
154 actor->SendPFileSystemRequestConstructor(this, params);
157 void FileSystemTaskChildBase::SetRequestResult(
158 const FileSystemResponseValue& aValue) {
159 mFileSystem->AssertIsOnOwningThread();
161 if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) {
162 FileSystemErrorResponse r = aValue;
163 mErrorValue = r.error();
164 } else {
165 ErrorResult rv;
166 SetSuccessRequestResult(aValue, rv);
167 mErrorValue = rv.StealNSResult();
171 mozilla::ipc::IPCResult FileSystemTaskChildBase::Recv__delete__(
172 const FileSystemResponseValue& aValue) {
173 mFileSystem->AssertIsOnOwningThread();
175 SetRequestResult(aValue);
176 HandlerCallback();
177 return IPC_OK();
180 void FileSystemTaskChildBase::SetError(const nsresult& aErrorValue) {
181 mErrorValue = FileSystemErrorFromNsError(aErrorValue);
185 * FileSystemTaskParentBase class
188 FileSystemTaskParentBase::FileSystemTaskParentBase(
189 FileSystemBase* aFileSystem, const FileSystemParams& aParam,
190 FileSystemRequestParent* aParent)
191 : Runnable("dom::FileSystemTaskParentBase"),
192 mErrorValue(NS_OK),
193 mFileSystem(aFileSystem),
194 mRequestParent(aParent),
195 mBackgroundEventTarget(GetCurrentThreadEventTarget()) {
196 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
197 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
198 MOZ_ASSERT(aParent);
199 MOZ_ASSERT(mBackgroundEventTarget);
200 AssertIsOnBackgroundThread();
203 FileSystemTaskParentBase::~FileSystemTaskParentBase() {
204 // This task can be released on different threads because we dispatch it (as
205 // runnable) to main-thread, I/O and then back to the PBackground thread.
206 NS_ProxyRelease("FileSystemTaskParentBase::mFileSystem",
207 mBackgroundEventTarget, mFileSystem.forget());
208 NS_ProxyRelease("FileSystemTaskParentBase::mRequestParent",
209 mBackgroundEventTarget, mRequestParent.forget());
212 void FileSystemTaskParentBase::Start() {
213 AssertIsOnBackgroundThread();
214 mFileSystem->AssertIsOnOwningThread();
216 DebugOnly<nsresult> rv = DispatchToIOThread(this);
217 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchToIOThread failed");
220 void FileSystemTaskParentBase::HandleResult() {
221 AssertIsOnBackgroundThread();
222 mFileSystem->AssertIsOnOwningThread();
224 if (mFileSystem->IsShutdown()) {
225 return;
228 MOZ_ASSERT(mRequestParent);
229 Unused << mRequestParent->Send__delete__(mRequestParent, GetRequestResult());
232 FileSystemResponseValue FileSystemTaskParentBase::GetRequestResult() const {
233 AssertIsOnBackgroundThread();
234 mFileSystem->AssertIsOnOwningThread();
236 if (HasError()) {
237 return FileSystemErrorResponse(mErrorValue);
240 ErrorResult rv;
241 FileSystemResponseValue value = GetSuccessRequestResult(rv);
242 if (NS_WARN_IF(rv.Failed())) {
243 return FileSystemErrorResponse(rv.StealNSResult());
246 return value;
249 void FileSystemTaskParentBase::SetError(const nsresult& aErrorValue) {
250 mErrorValue = FileSystemErrorFromNsError(aErrorValue);
253 NS_IMETHODIMP
254 FileSystemTaskParentBase::Run() {
255 // This method can run in 2 different threads. Here why:
256 // 1. We are are on the I/O thread and we call IOWork().
257 // 2. After step 1, it returns back to the PBackground thread.
259 // Run I/O thread tasks
260 if (!IsOnBackgroundThread()) {
261 nsresult rv = IOWork();
262 if (NS_WARN_IF(NS_FAILED(rv))) {
263 SetError(rv);
266 // Let's go back to PBackground thread to finish the work.
267 rv = mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
268 if (NS_WARN_IF(NS_FAILED(rv))) {
269 return rv;
272 return NS_OK;
275 // If we are here, it's because the I/O work has been done and we have to
276 // handle the result back via IPC.
277 AssertIsOnBackgroundThread();
278 HandleResult();
279 return NS_OK;
282 } // namespace dom
283 } // namespace mozilla