Bug 1360807 - FileReaderSync must work with sync inputStream - part 2 - nsIConverterInputStream needs a syncInputStream, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 09 May 2017 11:04:07 +0200
changeset 357317 d80ae4ab872f8f61cf323a0318696c89dbe07e2e
parent 357316 21d38bbbb10b8f9e45b061b6f44e1abd9435dda1
child 357318 8def8bb395587997d6e94338f1e09211dfee725b
push id31789
push userkwierso@gmail.com
push dateTue, 09 May 2017 21:36:07 +0000
treeherdermozilla-central@120d8562d4a5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1360807
milestone55.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 1360807 - FileReaderSync must work with sync inputStream - part 2 - nsIConverterInputStream needs a syncInputStream, r=smaug
dom/workers/FileReaderSync.cpp
dom/workers/FileReaderSync.h
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -177,39 +177,45 @@ FileReaderSync::ReadAsText(Blob& aBlob,
     }
   }
 
   if (numRead < sniffBuf.Length()) {
     sniffBuf.Truncate(numRead);
   }
 
   // Let's recreate the full stream using a:
-  // multiplexStream(stringStream + original stream)
+  // multiplexStream(syncStream + original stream)
   // In theory, we could try to see if the inputStream is a nsISeekableStream,
   // but this doesn't work correctly for nsPipe3 - See bug 1349570.
 
-  nsCOMPtr<nsIInputStream> stringStream;
-  aRv = NS_NewCStringInputStream(getter_AddRefs(stringStream), sniffBuf);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
   nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
     do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
   if (NS_WARN_IF(!multiplexStream)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  aRv = multiplexStream->AppendStream(stringStream);
+  nsCOMPtr<nsIInputStream> sniffStringStream;
+  aRv = NS_NewCStringInputStream(getter_AddRefs(sniffStringStream), sniffBuf);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  aRv = multiplexStream->AppendStream(stream);
+  aRv = multiplexStream->AppendStream(sniffStringStream);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  nsCOMPtr<nsIInputStream> syncStream;
+  aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  aRv = multiplexStream->AppendStream(syncStream);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   aRv = ConvertStream(multiplexStream, encoding.get(), aResult);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
@@ -429,8 +435,49 @@ FileReaderSync::SyncRead(nsIInputStream*
 
   if (!syncLoop.Run()) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   // Now, we can try to read again.
   return SyncRead(aStream, aBuffer, aBufferSize, aRead);
 }
+
+nsresult
+FileReaderSync::ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
+                                         nsIInputStream** aSyncStream)
+{
+  // If the stream is not async, we have nothing to do here.
+  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream);
+  if (!asyncStream) {
+    nsCOMPtr<nsIInputStream> stream = aAsyncStream;
+    stream.forget(aSyncStream);
+    return NS_OK;
+  }
+
+  uint64_t length;
+  nsresult rv = aAsyncStream->Available(&length);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsAutoCString buffer;
+  if (!buffer.SetLength(length, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  uint32_t read;
+  rv = SyncRead(aAsyncStream, buffer.BeginWriting(), length, &read);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (read != length) {
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = NS_NewCStringInputStream(aSyncStream, buffer);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -27,16 +27,19 @@ private:
   // Private destructor, to discourage deletion outside of Release():
   ~FileReaderSync()
   {
   }
 
   nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
                          nsAString &aResult);
 
+  nsresult ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
+                                    nsIInputStream** aSyncStream);
+
   nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
                     uint32_t aBufferSize, uint32_t* aRead);
 
 public:
   static already_AddRefed<FileReaderSync>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
 
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);