tor-browser

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

FileSystemAccessHandle.cpp (7998B)


      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 "FileSystemAccessHandle.h"
      8 
      9 #include "FileSystemDatabaseManager.h"
     10 #include "FileSystemParentTypes.h"
     11 #include "mozilla/dom/FileSystemDataManager.h"
     12 #include "mozilla/dom/FileSystemHelpers.h"
     13 #include "mozilla/dom/FileSystemLog.h"
     14 #include "mozilla/dom/quota/FileStreams.h"
     15 #include "mozilla/dom/quota/QuotaCommon.h"
     16 #include "mozilla/dom/quota/RemoteQuotaObjectParent.h"
     17 #include "mozilla/dom/quota/ResultExtensions.h"
     18 #include "mozilla/ipc/RandomAccessStreamParams.h"
     19 #include "mozilla/ipc/RandomAccessStreamUtils.h"
     20 #include "nsIFileStreams.h"
     21 
     22 namespace mozilla::dom {
     23 
     24 FileSystemAccessHandle::FileSystemAccessHandle(
     25    RefPtr<fs::data::FileSystemDataManager> aDataManager,
     26    const fs::EntryId& aEntryId, MovingNotNull<RefPtr<TaskQueue>> aIOTaskQueue)
     27    : mEntryId(aEntryId),
     28      mDataManager(std::move(aDataManager)),
     29      mIOTaskQueue(std::move(aIOTaskQueue)),
     30      mActor(nullptr),
     31      mControlActor(nullptr),
     32      mRegCount(0),
     33      mLocked(false),
     34      mRegistered(false),
     35      mClosed(false) {}
     36 
     37 FileSystemAccessHandle::~FileSystemAccessHandle() {
     38  MOZ_DIAGNOSTIC_ASSERT(mClosed);
     39 }
     40 
     41 // static
     42 RefPtr<FileSystemAccessHandle::CreatePromise> FileSystemAccessHandle::Create(
     43    RefPtr<fs::data::FileSystemDataManager> aDataManager,
     44    const fs::EntryId& aEntryId) {
     45  MOZ_ASSERT(aDataManager);
     46  aDataManager->AssertIsOnIOTarget();
     47 
     48  RefPtr<TaskQueue> ioTaskQueue = TaskQueue::Create(
     49      do_AddRef(aDataManager->MutableIOTargetPtr()), "FileSystemAccessHandle");
     50 
     51  RefPtr<FileSystemAccessHandle> accessHandle = new FileSystemAccessHandle(
     52      std::move(aDataManager), aEntryId, WrapMovingNotNull(ioTaskQueue));
     53 
     54  return accessHandle->BeginInit()->Then(
     55      GetCurrentSerialEventTarget(), __func__,
     56      [accessHandle = fs::Registered<FileSystemAccessHandle>(accessHandle)](
     57          InitPromise::ResolveOrRejectValue&& value) mutable {
     58        if (value.IsReject()) {
     59          return CreatePromise::CreateAndReject(value.RejectValue(), __func__);
     60        }
     61 
     62        mozilla::ipc::RandomAccessStreamParams streamParams =
     63            std::move(value.ResolveValue());
     64 
     65        return CreatePromise::CreateAndResolve(
     66            std::pair(std::move(accessHandle), std::move(streamParams)),
     67            __func__);
     68      });
     69 }
     70 
     71 NS_IMPL_ISUPPORTS_INHERITED0(FileSystemAccessHandle, FileSystemStreamCallbacks)
     72 
     73 void FileSystemAccessHandle::Register() { ++mRegCount; }
     74 
     75 void FileSystemAccessHandle::Unregister() {
     76  MOZ_ASSERT(mRegCount > 0);
     77 
     78  --mRegCount;
     79 
     80  if (IsInactive() && IsOpen()) {
     81    BeginClose();
     82  }
     83 }
     84 
     85 void FileSystemAccessHandle::RegisterActor(
     86    NotNull<FileSystemAccessHandleParent*> aActor) {
     87  MOZ_ASSERT(!mActor);
     88 
     89  mActor = aActor;
     90 }
     91 
     92 void FileSystemAccessHandle::UnregisterActor(
     93    NotNull<FileSystemAccessHandleParent*> aActor) {
     94  MOZ_ASSERT(mActor);
     95  MOZ_ASSERT(mActor == aActor);
     96 
     97  mActor = nullptr;
     98 
     99  if (IsInactive() && IsOpen()) {
    100    BeginClose();
    101  }
    102 }
    103 
    104 void FileSystemAccessHandle::RegisterControlActor(
    105    NotNull<FileSystemAccessHandleControlParent*> aControlActor) {
    106  MOZ_ASSERT(!mControlActor);
    107 
    108  mControlActor = aControlActor;
    109 }
    110 
    111 void FileSystemAccessHandle::UnregisterControlActor(
    112    NotNull<FileSystemAccessHandleControlParent*> aControlActor) {
    113  MOZ_ASSERT(mControlActor);
    114  MOZ_ASSERT(mControlActor == aControlActor);
    115 
    116  mControlActor = nullptr;
    117 
    118  if (IsInactive() && IsOpen()) {
    119    BeginClose();
    120  }
    121 }
    122 
    123 bool FileSystemAccessHandle::IsOpen() const { return !mClosed; }
    124 
    125 RefPtr<BoolPromise> FileSystemAccessHandle::BeginClose() {
    126  MOZ_ASSERT(IsOpen());
    127 
    128  LOG(("Closing AccessHandle"));
    129 
    130  mClosed = true;
    131 
    132  return InvokeAsync(mIOTaskQueue.get(), __func__,
    133                     [self = RefPtr(this)]() {
    134                       if (self->mRemoteQuotaObjectParent) {
    135                         self->mRemoteQuotaObjectParent->Close();
    136                       }
    137 
    138                       return BoolPromise::CreateAndResolve(true, __func__);
    139                     })
    140      ->Then(GetCurrentSerialEventTarget(), __func__,
    141             [self = RefPtr(this)](const BoolPromise::ResolveOrRejectValue&) {
    142               return self->mIOTaskQueue->BeginShutdown();
    143             })
    144      ->Then(
    145          GetCurrentSerialEventTarget(), __func__,
    146          [self = RefPtr(this)](const ShutdownPromise::ResolveOrRejectValue&) {
    147            if (self->mLocked) {
    148              self->mDataManager->UnlockExclusive(self->mEntryId);
    149            }
    150 
    151            return BoolPromise::CreateAndResolve(true, __func__);
    152          })
    153      ->Then(mDataManager->MutableBackgroundTargetPtr(), __func__,
    154             [self = RefPtr(this)](const BoolPromise::ResolveOrRejectValue&) {
    155               if (self->mRegistered) {
    156                 self->mDataManager->UnregisterAccessHandle(WrapNotNull(self));
    157               }
    158 
    159               self->mDataManager = nullptr;
    160 
    161               return BoolPromise::CreateAndResolve(true, __func__);
    162             });
    163 }
    164 
    165 bool FileSystemAccessHandle::IsInactive() const {
    166  return !mRegCount && !mActor && !mControlActor;
    167 }
    168 
    169 RefPtr<FileSystemAccessHandle::InitPromise>
    170 FileSystemAccessHandle::BeginInit() {
    171  QM_TRY_UNWRAP(fs::FileId fileId, mDataManager->LockExclusive(mEntryId),
    172                [](const auto& aRv) {
    173                  return InitPromise::CreateAndReject(ToNSResult(aRv),
    174                                                      __func__);
    175                });
    176 
    177  mLocked = true;
    178 
    179  auto CreateAndRejectInitPromise = [](StaticString aFunc, nsresult aRv) {
    180    return CreateAndRejectMozPromise<InitPromise>(aFunc, aRv);
    181  };
    182 
    183  fs::ContentType type;
    184  fs::TimeStamp lastModifiedMilliSeconds;
    185  fs::Path path;
    186  nsCOMPtr<nsIFile> file;
    187  QM_TRY(MOZ_TO_RESULT(mDataManager->MutableDatabaseManagerPtr()->GetFile(
    188             mEntryId, fileId, fs::FileMode::EXCLUSIVE, type,
    189             lastModifiedMilliSeconds, path, file)),
    190         CreateAndRejectInitPromise);
    191 
    192  if (LOG_ENABLED()) {
    193    nsAutoString path;
    194    if (NS_SUCCEEDED(file->GetPath(path))) {
    195      LOG(("Opening SyncAccessHandle %s", NS_ConvertUTF16toUTF8(path).get()));
    196    }
    197  }
    198 
    199  return InvokeAsync(
    200             mDataManager->MutableBackgroundTargetPtr(), __func__,
    201             [self = RefPtr(this)]() {
    202               self->mDataManager->RegisterAccessHandle(WrapNotNull(self));
    203 
    204               self->mRegistered = true;
    205 
    206               return BoolPromise::CreateAndResolve(true, __func__);
    207             })
    208      ->Then(mIOTaskQueue.get(), __func__,
    209             [self = RefPtr(this), CreateAndRejectInitPromise,
    210              file = std::move(file)](
    211                 const BoolPromise::ResolveOrRejectValue& value) {
    212               if (value.IsReject()) {
    213                 return InitPromise::CreateAndReject(value.RejectValue(),
    214                                                     __func__);
    215               }
    216 
    217               QM_TRY_UNWRAP(nsCOMPtr<nsIRandomAccessStream> stream,
    218                             CreateFileRandomAccessStream(
    219                                 quota::PERSISTENCE_TYPE_DEFAULT,
    220                                 self->mDataManager->OriginMetadataRef(),
    221                                 quota::Client::FILESYSTEM, file, -1, -1,
    222                                 nsIFileRandomAccessStream::DEFER_OPEN),
    223                             CreateAndRejectInitPromise);
    224 
    225               mozilla::ipc::RandomAccessStreamParams streamParams =
    226                   mozilla::ipc::SerializeRandomAccessStream(
    227                       WrapMovingNotNullUnchecked(std::move(stream)), self);
    228 
    229               return InitPromise::CreateAndResolve(std::move(streamParams),
    230                                                    __func__);
    231             });
    232 }
    233 
    234 }  // namespace mozilla::dom