Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/file/MemoryBlobImpl.cpp
Line
Count
Source (jump to first uncovered line)
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
#include "MemoryBlobImpl.h"
8
#include "mozilla/IntegerPrintfMacros.h"
9
#include "mozilla/SHA1.h"
10
#include "nsPrintfCString.h"
11
12
namespace mozilla {
13
namespace dom {
14
15
NS_IMPL_ADDREF(MemoryBlobImpl::DataOwnerAdapter)
16
NS_IMPL_RELEASE(MemoryBlobImpl::DataOwnerAdapter)
17
18
0
NS_INTERFACE_MAP_BEGIN(MemoryBlobImpl::DataOwnerAdapter)
19
0
  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
20
0
  NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
21
0
  NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
22
0
  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
23
0
                                     mSerializableInputStream)
24
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
25
0
NS_INTERFACE_MAP_END
26
27
nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
28
                                                  uint32_t aStart,
29
                                                  uint32_t aLength,
30
                                                  nsIInputStream** _retval)
31
0
{
32
0
  nsresult rv;
33
0
  MOZ_ASSERT(aDataOwner, "Uh ...");
34
0
35
0
  nsCOMPtr<nsIInputStream> stream;
36
0
37
0
  rv = NS_NewByteInputStream(getter_AddRefs(stream),
38
0
                             static_cast<const char*>(aDataOwner->mData) +
39
0
                             aStart,
40
0
                             (int32_t)aLength,
41
0
                             NS_ASSIGNMENT_DEPEND);
42
0
  NS_ENSURE_SUCCESS(rv, rv);
43
0
44
0
  NS_ADDREF(*_retval =
45
0
              new MemoryBlobImpl::DataOwnerAdapter(aDataOwner, stream));
46
0
47
0
  return NS_OK;
48
0
}
49
50
already_AddRefed<BlobImpl>
51
MemoryBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
52
                            const nsAString& aContentType,
53
                            ErrorResult& aRv)
54
0
{
55
0
  RefPtr<BlobImpl> impl =
56
0
    new MemoryBlobImpl(this, aStart, aLength, aContentType);
57
0
  return impl.forget();
58
0
}
59
60
void
61
MemoryBlobImpl::CreateInputStream(nsIInputStream** aStream, ErrorResult& aRv)
62
0
{
63
0
  if (mLength > INT32_MAX) {
64
0
    aRv.Throw(NS_ERROR_FAILURE);
65
0
    return;
66
0
  }
67
0
68
0
  aRv = MemoryBlobImpl::DataOwnerAdapter::Create(mDataOwner, mStart, mLength,
69
0
                                                 aStream);
70
0
}
71
72
/* static */ StaticMutex
73
MemoryBlobImpl::DataOwner::sDataOwnerMutex;
74
75
/* static */ StaticAutoPtr<LinkedList<MemoryBlobImpl::DataOwner>>
76
MemoryBlobImpl::DataOwner::sDataOwners;
77
78
/* static */ bool
79
MemoryBlobImpl::DataOwner::sMemoryReporterRegistered = false;
80
81
MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
82
83
class MemoryBlobImplDataOwnerMemoryReporter final
84
  : public nsIMemoryReporter
85
{
86
0
  ~MemoryBlobImplDataOwnerMemoryReporter() {}
87
88
public:
89
  NS_DECL_THREADSAFE_ISUPPORTS
90
91
  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
92
                            nsISupports* aData, bool aAnonymize) override
93
0
  {
94
0
    typedef MemoryBlobImpl::DataOwner DataOwner;
95
0
96
0
    StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
97
0
98
0
    if (!DataOwner::sDataOwners) {
99
0
      return NS_OK;
100
0
    }
101
0
102
0
    const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
103
0
    size_t smallObjectsTotal = 0;
104
0
105
0
    for (DataOwner *owner = DataOwner::sDataOwners->getFirst();
106
0
         owner; owner = owner->getNext()) {
107
0
108
0
      size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
109
0
110
0
      if (size < LARGE_OBJECT_MIN_SIZE) {
111
0
        smallObjectsTotal += size;
112
0
      } else {
113
0
        SHA1Sum sha1;
114
0
        sha1.update(owner->mData, owner->mLength);
115
0
        uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
116
0
        sha1.finish(digest);
117
0
118
0
        nsAutoCString digestString;
119
0
        for (size_t i = 0; i < sizeof(digest); i++) {
120
0
          digestString.AppendPrintf("%02x", digest[i]);
121
0
        }
122
0
123
0
        aHandleReport->Callback(
124
0
          /* process */ NS_LITERAL_CSTRING(""),
125
0
          nsPrintfCString(
126
0
            "explicit/dom/memory-file-data/large/file(length=%" PRIu64 ", sha1=%s)",
127
0
            owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
128
0
          KIND_HEAP, UNITS_BYTES, size,
129
0
          nsPrintfCString(
130
0
            "Memory used to back a memory file of length %" PRIu64 " bytes.  The file "
131
0
            "has a sha1 of %s.\n\n"
132
0
            "Note that the allocator may round up a memory file's length -- "
133
0
            "that is, an N-byte memory file may take up more than N bytes of "
134
0
            "memory.",
135
0
            owner->mLength, digestString.get()),
136
0
          aData);
137
0
      }
138
0
    }
139
0
140
0
    if (smallObjectsTotal > 0) {
141
0
      aHandleReport->Callback(
142
0
        /* process */ NS_LITERAL_CSTRING(""),
143
0
        NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
144
0
        KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
145
0
        nsPrintfCString(
146
0
          "Memory used to back small memory files (i.e. those taking up less "
147
0
          "than %zu bytes of memory each).\n\n"
148
0
          "Note that the allocator may round up a memory file's length -- "
149
0
          "that is, an N-byte memory file may take up more than N bytes of "
150
0
          "memory.", LARGE_OBJECT_MIN_SIZE),
151
0
        aData);
152
0
    }
153
0
154
0
    return NS_OK;
155
0
  }
156
};
157
158
NS_IMPL_ISUPPORTS(MemoryBlobImplDataOwnerMemoryReporter, nsIMemoryReporter)
159
160
/* static */ void
161
MemoryBlobImpl::DataOwner::EnsureMemoryReporterRegistered()
162
0
{
163
0
  sDataOwnerMutex.AssertCurrentThreadOwns();
164
0
  if (sMemoryReporterRegistered) {
165
0
    return;
166
0
  }
167
0
168
0
  RegisterStrongMemoryReporter(new MemoryBlobImplDataOwnerMemoryReporter());
169
0
170
0
  sMemoryReporterRegistered = true;
171
0
}
172
173
} // namespace dom
174
} // namespace mozilla