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