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