Bug 1360807 - FileReaderSync must work with sync inputStream - part 2 - nsIConverterInputStream needs a syncInputStream, r=smaug
☠☠ backed out by 146f3b415f6c ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 04 May 2017 14:50:25 +0200
changeset 572797 6b389f6ad9710d4629dd171387d1420be9448bcb
parent 572796 8275594fe23583a6360062d4b03d6bf58a23ad6a
child 572798 d43275b33f002a1729d32a7ac5d422cf20ade220
push id57195
push userbmo:rbarker@mozilla.com
push dateThu, 04 May 2017 20:08:56 +0000
reviewerssmaug
bugs1360807
milestone55.0a1
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);