tor-browser

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

FileSystemManager.cpp (6269B)


      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 "mozilla/dom/FileSystemManager.h"
      8 
      9 #include "FileSystemBackgroundRequestHandler.h"
     10 #include "fs/FileSystemRequestHandler.h"
     11 #include "mozilla/ErrorResult.h"
     12 #include "mozilla/dom/FileSystemManagerChild.h"
     13 #include "mozilla/dom/Promise.h"
     14 #include "mozilla/dom/StorageManager.h"
     15 #include "mozilla/dom/fs/ManagedMozPromiseRequestHolder.h"
     16 #include "mozilla/dom/quota/QuotaCommon.h"
     17 #include "mozilla/dom/quota/ResultExtensions.h"
     18 
     19 namespace mozilla::dom {
     20 
     21 FileSystemManager::FileSystemManager(
     22    nsIGlobalObject* aGlobal, RefPtr<StorageManager> aStorageManager,
     23    RefPtr<FileSystemBackgroundRequestHandler> aBackgroundRequestHandler)
     24    : mGlobal(aGlobal),
     25      mStorageManager(std::move(aStorageManager)),
     26      mBackgroundRequestHandler(std::move(aBackgroundRequestHandler)),
     27      mRequestHandler(new fs::FileSystemRequestHandler()) {}
     28 
     29 FileSystemManager::FileSystemManager(nsIGlobalObject* aGlobal,
     30                                     RefPtr<StorageManager> aStorageManager)
     31    : FileSystemManager(aGlobal, std::move(aStorageManager),
     32                        MakeRefPtr<FileSystemBackgroundRequestHandler>()) {}
     33 
     34 FileSystemManager::~FileSystemManager() { MOZ_ASSERT(mShutdown); }
     35 
     36 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileSystemManager)
     37  NS_INTERFACE_MAP_ENTRY(nsISupports)
     38 NS_INTERFACE_MAP_END
     39 NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemManager);
     40 NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemManager);
     41 NS_IMPL_CYCLE_COLLECTION(FileSystemManager, mGlobal, mStorageManager);
     42 
     43 void FileSystemManager::Shutdown() {
     44  mShutdown.Flip();
     45 
     46  auto shutdownAndDisconnect = [self = RefPtr(this)]() {
     47    self->mBackgroundRequestHandler->Shutdown();
     48 
     49    for (RefPtr<PromiseRequestHolder<FileSystemManagerChild::ActorPromise>>
     50             holder : self->mPromiseRequestHolders.ForwardRange()) {
     51      holder->DisconnectIfExists();
     52    }
     53  };
     54 
     55  if (NS_IsMainThread()) {
     56    if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
     57      mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
     58          ->CloseAllWritables(
     59              [shutdownAndDisconnect = std::move(shutdownAndDisconnect)]() {
     60                shutdownAndDisconnect();
     61              });
     62    } else {
     63      shutdownAndDisconnect();
     64    }
     65  } else {
     66    if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
     67      // FileSystemAccessHandles and FileSystemWritableFileStreams prevent
     68      // shutdown until they are full closed, so at this point, they all should
     69      // be closed.
     70      MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
     71                     ->AllSyncAccessHandlesClosed());
     72      MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
     73                     ->AllWritableFileStreamsClosed());
     74    }
     75 
     76    shutdownAndDisconnect();
     77  }
     78 }
     79 
     80 const RefPtr<FileSystemManagerChild>& FileSystemManager::ActorStrongRef()
     81    const {
     82  return mBackgroundRequestHandler->FileSystemManagerChildStrongRef();
     83 }
     84 
     85 void FileSystemManager::RegisterPromiseRequestHolder(
     86    PromiseRequestHolder<FileSystemManagerChild::ActorPromise>* aHolder) {
     87  mPromiseRequestHolders.AppendElement(aHolder);
     88 }
     89 
     90 void FileSystemManager::UnregisterPromiseRequestHolder(
     91    PromiseRequestHolder<FileSystemManagerChild::ActorPromise>* aHolder) {
     92  mPromiseRequestHolders.RemoveElement(aHolder);
     93 }
     94 
     95 void FileSystemManager::BeginRequest(
     96    MoveOnlyFunction<void(RefPtr<FileSystemManagerChild>)>&& aSuccess,
     97    MoveOnlyFunction<void(nsresult)>&& aFailure) {
     98  MOZ_ASSERT(!mShutdown);
     99 
    100  MOZ_ASSERT(mGlobal);
    101 
    102  nsICookieJarSettings* cookieJarSettings = mGlobal->GetCookieJarSettings();
    103  nsIPrincipal* unpartitionedPrincipal = mGlobal->PrincipalOrNull();
    104  if (NS_WARN_IF(!cookieJarSettings) || NS_WARN_IF(!unpartitionedPrincipal) ||
    105      NS_WARN_IF(unpartitionedPrincipal->GetIsInPrivateBrowsing())) {
    106    // ePartition values can be returned for Private Browsing Mode
    107    // for third-party iframes, so we also need to check the private browsing
    108    // in that case which means we need to check the principal.
    109    aFailure(NS_ERROR_DOM_SECURITY_ERR);
    110    return;
    111  }
    112 
    113  // Check if we're allowed to use storage.
    114  StorageAccess access = mGlobal->GetStorageAccess();
    115 
    116  // Use allow list to decide the permission.
    117  const bool allowed = access == StorageAccess::eAllow ||
    118                       StoragePartitioningEnabled(access, cookieJarSettings);
    119  if (NS_WARN_IF(!allowed)) {
    120    aFailure(NS_ERROR_DOM_SECURITY_ERR);
    121    return;
    122  }
    123 
    124  if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
    125    aSuccess(mBackgroundRequestHandler->FileSystemManagerChildStrongRef());
    126    return;
    127  }
    128 
    129  auto holder =
    130      MakeRefPtr<PromiseRequestHolder<FileSystemManagerChild::ActorPromise>>(
    131          this);
    132 
    133  QM_TRY_INSPECT(const auto& principalInfo, mGlobal->GetStorageKey(), QM_VOID,
    134                 [&aFailure](nsresult rv) { aFailure(rv); });
    135 
    136  mBackgroundRequestHandler->CreateFileSystemManagerChild(principalInfo)
    137      ->Then(
    138          GetCurrentSerialEventTarget(), __func__,
    139          [self = RefPtr<FileSystemManager>(this), holder,
    140           success = std::move(aSuccess), failure = std::move(aFailure)](
    141              const FileSystemManagerChild::ActorPromise::ResolveOrRejectValue&
    142                  aValue) mutable {
    143            holder->Complete();
    144 
    145            if (aValue.IsResolve()) {
    146              success(aValue.ResolveValue());
    147            } else {
    148              failure(aValue.RejectValue());
    149            }
    150          })
    151      ->Track(*holder);
    152 }
    153 
    154 already_AddRefed<Promise> FileSystemManager::GetDirectory(ErrorResult& aError) {
    155  MOZ_ASSERT(mGlobal);
    156 
    157  RefPtr<Promise> promise = Promise::Create(mGlobal, aError);
    158  if (NS_WARN_IF(aError.Failed())) {
    159    return nullptr;
    160  }
    161 
    162  MOZ_ASSERT(promise);
    163 
    164  mRequestHandler->GetRootHandle(this, promise, aError);
    165  if (NS_WARN_IF(aError.Failed())) {
    166    return nullptr;
    167  }
    168 
    169  return promise.forget();
    170 }
    171 
    172 }  // namespace mozilla::dom