|
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 "GetFileOrDirectoryTask.h" |
|
8 |
|
9 #include "js/Value.h" |
|
10 #include "mozilla/dom/Directory.h" |
|
11 #include "mozilla/dom/FileSystemBase.h" |
|
12 #include "mozilla/dom/FileSystemUtils.h" |
|
13 #include "mozilla/dom/Promise.h" |
|
14 #include "nsDOMFile.h" |
|
15 #include "nsIFile.h" |
|
16 #include "nsStringGlue.h" |
|
17 |
|
18 namespace mozilla { |
|
19 namespace dom { |
|
20 |
|
21 GetFileOrDirectoryTask::GetFileOrDirectoryTask( |
|
22 FileSystemBase* aFileSystem, |
|
23 const nsAString& aTargetPath, |
|
24 bool aDirectoryOnly) |
|
25 : FileSystemTaskBase(aFileSystem) |
|
26 , mTargetRealPath(aTargetPath) |
|
27 , mIsDirectory(aDirectoryOnly) |
|
28 { |
|
29 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
30 MOZ_ASSERT(aFileSystem); |
|
31 nsCOMPtr<nsIGlobalObject> globalObject = |
|
32 do_QueryInterface(aFileSystem->GetWindow()); |
|
33 if (!globalObject) { |
|
34 return; |
|
35 } |
|
36 mPromise = new Promise(globalObject); |
|
37 } |
|
38 |
|
39 GetFileOrDirectoryTask::GetFileOrDirectoryTask( |
|
40 FileSystemBase* aFileSystem, |
|
41 const FileSystemGetFileOrDirectoryParams& aParam, |
|
42 FileSystemRequestParent* aParent) |
|
43 : FileSystemTaskBase(aFileSystem, aParam, aParent) |
|
44 , mIsDirectory(false) |
|
45 { |
|
46 MOZ_ASSERT(FileSystemUtils::IsParentProcess(), |
|
47 "Only call from parent process!"); |
|
48 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
49 MOZ_ASSERT(aFileSystem); |
|
50 mTargetRealPath = aParam.realPath(); |
|
51 } |
|
52 |
|
53 GetFileOrDirectoryTask::~GetFileOrDirectoryTask() |
|
54 { |
|
55 MOZ_ASSERT(!mPromise || NS_IsMainThread(), |
|
56 "mPromise should be released on main thread!"); |
|
57 } |
|
58 |
|
59 already_AddRefed<Promise> |
|
60 GetFileOrDirectoryTask::GetPromise() |
|
61 { |
|
62 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
63 return nsRefPtr<Promise>(mPromise).forget(); |
|
64 } |
|
65 |
|
66 FileSystemParams |
|
67 GetFileOrDirectoryTask::GetRequestParams(const nsString& aFileSystem) const |
|
68 { |
|
69 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
70 return FileSystemGetFileOrDirectoryParams(aFileSystem, mTargetRealPath); |
|
71 } |
|
72 |
|
73 FileSystemResponseValue |
|
74 GetFileOrDirectoryTask::GetSuccessRequestResult() const |
|
75 { |
|
76 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
77 if (mIsDirectory) { |
|
78 return FileSystemDirectoryResponse(mTargetRealPath); |
|
79 } |
|
80 BlobParent* actor = GetBlobParent(mTargetFile); |
|
81 if (!actor) { |
|
82 return FileSystemErrorResponse(NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR); |
|
83 } |
|
84 FileSystemFileResponse response; |
|
85 response.blobParent() = actor; |
|
86 return response; |
|
87 } |
|
88 |
|
89 void |
|
90 GetFileOrDirectoryTask::SetSuccessRequestResult(const FileSystemResponseValue& aValue) |
|
91 { |
|
92 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
93 switch (aValue.type()) { |
|
94 case FileSystemResponseValue::TFileSystemFileResponse: { |
|
95 FileSystemFileResponse r = aValue; |
|
96 BlobChild* actor = static_cast<BlobChild*>(r.blobChild()); |
|
97 nsCOMPtr<nsIDOMBlob> blob = actor->GetBlob(); |
|
98 mTargetFile = do_QueryInterface(blob); |
|
99 mIsDirectory = false; |
|
100 break; |
|
101 } |
|
102 case FileSystemResponseValue::TFileSystemDirectoryResponse: { |
|
103 FileSystemDirectoryResponse r = aValue; |
|
104 mTargetRealPath = r.realPath(); |
|
105 mIsDirectory = true; |
|
106 break; |
|
107 } |
|
108 default: { |
|
109 NS_RUNTIMEABORT("not reached"); |
|
110 break; |
|
111 } |
|
112 } |
|
113 } |
|
114 |
|
115 nsresult |
|
116 GetFileOrDirectoryTask::Work() |
|
117 { |
|
118 MOZ_ASSERT(FileSystemUtils::IsParentProcess(), |
|
119 "Only call from parent process!"); |
|
120 MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!"); |
|
121 |
|
122 if (mFileSystem->IsShutdown()) { |
|
123 return NS_ERROR_FAILURE; |
|
124 } |
|
125 |
|
126 // Whether we want to get the root directory. |
|
127 bool getRoot = mTargetRealPath.IsEmpty(); |
|
128 |
|
129 nsCOMPtr<nsIFile> file = mFileSystem->GetLocalFile(mTargetRealPath); |
|
130 if (!file) { |
|
131 return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR; |
|
132 } |
|
133 |
|
134 bool exists; |
|
135 nsresult rv = file->Exists(&exists); |
|
136 if (NS_WARN_IF(NS_FAILED(rv))) { |
|
137 return rv; |
|
138 } |
|
139 |
|
140 if (!exists) { |
|
141 if (!getRoot) { |
|
142 return NS_ERROR_DOM_FILE_NOT_FOUND_ERR; |
|
143 } |
|
144 |
|
145 // If the root directory doesn't exit, create it. |
|
146 rv = file->Create(nsIFile::DIRECTORY_TYPE, 0777); |
|
147 if (NS_WARN_IF(NS_FAILED(rv))) { |
|
148 return rv; |
|
149 } |
|
150 } |
|
151 |
|
152 // Get isDirectory. |
|
153 rv = file->IsDirectory(&mIsDirectory); |
|
154 if (NS_WARN_IF(NS_FAILED(rv))) { |
|
155 return rv; |
|
156 } |
|
157 |
|
158 if (mIsDirectory) { |
|
159 return NS_OK; |
|
160 } |
|
161 |
|
162 // Check if the root is a directory. |
|
163 if (getRoot) { |
|
164 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR; |
|
165 } |
|
166 |
|
167 bool isFile; |
|
168 // Get isFile |
|
169 rv = file->IsFile(&isFile); |
|
170 if (NS_WARN_IF(NS_FAILED(rv))) { |
|
171 return rv; |
|
172 } |
|
173 |
|
174 if (!isFile) { |
|
175 // Neither directory or file. |
|
176 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR; |
|
177 } |
|
178 |
|
179 if (!mFileSystem->IsSafeFile(file)) { |
|
180 return NS_ERROR_DOM_SECURITY_ERR; |
|
181 } |
|
182 |
|
183 mTargetFile = new nsDOMFileFile(file); |
|
184 |
|
185 return NS_OK; |
|
186 } |
|
187 |
|
188 void |
|
189 GetFileOrDirectoryTask::HandlerCallback() |
|
190 { |
|
191 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!"); |
|
192 if (mFileSystem->IsShutdown()) { |
|
193 mPromise = nullptr; |
|
194 return; |
|
195 } |
|
196 |
|
197 if (HasError()) { |
|
198 nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(), |
|
199 mErrorValue); |
|
200 mPromise->MaybeReject(domError); |
|
201 mPromise = nullptr; |
|
202 return; |
|
203 } |
|
204 |
|
205 if (mIsDirectory) { |
|
206 nsRefPtr<Directory> dir = new Directory(mFileSystem, mTargetRealPath); |
|
207 mPromise->MaybeResolve(dir); |
|
208 mPromise = nullptr; |
|
209 return; |
|
210 } |
|
211 |
|
212 mPromise->MaybeResolve(mTargetFile); |
|
213 mPromise = nullptr; |
|
214 } |
|
215 |
|
216 void |
|
217 GetFileOrDirectoryTask::GetPermissionAccessType(nsCString& aAccess) const |
|
218 { |
|
219 aAccess.AssignLiteral("read"); |
|
220 } |
|
221 |
|
222 } // namespace dom |
|
223 } // namespace mozilla |