summaryrefslogtreecommitdiffstats
path: root/dom/file/MemoryBlobImpl.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /dom/file/MemoryBlobImpl.cpp
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/file/MemoryBlobImpl.cpp')
-rw-r--r--dom/file/MemoryBlobImpl.cpp168
1 files changed, 168 insertions, 0 deletions
diff --git a/dom/file/MemoryBlobImpl.cpp b/dom/file/MemoryBlobImpl.cpp
new file mode 100644
index 0000000000..b6d5c442d1
--- /dev/null
+++ b/dom/file/MemoryBlobImpl.cpp
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MemoryBlobImpl.h"
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/SHA1.h"
+#include "nsIMemoryReporter.h"
+#include "nsPrintfCString.h"
+#include "nsRFPService.h"
+#include "nsStringStream.h"
+#include "prtime.h"
+
+namespace mozilla::dom {
+
+// static
+already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithCustomLastModified(
+ void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
+ const nsAString& aContentType, int64_t aLastModifiedDate) {
+ RefPtr<MemoryBlobImpl> blobImpl = new MemoryBlobImpl(
+ aMemoryBuffer, aLength, aName, aContentType, aLastModifiedDate);
+ return blobImpl.forget();
+}
+
+// static
+already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithLastModifiedNow(
+ void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
+ const nsAString& aContentType, RTPCallerType aRTPCallerType) {
+ int64_t lastModificationDate =
+ nsRFPService::ReduceTimePrecisionAsUSecs(PR_Now(), 0, aRTPCallerType);
+ return CreateWithCustomLastModified(aMemoryBuffer, aLength, aName,
+ aContentType, lastModificationDate);
+}
+
+nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
+ size_t aStart, size_t aLength,
+ nsIInputStream** _retval) {
+ MOZ_ASSERT(aDataOwner, "Uh ...");
+ Span data{static_cast<const char*>(aDataOwner->mData) + aStart, aLength};
+ RefPtr adapter = new MemoryBlobImpl::DataOwnerAdapter(aDataOwner, data);
+ return NS_NewByteInputStream(_retval, adapter);
+}
+
+already_AddRefed<BlobImpl> MemoryBlobImpl::CreateSlice(
+ uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
+ ErrorResult& aRv) const {
+ RefPtr<BlobImpl> impl =
+ new MemoryBlobImpl(this, aStart, aLength, aContentType);
+ return impl.forget();
+}
+
+void MemoryBlobImpl::CreateInputStream(nsIInputStream** aStream,
+ ErrorResult& aRv) const {
+ if (mLength >= INT32_MAX) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
+
+ aRv = MemoryBlobImpl::DataOwnerAdapter::Create(mDataOwner, mStart, mLength,
+ aStream);
+}
+
+/* static */
+StaticMutex MemoryBlobImpl::DataOwner::sDataOwnerMutex;
+
+/* static */ StaticAutoPtr<LinkedList<MemoryBlobImpl::DataOwner>>
+ MemoryBlobImpl::DataOwner::sDataOwners;
+
+/* static */
+bool MemoryBlobImpl::DataOwner::sMemoryReporterRegistered = false;
+
+MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
+
+class MemoryBlobImplDataOwnerMemoryReporter final : public nsIMemoryReporter {
+ ~MemoryBlobImplDataOwnerMemoryReporter() = default;
+
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) override {
+ using DataOwner = MemoryBlobImpl::DataOwner;
+
+ StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
+
+ if (!DataOwner::sDataOwners) {
+ return NS_OK;
+ }
+
+ const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
+ size_t smallObjectsTotal = 0;
+
+ for (DataOwner* owner = DataOwner::sDataOwners->getFirst(); owner;
+ owner = owner->getNext()) {
+ size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
+
+ if (size < LARGE_OBJECT_MIN_SIZE) {
+ smallObjectsTotal += size;
+ } else {
+ SHA1Sum sha1;
+ sha1.update(owner->mData, owner->mLength);
+ uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
+ sha1.finish(digest);
+
+ nsAutoCString digestString;
+ for (size_t i = 0; i < sizeof(digest); i++) {
+ digestString.AppendPrintf("%02x", digest[i]);
+ }
+
+ aHandleReport->Callback(
+ /* process */ ""_ns,
+ nsPrintfCString(
+ "explicit/dom/memory-file-data/large/file(length=%" PRIu64
+ ", sha1=%s)",
+ owner->mLength,
+ aAnonymize ? "<anonymized>" : digestString.get()),
+ KIND_HEAP, UNITS_BYTES, size,
+ nsPrintfCString(
+ "Memory used to back a memory file of length %" PRIu64
+ " bytes. The file "
+ "has a sha1 of %s.\n\n"
+ "Note that the allocator may round up a memory file's length "
+ "-- "
+ "that is, an N-byte memory file may take up more than N bytes "
+ "of "
+ "memory.",
+ owner->mLength, digestString.get()),
+ aData);
+ }
+ }
+
+ if (smallObjectsTotal > 0) {
+ aHandleReport->Callback(
+ /* process */ ""_ns, "explicit/dom/memory-file-data/small"_ns,
+ KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
+ nsPrintfCString(
+ "Memory used to back small memory files (i.e. those taking up "
+ "less "
+ "than %zu bytes of memory each).\n\n"
+ "Note that the allocator may round up a memory file's length -- "
+ "that is, an N-byte memory file may take up more than N bytes of "
+ "memory.",
+ LARGE_OBJECT_MIN_SIZE),
+ aData);
+ }
+
+ return NS_OK;
+ }
+};
+
+NS_IMPL_ISUPPORTS(MemoryBlobImplDataOwnerMemoryReporter, nsIMemoryReporter)
+
+/* static */
+void MemoryBlobImpl::DataOwner::EnsureMemoryReporterRegistered() {
+ sDataOwnerMutex.AssertCurrentThreadOwns();
+ if (sMemoryReporterRegistered) {
+ return;
+ }
+
+ RegisterStrongMemoryReporter(new MemoryBlobImplDataOwnerMemoryReporter());
+
+ sMemoryReporterRegistered = true;
+}
+
+} // namespace mozilla::dom