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/. */
7 #ifndef mozilla_dom_MemoryBlobImpl_h
8 #define mozilla_dom_MemoryBlobImpl_h
10 #include "mozilla/dom/BaseBlobImpl.h"
11 #include "mozilla/LinkedList.h"
12 #include "mozilla/StaticMutex.h"
13 #include "mozilla/StaticPtr.h"
14 #include "mozilla/StreamBufferSource.h"
16 #include "nsICloneableInputStream.h"
17 #include "nsIInputStream.h"
18 #include "nsIIPCSerializableInputStream.h"
19 #include "nsISeekableStream.h"
21 namespace mozilla::dom
{
23 class MemoryBlobImpl final
: public BaseBlobImpl
{
25 NS_INLINE_DECL_REFCOUNTING_INHERITED(MemoryBlobImpl
, BaseBlobImpl
)
28 static already_AddRefed
<MemoryBlobImpl
> CreateWithLastModifiedNow(
29 void* aMemoryBuffer
, uint64_t aLength
, const nsAString
& aName
,
30 const nsAString
& aContentType
, RTPCallerType aRTPCallerType
);
32 // File constructor with custom lastModified attribue value. You should
33 // probably use CreateWithLastModifiedNow() instead of this one.
34 static already_AddRefed
<MemoryBlobImpl
> CreateWithCustomLastModified(
35 void* aMemoryBuffer
, uint64_t aLength
, const nsAString
& aName
,
36 const nsAString
& aContentType
, int64_t aLastModifiedDate
);
39 MemoryBlobImpl(void* aMemoryBuffer
, uint64_t aLength
,
40 const nsAString
& aContentType
)
41 : BaseBlobImpl(aContentType
, aLength
),
42 mDataOwner(new DataOwner(aMemoryBuffer
, aLength
)) {
43 MOZ_ASSERT(mDataOwner
&& mDataOwner
->mData
, "must have data");
46 void CreateInputStream(nsIInputStream
** aStream
,
47 ErrorResult
& aRv
) const override
;
49 already_AddRefed
<BlobImpl
> CreateSlice(uint64_t aStart
, uint64_t aLength
,
50 const nsAString
& aContentType
,
51 ErrorResult
& aRv
) const override
;
53 bool IsMemoryFile() const override
{ return true; }
55 size_t GetAllocationSize() const override
{ return mLength
; }
57 size_t GetAllocationSize(
58 FallibleTArray
<BlobImpl
*>& aVisitedBlobImpls
) const override
{
59 return GetAllocationSize();
62 void GetBlobImplType(nsAString
& aBlobImplType
) const override
{
63 aBlobImplType
= u
"MemoryBlobImpl"_ns
;
66 class DataOwner final
: public mozilla::LinkedListElement
<DataOwner
> {
68 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner
)
69 DataOwner(void* aMemoryBuffer
, uint64_t aLength
)
70 : mData(aMemoryBuffer
), mLength(aLength
) {
71 mozilla::StaticMutexAutoLock
lock(sDataOwnerMutex
);
74 sDataOwners
= new mozilla::LinkedList
<DataOwner
>();
75 EnsureMemoryReporterRegistered();
77 sDataOwners
->insertBack(this);
81 // Private destructor, to discourage deletion outside of Release():
83 mozilla::StaticMutexAutoLock
lock(sDataOwnerMutex
);
86 if (sDataOwners
->isEmpty()) {
87 // Free the linked list if it's empty.
88 sDataOwners
= nullptr;
95 static void EnsureMemoryReporterRegistered();
97 // sDataOwners and sMemoryReporterRegistered may only be accessed while
98 // holding sDataOwnerMutex! You also must hold the mutex while touching
99 // elements of the linked list that DataOwner inherits from.
100 static mozilla::StaticMutex sDataOwnerMutex MOZ_UNANNOTATED
;
101 static mozilla::StaticAutoPtr
<mozilla::LinkedList
<DataOwner
> > sDataOwners
;
102 static bool sMemoryReporterRegistered
;
108 class DataOwnerAdapter final
: public StreamBufferSource
{
109 using DataOwner
= MemoryBlobImpl::DataOwner
;
112 static nsresult
Create(DataOwner
* aDataOwner
, size_t aStart
, size_t aLength
,
113 nsIInputStream
** _retval
);
115 Span
<const char> Data() override
{ return mData
; }
117 // This StreamBufferSource is owning, as the `mData` span references the
118 // immutable data buffer owned by `mDataOwner` which is being kept alive.
119 bool Owning() override
{ return true; }
121 // The memory usage from `DataOwner` is reported elsewhere, so we don't need
122 // to record it here.
123 size_t SizeOfExcludingThisEvenIfShared(MallocSizeOf
) override
{ return 0; }
126 ~DataOwnerAdapter() override
= default;
128 DataOwnerAdapter(DataOwner
* aDataOwner
, Span
<const char> aData
)
129 : mDataOwner(aDataOwner
), mData(aData
) {}
131 RefPtr
<DataOwner
> mDataOwner
;
132 Span
<const char> mData
;
137 MemoryBlobImpl(void* aMemoryBuffer
, uint64_t aLength
, const nsAString
& aName
,
138 const nsAString
& aContentType
, int64_t aLastModifiedDate
)
139 : BaseBlobImpl(aName
, aContentType
, aLength
, aLastModifiedDate
),
140 mDataOwner(new DataOwner(aMemoryBuffer
, aLength
)) {
141 MOZ_ASSERT(mDataOwner
&& mDataOwner
->mData
, "must have data");
145 MemoryBlobImpl(const MemoryBlobImpl
* aOther
, uint64_t aStart
,
146 uint64_t aLength
, const nsAString
& aContentType
)
147 : BaseBlobImpl(aContentType
, aOther
->mStart
+ aStart
, aLength
),
148 mDataOwner(aOther
->mDataOwner
) {
149 MOZ_ASSERT(mDataOwner
&& mDataOwner
->mData
, "must have data");
152 ~MemoryBlobImpl() override
= default;
154 // Used when backed by a memory store
155 RefPtr
<DataOwner
> mDataOwner
;
158 } // namespace mozilla::dom
160 #endif // mozilla_dom_MemoryBlobImpl_h