tor-browser

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

FileSystemManagerParentFactory.cpp (8021B)


      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 "FileSystemManagerParentFactory.h"
      8 
      9 #include "mozilla/OriginAttributes.h"
     10 #include "mozilla/StaticPrefs_dom.h"
     11 #include "mozilla/dom/FileSystemDataManager.h"
     12 #include "mozilla/dom/FileSystemLog.h"
     13 #include "mozilla/dom/FileSystemManagerParent.h"
     14 #include "mozilla/dom/FileSystemTypes.h"
     15 #include "mozilla/dom/quota/PrincipalUtils.h"
     16 #include "mozilla/dom/quota/QuotaCommon.h"
     17 #include "mozilla/dom/quota/QuotaManager.h"
     18 #include "mozilla/dom/quota/ResultExtensions.h"
     19 #include "mozilla/ipc/Endpoint.h"
     20 #include "mozilla/ipc/PBackgroundParent.h"
     21 #include "nsIScriptObjectPrincipal.h"
     22 #include "nsString.h"
     23 
     24 namespace mozilla::dom {
     25 mozilla::ipc::IPCResult CreateFileSystemManagerParent(
     26    RefPtr<mozilla::ipc::PBackgroundParent> aBackgroundActor,
     27    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
     28    mozilla::ipc::Endpoint<PFileSystemManagerParent>&& aParentEndpoint,
     29    std::function<void(const nsresult&)>&& aResolver) {
     30  using CreateActorPromise =
     31      MozPromise<RefPtr<FileSystemManagerParent>, nsresult, true>;
     32 
     33  QM_TRY(OkIf(StaticPrefs::dom_fs_enabled()), IPC_OK(),
     34         [aResolver](const auto&) { aResolver(NS_ERROR_DOM_NOT_ALLOWED_ERR); });
     35 
     36  QM_TRY(OkIf(aParentEndpoint.IsValid()), IPC_OK(),
     37         [aResolver](const auto&) { aResolver(NS_ERROR_INVALID_ARG); });
     38 
     39  // This blocks Null and Expanded principals
     40  QM_TRY(OkIf(quota::IsPrincipalInfoValid(aPrincipalInfo)), IPC_OK(),
     41         [aResolver](const auto&) { aResolver(NS_ERROR_DOM_SECURITY_ERR); });
     42 
     43  QM_TRY(quota::QuotaManager::EnsureCreated(), IPC_OK(),
     44         [aResolver](const auto rv) { aResolver(rv); });
     45 
     46  auto* const quotaManager = quota::QuotaManager::Get();
     47  MOZ_ASSERT(quotaManager);
     48 
     49  QM_TRY_UNWRAP(
     50      auto principalMetadata,
     51      quota::GetInfoFromValidatedPrincipalInfo(*quotaManager, aPrincipalInfo),
     52      IPC_OK(), [aResolver](const auto rv) { aResolver(rv); });
     53 
     54  quota::OriginMetadata originMetadata(std::move(principalMetadata),
     55                                       quota::PERSISTENCE_TYPE_DEFAULT);
     56 
     57  // Block use for now in PrivateBrowsing
     58  QM_TRY(OkIf(!OriginAttributes::IsPrivateBrowsing(originMetadata.mOrigin)),
     59         IPC_OK(),
     60         [aResolver](const auto&) { aResolver(NS_ERROR_DOM_NOT_ALLOWED_ERR); });
     61 
     62  LOG(("CreateFileSystemManagerParent, origin: %s",
     63       originMetadata.mOrigin.get()));
     64 
     65  RefPtr<mozilla::ipc::PBackgroundParent> backgroundActor =
     66      std::move(aBackgroundActor);
     67 
     68  // This creates the file system data manager, which has to be done on
     69  // PBackground
     70  fs::data::FileSystemDataManager::GetOrCreateFileSystemDataManager(
     71      originMetadata)
     72      ->Then(
     73          GetCurrentSerialEventTarget(), __func__,
     74          [origin = originMetadata.mOrigin,
     75           parentEndpoint = std::move(aParentEndpoint), backgroundActor,
     76           aResolver](const fs::Registered<fs::data::FileSystemDataManager>&
     77                          dataManager) mutable {
     78            QM_TRY_UNWRAP(fs::EntryId rootId, fs::data::GetRootHandle(origin),
     79                          QM_VOID,
     80                          ([backgroundActor, aResolver](const auto& aRv) {
     81                            if (!backgroundActor->CanSend()) {
     82                              return;
     83                            }
     84 
     85                            aResolver(ToNSResult(aRv));
     86                          }));
     87 
     88            InvokeAsync(
     89                dataManager->MutableIOTaskQueuePtr(), __func__,
     90                [dataManager = dataManager, rootId,
     91                 parentEndpoint = std::move(parentEndpoint)]() mutable {
     92                  RefPtr<FileSystemManagerParent> parent =
     93                      new FileSystemManagerParent(dataManager.inspect(),
     94                                                  rootId);
     95 
     96                  auto autoProxyDestroyFileSystemDataManagerHandle =
     97                      MakeScopeExit([&dataManager] {
     98                        nsCOMPtr<nsISerialEventTarget> target =
     99                            dataManager->MutableBackgroundTargetPtr();
    100 
    101                        MOZ_ALWAYS_SUCCEEDS(target->Dispatch(
    102                            NS_NewRunnableFunction(
    103                                "DestroyFileSystemDataManagerHandle",
    104                                [dataManager = std::move(dataManager)]() {}),
    105                            NS_DISPATCH_NORMAL));
    106                      });
    107 
    108                  LOG(("Binding parent endpoint"));
    109                  if (!parentEndpoint.Bind(parent)) {
    110                    return CreateActorPromise::CreateAndReject(NS_ERROR_FAILURE,
    111                                                               __func__);
    112                  }
    113 
    114                  return CreateActorPromise::CreateAndResolve(std::move(parent),
    115                                                              __func__);
    116                })
    117                ->Then(GetCurrentSerialEventTarget(), __func__,
    118                       [dataManager = dataManager](
    119                           CreateActorPromise::ResolveOrRejectValue&& aValue) {
    120                         if (aValue.IsReject()) {
    121                           return BoolPromise::CreateAndReject(
    122                               aValue.RejectValue(), __func__);
    123                         }
    124 
    125                         RefPtr<FileSystemManagerParent> parent =
    126                             std::move(aValue.ResolveValue());
    127 
    128                         if (!parent->IsAlive()) {
    129                           return BoolPromise::CreateAndReject(NS_ERROR_ABORT,
    130                                                               __func__);
    131                         }
    132 
    133                         dataManager->RegisterActor(WrapNotNull(parent));
    134 
    135                         return BoolPromise::CreateAndResolve(true, __func__);
    136                       })
    137                ->Then(dataManager->MutableIOTaskQueuePtr(), __func__,
    138                       [](const BoolPromise::ResolveOrRejectValue& aValue) {
    139                         // Hopping to the I/O task queue is needed to avoid
    140                         // a potential race triggered by
    141                         // FileSystemManagerParent::SendCloseAll called by
    142                         // FileSystemManagerParent::RequestAllowToClose called
    143                         // by FileSystemDataManager::RegisterActor when the
    144                         // directory lock has been invalidated in the
    145                         // meantime. The race would cause that the child side
    146                         // could sometimes use the child actor for sending
    147                         // messages and sometimes not. This extra hop
    148                         // guarantees that the created child actor will always
    149                         // refuse to send messages.
    150                         return BoolPromise::CreateAndResolveOrReject(aValue,
    151                                                                      __func__);
    152                       })
    153                ->Then(GetCurrentSerialEventTarget(), __func__,
    154                       [backgroundActor, aResolver](
    155                           const BoolPromise::ResolveOrRejectValue& aValue) {
    156                         if (!backgroundActor->CanSend()) {
    157                           return;
    158                         }
    159 
    160                         if (aValue.IsReject()) {
    161                           aResolver(aValue.RejectValue());
    162                         } else {
    163                           aResolver(NS_OK);
    164                         }
    165                       });
    166          },
    167          [backgroundActor, aResolver](nsresult aRejectValue) {
    168            if (!backgroundActor->CanSend()) {
    169              return;
    170            }
    171 
    172            aResolver(aRejectValue);
    173          });
    174 
    175  return IPC_OK();
    176 }
    177 
    178 }  // namespace mozilla::dom