diff options
Diffstat (limited to '')
-rw-r--r-- | dom/fs/child/FileSystemRequestHandler.cpp | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/dom/fs/child/FileSystemRequestHandler.cpp b/dom/fs/child/FileSystemRequestHandler.cpp new file mode 100644 index 0000000000..87c06e409a --- /dev/null +++ b/dom/fs/child/FileSystemRequestHandler.cpp @@ -0,0 +1,648 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "fs/FileSystemRequestHandler.h" + +#include "FileSystemEntryMetadataArray.h" +#include "fs/FileSystemConstants.h" +#include "mozilla/ResultVariant.h" +#include "mozilla/StaticPrefs_dom.h" +#include "mozilla/dom/BlobImpl.h" +#include "mozilla/dom/File.h" +#include "mozilla/dom/FileSystemAccessHandleChild.h" +#include "mozilla/dom/FileSystemDirectoryHandle.h" +#include "mozilla/dom/FileSystemFileHandle.h" +#include "mozilla/dom/FileSystemHandle.h" +#include "mozilla/dom/FileSystemHelpers.h" +#include "mozilla/dom/FileSystemLog.h" +#include "mozilla/dom/FileSystemManager.h" +#include "mozilla/dom/FileSystemManagerChild.h" +#include "mozilla/dom/FileSystemSyncAccessHandle.h" +#include "mozilla/dom/FileSystemWritableFileStream.h" +#include "mozilla/dom/FileSystemWritableFileStreamChild.h" +#include "mozilla/dom/IPCBlobUtils.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/quota/QuotaCommon.h" + +namespace mozilla::dom::fs { + +using mozilla::ipc::RejectCallback; + +namespace { + +void HandleFailedStatus(nsresult aError, const RefPtr<Promise>& aPromise) { + switch (aError) { + case NS_ERROR_FILE_ACCESS_DENIED: + aPromise->MaybeRejectWithNotAllowedError("Permission denied"); + break; + case NS_ERROR_DOM_NOT_FOUND_ERR: + aPromise->MaybeRejectWithNotFoundError("Entry not found"); + break; + case NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR: + aPromise->MaybeRejectWithInvalidModificationError("Disallowed by system"); + break; + case NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR: + aPromise->MaybeRejectWithNoModificationAllowedError( + "No modification allowed"); + break; + case NS_ERROR_DOM_TYPE_MISMATCH_ERR: + aPromise->MaybeRejectWithTypeMismatchError("Wrong type"); + break; + case NS_ERROR_DOM_INVALID_MODIFICATION_ERR: + aPromise->MaybeRejectWithInvalidModificationError("Invalid modification"); + break; + default: + if (NS_FAILED(aError)) { + aPromise->MaybeRejectWithUnknownError("Unknown failure"); + } else { + aPromise->MaybeResolveWithUndefined(); + } + break; + } +} + +bool MakeResolution(nsIGlobalObject* aGlobal, + FileSystemGetEntriesResponse&& aResponse, + const bool& /* aResult */, + RefPtr<FileSystemEntryMetadataArray>& aSink) { + // TODO: Add page size to FileSystemConstants, preallocate and handle overflow + const auto& listing = aResponse.get_FileSystemDirectoryListing(); + + for (const auto& it : listing.files()) { + aSink->AppendElement(it); + } + + for (const auto& it : listing.directories()) { + aSink->AppendElement(it); + } + + return true; +} + +RefPtr<FileSystemDirectoryHandle> MakeResolution( + nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, + const RefPtr<FileSystemDirectoryHandle>& /* aResult */, + RefPtr<FileSystemManager>& aManager) { + RefPtr<FileSystemDirectoryHandle> result = new FileSystemDirectoryHandle( + aGlobal, aManager, + FileSystemEntryMetadata(aResponse.get_EntryId(), kRootName, + /* directory */ true)); + return result; +} + +RefPtr<FileSystemDirectoryHandle> MakeResolution( + nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, + const RefPtr<FileSystemDirectoryHandle>& /* aResult */, const Name& aName, + RefPtr<FileSystemManager>& aManager) { + RefPtr<FileSystemDirectoryHandle> result = new FileSystemDirectoryHandle( + aGlobal, aManager, + FileSystemEntryMetadata(aResponse.get_EntryId(), aName, + /* directory */ true)); + + return result; +} + +RefPtr<FileSystemFileHandle> MakeResolution( + nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, + const RefPtr<FileSystemFileHandle>& /* aResult */, const Name& aName, + RefPtr<FileSystemManager>& aManager) { + RefPtr<FileSystemFileHandle> result = new FileSystemFileHandle( + aGlobal, aManager, + FileSystemEntryMetadata(aResponse.get_EntryId(), aName, + /* directory */ false)); + return result; +} + +RefPtr<FileSystemSyncAccessHandle> MakeResolution( + nsIGlobalObject* aGlobal, FileSystemGetAccessHandleResponse&& aResponse, + const RefPtr<FileSystemSyncAccessHandle>& /* aReturns */, + const FileSystemEntryMetadata& aMetadata, + RefPtr<FileSystemManager>& aManager) { + auto& properties = aResponse.get_FileSystemAccessHandleProperties(); + + auto* const actor = + static_cast<FileSystemAccessHandleChild*>(properties.accessHandleChild()); + + QM_TRY_UNWRAP(RefPtr<FileSystemSyncAccessHandle> result, + FileSystemSyncAccessHandle::Create( + aGlobal, aManager, actor, + std::move(properties.streamParams()), aMetadata), + nullptr); + + return result; +} + +RefPtr<FileSystemWritableFileStream> MakeResolution( + nsIGlobalObject* aGlobal, + FileSystemGetWritableFileStreamResponse&& aResponse, + const RefPtr<FileSystemWritableFileStream>& /* aReturns */, + const FileSystemEntryMetadata& aMetadata, + RefPtr<FileSystemManager>& aManager) { + const auto& properties = + aResponse.get_FileSystemWritableFileStreamProperties(); + + auto* const actor = static_cast<FileSystemWritableFileStreamChild*>( + properties.writableFileStreamChild()); + + RefPtr<FileSystemWritableFileStream> result = + FileSystemWritableFileStream::Create( + aGlobal, aManager, actor, properties.fileDescriptor(), aMetadata); + + return result; +} + +RefPtr<File> MakeResolution(nsIGlobalObject* aGlobal, + FileSystemGetFileResponse&& aResponse, + const RefPtr<File>& /* aResult */, + const Name& aName, + RefPtr<FileSystemManager>& aManager) { + auto& fileProperties = aResponse.get_FileSystemFileProperties(); + + RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(fileProperties.file()); + MOZ_ASSERT(blobImpl); + RefPtr<File> result = File::Create(aGlobal, blobImpl); + return result; +} + +template <class TResponse, class... Args> +void ResolveCallback( + TResponse&& aResponse, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + Args&&... args) { + MOZ_ASSERT(aPromise); + QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); + + if (TResponse::Tnsresult == aResponse.type()) { + HandleFailedStatus(aResponse.get_nsresult(), aPromise); + return; + } + + auto resolution = MakeResolution(aPromise->GetParentObject(), + std::forward<TResponse>(aResponse), + std::forward<Args>(args)...); + if (!resolution) { + aPromise->MaybeRejectWithUnknownError("Could not complete request"); + return; + } + + aPromise->MaybeResolve(resolution); +} + +template <> +void ResolveCallback( + FileSystemRemoveEntryResponse&& aResponse, + RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param) + MOZ_ASSERT(aPromise); + QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); + + if (FileSystemRemoveEntryResponse::Tvoid_t == aResponse.type()) { + aPromise->MaybeResolveWithUndefined(); + return; + } + + MOZ_ASSERT(FileSystemRemoveEntryResponse::Tnsresult == aResponse.type()); + HandleFailedStatus(aResponse.get_nsresult(), aPromise); +} + +template <> +void ResolveCallback( + FileSystemMoveEntryResponse&& aResponse, + RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param) + MOZ_ASSERT(aPromise); + QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); + + MOZ_ASSERT(FileSystemMoveEntryResponse::Tnsresult == aResponse.type()); + const auto& status = aResponse.get_nsresult(); + if (NS_OK == status) { + aPromise->MaybeResolveWithUndefined(); + return; + } + HandleFailedStatus(status, aPromise); +} + +template <> +void ResolveCallback(FileSystemResolveResponse&& aResponse, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + RefPtr<Promise> aPromise) { + MOZ_ASSERT(aPromise); + QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); + + if (FileSystemResolveResponse::Tnsresult == aResponse.type()) { + HandleFailedStatus(aResponse.get_nsresult(), aPromise); + return; + } + + auto& maybePath = aResponse.get_MaybeFileSystemPath(); + if (maybePath.isSome()) { + aPromise->MaybeResolve(maybePath.value().path()); + return; + } + + // Spec says if there is no parent/child relationship, return null + aPromise->MaybeResolve(JS::NullHandleValue); +} + +template <class TResponse, class TReturns, class... Args, + std::enable_if_t<std::is_same<TReturns, void>::value, bool> = true> +mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback( + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + Args&&... args) { + using TOverload = void (*)(TResponse&&, RefPtr<Promise>, Args...); + return static_cast<std::function<void(TResponse &&)>>( + // NOLINTNEXTLINE(modernize-avoid-bind) + std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1, + aPromise, std::forward<Args>(args)...)); +} + +template <class TResponse, class TReturns, class... Args, + std::enable_if_t<!std::is_same<TReturns, void>::value, bool> = true> +mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback( + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + Args&&... args) { + using TOverload = + void (*)(TResponse&&, RefPtr<Promise>, const TReturns&, Args...); + return static_cast<std::function<void(TResponse &&)>>( + // NOLINTNEXTLINE(modernize-avoid-bind) + std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1, + aPromise, TReturns(), std::forward<Args>(args)...)); +} + +// TODO: Find a better way to deal with these errors +void IPCRejectReporter(mozilla::ipc::ResponseRejectReason aReason) { + switch (aReason) { + case mozilla::ipc::ResponseRejectReason::ActorDestroyed: + // This is ok + break; + case mozilla::ipc::ResponseRejectReason::HandlerRejected: + QM_TRY(OkIf(false), QM_VOID); + break; + case mozilla::ipc::ResponseRejectReason::ChannelClosed: + QM_TRY(OkIf(false), QM_VOID); + break; + case mozilla::ipc::ResponseRejectReason::ResolverDestroyed: + QM_TRY(OkIf(false), QM_VOID); + break; + case mozilla::ipc::ResponseRejectReason::SendError: + QM_TRY(OkIf(false), QM_VOID); + break; + default: + QM_TRY(OkIf(false), QM_VOID); + break; + } +} + +void RejectCallback( + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + mozilla::ipc::ResponseRejectReason aReason) { + IPCRejectReporter(aReason); + QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID); + aPromise->MaybeRejectWithUndefined(); +} + +mozilla::ipc::RejectCallback GetRejectCallback( + RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param) + return static_cast<mozilla::ipc::RejectCallback>( + // NOLINTNEXTLINE(modernize-avoid-bind) + std::bind(RejectCallback, aPromise, std::placeholders::_1)); +} + +struct BeginRequestFailureCallback { + explicit BeginRequestFailureCallback(RefPtr<Promise> aPromise) + : mPromise(std::move(aPromise)) {} + + void operator()(nsresult aRv) const { + if (aRv == NS_ERROR_DOM_SECURITY_ERR) { + mPromise->MaybeRejectWithSecurityError( + "Security error when calling GetDirectory"); + return; + } + mPromise->MaybeRejectWithUnknownError("Could not create actor"); + } + + RefPtr<Promise> mPromise; +}; + +} // namespace + +void FileSystemRequestHandler::GetRootHandle( + RefPtr<FileSystemManager> + aManager, // NOLINT(performance-unnecessary-value-param) + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(aPromise); + LOG(("GetRootHandle")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [onResolve = SelectResolveCallback<FileSystemGetHandleResponse, + RefPtr<FileSystemDirectoryHandle>>( + aPromise, aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetRootHandle(std::move(onResolve), std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::GetDirectoryHandle( + RefPtr<FileSystemManager>& aManager, + const FileSystemChildMetadata& aDirectory, bool aCreate, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aDirectory.parentId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("GetDirectoryHandle")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + if (!IsValidName(aDirectory.childName())) { + aPromise->MaybeRejectWithTypeError("Invalid directory name"); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetHandleRequest(aDirectory, aCreate), + onResolve = SelectResolveCallback<FileSystemGetHandleResponse, + RefPtr<FileSystemDirectoryHandle>>( + aPromise, aDirectory.childName(), aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetDirectoryHandle(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::GetFileHandle( + RefPtr<FileSystemManager>& aManager, const FileSystemChildMetadata& aFile, + bool aCreate, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aFile.parentId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("GetFileHandle")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + if (!IsValidName(aFile.childName())) { + aPromise->MaybeRejectWithTypeError("Invalid filename"); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetHandleRequest(aFile, aCreate), + onResolve = SelectResolveCallback<FileSystemGetHandleResponse, + RefPtr<FileSystemFileHandle>>( + aPromise, aFile.childName(), aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetFileHandle(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::GetAccessHandle( + RefPtr<FileSystemManager>& aManager, const FileSystemEntryMetadata& aFile, + const RefPtr<Promise>& aPromise, ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(aPromise); + LOG(("GetAccessHandle %s", NS_ConvertUTF16toUTF8(aFile.entryName()).get())); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetAccessHandleRequest(aFile.entryId()), + onResolve = SelectResolveCallback<FileSystemGetAccessHandleResponse, + RefPtr<FileSystemSyncAccessHandle>>( + aPromise, aFile, aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetAccessHandle(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::GetWritable(RefPtr<FileSystemManager>& aManager, + const FileSystemEntryMetadata& aFile, + bool aKeepData, + const RefPtr<Promise>& aPromise, + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(aPromise); + LOG(("GetWritable %s keep %d", NS_ConvertUTF16toUTF8(aFile.entryName()).get(), + aKeepData)); + + // XXX This should be removed once bug 1798513 is fixed. + if (!StaticPrefs::dom_fs_writable_file_stream_enabled()) { + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); + return; + } + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetWritableRequest(aFile.entryId(), aKeepData), + onResolve = + SelectResolveCallback<FileSystemGetWritableFileStreamResponse, + RefPtr<FileSystemWritableFileStream>>( + aPromise, aFile, aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetWritable(request, std::move(onResolve), + std::move(onReject)); + }, + [promise = aPromise](const auto&) { + promise->MaybeRejectWithUnknownError("Could not create actor"); + }); +} + +void FileSystemRequestHandler::GetFile( + RefPtr<FileSystemManager>& aManager, const FileSystemEntryMetadata& aFile, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aFile.entryId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("GetFile %s", NS_ConvertUTF16toUTF8(aFile.entryName()).get())); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetFileRequest(aFile.entryId()), + onResolve = + SelectResolveCallback<FileSystemGetFileResponse, RefPtr<File>>( + aPromise, aFile.entryName(), aManager), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetFile(request, std::move(onResolve), std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::GetEntries( + RefPtr<FileSystemManager>& aManager, const EntryId& aDirectory, + PageNumber aPage, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + RefPtr<FileSystemEntryMetadataArray>& aSink, ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aDirectory.IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("GetEntries, page %u", aPage)); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [request = FileSystemGetEntriesRequest(aDirectory, aPage), + onResolve = SelectResolveCallback<FileSystemGetEntriesResponse, bool>( + aPromise, aSink), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendGetEntries(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::RemoveEntry( + RefPtr<FileSystemManager>& aManager, const FileSystemChildMetadata& aEntry, + bool aRecursive, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aEntry.parentId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("RemoveEntry")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + if (!IsValidName(aEntry.childName())) { + aPromise->MaybeRejectWithTypeError("Invalid name"); + return; + } + + aManager->BeginRequest( + [request = FileSystemRemoveEntryRequest(aEntry, aRecursive), + onResolve = + SelectResolveCallback<FileSystemRemoveEntryResponse, void>(aPromise), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendRemoveEntry(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::MoveEntry( + RefPtr<FileSystemManager>& aManager, FileSystemHandle* aHandle, + const FileSystemEntryMetadata& aEntry, + const FileSystemChildMetadata& aNewEntry, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(aPromise); + LOG(("MoveEntry")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + // reject invalid names: empty, path separators, current & parent directories + if (!IsValidName(aNewEntry.childName())) { + aPromise->MaybeRejectWithTypeError("Invalid name"); + return; + } + + aManager->BeginRequest( + [request = FileSystemMoveEntryRequest(aEntry, aNewEntry), + onResolve = + SelectResolveCallback<FileSystemMoveEntryResponse, void>(aPromise), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendMoveEntry(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::RenameEntry( + RefPtr<FileSystemManager>& aManager, FileSystemHandle* aHandle, + const FileSystemEntryMetadata& aEntry, const Name& aName, + RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param) + ErrorResult& aError) { + MOZ_ASSERT(!aEntry.entryId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("RenameEntry")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + // reject invalid names: empty, path separators, current & parent directories + if (!IsValidName(aName)) { + aPromise->MaybeRejectWithTypeError("Invalid name"); + return; + } + + aManager->BeginRequest( + [request = FileSystemRenameEntryRequest(aEntry, aName), + onResolve = + SelectResolveCallback<FileSystemMoveEntryResponse, void>(aPromise), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendRenameEntry(request, std::move(onResolve), + std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +void FileSystemRequestHandler::Resolve( + RefPtr<FileSystemManager>& aManager, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + const FileSystemEntryPair& aEndpoints, RefPtr<Promise> aPromise, + ErrorResult& aError) { + MOZ_ASSERT(aManager); + MOZ_ASSERT(!aEndpoints.parentId().IsEmpty()); + MOZ_ASSERT(!aEndpoints.childId().IsEmpty()); + MOZ_ASSERT(aPromise); + LOG(("Resolve")); + + if (aManager->IsShutdown()) { + aError.Throw(NS_ERROR_ILLEGAL_DURING_SHUTDOWN); + return; + } + + aManager->BeginRequest( + [request = FileSystemResolveRequest(aEndpoints), + onResolve = + SelectResolveCallback<FileSystemResolveResponse, void>(aPromise), + onReject = GetRejectCallback(aPromise)](const auto& actor) mutable { + actor->SendResolve(request, std::move(onResolve), std::move(onReject)); + }, + BeginRequestFailureCallback(aPromise)); +} + +} // namespace mozilla::dom::fs |