Bug 1360807 - FileReaderSync must work with sync inputStream - part 4 - Base64EncodeInputStream needs a sync inputStream, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 09 May 2017 11:04:49 +0200
changeset 357184 86b8a2a927048fbafa15e7729580402881c061a3
parent 357183 8def8bb395587997d6e94338f1e09211dfee725b
child 357185 e7d08d835dcb5a481e71b17188d8c9a9d70cc0ec
push id90068
push useramarchesini@mozilla.com
push dateTue, 09 May 2017 09:07:54 +0000
treeherdermozilla-inbound@e7d08d835dcb [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 4 - Base64EncodeInputStream needs a sync inputStream, r=smaug
dom/file/FileReader.cpp
dom/workers/FileReaderSync.cpp
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -646,20 +646,20 @@ FileReader::OnInputStreamReady(nsIAsyncI
   // be 100% sure we have a workerHolder when OnLoadEnd() is called.
   FileReaderDecreaseBusyCounter RAII(this);
 
   uint64_t count;
   nsresult rv = aStream->Available(&count);
 
   if (NS_SUCCEEDED(rv) && count) {
     rv = DoReadData(count);
-  }
 
-  if (NS_SUCCEEDED(rv)) {
-    rv = DoAsyncWait();
+    if (NS_SUCCEEDED(rv)) {
+      rv = DoAsyncWait();
+    }
   }
 
   if (NS_FAILED(rv) || !count) {
     if (rv == NS_BASE_STREAM_CLOSED) {
       rv = NS_OK;
     }
     return OnLoadEnd(rv);
   }
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -16,16 +16,17 @@
 #include "nsCExternalHandlerService.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsError.h"
 #include "nsIConverterInputStream.h"
 #include "nsIInputStream.h"
 #include "nsIMultiplexInputStream.h"
+#include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "nsISupportsImpl.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIAsyncInputStream.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
@@ -77,17 +78,22 @@ FileReaderSync::ReadAsArrayBuffer(JSCont
     return;
   }
 
   uint32_t numRead;
   aRv = SyncRead(stream, bufferData.get(), blobSize, &numRead);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
-  NS_ASSERTION(numRead == blobSize, "failed to read data");
+
+  // The file is changed in the meantime?
+  if (numRead != blobSize) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   JSObject* arrayBuffer = JS_NewArrayBufferWithContents(aCx, blobSize, bufferData.get());
   if (!arrayBuffer) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
   // arrayBuffer takes the ownership when it is not null. Otherwise we
   // need to release it explicitly.
@@ -145,16 +151,22 @@ FileReaderSync::ReadAsText(Blob& aBlob,
   }
 
   uint32_t numRead = 0;
   aRv = SyncRead(stream, sniffBuf.BeginWriting(), sniffBuf.Length(), &numRead);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
+  // No data, we don't need to continue.
+  if (numRead == 0) {
+    aResult.Truncate();
+    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)) {
     // BOM sniffing failed. Try the API argument.
     if (!aEncoding.WasPassed() ||
         !EncodingUtils::FindEncodingForLabel(aEncoding.Value(),
                                              encoding)) {
@@ -239,29 +251,40 @@ FileReaderSync::ReadAsDataURL(Blob& aBlo
   scratchResult.AppendLiteral(";base64,");
 
   nsCOMPtr<nsIInputStream> stream;
   aBlob.GetInternalStream(getter_AddRefs(stream), aRv);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
-  uint64_t size = aBlob.GetSize(aRv);
+  nsCOMPtr<nsIInputStream> syncStream;
+  aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  uint64_t size;
+  aRv = syncStream->Available(&size);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  uint64_t blobSize = aBlob.GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
-  nsCOMPtr<nsIInputStream> bufferedStream;
-  aRv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, size);
-  if (NS_WARN_IF(aRv.Failed())){
+  // The file is changed in the meantime?
+  if (blobSize != size) {
     return;
   }
 
   nsAutoString encodedData;
-  aRv = Base64EncodeInputStream(bufferedStream, encodedData, size);
+  aRv = Base64EncodeInputStream(syncStream, encodedData, size);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
   scratchResult.Append(encodedData);
 
   aResult = scratchResult;
 }
@@ -440,22 +463,20 @@ FileReaderSync::SyncRead(nsIInputStream*
   // 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.
+  // If the stream is not async, we just need it to be bufferable.
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream);
   if (!asyncStream) {
-    nsCOMPtr<nsIInputStream> stream = aAsyncStream;
-    stream.forget(aSyncStream);
-    return NS_OK;
+    return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
   }
 
   uint64_t length;
   nsresult rv = aAsyncStream->Available(&length);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }