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