Bug 1756164: part 2) Document the order of the external clipboard formats and remove...
[gecko.git] / dom / file / MemoryBlobImpl.cpp
blob04f2e75e6b2171d67feb7bd1dfd477c312bab32c
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 "nsMemory.h"
13 #include "nsPrintfCString.h"
14 #include "nsRFPService.h"
15 #include "nsStringStream.h"
16 #include "prtime.h"
18 namespace mozilla::dom {
20 // static
21 already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithCustomLastModified(
22 void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
23 const nsAString& aContentType, int64_t aLastModifiedDate) {
24 RefPtr<MemoryBlobImpl> blobImpl = new MemoryBlobImpl(
25 aMemoryBuffer, aLength, aName, aContentType, aLastModifiedDate);
26 return blobImpl.forget();
29 // static
30 already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithLastModifiedNow(
31 void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
32 const nsAString& aContentType, bool aCrossOriginIsolated) {
33 int64_t lastModificationDate = nsRFPService::ReduceTimePrecisionAsUSecs(
34 PR_Now(), 0,
35 /* aIsSystemPrincipal */ false, aCrossOriginIsolated);
36 return CreateWithCustomLastModified(aMemoryBuffer, aLength, aName,
37 aContentType, lastModificationDate);
40 nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
41 size_t aStart, size_t aLength,
42 nsIInputStream** _retval) {
43 MOZ_ASSERT(aDataOwner, "Uh ...");
44 Span data{static_cast<const char*>(aDataOwner->mData) + aStart, aLength};
45 RefPtr adapter = new MemoryBlobImpl::DataOwnerAdapter(aDataOwner, data);
46 return NS_NewByteInputStream(_retval, adapter);
49 already_AddRefed<BlobImpl> MemoryBlobImpl::CreateSlice(
50 uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
51 ErrorResult& aRv) {
52 RefPtr<BlobImpl> impl =
53 new MemoryBlobImpl(this, aStart, aLength, aContentType);
54 return impl.forget();
57 void MemoryBlobImpl::CreateInputStream(nsIInputStream** aStream,
58 ErrorResult& aRv) {
59 if (mLength >= INT32_MAX) {
60 aRv.Throw(NS_ERROR_FAILURE);
61 return;
64 aRv = MemoryBlobImpl::DataOwnerAdapter::Create(mDataOwner, mStart, mLength,
65 aStream);
68 /* static */
69 StaticMutex MemoryBlobImpl::DataOwner::sDataOwnerMutex;
71 /* static */ StaticAutoPtr<LinkedList<MemoryBlobImpl::DataOwner>>
72 MemoryBlobImpl::DataOwner::sDataOwners;
74 /* static */
75 bool MemoryBlobImpl::DataOwner::sMemoryReporterRegistered = false;
77 MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
79 class MemoryBlobImplDataOwnerMemoryReporter final : public nsIMemoryReporter {
80 ~MemoryBlobImplDataOwnerMemoryReporter() = default;
82 public:
83 NS_DECL_THREADSAFE_ISUPPORTS
85 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
86 nsISupports* aData, bool aAnonymize) override {
87 using DataOwner = MemoryBlobImpl::DataOwner;
89 StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
91 if (!DataOwner::sDataOwners) {
92 return NS_OK;
95 const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
96 size_t smallObjectsTotal = 0;
98 for (DataOwner* owner = DataOwner::sDataOwners->getFirst(); owner;
99 owner = owner->getNext()) {
100 size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
102 if (size < LARGE_OBJECT_MIN_SIZE) {
103 smallObjectsTotal += size;
104 } else {
105 SHA1Sum sha1;
106 sha1.update(owner->mData, owner->mLength);
107 uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
108 sha1.finish(digest);
110 nsAutoCString digestString;
111 for (size_t i = 0; i < sizeof(digest); i++) {
112 digestString.AppendPrintf("%02x", digest[i]);
115 aHandleReport->Callback(
116 /* process */ ""_ns,
117 nsPrintfCString(
118 "explicit/dom/memory-file-data/large/file(length=%" PRIu64
119 ", sha1=%s)",
120 owner->mLength,
121 aAnonymize ? "<anonymized>" : digestString.get()),
122 KIND_HEAP, UNITS_BYTES, size,
123 nsPrintfCString(
124 "Memory used to back a memory file of length %" PRIu64
125 " bytes. The file "
126 "has a sha1 of %s.\n\n"
127 "Note that the allocator may round up a memory file's length "
128 "-- "
129 "that is, an N-byte memory file may take up more than N bytes "
130 "of "
131 "memory.",
132 owner->mLength, digestString.get()),
133 aData);
137 if (smallObjectsTotal > 0) {
138 aHandleReport->Callback(
139 /* process */ ""_ns, "explicit/dom/memory-file-data/small"_ns,
140 KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
141 nsPrintfCString(
142 "Memory used to back small memory files (i.e. those taking up "
143 "less "
144 "than %zu bytes of memory each).\n\n"
145 "Note that the allocator may round up a memory file's length -- "
146 "that is, an N-byte memory file may take up more than N bytes of "
147 "memory.",
148 LARGE_OBJECT_MIN_SIZE),
149 aData);
152 return NS_OK;
156 NS_IMPL_ISUPPORTS(MemoryBlobImplDataOwnerMemoryReporter, nsIMemoryReporter)
158 /* static */
159 void MemoryBlobImpl::DataOwner::EnsureMemoryReporterRegistered() {
160 sDataOwnerMutex.AssertCurrentThreadOwns();
161 if (sMemoryReporterRegistered) {
162 return;
165 RegisterStrongMemoryReporter(new MemoryBlobImplDataOwnerMemoryReporter());
167 sMemoryReporterRegistered = true;
170 } // namespace mozilla::dom