GetFilesTask.cpp (7019B)
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/. */ 6 7 #include "GetFilesTask.h" 8 9 #include "HTMLSplitOnSpacesTokenizer.h" 10 #include "js/Value.h" 11 #include "mozilla/dom/BlobImpl.h" 12 #include "mozilla/dom/File.h" 13 #include "mozilla/dom/FileSystemBase.h" 14 #include "mozilla/dom/FileSystemUtils.h" 15 #include "mozilla/dom/IPCBlobUtils.h" 16 #include "mozilla/dom/PFileSystemParams.h" 17 #include "mozilla/dom/Promise.h" 18 #include "mozilla/ipc/BackgroundParent.h" 19 #include "nsIFile.h" 20 #include "nsString.h" 21 22 namespace mozilla::dom { 23 24 /** 25 * GetFilesTaskChild 26 */ 27 28 /* static */ 29 already_AddRefed<GetFilesTaskChild> GetFilesTaskChild::Create( 30 FileSystemBase* aFileSystem, Directory* aDirectory, nsIFile* aTargetPath, 31 bool aRecursiveFlag, ErrorResult& aRv) { 32 MOZ_ASSERT(aFileSystem); 33 MOZ_ASSERT(aDirectory); 34 aFileSystem->AssertIsOnOwningThread(); 35 36 nsCOMPtr<nsIGlobalObject> globalObject = aFileSystem->GetParentObject(); 37 if (NS_WARN_IF(!globalObject)) { 38 aRv.Throw(NS_ERROR_FAILURE); 39 return nullptr; 40 } 41 42 RefPtr<GetFilesTaskChild> task = new GetFilesTaskChild( 43 globalObject, aFileSystem, aDirectory, aTargetPath, aRecursiveFlag); 44 45 // aTargetPath can be null. In this case SetError will be called. 46 47 task->mPromise = Promise::Create(globalObject, aRv); 48 if (NS_WARN_IF(aRv.Failed())) { 49 return nullptr; 50 } 51 52 return task.forget(); 53 } 54 55 GetFilesTaskChild::GetFilesTaskChild(nsIGlobalObject* aGlobalObject, 56 FileSystemBase* aFileSystem, 57 Directory* aDirectory, 58 nsIFile* aTargetPath, bool aRecursiveFlag) 59 : FileSystemTaskChildBase(aGlobalObject, aFileSystem), 60 mDirectory(aDirectory), 61 mTargetPath(aTargetPath), 62 mRecursiveFlag(aRecursiveFlag) { 63 MOZ_ASSERT(aFileSystem); 64 MOZ_ASSERT(aDirectory); 65 aFileSystem->AssertIsOnOwningThread(); 66 } 67 68 GetFilesTaskChild::~GetFilesTaskChild() { 69 mFileSystem->AssertIsOnOwningThread(); 70 } 71 72 already_AddRefed<Promise> GetFilesTaskChild::GetPromise() { 73 mFileSystem->AssertIsOnOwningThread(); 74 return RefPtr<Promise>(mPromise).forget(); 75 } 76 77 FileSystemParams GetFilesTaskChild::GetRequestParams( 78 const nsString& aSerializedDOMPath, ErrorResult& aRv) const { 79 mFileSystem->AssertIsOnOwningThread(); 80 81 nsAutoString path; 82 aRv = mTargetPath->GetPath(path); 83 if (NS_WARN_IF(aRv.Failed())) { 84 return FileSystemGetFilesParams(); 85 } 86 87 nsAutoString domPath; 88 mDirectory->GetPath(domPath, aRv); 89 if (NS_WARN_IF(aRv.Failed())) { 90 return FileSystemGetFilesParams(); 91 } 92 93 return FileSystemGetFilesParams(aSerializedDOMPath, path, domPath, 94 mRecursiveFlag); 95 } 96 97 void GetFilesTaskChild::SetSuccessRequestResult( 98 const FileSystemResponseValue& aValue, ErrorResult& aRv) { 99 mFileSystem->AssertIsOnOwningThread(); 100 MOZ_ASSERT(aValue.type() == 101 FileSystemResponseValue::TFileSystemFilesResponse); 102 103 FileSystemFilesResponse r = aValue; 104 105 if (!mTargetData.SetLength(r.data().Length(), mozilla::fallible_t())) { 106 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); 107 return; 108 } 109 110 nsCOMPtr<nsIGlobalObject> globalObject = mFileSystem->GetParentObject(); 111 MOZ_ASSERT(globalObject); 112 113 for (uint32_t i = 0; i < r.data().Length(); ++i) { 114 const FileSystemFileResponse& data = r.data()[i]; 115 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob()); 116 MOZ_ASSERT(blobImpl); 117 118 mTargetData[i] = File::Create(globalObject, blobImpl); 119 if (NS_WARN_IF(!mTargetData[i])) { 120 aRv.Throw(NS_ERROR_FAILURE); 121 return; 122 } 123 } 124 } 125 126 void GetFilesTaskChild::HandlerCallback() { 127 mFileSystem->AssertIsOnOwningThread(); 128 if (mFileSystem->IsShutdown()) { 129 mPromise = nullptr; 130 return; 131 } 132 133 if (HasError()) { 134 mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); 135 mPromise = nullptr; 136 return; 137 } 138 139 mPromise->MaybeResolve(mTargetData); 140 mPromise = nullptr; 141 } 142 143 /** 144 * GetFilesTaskParent 145 */ 146 147 /* static */ 148 already_AddRefed<GetFilesTaskParent> GetFilesTaskParent::Create( 149 FileSystemBase* aFileSystem, const FileSystemGetFilesParams& aParam, 150 FileSystemRequestParent* aParent, ErrorResult& aRv) { 151 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); 152 mozilla::ipc::AssertIsOnBackgroundThread(); 153 MOZ_ASSERT(aFileSystem); 154 155 RefPtr<GetFilesTaskParent> task = 156 new GetFilesTaskParent(aFileSystem, aParam, aParent); 157 158 aRv = NS_NewLocalFile(aParam.realPath(), getter_AddRefs(task->mTargetPath)); 159 if (NS_WARN_IF(aRv.Failed())) { 160 return nullptr; 161 } 162 163 return task.forget(); 164 } 165 166 GetFilesTaskParent::GetFilesTaskParent(FileSystemBase* aFileSystem, 167 const FileSystemGetFilesParams& aParam, 168 FileSystemRequestParent* aParent) 169 : FileSystemTaskParentBase(aFileSystem, aParam, aParent), 170 GetFilesHelperBase(aParam.recursiveFlag()), 171 mDirectoryDOMPath(aParam.domPath()) { 172 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); 173 mozilla::ipc::AssertIsOnBackgroundThread(); 174 MOZ_ASSERT(aFileSystem); 175 } 176 177 FileSystemResponseValue GetFilesTaskParent::GetSuccessRequestResult( 178 ErrorResult& aRv) const { 179 mozilla::ipc::AssertIsOnBackgroundThread(); 180 181 FallibleTArray<FileSystemFileResponse> inputs; 182 if (!inputs.SetLength(mTargetBlobImplArray.Length(), mozilla::fallible_t())) { 183 FileSystemFilesResponse response; 184 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); 185 return response; 186 } 187 188 for (unsigned i = 0; i < mTargetBlobImplArray.Length(); i++) { 189 IPCBlob ipcBlob; 190 aRv = IPCBlobUtils::Serialize(mTargetBlobImplArray[i], ipcBlob); 191 if (NS_WARN_IF(aRv.Failed())) { 192 FileSystemFilesResponse response; 193 return response; 194 } 195 196 inputs[i] = FileSystemFileResponse(ipcBlob); 197 } 198 199 FileSystemFilesResponse response; 200 response.data() = std::move(inputs); 201 return response; 202 } 203 204 nsresult GetFilesTaskParent::IOWork() { 205 MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!"); 206 MOZ_ASSERT(!NS_IsMainThread(), "Only call on I/O thread!"); 207 208 if (mFileSystem->IsShutdown()) { 209 return NS_ERROR_FAILURE; 210 } 211 212 bool exists; 213 nsresult rv = mTargetPath->Exists(&exists); 214 if (NS_WARN_IF(NS_FAILED(rv))) { 215 return rv; 216 } 217 218 if (!exists) { 219 return NS_OK; 220 } 221 222 bool isDir; 223 rv = mTargetPath->IsDirectory(&isDir); 224 if (NS_WARN_IF(NS_FAILED(rv))) { 225 return rv; 226 } 227 228 if (!isDir) { 229 return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR; 230 } 231 232 // Get isDirectory. 233 rv = ExploreDirectory(mDirectoryDOMPath, mTargetPath); 234 if (NS_WARN_IF(NS_FAILED(rv))) { 235 return rv; 236 } 237 238 return NS_OK; 239 } 240 241 nsresult GetFilesTaskParent::GetTargetPath(nsAString& aPath) const { 242 return mTargetPath->GetPath(aPath); 243 } 244 245 } // namespace mozilla::dom