Backed out changeset 51d87c2129d2 (bug 1865372) for causing RunWatchdog crashes in...
[gecko.git] / dom / file / MemoryBlobImpl.cpp
blobb6d5c442d149ccc200cabd673e2adecfd4264abc
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 #include "MemoryBlobImpl.h"
8 #include "mozilla/ipc/InputStreamUtils.h"
9 #include "mozilla/IntegerPrintfMacros.h"
10 #include "mozilla/SHA1.h"
11 #include "nsIMemoryReporter.h"
12 #include "nsPrintfCString.h"
13 #include "nsRFPService.h"
14 #include "nsStringStream.h"
15 #include "prtime.h"
17 namespace mozilla::dom {
19 // static
20 already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithCustomLastModified(
21 void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
22 const nsAString& aContentType, int64_t aLastModifiedDate) {
23 RefPtr<MemoryBlobImpl> blobImpl = new MemoryBlobImpl(
24 aMemoryBuffer, aLength, aName, aContentType, aLastModifiedDate);
25 return blobImpl.forget();
28 // static
29 already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithLastModifiedNow(
30 void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
31 const nsAString& aContentType, RTPCallerType aRTPCallerType) {
32 int64_t lastModificationDate =
33 nsRFPService::ReduceTimePrecisionAsUSecs(PR_Now(), 0, aRTPCallerType);
34 return CreateWithCustomLastModified(aMemoryBuffer, aLength, aName,
35 aContentType, lastModificationDate);
38 nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
39 size_t aStart, size_t aLength,
40 nsIInputStream** _retval) {
41 MOZ_ASSERT(aDataOwner, "Uh ...");
42 Span data{static_cast<const char*>(aDataOwner->mData) + aStart, aLength};
43 RefPtr adapter = new MemoryBlobImpl::DataOwnerAdapter(aDataOwner, data);
44 return NS_NewByteInputStream(_retval, adapter);
47 already_AddRefed<BlobImpl> MemoryBlobImpl::CreateSlice(
48 uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
49 ErrorResult& aRv) const {
50 RefPtr<BlobImpl> impl =
51 new MemoryBlobImpl(this, aStart, aLength, aContentType);
52 return impl.forget();
55 void MemoryBlobImpl::CreateInputStream(nsIInputStream** aStream,
56 ErrorResult& aRv) const {
57 if (mLength >= INT32_MAX) {
58 aRv.Throw(NS_ERROR_FAILURE);
59 return;
62 aRv = MemoryBlobImpl::DataOwnerAdapter::Create(mDataOwner, mStart, mLength,
63 aStream);
66 /* static */
67 StaticMutex MemoryBlobImpl::DataOwner::sDataOwnerMutex;
69 /* static */ StaticAutoPtr<LinkedList<MemoryBlobImpl::DataOwner>>
70 MemoryBlobImpl::DataOwner::sDataOwners;
72 /* static */
73 bool MemoryBlobImpl::DataOwner::sMemoryReporterRegistered = false;
75 MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
77 class MemoryBlobImplDataOwnerMemoryReporter final : public nsIMemoryReporter {
78 ~MemoryBlobImplDataOwnerMemoryReporter() = default;
80 public:
81 NS_DECL_THREADSAFE_ISUPPORTS
83 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
84 nsISupports* aData, bool aAnonymize) override {
85 using DataOwner = MemoryBlobImpl::DataOwner;
87 StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
89 if (!DataOwner::sDataOwners) {
90 return NS_OK;
93 const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
94 size_t smallObjectsTotal = 0;
96 for (DataOwner* owner = DataOwner::sDataOwners->getFirst(); owner;
97 owner = owner->getNext()) {
98 size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
100 if (size < LARGE_OBJECT_MIN_SIZE) {
101 smallObjectsTotal += size;
102 } else {
103 SHA1Sum sha1;
104 sha1.update(owner->mData, owner->mLength);
105 uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
106 sha1.finish(digest);
108 nsAutoCString digestString;
109 for (size_t i = 0; i < sizeof(digest); i++) {
110 digestString.AppendPrintf("%02x", digest[i]);
113 aHandleReport->Callback(
114 /* process */ ""_ns,
115 nsPrintfCString(
116 "explicit/dom/memory-file-data/large/file(length=%" PRIu64
117 ", sha1=%s)",
118 owner->mLength,
119 aAnonymize ? "<anonymized>" : digestString.get()),
120 KIND_HEAP, UNITS_BYTES, size,
121 nsPrintfCString(
122 "Memory used to back a memory file of length %" PRIu64
123 " bytes. The file "
124 "has a sha1 of %s.\n\n"
125 "Note that the allocator may round up a memory file's length "
126 "-- "
127 "that is, an N-byte memory file may take up more than N bytes "
128 "of "
129 "memory.",
130 owner->mLength, digestString.get()),
131 aData);
135 if (smallObjectsTotal > 0) {
136 aHandleReport->Callback(
137 /* process */ ""_ns, "explicit/dom/memory-file-data/small"_ns,
138 KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
139 nsPrintfCString(
140 "Memory used to back small memory files (i.e. those taking up "
141 "less "
142 "than %zu bytes of memory each).\n\n"
143 "Note that the allocator may round up a memory file's length -- "
144 "that is, an N-byte memory file may take up more than N bytes of "
145 "memory.",
146 LARGE_OBJECT_MIN_SIZE),
147 aData);
150 return NS_OK;
154 NS_IMPL_ISUPPORTS(MemoryBlobImplDataOwnerMemoryReporter, nsIMemoryReporter)
156 /* static */
157 void MemoryBlobImpl::DataOwner::EnsureMemoryReporterRegistered() {
158 sDataOwnerMutex.AssertCurrentThreadOwns();
159 if (sMemoryReporterRegistered) {
160 return;
163 RegisterStrongMemoryReporter(new MemoryBlobImplDataOwnerMemoryReporter());
165 sMemoryReporterRegistered = true;
168 } // namespace mozilla::dom