Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
7 #include "GetFileOrDirectoryTask.h"
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"
18 namespace mozilla {
19 namespace dom {
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 }
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 }
53 GetFileOrDirectoryTask::~GetFileOrDirectoryTask()
54 {
55 MOZ_ASSERT(!mPromise || NS_IsMainThread(),
56 "mPromise should be released on main thread!");
57 }
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 }
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 }
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 }
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 }
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!");
122 if (mFileSystem->IsShutdown()) {
123 return NS_ERROR_FAILURE;
124 }
126 // Whether we want to get the root directory.
127 bool getRoot = mTargetRealPath.IsEmpty();
129 nsCOMPtr<nsIFile> file = mFileSystem->GetLocalFile(mTargetRealPath);
130 if (!file) {
131 return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
132 }
134 bool exists;
135 nsresult rv = file->Exists(&exists);
136 if (NS_WARN_IF(NS_FAILED(rv))) {
137 return rv;
138 }
140 if (!exists) {
141 if (!getRoot) {
142 return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
143 }
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 }
152 // Get isDirectory.
153 rv = file->IsDirectory(&mIsDirectory);
154 if (NS_WARN_IF(NS_FAILED(rv))) {
155 return rv;
156 }
158 if (mIsDirectory) {
159 return NS_OK;
160 }
162 // Check if the root is a directory.
163 if (getRoot) {
164 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
165 }
167 bool isFile;
168 // Get isFile
169 rv = file->IsFile(&isFile);
170 if (NS_WARN_IF(NS_FAILED(rv))) {
171 return rv;
172 }
174 if (!isFile) {
175 // Neither directory or file.
176 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
177 }
179 if (!mFileSystem->IsSafeFile(file)) {
180 return NS_ERROR_DOM_SECURITY_ERR;
181 }
183 mTargetFile = new nsDOMFileFile(file);
185 return NS_OK;
186 }
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 }
197 if (HasError()) {
198 nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
199 mErrorValue);
200 mPromise->MaybeReject(domError);
201 mPromise = nullptr;
202 return;
203 }
205 if (mIsDirectory) {
206 nsRefPtr<Directory> dir = new Directory(mFileSystem, mTargetRealPath);
207 mPromise->MaybeResolve(dir);
208 mPromise = nullptr;
209 return;
210 }
212 mPromise->MaybeResolve(mTargetFile);
213 mPromise = nullptr;
214 }
216 void
217 GetFileOrDirectoryTask::GetPermissionAccessType(nsCString& aAccess) const
218 {
219 aAccess.AssignLiteral("read");
220 }
222 } // namespace dom
223 } // namespace mozilla