Bug 1313859 - BlobImplStream implements nsIMemoryReporter, r=njn
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 04 Nov 2016 07:52:04 +0100
changeset 347706 176e40639a6c0d12aa45991546a2e5475095da39
parent 347705 84d61318bd70bdbc2d1eb46656725571f40996c2
child 347707 10d225cf619c678ddf631a60a6d3748bcfc4b3ae
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1313859
milestone52.0a1
Bug 1313859 - BlobImplStream implements nsIMemoryReporter, r=njn
dom/base/File.cpp
dom/base/File.h
dom/ipc/Blob.cpp
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -1255,17 +1255,42 @@ BlobImplTemporaryBlob::GetInternalStream
   nsCOMPtr<nsIInputStream> stream =
     new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength);
   stream.forget(aStream);
 }
 
 ////////////////////////////////////////////////////////////////////////////
 // BlobImplStream implementation
 
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplStream, BlobImpl)
+NS_IMPL_ISUPPORTS_INHERITED(BlobImplStream, BlobImpl, nsIMemoryReporter)
+
+/* static */ already_AddRefed<BlobImplStream>
+BlobImplStream::Create(nsIInputStream* aInputStream,
+                       const nsAString& aContentType,
+                       uint64_t aLength)
+{
+  RefPtr<BlobImplStream> blobImplStream =
+    new BlobImplStream(aInputStream, aContentType, aLength);
+  blobImplStream->MaybeRegisterMemoryReporter();
+  return blobImplStream.forget();
+}
+
+/* static */ already_AddRefed<BlobImplStream>
+BlobImplStream::Create(nsIInputStream* aInputStream,
+                       const nsAString& aName,
+                       const nsAString& aContentType,
+                       int64_t aLastModifiedDate,
+                       uint64_t aLength)
+{
+  RefPtr<BlobImplStream> blobImplStream =
+    new BlobImplStream(aInputStream, aName, aContentType, aLastModifiedDate,
+                       aLength);
+  blobImplStream->MaybeRegisterMemoryReporter();
+  return blobImplStream.forget();
+}
 
 BlobImplStream::BlobImplStream(nsIInputStream* aInputStream,
                                const nsAString& aContentType,
                                uint64_t aLength)
   : BlobImplBase(aContentType, aLength)
   , mInputStream(aInputStream)
 {
   mImmutable = true;
@@ -1287,17 +1312,19 @@ BlobImplStream::BlobImplStream(nsIInputS
                                uint64_t aLength)
   : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
   , mInputStream(aInputStream)
 {
   mImmutable = true;
 }
 
 BlobImplStream::~BlobImplStream()
-{}
+{
+  UnregisterWeakMemoryReporter(this);
+}
 
 void
 BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
 {
   nsCOMPtr<nsIInputStream> clonedStream;
   nsCOMPtr<nsIInputStream> replacementStream;
 
   aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
@@ -1322,10 +1349,41 @@ BlobImplStream::CreateSlice(uint64_t aSt
     return impl.forget();
   }
 
   RefPtr<BlobImpl> impl =
     new BlobImplStream(this, aContentType, aStart, aLength);
   return impl.forget();
 }
 
+void
+BlobImplStream::MaybeRegisterMemoryReporter()
+{
+  // We report only stringInputStream.
+  nsCOMPtr<nsIStringInputStream> stringInputStream =
+    do_QueryInterface(mInputStream);
+  if (!stringInputStream) {
+    return;
+  }
+
+  RegisterWeakMemoryReporter(this);
+}
+
+NS_IMETHODIMP
+BlobImplStream::CollectReports(nsIHandleReportCallback* aHandleReport,
+                               nsISupports* aData, bool aAnonymize)
+{
+  uint64_t size;
+  nsresult rv = mInputStream->Available(&size);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  MOZ_COLLECT_REPORT(
+    "explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
+    size,
+    "Memory used to back a File/Blob based on an input stream.");
+
+  return NS_OK;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -825,49 +825,65 @@ public:
     return true;
   }
 
 private:
   ~EmptyBlobImpl() {}
 };
 
 class BlobImplStream final : public BlobImplBase
+                           , public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIMEMORYREPORTER
 
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aContentType,
-                 uint64_t aLength);
+  static already_AddRefed<BlobImplStream>
+  Create(nsIInputStream* aInputStream,
+         const nsAString& aContentType,
+         uint64_t aLength);
 
-  BlobImplStream(nsIInputStream* aInputStream,
-                 const nsAString& aName,
-                 const nsAString& aContentType,
-                 int64_t aLastModifiedDate,
-                 uint64_t aLength);
+  static already_AddRefed<BlobImplStream>
+  Create(nsIInputStream* aInputStream,
+         const nsAString& aName,
+         const nsAString& aContentType,
+         int64_t aLastModifiedDate,
+         uint64_t aLength);
 
   virtual void GetInternalStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override;
 
   virtual already_AddRefed<BlobImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
               const nsAString& aContentType, ErrorResult& aRv) override;
 
   virtual bool IsMemoryFile() const override
   {
     return true;
   }
 
 private:
+  BlobImplStream(nsIInputStream* aInputStream,
+                 const nsAString& aContentType,
+                 uint64_t aLength);
+
+  BlobImplStream(nsIInputStream* aInputStream,
+                 const nsAString& aName,
+                 const nsAString& aContentType,
+                 int64_t aLastModifiedDate,
+                 uint64_t aLength);
+
   BlobImplStream(BlobImplStream* aOther,
                  const nsAString& aContentType,
                  uint64_t aStart,
                  uint64_t aLength);
 
   ~BlobImplStream();
 
+  void MaybeRegisterMemoryReporter();
+
   nsCOMPtr<nsIInputStream> mInputStream;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_File_h
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -743,31 +743,31 @@ CreateBlobImpl(const BlobDataStream& aSt
   }
 
   uint64_t length = aStream.length();
 
   RefPtr<BlobImpl> blobImpl;
   if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
     if (length) {
       blobImpl =
-        new BlobImplStream(inputStream,
-                           aMetadata.mName,
-                           aMetadata.mContentType,
-                           aMetadata.mLastModifiedDate,
-                           length);
+        BlobImplStream::Create(inputStream,
+                               aMetadata.mName,
+                               aMetadata.mContentType,
+                               aMetadata.mLastModifiedDate,
+                               length);
     } else {
       blobImpl =
         new EmptyBlobImpl(aMetadata.mName,
                           aMetadata.mContentType,
                           aMetadata.mLastModifiedDate);
     }
   } else if (length) {
     blobImpl =
-      new BlobImplStream(inputStream, aMetadata.mContentType,
-                         length);
+      BlobImplStream::Create(inputStream, aMetadata.mContentType,
+                             length);
   } else {
     blobImpl = new EmptyBlobImpl(aMetadata.mContentType);
   }
 
   MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
 
   return blobImpl.forget();
 }