tor-browser

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

FileStreams.cpp (6865B)


      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 "FileStreams.h"
      8 
      9 // Local includes
     10 #include "QuotaCommon.h"
     11 #include "QuotaManager.h"
     12 #include "QuotaObject.h"
     13 #include "RemoteQuotaObject.h"
     14 
     15 // Global includes
     16 #include <utility>
     17 
     18 #include "mozilla/Assertions.h"
     19 #include "mozilla/DebugOnly.h"
     20 #include "mozilla/Result.h"
     21 #include "mozilla/dom/quota/ResultExtensions.h"
     22 #include "mozilla/ipc/RandomAccessStreamParams.h"
     23 #include "nsDebug.h"
     24 #include "prio.h"
     25 
     26 namespace mozilla::dom::quota {
     27 
     28 template <class FileStreamBase>
     29 NS_IMETHODIMP FileQuotaStream<FileStreamBase>::SetEOF() {
     30  // If the stream is not quota tracked, or on an early or late stage in the
     31  // lifecycle, mQuotaObject is null. Under these circumstances,
     32  // we don't check the quota limit in order to avoid breakage.
     33  if (mQuotaObject) {
     34    int64_t offset = 0;
     35    QM_TRY(MOZ_TO_RESULT(FileStreamBase::Tell(&offset)));
     36 
     37    QM_TRY(OkIf(mQuotaObject->MaybeUpdateSize(offset, /* aTruncate */ true)),
     38           NS_ERROR_FILE_NO_DEVICE_SPACE);
     39  }
     40 
     41  QM_TRY(MOZ_TO_RESULT(FileStreamBase::SetEOF()));
     42 
     43  return NS_OK;
     44 }
     45 
     46 template <class FileStreamBase>
     47 NS_IMETHODIMP FileQuotaStream<FileStreamBase>::Close() {
     48  QM_TRY(MOZ_TO_RESULT(FileStreamBase::Close()));
     49 
     50  if (mQuotaObject) {
     51    if (auto* remoteQuotaObject = mQuotaObject->AsRemoteQuotaObject()) {
     52      remoteQuotaObject->Close();
     53    }
     54 
     55    mQuotaObject = nullptr;
     56  }
     57 
     58  return NS_OK;
     59 }
     60 
     61 template <class FileStreamBase>
     62 nsresult FileQuotaStream<FileStreamBase>::DoOpen() {
     63  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
     64  MOZ_RELEASE_ASSERT(!mDeserialized);
     65 
     66  QuotaManager* quotaManager = QuotaManager::Get();
     67  MOZ_ASSERT(quotaManager, "Shouldn't be null!");
     68 
     69  MOZ_ASSERT(!mQuotaObject, "Creating quota object more than once?");
     70  mQuotaObject = quotaManager->GetQuotaObject(
     71      mPersistenceType, mOriginMetadata, mClientType,
     72      FileStreamBase::mOpenParams.localFile);
     73 
     74  QM_TRY(MOZ_TO_RESULT(FileStreamBase::DoOpen()));
     75 
     76  if (mQuotaObject && (FileStreamBase::mOpenParams.ioFlags & PR_TRUNCATE)) {
     77    DebugOnly<bool> res =
     78        mQuotaObject->MaybeUpdateSize(0, /* aTruncate */ true);
     79    MOZ_ASSERT(res);
     80  }
     81 
     82  return NS_OK;
     83 }
     84 
     85 template <class FileStreamBase>
     86 NS_IMETHODIMP FileQuotaStreamWithWrite<FileStreamBase>::Write(
     87    const char* aBuf, uint32_t aCount, uint32_t* _retval) {
     88  if (FileQuotaStreamWithWrite::mQuotaObject) {
     89    int64_t offset;
     90    QM_TRY(MOZ_TO_RESULT(FileStreamBase::Tell(&offset)));
     91 
     92    MOZ_ASSERT(INT64_MAX - offset >= int64_t(aCount));
     93 
     94    if (!FileQuotaStreamWithWrite::mQuotaObject->MaybeUpdateSize(
     95            offset + int64_t(aCount),
     96            /* aTruncate */ false)) {
     97      *_retval = 0;
     98      return NS_ERROR_FILE_NO_DEVICE_SPACE;
     99    }
    100  }
    101 
    102  QM_TRY(MOZ_TO_RESULT(FileStreamBase::Write(aBuf, aCount, _retval)));
    103 
    104  return NS_OK;
    105 }
    106 
    107 mozilla::ipc::RandomAccessStreamParams FileRandomAccessStream::Serialize(
    108    nsIInterfaceRequestor* aCallbacks) {
    109  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
    110  MOZ_RELEASE_ASSERT(!mDeserialized);
    111  MOZ_ASSERT(mOpenParams.localFile);
    112 
    113  QuotaManager* quotaManager = QuotaManager::Get();
    114  MOZ_ASSERT(quotaManager);
    115 
    116  RefPtr<QuotaObject> quotaObject = quotaManager->GetQuotaObject(
    117      mPersistenceType, mOriginMetadata, mClientType, mOpenParams.localFile);
    118  MOZ_ASSERT(quotaObject);
    119 
    120  IPCQuotaObject ipcQuotaObject = quotaObject->Serialize(aCallbacks);
    121 
    122  mozilla::ipc::RandomAccessStreamParams randomAccessStreamParams =
    123      nsFileRandomAccessStream::Serialize(aCallbacks);
    124 
    125  MOZ_ASSERT(
    126      randomAccessStreamParams.type() ==
    127      mozilla::ipc::RandomAccessStreamParams::TFileRandomAccessStreamParams);
    128 
    129  mozilla::ipc::LimitingFileRandomAccessStreamParams
    130      limitingFileRandomAccessStreamParams;
    131  limitingFileRandomAccessStreamParams.fileRandomAccessStreamParams() =
    132      std::move(randomAccessStreamParams);
    133  limitingFileRandomAccessStreamParams.quotaObject() =
    134      std::move(ipcQuotaObject);
    135 
    136  return limitingFileRandomAccessStreamParams;
    137 }
    138 
    139 bool FileRandomAccessStream::Deserialize(
    140    mozilla::ipc::RandomAccessStreamParams& aParams) {
    141  MOZ_ASSERT(aParams.type() == mozilla::ipc::RandomAccessStreamParams::
    142                                   TLimitingFileRandomAccessStreamParams);
    143 
    144  auto& params = aParams.get_LimitingFileRandomAccessStreamParams();
    145 
    146  mozilla::ipc::RandomAccessStreamParams randomAccessStreamParams(
    147      std::move(params.fileRandomAccessStreamParams()));
    148 
    149  QM_TRY(MOZ_TO_RESULT(
    150             nsFileRandomAccessStream::Deserialize(randomAccessStreamParams)),
    151         false);
    152 
    153  mQuotaObject = QuotaObject::Deserialize(params.quotaObject());
    154 
    155  return true;
    156 }
    157 
    158 Result<MovingNotNull<nsCOMPtr<nsIInputStream>>, nsresult> CreateFileInputStream(
    159    PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
    160    Client::Type aClientType, nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
    161    int32_t aBehaviorFlags) {
    162  auto stream = MakeRefPtr<FileInputStream>(aPersistenceType, aOriginMetadata,
    163                                            aClientType);
    164 
    165  QM_TRY(MOZ_TO_RESULT(stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags)));
    166 
    167  return WrapMovingNotNullUnchecked(
    168      nsCOMPtr<nsIInputStream>(std::move(stream)));
    169 }
    170 
    171 Result<MovingNotNull<nsCOMPtr<nsIOutputStream>>, nsresult>
    172 CreateFileOutputStream(PersistenceType aPersistenceType,
    173                       const OriginMetadata& aOriginMetadata,
    174                       Client::Type aClientType, nsIFile* aFile,
    175                       int32_t aIOFlags, int32_t aPerm,
    176                       int32_t aBehaviorFlags) {
    177  auto stream = MakeRefPtr<FileOutputStream>(aPersistenceType, aOriginMetadata,
    178                                             aClientType);
    179 
    180  QM_TRY(MOZ_TO_RESULT(stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags)));
    181 
    182  return WrapMovingNotNullUnchecked(
    183      nsCOMPtr<nsIOutputStream>(std::move(stream)));
    184 }
    185 
    186 Result<MovingNotNull<nsCOMPtr<nsIRandomAccessStream>>, nsresult>
    187 CreateFileRandomAccessStream(PersistenceType aPersistenceType,
    188                             const OriginMetadata& aOriginMetadata,
    189                             Client::Type aClientType, nsIFile* aFile,
    190                             int32_t aIOFlags, int32_t aPerm,
    191                             int32_t aBehaviorFlags) {
    192  auto stream = MakeRefPtr<FileRandomAccessStream>(
    193      aPersistenceType, aOriginMetadata, aClientType);
    194 
    195  QM_TRY(MOZ_TO_RESULT(stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags)));
    196 
    197  return WrapMovingNotNullUnchecked(
    198      nsCOMPtr<nsIRandomAccessStream>(std::move(stream)));
    199 }
    200 
    201 }  // namespace mozilla::dom::quota