tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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