Bug 1466314 - StreamBlobImpl should wrap the cloned stream with InputStreamLengthWrapper if needed, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 13 Jun 2018 08:37:26 -0700
changeset 422429 3f522a95458d15844af23f792caff4e6c11f01e8
parent 422428 53eda8b305e9fd3a625086bad6ee2a17f9e6b58f
child 422430 e4b352ed03f7bef3af5aa4c163a1a050177ab061
push id34134
push usernbeleuzu@mozilla.com
push dateWed, 13 Jun 2018 21:53:17 +0000
treeherdermozilla-central@c7a7df27ff38 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1466314
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1466314 - StreamBlobImpl should wrap the cloned stream with InputStreamLengthWrapper if needed, r=smaug
dom/file/StreamBlobImpl.cpp
xpcom/io/InputStreamLengthWrapper.cpp
xpcom/io/InputStreamLengthWrapper.h
--- a/dom/file/StreamBlobImpl.cpp
+++ b/dom/file/StreamBlobImpl.cpp
@@ -1,15 +1,16 @@
 /* -*- 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 "EmptyBlobImpl.h"
+#include "mozilla/InputStreamLengthWrapper.h"
 #include "mozilla/SlicedInputStream.h"
 #include "StreamBlobImpl.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "nsICloneableInputStream.h"
 
 namespace mozilla {
 namespace dom {
@@ -85,17 +86,20 @@ StreamBlobImpl::CreateInputStream(nsIInp
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (replacementStream) {
     mInputStream = replacementStream.forget();
   }
 
-  clonedStream.forget(aStream);
+  nsCOMPtr<nsIInputStream> wrappedStream =
+    InputStreamLengthWrapper::MaybeWrap(clonedStream.forget(), mLength);
+
+  wrappedStream.forget(aStream);
 }
 
 already_AddRefed<BlobImpl>
 StreamBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
                             const nsAString& aContentType, ErrorResult& aRv)
 {
   if (!aLength) {
     RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
--- a/xpcom/io/InputStreamLengthWrapper.cpp
+++ b/xpcom/io/InputStreamLengthWrapper.cpp
@@ -27,16 +27,42 @@ NS_INTERFACE_MAP_BEGIN(InputStreamLength
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
                                      mWeakAsyncInputStream || !mInputStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
                                      mWeakAsyncInputStream || !mInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
+/* static */ already_AddRefed<nsIInputStream>
+InputStreamLengthWrapper::MaybeWrap(already_AddRefed<nsIInputStream> aInputStream,
+                                    int64_t aLength)
+{
+  nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream);
+  MOZ_ASSERT(inputStream);
+
+  nsCOMPtr<nsIInputStreamLength> length = do_QueryInterface(inputStream);
+  if (length) {
+    return inputStream.forget();
+  }
+
+  nsCOMPtr<nsIAsyncInputStreamLength> asyncLength = do_QueryInterface(inputStream);
+  if (asyncLength) {
+    return inputStream.forget();
+  }
+
+  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(inputStream);
+  if (!asyncStream) {
+    return inputStream.forget();
+  }
+
+  inputStream = new InputStreamLengthWrapper(inputStream.forget(), aLength);
+  return inputStream.forget();
+}
+
 InputStreamLengthWrapper::InputStreamLengthWrapper(already_AddRefed<nsIInputStream> aInputStream,
                                                    int64_t aLength)
   : mWeakCloneableInputStream(nullptr)
   , mWeakIPCSerializableInputStream(nullptr)
   , mWeakSeekableInputStream(nullptr)
   , mWeakAsyncInputStream(nullptr)
   , mLength(aLength)
   , mConsumed(false)
--- a/xpcom/io/InputStreamLengthWrapper.h
+++ b/xpcom/io/InputStreamLengthWrapper.h
@@ -34,16 +34,27 @@ public:
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
   NS_DECL_NSICLONEABLEINPUTSTREAM
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
   NS_DECL_NSISEEKABLESTREAM
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSIINPUTSTREAMLENGTH
 
+  // This method creates a InputStreamLengthWrapper around aInputStream if
+  // this doesn't implement nsIInputStreamLength or
+  // nsIInputStreamAsyncLength interface, but it implements
+  // nsIAsyncInputStream. For this kind of streams,
+  // InputStreamLengthHelper is not able to retrieve the length. This
+  // method will make such streams ready to be used with
+  // InputStreamLengthHelper.
+  static already_AddRefed<nsIInputStream>
+  MaybeWrap(already_AddRefed<nsIInputStream> aInputStream,
+            int64_t aLength);
+
   // The length here will be used when nsIInputStreamLength::Length() is called.
   InputStreamLengthWrapper(already_AddRefed<nsIInputStream> aInputStream,
                            int64_t aLength);
 
   // This CTOR is meant to be used just for IPC.
   InputStreamLengthWrapper();
 
 private: