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