Bug 1360807 - FileReaderSync must work with sync inputStream - part 1 - SyncRead should read as much as required, r=smaug
☠☠ backed out by 797a743271c6 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 04 May 2017 14:49:56 +0200
changeset 572817 4ab091bdeda1baad4edf8c193260397fddb66016
parent 572816 e9078bccc0a3cb05d7605fe7a270b6f240d27aac
child 572818 c800cb830b36bd401b22724587b2a810a3234562
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 1 - SyncRead should read as much as required, r=smaug
dom/workers/FileReaderSync.cpp
dom/workers/FileReaderSync.h
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -73,17 +73,17 @@ FileReaderSync::ReadAsArrayBuffer(JSCont
 
   nsCOMPtr<nsIInputStream> stream;
   aBlob.GetInternalStream(getter_AddRefs(stream), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   uint32_t numRead;
-  aRv = Read(stream, bufferData.get(), blobSize, &numRead);
+  aRv = SyncRead(stream, bufferData.get(), blobSize, &numRead);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
   NS_ASSERTION(numRead == blobSize, "failed to read data");
 
   JSObject* arrayBuffer = JS_NewArrayBufferWithContents(aCx, blobSize, bufferData.get());
   if (!arrayBuffer) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@@ -105,17 +105,17 @@ FileReaderSync::ReadAsBinaryString(Blob&
   aBlob.GetInternalStream(getter_AddRefs(stream), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   uint32_t numRead;
   do {
     char readBuf[4096];
-    aRv = Read(stream, readBuf, sizeof(readBuf), &numRead);
+    aRv = SyncRead(stream, readBuf, sizeof(readBuf), &numRead);
     if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
 
     uint32_t oldLength = aResult.Length();
     AppendASCIItoUTF16(Substring(readBuf, readBuf + numRead), aResult);
     if (aResult.Length() - oldLength != numRead) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@@ -140,17 +140,17 @@ FileReaderSync::ReadAsText(Blob& aBlob,
 
   nsCString sniffBuf;
   if (!sniffBuf.SetLength(3, fallible)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   uint32_t numRead = 0;
-  aRv = Read(stream, sniffBuf.BeginWriting(), sniffBuf.Length(), &numRead);
+  aRv = SyncRead(stream, sniffBuf.BeginWriting(), sniffBuf.Length(), &numRead);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // The BOM sniffing is baked into the "decode" part of the Encoding
   // Standard, which the File API references.
   if (!nsContentUtils::CheckForBOM((const unsigned char*)sniffBuf.BeginReading(),
                                    numRead, encoding)) {
@@ -356,29 +356,53 @@ NS_IMPL_RELEASE(ReadCallback);
 NS_INTERFACE_MAP_BEGIN(ReadCallback)
   NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStreamCallback)
 NS_INTERFACE_MAP_END
 
 } // anonymous
 
 nsresult
-FileReaderSync::Read(nsIInputStream* aStream, char* aBuffer, uint32_t aBufferSize,
-                     uint32_t* aRead)
+FileReaderSync::SyncRead(nsIInputStream* aStream, char* aBuffer,
+                         uint32_t aBufferSize, uint32_t* aRead)
 {
   MOZ_ASSERT(aStream);
   MOZ_ASSERT(aBuffer);
   MOZ_ASSERT(aRead);
 
   // Let's try to read, directly.
   nsresult rv = aStream->Read(aBuffer, aBufferSize, aRead);
-  if (NS_SUCCEEDED(rv) || rv != NS_BASE_STREAM_WOULD_BLOCK) {
+
+  // Nothing else to read.
+  if (rv == NS_BASE_STREAM_CLOSED ||
+      (NS_SUCCEEDED(rv) && *aRead == 0)) {
+    return NS_OK;
+  }
+
+  // An error.
+  if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
     return rv;
   }
 
+  // All good.
+  if (NS_SUCCEEDED(rv)) {
+    // Not enough data, let's read recursively.
+    if (*aRead != aBufferSize) {
+      uint32_t byteRead = 0;
+      rv = SyncRead(aStream, aBuffer + *aRead, aBufferSize - *aRead, &byteRead);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      *aRead += byteRead;
+    }
+
+    return NS_OK;
+  }
+
   // We need to proceed async.
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
   if (!asyncStream) {
     return rv;
   }
 
   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(workerPrivate);
@@ -403,10 +427,10 @@ FileReaderSync::Read(nsIInputStream* aSt
     return rv;
   }
 
   if (!syncLoop.Run()) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   // Now, we can try to read again.
-  return Read(aStream, aBuffer, aBufferSize, aRead);
+  return SyncRead(aStream, aBuffer, aBufferSize, aRead);
 }
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -27,18 +27,18 @@ private:
   // Private destructor, to discourage deletion outside of Release():
   ~FileReaderSync()
   {
   }
 
   nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
                          nsAString &aResult);
 
-  nsresult Read(nsIInputStream* aStream, char* aBuffer, uint32_t aBufferSize,
-                uint32_t* aRead);
+  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);
 
   void ReadAsArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aScopeObj,