|
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
|
2 /* vim: set ts=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 "mozilla/dom/FileSystemTaskBase.h" |
|
8 |
|
9 #include "nsNetUtil.h" // Stream transport service. |
|
10 #include "mozilla/dom/ContentChild.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/dom/PContent.h" |
|
16 #include "mozilla/unused.h" |
|
17 #include "nsDOMFile.h" |
|
18 |
|
19 namespace mozilla { |
|
20 namespace dom { |
|
21 |
|
22 FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem) |
|
23 : mErrorValue(NS_OK) |
|
24 , mFileSystem(aFileSystem) |
|
25 { |
|
26 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
27 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null."); |
|
28 } |
|
29 |
|
30 FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem, |
|
31 const FileSystemParams& aParam, |
|
32 FileSystemRequestParent* aParent) |
|
33 : mErrorValue(NS_OK) |
|
34 , mFileSystem(aFileSystem) |
|
35 , mRequestParent(aParent) |
|
36 { |
|
37 MOZ_ASSERT(FileSystemUtils::IsParentProcess(), |
|
38 "Only call from parent process!"); |
|
39 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
40 MOZ_ASSERT(aFileSystem, "aFileSystem should not be null."); |
|
41 } |
|
42 |
|
43 FileSystemTaskBase::~FileSystemTaskBase() |
|
44 { |
|
45 } |
|
46 |
|
47 FileSystemBase* |
|
48 FileSystemTaskBase::GetFileSystem() const |
|
49 { |
|
50 return mFileSystem.get(); |
|
51 } |
|
52 |
|
53 void |
|
54 FileSystemTaskBase::Start() |
|
55 { |
|
56 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
57 |
|
58 if (HasError()) { |
|
59 NS_DispatchToMainThread(this); |
|
60 return; |
|
61 } |
|
62 |
|
63 if (FileSystemUtils::IsParentProcess()) { |
|
64 // Run in parent process. |
|
65 // Start worker thread. |
|
66 nsCOMPtr<nsIEventTarget> target |
|
67 = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); |
|
68 NS_ASSERTION(target, "Must have stream transport service."); |
|
69 target->Dispatch(this, NS_DISPATCH_NORMAL); |
|
70 return; |
|
71 } |
|
72 |
|
73 // Run in child process. |
|
74 if (mFileSystem->IsShutdown()) { |
|
75 return; |
|
76 } |
|
77 |
|
78 // Retain a reference so the task object isn't deleted without IPDL's |
|
79 // knowledge. The reference will be released by |
|
80 // mozilla::dom::ContentChild::DeallocPFileSystemRequestChild. |
|
81 NS_ADDREF_THIS(); |
|
82 ContentChild::GetSingleton()->SendPFileSystemRequestConstructor(this, |
|
83 GetRequestParams(mFileSystem->ToString())); |
|
84 } |
|
85 |
|
86 NS_IMETHODIMP |
|
87 FileSystemTaskBase::Run() |
|
88 { |
|
89 if (!NS_IsMainThread()) { |
|
90 // Run worker thread tasks |
|
91 nsresult rv = Work(); |
|
92 if (NS_FAILED(rv)) { |
|
93 SetError(rv); |
|
94 } |
|
95 // Dispatch itself to main thread |
|
96 NS_DispatchToMainThread(this); |
|
97 return NS_OK; |
|
98 } |
|
99 |
|
100 // Run main thread tasks |
|
101 HandleResult(); |
|
102 return NS_OK; |
|
103 } |
|
104 |
|
105 void |
|
106 FileSystemTaskBase::HandleResult() |
|
107 { |
|
108 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
109 if (mFileSystem->IsShutdown()) { |
|
110 return; |
|
111 } |
|
112 if (mRequestParent && mRequestParent->IsRunning()) { |
|
113 unused << mRequestParent->Send__delete__(mRequestParent, |
|
114 GetRequestResult()); |
|
115 } else { |
|
116 HandlerCallback(); |
|
117 } |
|
118 } |
|
119 |
|
120 FileSystemResponseValue |
|
121 FileSystemTaskBase::GetRequestResult() const |
|
122 { |
|
123 MOZ_ASSERT(FileSystemUtils::IsParentProcess(), |
|
124 "Only call from parent process!"); |
|
125 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
126 if (HasError()) { |
|
127 return FileSystemErrorResponse(mErrorValue); |
|
128 } else { |
|
129 return GetSuccessRequestResult(); |
|
130 } |
|
131 } |
|
132 |
|
133 void |
|
134 FileSystemTaskBase::SetRequestResult(const FileSystemResponseValue& aValue) |
|
135 { |
|
136 MOZ_ASSERT(!FileSystemUtils::IsParentProcess(), |
|
137 "Only call from child process!"); |
|
138 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
139 if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) { |
|
140 FileSystemErrorResponse r = aValue; |
|
141 mErrorValue = r.error(); |
|
142 } else { |
|
143 SetSuccessRequestResult(aValue); |
|
144 } |
|
145 } |
|
146 |
|
147 bool |
|
148 FileSystemTaskBase::Recv__delete__(const FileSystemResponseValue& aValue) |
|
149 { |
|
150 SetRequestResult(aValue); |
|
151 HandlerCallback(); |
|
152 return true; |
|
153 } |
|
154 |
|
155 BlobParent* |
|
156 FileSystemTaskBase::GetBlobParent(nsIDOMFile* aFile) const |
|
157 { |
|
158 MOZ_ASSERT(FileSystemUtils::IsParentProcess(), |
|
159 "Only call from parent process!"); |
|
160 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
161 MOZ_ASSERT(aFile); |
|
162 |
|
163 // Load the lazy dom file data from the parent before sending to the child. |
|
164 nsString mimeType; |
|
165 aFile->GetType(mimeType); |
|
166 uint64_t fileSize; |
|
167 aFile->GetSize(&fileSize); |
|
168 uint64_t lastModifiedDate; |
|
169 aFile->GetMozLastModifiedDate(&lastModifiedDate); |
|
170 |
|
171 ContentParent* cp = static_cast<ContentParent*>(mRequestParent->Manager()); |
|
172 return cp->GetOrCreateActorForBlob(aFile); |
|
173 } |
|
174 |
|
175 void |
|
176 FileSystemTaskBase::SetError(const nsresult& aErrorValue) |
|
177 { |
|
178 uint16_t module = NS_ERROR_GET_MODULE(aErrorValue); |
|
179 if (module == NS_ERROR_MODULE_DOM_FILESYSTEM || |
|
180 module == NS_ERROR_MODULE_DOM_FILE || |
|
181 module == NS_ERROR_MODULE_DOM) { |
|
182 mErrorValue = aErrorValue; |
|
183 return; |
|
184 } |
|
185 |
|
186 switch (aErrorValue) { |
|
187 case NS_OK: |
|
188 mErrorValue = NS_OK; |
|
189 return; |
|
190 |
|
191 case NS_ERROR_FILE_INVALID_PATH: |
|
192 case NS_ERROR_FILE_UNRECOGNIZED_PATH: |
|
193 mErrorValue = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR; |
|
194 return; |
|
195 |
|
196 case NS_ERROR_FILE_DESTINATION_NOT_DIR: |
|
197 mErrorValue = NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR; |
|
198 return; |
|
199 |
|
200 case NS_ERROR_FILE_ACCESS_DENIED: |
|
201 case NS_ERROR_FILE_DIR_NOT_EMPTY: |
|
202 mErrorValue = NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR; |
|
203 return; |
|
204 |
|
205 case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST: |
|
206 case NS_ERROR_NOT_AVAILABLE: |
|
207 mErrorValue = NS_ERROR_DOM_FILE_NOT_FOUND_ERR; |
|
208 return; |
|
209 |
|
210 case NS_ERROR_FILE_ALREADY_EXISTS: |
|
211 mErrorValue = NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR; |
|
212 return; |
|
213 |
|
214 case NS_ERROR_FILE_NOT_DIRECTORY: |
|
215 mErrorValue = NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR; |
|
216 return; |
|
217 |
|
218 case NS_ERROR_UNEXPECTED: |
|
219 default: |
|
220 mErrorValue = NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR; |
|
221 return; |
|
222 } |
|
223 } |
|
224 |
|
225 } // namespace dom |
|
226 } // namespace mozilla |