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 "StreamBlobImpl.h"
8 #include "nsStringStream.h"
9 #include "nsICloneableInputStream.h"
10
11 namespace mozilla {
12 namespace dom {
13
NS_IMPL_ISUPPORTS_INHERITED(StreamBlobImpl,BlobImpl,nsIMemoryReporter)14 NS_IMPL_ISUPPORTS_INHERITED(StreamBlobImpl, BlobImpl, nsIMemoryReporter)
15
16 /* static */ already_AddRefed<StreamBlobImpl> StreamBlobImpl::Create(
17 nsIInputStream* aInputStream, const nsAString& aContentType,
18 uint64_t aLength) {
19 RefPtr<StreamBlobImpl> blobImplStream =
20 new StreamBlobImpl(aInputStream, aContentType, aLength);
21 blobImplStream->MaybeRegisterMemoryReporter();
22 return blobImplStream.forget();
23 }
24
Create(nsIInputStream * aInputStream,const nsAString & aName,const nsAString & aContentType,int64_t aLastModifiedDate,uint64_t aLength)25 /* static */ already_AddRefed<StreamBlobImpl> StreamBlobImpl::Create(
26 nsIInputStream* aInputStream, const nsAString& aName,
27 const nsAString& aContentType, int64_t aLastModifiedDate,
28 uint64_t aLength) {
29 RefPtr<StreamBlobImpl> blobImplStream = new StreamBlobImpl(
30 aInputStream, aName, aContentType, aLastModifiedDate, aLength);
31 blobImplStream->MaybeRegisterMemoryReporter();
32 return blobImplStream.forget();
33 }
34
StreamBlobImpl(nsIInputStream * aInputStream,const nsAString & aContentType,uint64_t aLength)35 StreamBlobImpl::StreamBlobImpl(nsIInputStream* aInputStream,
36 const nsAString& aContentType, uint64_t aLength)
37 : BaseBlobImpl(aContentType, aLength),
38 mInputStream(aInputStream),
39 mIsDirectory(false),
40 mFileId(-1) {
41 mImmutable = true;
42 }
43
StreamBlobImpl(nsIInputStream * aInputStream,const nsAString & aName,const nsAString & aContentType,int64_t aLastModifiedDate,uint64_t aLength)44 StreamBlobImpl::StreamBlobImpl(nsIInputStream* aInputStream,
45 const nsAString& aName,
46 const nsAString& aContentType,
47 int64_t aLastModifiedDate, uint64_t aLength)
48 : BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate),
49 mInputStream(aInputStream),
50 mIsDirectory(false),
51 mFileId(-1) {
52 mImmutable = true;
53 }
54
~StreamBlobImpl()55 StreamBlobImpl::~StreamBlobImpl() { UnregisterWeakMemoryReporter(this); }
56
CreateInputStream(nsIInputStream ** aStream,ErrorResult & aRv)57 void StreamBlobImpl::CreateInputStream(nsIInputStream** aStream,
58 ErrorResult& aRv) {
59 nsCOMPtr<nsIInputStream> clonedStream;
60 nsCOMPtr<nsIInputStream> replacementStream;
61
62 aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
63 getter_AddRefs(replacementStream));
64 if (NS_WARN_IF(aRv.Failed())) {
65 return;
66 }
67
68 if (replacementStream) {
69 mInputStream = replacementStream.forget();
70 }
71
72 clonedStream.forget(aStream);
73 }
74
CreateSlice(uint64_t aStart,uint64_t aLength,const nsAString & aContentType,ErrorResult & aRv)75 already_AddRefed<BlobImpl> StreamBlobImpl::CreateSlice(
76 uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
77 ErrorResult& aRv) {
78 if (!aLength) {
79 RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
80 return impl.forget();
81 }
82
83 nsCOMPtr<nsIInputStream> clonedStream;
84
85 nsCOMPtr<nsICloneableInputStreamWithRange> stream =
86 do_QueryInterface(mInputStream);
87 if (stream) {
88 aRv = stream->CloneWithRange(aStart, aLength, getter_AddRefs(clonedStream));
89 if (NS_WARN_IF(aRv.Failed())) {
90 return nullptr;
91 }
92 } else {
93 CreateInputStream(getter_AddRefs(clonedStream), aRv);
94 if (NS_WARN_IF(aRv.Failed())) {
95 return nullptr;
96 }
97
98 clonedStream =
99 new SlicedInputStream(clonedStream.forget(), aStart, aLength);
100 }
101
102 MOZ_ASSERT(clonedStream);
103
104 RefPtr<BlobImpl> impl =
105 new StreamBlobImpl(clonedStream, aContentType, aLength);
106 return impl.forget();
107 }
108
MaybeRegisterMemoryReporter()109 void StreamBlobImpl::MaybeRegisterMemoryReporter() {
110 // We report only stringInputStream.
111 nsCOMPtr<nsIStringInputStream> stringInputStream =
112 do_QueryInterface(mInputStream);
113 if (!stringInputStream) {
114 return;
115 }
116
117 RegisterWeakMemoryReporter(this);
118 }
119
120 NS_IMETHODIMP
CollectReports(nsIHandleReportCallback * aHandleReport,nsISupports * aData,bool aAnonymize)121 StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
122 nsISupports* aData, bool aAnonymize) {
123 nsCOMPtr<nsIStringInputStream> stringInputStream =
124 do_QueryInterface(mInputStream);
125 if (!stringInputStream) {
126 return NS_OK;
127 }
128
129 MOZ_COLLECT_REPORT(
130 "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
131 stringInputStream->SizeOfIncludingThis(MallocSizeOf),
132 "Memory used to back a File/Blob based on an input stream.");
133
134 return NS_OK;
135 }
136
GetAllocationSize() const137 size_t StreamBlobImpl::GetAllocationSize() const {
138 nsCOMPtr<nsIStringInputStream> stringInputStream =
139 do_QueryInterface(mInputStream);
140 if (!stringInputStream) {
141 return 0;
142 }
143
144 return stringInputStream->SizeOfIncludingThis(MallocSizeOf);
145 }
146
147 } // namespace dom
148 } // namespace mozilla
149