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 #ifndef mozilla_dom_MutableBlobStorage_h 8 #define mozilla_dom_MutableBlobStorage_h 9 10 #include "mozilla/RefPtr.h" 11 #include "mozilla/Mutex.h" 12 #include "nsCOMPtr.h" 13 #include "nsString.h" 14 #include "prio.h" 15 16 class nsIEventTarget; 17 class nsIRunnable; 18 19 namespace mozilla { 20 21 class TaskQueue; 22 23 namespace dom { 24 25 class Blob; 26 class BlobImpl; 27 class MutableBlobStorage; 28 class TemporaryIPCBlobChild; 29 class TemporaryIPCBlobChildCallback; 30 31 class MutableBlobStorageCallback { 32 public: 33 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 34 35 virtual void BlobStoreCompleted(MutableBlobStorage* aBlobStorage, 36 BlobImpl* aBlob, nsresult aRv) = 0; 37 }; 38 39 // This class is must be created and used on main-thread, except for Append() 40 // that can be called on any thread. 41 class MutableBlobStorage final { 42 public: 43 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MutableBlobStorage) 44 45 enum MutableBlobStorageType { 46 eOnlyInMemory, 47 eCouldBeInTemporaryFile, 48 }; 49 50 explicit MutableBlobStorage(MutableBlobStorageType aType, 51 nsIEventTarget* aEventTarget = nullptr, 52 uint32_t aMaxMemory = 0); 53 54 nsresult Append(const void* aData, uint32_t aLength); 55 56 // This method can be called just once. 57 // The callback will be called when the BlobImpl is ready. 58 void GetBlobImplWhenReady(const nsACString& aContentType, 59 MutableBlobStorageCallback* aCallback); 60 61 void TemporaryFileCreated(PRFileDesc* aFD); 62 63 void AskForBlob(TemporaryIPCBlobChildCallback* aCallback, 64 const nsACString& aContentType); 65 66 void ErrorPropagated(nsresult aRv); 67 EventTarget()68 nsIEventTarget* EventTarget() { 69 MOZ_ASSERT(mEventTarget); 70 return mEventTarget; 71 } 72 73 // Returns the heap size in bytes of our internal buffers. 74 // Note that this intentionally ignores the data in the temp file. 75 size_t SizeOfCurrentMemoryBuffer(); 76 77 PRFileDesc* GetFD(); 78 79 void CloseFD(); 80 81 private: 82 ~MutableBlobStorage(); 83 84 bool ExpandBufferSize(const MutexAutoLock& aProofOfLock, uint64_t aSize); 85 86 bool ShouldBeTemporaryStorage(const MutexAutoLock& aProofOfLock, 87 uint64_t aSize) const; 88 89 bool MaybeCreateTemporaryFile(const MutexAutoLock& aProofOfLock); 90 void MaybeCreateTemporaryFileOnMainThread(const MutexAutoLock& aProofOfLock); 91 92 [[nodiscard]] nsresult DispatchToIOThread( 93 already_AddRefed<nsIRunnable> aRunnable); 94 95 Mutex mMutex; 96 97 // All these variables are touched on the main thread only or in the 98 // retargeted thread when used by Append(). They are protected by mMutex. 99 100 void* mData; 101 uint64_t mDataLen; 102 uint64_t mDataBufferLen; 103 104 enum StorageState { 105 eKeepInMemory, 106 eInMemory, 107 eWaitingForTemporaryFile, 108 eInTemporaryFile, 109 eClosed 110 }; 111 112 StorageState mStorageState; 113 114 PRFileDesc* mFD; 115 116 nsresult mErrorResult; 117 118 RefPtr<TaskQueue> mTaskQueue; 119 nsCOMPtr<nsIEventTarget> mEventTarget; 120 121 nsCString mPendingContentType; 122 RefPtr<MutableBlobStorageCallback> mPendingCallback; 123 124 RefPtr<TemporaryIPCBlobChild> mActor; 125 126 // This value is used when we go from eInMemory to eWaitingForTemporaryFile 127 // and eventually eInTemporaryFile. If the size of the buffer is >= 128 // mMaxMemory, the creation of the temporary file will start. 129 // It's not used if mStorageState is eKeepInMemory. 130 uint32_t mMaxMemory; 131 }; 132 133 } // namespace dom 134 } // namespace mozilla 135 136 #endif // mozilla_dom_MutableBlobStorage_h 137