FileSystemRequestHandler.cpp (23591B)
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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "fs/FileSystemRequestHandler.h" 8 9 #include "FileSystemEntryMetadataArray.h" 10 #include "fs/FileSystemConstants.h" 11 #include "mozilla/StaticPrefs_dom.h" 12 #include "mozilla/dom/BlobImpl.h" 13 #include "mozilla/dom/File.h" 14 #include "mozilla/dom/FileSystemAccessHandleChild.h" 15 #include "mozilla/dom/FileSystemDirectoryHandle.h" 16 #include "mozilla/dom/FileSystemFileHandle.h" 17 #include "mozilla/dom/FileSystemHandle.h" 18 #include "mozilla/dom/FileSystemHelpers.h" 19 #include "mozilla/dom/FileSystemLog.h" 20 #include "mozilla/dom/FileSystemManager.h" 21 #include "mozilla/dom/FileSystemManagerChild.h" 22 #include "mozilla/dom/FileSystemSyncAccessHandle.h" 23 #include "mozilla/dom/FileSystemWritableFileStream.h" 24 #include "mozilla/dom/FileSystemWritableFileStreamChild.h" 25 #include "mozilla/dom/IPCBlobUtils.h" 26 #include "mozilla/dom/Promise.h" 27 #include "mozilla/dom/WorkerCommon.h" 28 #include "mozilla/dom/WorkerRef.h" 29 #include "mozilla/dom/fs/IPCRejectReporter.h" 30 #include "mozilla/dom/quota/QuotaCommon.h" 31 #include "mozilla/dom/quota/ResultExtensions.h" 32 #include "mozilla/ipc/RandomAccessStreamUtils.h" 33 34 namespace mozilla::dom::fs { 35 36 using mozilla::ipc::RejectCallback; 37 38 namespace { 39 40 void HandleFailedStatus(nsresult aError, const RefPtr<Promise>& aPromise) { 41 switch (aError) { 42 case NS_ERROR_FILE_ACCESS_DENIED: 43 aPromise->MaybeRejectWithNotAllowedError("Permission denied"); 44 break; 45 case NS_ERROR_FILE_NOT_FOUND: 46 [[fallthrough]]; 47 case NS_ERROR_DOM_NOT_FOUND_ERR: 48 aPromise->MaybeRejectWithNotFoundError("Entry not found"); 49 break; 50 case NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR: 51 aPromise->MaybeRejectWithInvalidModificationError("Disallowed by system"); 52 break; 53 case NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR: 54 aPromise->MaybeRejectWithNoModificationAllowedError( 55 "No modification allowed"); 56 break; 57 case NS_ERROR_DOM_TYPE_MISMATCH_ERR: 58 aPromise->MaybeRejectWithTypeMismatchError("Wrong type"); 59 break; 60 case NS_ERROR_DOM_INVALID_MODIFICATION_ERR: 61 aPromise->MaybeRejectWithInvalidModificationError("Invalid modification"); 62 break; 63 default: 64 if (NS_FAILED(aError)) { 65 aPromise->MaybeRejectWithUnknownError("Unknown failure"); 66 } else { 67 aPromise->MaybeResolveWithUndefined(); 68 } 69 break; 70 } 71 } 72 73 bool MakeResolution(nsIGlobalObject* aGlobal, 74 FileSystemGetEntriesResponse&& aResponse, 75 const bool& /* aResult */, 76 RefPtr<FileSystemEntryMetadataArray>& aSink) { 77 // TODO: Add page size to FileSystemConstants, preallocate and handle overflow 78 const auto& listing = aResponse.get_FileSystemDirectoryListing(); 79 80 for (const auto& it : listing.files()) { 81 aSink->AppendElement(it); 82 } 83 84 for (const auto& it : listing.directories()) { 85 aSink->AppendElement(it); 86 } 87 88 return true; 89 } 90 91 RefPtr<FileSystemDirectoryHandle> MakeResolution( 92 nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, 93 const RefPtr<FileSystemDirectoryHandle>& /* aResult */, 94 RefPtr<FileSystemManager>& aManager) { 95 RefPtr<FileSystemDirectoryHandle> result = new FileSystemDirectoryHandle( 96 aGlobal, aManager, 97 FileSystemEntryMetadata(aResponse.get_EntryId(), kRootName, 98 /* directory */ true)); 99 return result; 100 } 101 102 RefPtr<FileSystemDirectoryHandle> MakeResolution( 103 nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, 104 const RefPtr<FileSystemDirectoryHandle>& /* aResult */, const Name& aName, 105 RefPtr<FileSystemManager>& aManager) { 106 RefPtr<FileSystemDirectoryHandle> result = new FileSystemDirectoryHandle( 107 aGlobal, aManager, 108 FileSystemEntryMetadata(aResponse.get_EntryId(), aName, 109 /* directory */ true)); 110 111 return result; 112 } 113 114 RefPtr<FileSystemFileHandle> MakeResolution( 115 nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, 116 const RefPtr<FileSystemFileHandle>& /* aResult */, const Name& aName, 117 RefPtr<FileSystemManager>& aManager) { 118 RefPtr<FileSystemFileHandle> result = new FileSystemFileHandle( 119 aGlobal, aManager, 120 FileSystemEntryMetadata(aResponse.get_EntryId(), aName, 121 /* directory */ false)); 122 return result; 123 } 124 125 RefPtr<FileSystemSyncAccessHandle> MakeResolution( 126 nsIGlobalObject* aGlobal, FileSystemGetAccessHandleResponse&& aResponse, 127 const RefPtr<FileSystemSyncAccessHandle>& /* aReturns */, 128 const FileSystemEntryMetadata& aMetadata, 129 RefPtr<FileSystemManager>& aManager) { 130 auto& properties = aResponse.get_FileSystemAccessHandleProperties(); 131 132 QM_TRY_UNWRAP( 133 RefPtr<FileSystemSyncAccessHandle> result, 134 FileSystemSyncAccessHandle::Create( 135 aGlobal, aManager, std::move(properties.streamParams()), 136 std::move(properties.accessHandleChildEndpoint()), 137 std::move(properties.accessHandleControlChildEndpoint()), aMetadata), 138 nullptr); 139 140 return result; 141 } 142 143 RefPtr<FileSystemWritableFileStream> MakeResolution( 144 nsIGlobalObject* aGlobal, 145 FileSystemGetWritableFileStreamResponse&& aResponse, 146 const RefPtr<FileSystemWritableFileStream>& /* aReturns */, 147 const FileSystemEntryMetadata& aMetadata, 148 RefPtr<FileSystemManager>& aManager) { 149 auto& properties = aResponse.get_FileSystemWritableFileStreamProperties(); 150 151 auto* const actor = static_cast<FileSystemWritableFileStreamChild*>( 152 properties.writableFileStream().AsChild().get()); 153 154 QM_TRY_UNWRAP(RefPtr<FileSystemWritableFileStream> result, 155 FileSystemWritableFileStream::Create( 156 aGlobal, aManager, std::move(properties.streamParams()), 157 actor, aMetadata), 158 nullptr); 159 160 return result; 161 } 162 163 RefPtr<File> MakeResolution(nsIGlobalObject* aGlobal, 164 FileSystemGetFileResponse&& aResponse, 165 const RefPtr<File>& /* aResult */, 166 const Name& aName, 167 RefPtr<FileSystemManager>& aManager) { 168 auto& fileProperties = aResponse.get_FileSystemFileProperties(); 169 170 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(fileProperties.file()); 171 MOZ_ASSERT(blobImpl); 172 RefPtr<File> result = File::Create(aGlobal, blobImpl); 173 return result; 174 } 175 176 template <class TResponse, class... Args> 177 void ResolveCallback( 178 TResponse&& aResponse, 179 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 180 Args&&... args) { 181 MOZ_ASSERT(aPromise); 182 QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); 183 184 if (TResponse::Tnsresult == aResponse.type()) { 185 HandleFailedStatus(aResponse.get_nsresult(), aPromise); 186 return; 187 } 188 189 auto resolution = MakeResolution(aPromise->GetParentObject(), 190 std::forward<TResponse>(aResponse), 191 std::forward<Args>(args)...); 192 if (!resolution) { 193 aPromise->MaybeRejectWithUnknownError("Could not complete request"); 194 return; 195 } 196 197 aPromise->MaybeResolve(resolution); 198 } 199 200 template <> 201 void ResolveCallback( 202 FileSystemRemoveEntryResponse&& aResponse, 203 RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param) 204 MOZ_ASSERT(aPromise); 205 QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); 206 207 if (FileSystemRemoveEntryResponse::Tvoid_t == aResponse.type()) { 208 aPromise->MaybeResolveWithUndefined(); 209 return; 210 } 211 212 MOZ_ASSERT(FileSystemRemoveEntryResponse::Tnsresult == aResponse.type()); 213 HandleFailedStatus(aResponse.get_nsresult(), aPromise); 214 } 215 216 template <> 217 void ResolveCallback( 218 FileSystemMoveEntryResponse&& aResponse, 219 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 220 FileSystemEntryMetadata* const& aEntry, const Name& aName) { 221 MOZ_ASSERT(aPromise); 222 QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); 223 224 if (FileSystemMoveEntryResponse::TEntryId == aResponse.type()) { 225 if (aEntry) { 226 aEntry->entryId() = std::move(aResponse.get_EntryId()); 227 aEntry->entryName() = aName; 228 } 229 230 aPromise->MaybeResolveWithUndefined(); 231 return; 232 } 233 MOZ_ASSERT(FileSystemMoveEntryResponse::Tnsresult == aResponse.type()); 234 const auto& status = aResponse.get_nsresult(); 235 MOZ_ASSERT(NS_FAILED(status)); 236 HandleFailedStatus(status, aPromise); 237 } 238 239 template <> 240 void ResolveCallback(FileSystemResolveResponse&& aResponse, 241 // NOLINTNEXTLINE(performance-unnecessary-value-param) 242 RefPtr<Promise> aPromise) { 243 MOZ_ASSERT(aPromise); 244 QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); 245 246 if (FileSystemResolveResponse::Tnsresult == aResponse.type()) { 247 HandleFailedStatus(aResponse.get_nsresult(), aPromise); 248 return; 249 } 250 251 auto& maybePath = aResponse.get_MaybeFileSystemPath(); 252 if (maybePath.isSome()) { 253 aPromise->MaybeResolve(maybePath.value().path()); 254 return; 255 } 256 257 // Spec says if there is no parent/child relationship, return null 258 aPromise->MaybeResolve(JS::NullHandleValue); 259 } 260 261 template <class TResponse, class TReturns, class... Args, 262 std::enable_if_t<std::is_same<TReturns, void>::value, bool> = true> 263 mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback( 264 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 265 Args&&... args) { 266 using TOverload = void (*)(TResponse&&, RefPtr<Promise>, Args...); 267 return static_cast<std::function<void(TResponse&&)>>( 268 // NOLINTNEXTLINE(modernize-avoid-bind) 269 std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1, 270 aPromise, std::forward<Args>(args)...)); 271 } 272 273 template <class TResponse, class TReturns, class... Args, 274 std::enable_if_t<!std::is_same<TReturns, void>::value, bool> = true> 275 mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback( 276 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 277 Args&&... args) { 278 using TOverload = 279 void (*)(TResponse&&, RefPtr<Promise>, const TReturns&, Args...); 280 return static_cast<std::function<void(TResponse&&)>>( 281 // NOLINTNEXTLINE(modernize-avoid-bind) 282 std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1, 283 aPromise, TReturns(), std::forward<Args>(args)...)); 284 } 285 286 void RejectCallback( 287 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 288 mozilla::ipc::ResponseRejectReason aReason) { 289 IPCRejectReporter(aReason); 290 QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); 291 aPromise->MaybeRejectWithUndefined(); 292 } 293 294 mozilla::ipc::RejectCallback GetRejectCallback( 295 RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param) 296 return static_cast<mozilla::ipc::RejectCallback>( 297 // NOLINTNEXTLINE(modernize-avoid-bind) 298 std::bind(RejectCallback, aPromise, std::placeholders::_1)); 299 } 300 301 struct BeginRequestFailureCallback { 302 explicit BeginRequestFailureCallback(RefPtr<Promise> aPromise) 303 : mPromise(std::move(aPromise)) {} 304 305 void operator()(nsresult aRv) const { 306 if (aRv == NS_ERROR_ABORT) { 307 mPromise->MaybeRejectWithAbortError( 308 "Abort error when calling GetDirectory"); 309 return; 310 } 311 if (aRv == NS_ERROR_DOM_SECURITY_ERR) { 312 mPromise->MaybeRejectWithSecurityError( 313 "Security error when calling GetDirectory"); 314 return; 315 } 316 mPromise->MaybeRejectWithUnknownError("Could not create actor"); 317 } 318 319 RefPtr<Promise> mPromise; 320 }; 321 322 } // namespace 323 324 void FileSystemRequestHandler::GetRootHandle( 325 RefPtr<FileSystemManager> 326 aManager, // NOLINT(performance-unnecessary-value-param) 327 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 328 ErrorResult& aError) { 329 MOZ_ASSERT(aManager); 330 MOZ_ASSERT(aPromise); 331 LOG(("GetRootHandle")); 332 333 if (aManager->IsShutdown()) { 334 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 335 return; 336 } 337 338 aManager->BeginRequest( 339 [onResolve = SelectResolveCallback<FileSystemGetHandleResponse, 340 RefPtr<FileSystemDirectoryHandle>>( 341 aPromise, aManager), 342 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 343 actor->SendGetRootHandle(std::move(onResolve), std::move(onReject)); 344 }, 345 BeginRequestFailureCallback(aPromise)); 346 } 347 348 void FileSystemRequestHandler::GetDirectoryHandle( 349 RefPtr<FileSystemManager>& aManager, 350 const FileSystemChildMetadata& aDirectory, bool aCreate, 351 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 352 ErrorResult& aError) { 353 MOZ_ASSERT(aManager); 354 MOZ_ASSERT(!aDirectory.parentId().IsEmpty()); 355 MOZ_ASSERT(aPromise); 356 LOG(("GetDirectoryHandle")); 357 358 if (aManager->IsShutdown()) { 359 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 360 return; 361 } 362 363 if (!IsValidName(aDirectory.childName())) { 364 aPromise->MaybeRejectWithTypeError("Invalid directory name"); 365 return; 366 } 367 368 aManager->BeginRequest( 369 [request = FileSystemGetHandleRequest(aDirectory, aCreate), 370 onResolve = SelectResolveCallback<FileSystemGetHandleResponse, 371 RefPtr<FileSystemDirectoryHandle>>( 372 aPromise, aDirectory.childName(), aManager), 373 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 374 actor->SendGetDirectoryHandle(request, std::move(onResolve), 375 std::move(onReject)); 376 }, 377 BeginRequestFailureCallback(aPromise)); 378 } 379 380 void FileSystemRequestHandler::GetFileHandle( 381 RefPtr<FileSystemManager>& aManager, const FileSystemChildMetadata& aFile, 382 bool aCreate, 383 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 384 ErrorResult& aError) { 385 MOZ_ASSERT(aManager); 386 MOZ_ASSERT(!aFile.parentId().IsEmpty()); 387 MOZ_ASSERT(aPromise); 388 LOG(("GetFileHandle")); 389 390 if (aManager->IsShutdown()) { 391 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 392 return; 393 } 394 395 if (!IsValidName(aFile.childName())) { 396 aPromise->MaybeRejectWithTypeError("Invalid filename"); 397 return; 398 } 399 400 aManager->BeginRequest( 401 [request = FileSystemGetHandleRequest(aFile, aCreate), 402 onResolve = SelectResolveCallback<FileSystemGetHandleResponse, 403 RefPtr<FileSystemFileHandle>>( 404 aPromise, aFile.childName(), aManager), 405 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 406 actor->SendGetFileHandle(request, std::move(onResolve), 407 std::move(onReject)); 408 }, 409 BeginRequestFailureCallback(aPromise)); 410 } 411 412 void FileSystemRequestHandler::GetAccessHandle( 413 RefPtr<FileSystemManager>& aManager, const FileSystemEntryMetadata& aFile, 414 const RefPtr<Promise>& aPromise, ErrorResult& aError) { 415 MOZ_ASSERT(aManager); 416 MOZ_ASSERT(aPromise); 417 LOG(("GetAccessHandle %s", NS_ConvertUTF16toUTF8(aFile.entryName()).get())); 418 419 if (aManager->IsShutdown()) { 420 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 421 return; 422 } 423 424 aManager->BeginRequest( 425 [request = FileSystemGetAccessHandleRequest(aFile.entryId()), 426 onResolve = SelectResolveCallback<FileSystemGetAccessHandleResponse, 427 RefPtr<FileSystemSyncAccessHandle>>( 428 aPromise, aFile, aManager), 429 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 430 actor->SendGetAccessHandle(request, std::move(onResolve), 431 std::move(onReject)); 432 }, 433 BeginRequestFailureCallback(aPromise)); 434 } 435 436 void FileSystemRequestHandler::GetWritable(RefPtr<FileSystemManager>& aManager, 437 const FileSystemEntryMetadata& aFile, 438 bool aKeepData, 439 const RefPtr<Promise>& aPromise, 440 ErrorResult& aError) { 441 MOZ_ASSERT(aManager); 442 MOZ_ASSERT(aPromise); 443 LOG(("GetWritable %s keep %d", NS_ConvertUTF16toUTF8(aFile.entryName()).get(), 444 aKeepData)); 445 446 // XXX This should be removed once bug 1798513 is fixed. 447 if (!StaticPrefs::dom_fs_writable_file_stream_enabled()) { 448 aError.Throw(NS_ERROR_NOT_IMPLEMENTED); 449 return; 450 } 451 452 if (aManager->IsShutdown()) { 453 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 454 return; 455 } 456 457 aManager->BeginRequest( 458 [request = FileSystemGetWritableRequest(aFile.entryId(), aKeepData), 459 onResolve = 460 SelectResolveCallback<FileSystemGetWritableFileStreamResponse, 461 RefPtr<FileSystemWritableFileStream>>( 462 aPromise, aFile, aManager), 463 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 464 actor->SendGetWritable(request, std::move(onResolve), 465 std::move(onReject)); 466 }, 467 [promise = aPromise](const auto&) { 468 promise->MaybeRejectWithUnknownError("Could not create actor"); 469 }); 470 } 471 472 void FileSystemRequestHandler::GetFile( 473 RefPtr<FileSystemManager>& aManager, const FileSystemEntryMetadata& aFile, 474 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 475 ErrorResult& aError) { 476 MOZ_ASSERT(aManager); 477 MOZ_ASSERT(!aFile.entryId().IsEmpty()); 478 MOZ_ASSERT(aPromise); 479 LOG(("GetFile %s", NS_ConvertUTF16toUTF8(aFile.entryName()).get())); 480 481 if (aManager->IsShutdown()) { 482 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 483 return; 484 } 485 486 aManager->BeginRequest( 487 [request = FileSystemGetFileRequest(aFile.entryId()), 488 onResolve = 489 SelectResolveCallback<FileSystemGetFileResponse, RefPtr<File>>( 490 aPromise, aFile.entryName(), aManager), 491 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 492 actor->SendGetFile(request, std::move(onResolve), std::move(onReject)); 493 }, 494 BeginRequestFailureCallback(aPromise)); 495 } 496 497 void FileSystemRequestHandler::GetEntries( 498 RefPtr<FileSystemManager>& aManager, const EntryId& aDirectory, 499 PageNumber aPage, 500 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 501 RefPtr<FileSystemEntryMetadataArray>& aSink, ErrorResult& aError) { 502 MOZ_ASSERT(aManager); 503 MOZ_ASSERT(!aDirectory.IsEmpty()); 504 MOZ_ASSERT(aPromise); 505 LOG(("GetEntries, page %u", aPage)); 506 507 if (aManager->IsShutdown()) { 508 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 509 return; 510 } 511 512 aManager->BeginRequest( 513 [request = FileSystemGetEntriesRequest(aDirectory, aPage), 514 onResolve = SelectResolveCallback<FileSystemGetEntriesResponse, bool>( 515 aPromise, aSink), 516 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 517 actor->SendGetEntries(request, std::move(onResolve), 518 std::move(onReject)); 519 }, 520 BeginRequestFailureCallback(aPromise)); 521 } 522 523 void FileSystemRequestHandler::RemoveEntry( 524 RefPtr<FileSystemManager>& aManager, const FileSystemChildMetadata& aEntry, 525 bool aRecursive, 526 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 527 ErrorResult& aError) { 528 MOZ_ASSERT(aManager); 529 MOZ_ASSERT(!aEntry.parentId().IsEmpty()); 530 MOZ_ASSERT(aPromise); 531 LOG(("RemoveEntry")); 532 533 if (aManager->IsShutdown()) { 534 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 535 return; 536 } 537 538 if (!IsValidName(aEntry.childName())) { 539 aPromise->MaybeRejectWithTypeError("Invalid name"); 540 return; 541 } 542 543 aManager->BeginRequest( 544 [request = FileSystemRemoveEntryRequest(aEntry, aRecursive), 545 onResolve = 546 SelectResolveCallback<FileSystemRemoveEntryResponse, void>(aPromise), 547 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 548 actor->SendRemoveEntry(request, std::move(onResolve), 549 std::move(onReject)); 550 }, 551 BeginRequestFailureCallback(aPromise)); 552 } 553 554 void FileSystemRequestHandler::MoveEntry( 555 RefPtr<FileSystemManager>& aManager, FileSystemHandle* aHandle, 556 FileSystemEntryMetadata* const aEntry, 557 const FileSystemChildMetadata& aNewEntry, 558 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 559 ErrorResult& aError) { 560 MOZ_ASSERT(aEntry); 561 MOZ_ASSERT(!aEntry->entryId().IsEmpty()); 562 MOZ_ASSERT(aPromise); 563 LOG(("MoveEntry")); 564 565 if (aManager->IsShutdown()) { 566 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 567 return; 568 } 569 570 // reject invalid names: empty, path separators, current & parent directories 571 if (!IsValidName(aNewEntry.childName())) { 572 aPromise->MaybeRejectWithTypeError("Invalid name"); 573 return; 574 } 575 576 aManager->BeginRequest( 577 [request = FileSystemMoveEntryRequest(*aEntry, aNewEntry), 578 onResolve = SelectResolveCallback<FileSystemMoveEntryResponse, void>( 579 aPromise, aEntry, aNewEntry.childName()), 580 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 581 actor->SendMoveEntry(request, std::move(onResolve), 582 std::move(onReject)); 583 }, 584 BeginRequestFailureCallback(aPromise)); 585 } 586 587 void FileSystemRequestHandler::RenameEntry( 588 RefPtr<FileSystemManager>& aManager, FileSystemHandle* aHandle, 589 FileSystemEntryMetadata* const aEntry, const Name& aName, 590 RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) 591 ErrorResult& aError) { 592 MOZ_ASSERT(aEntry); 593 MOZ_ASSERT(!aEntry->entryId().IsEmpty()); 594 MOZ_ASSERT(aPromise); 595 LOG(("RenameEntry")); 596 597 if (aManager->IsShutdown()) { 598 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 599 return; 600 } 601 602 // reject invalid names: empty, path separators, current & parent directories 603 if (!IsValidName(aName)) { 604 aPromise->MaybeRejectWithTypeError("Invalid name"); 605 return; 606 } 607 608 aManager->BeginRequest( 609 [request = FileSystemRenameEntryRequest(*aEntry, aName), 610 onResolve = SelectResolveCallback<FileSystemMoveEntryResponse, void>( 611 aPromise, aEntry, aName), 612 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 613 actor->SendRenameEntry(request, std::move(onResolve), 614 std::move(onReject)); 615 }, 616 BeginRequestFailureCallback(aPromise)); 617 } 618 619 void FileSystemRequestHandler::Resolve( 620 RefPtr<FileSystemManager>& aManager, 621 // NOLINTNEXTLINE(performance-unnecessary-value-param) 622 const FileSystemEntryPair& aEndpoints, RefPtr<Promise> aPromise, 623 ErrorResult& aError) { 624 MOZ_ASSERT(aManager); 625 MOZ_ASSERT(!aEndpoints.parentId().IsEmpty()); 626 MOZ_ASSERT(!aEndpoints.childId().IsEmpty()); 627 MOZ_ASSERT(aPromise); 628 LOG(("Resolve")); 629 630 if (aManager->IsShutdown()) { 631 aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); 632 return; 633 } 634 635 aManager->BeginRequest( 636 [request = FileSystemResolveRequest(aEndpoints), 637 onResolve = 638 SelectResolveCallback<FileSystemResolveResponse, void>(aPromise), 639 onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { 640 actor->SendResolve(request, std::move(onResolve), std::move(onReject)); 641 }, 642 BeginRequestFailureCallback(aPromise)); 643 } 644 645 } // namespace mozilla::dom::fs