Bug 1369619. Use ReadSegments in the SRI case in FetchDriver::OnDataAvailable. r=bkelly
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 06 Jun 2017 00:49:32 -0400
changeset 413014 61599ed0f713304e0ffb0564dffd4f8918ad68dd
parent 412943 cac26305ac53144a8fad330cc27a1a0e66931c6f
child 413015 3e1dea2784281f3fb022d2c96df48338afc825f5
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1369619
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 1369619. Use ReadSegments in the SRI case in FetchDriver::OnDataAvailable. r=bkelly This avoids some buffer copies and is arguably more readble.
dom/fetch/FetchDriver.cpp
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -652,16 +652,63 @@ public:
   Run() override
   {
     mObserver->OnDataAvailable();
     mObserver = nullptr;
     return NS_OK;
   }
 };
 
+struct SRIVerifierAndOutputHolder {
+  SRIVerifierAndOutputHolder(SRICheckDataVerifier* aVerifier,
+                             nsIOutputStream* aOutputStream)
+    : mVerifier(aVerifier)
+    , mOutputStream(aOutputStream)
+  {}
+
+  SRICheckDataVerifier* mVerifier;
+  nsIOutputStream* mOutputStream;
+
+private:
+  SRIVerifierAndOutputHolder() = delete;
+};
+
+// Just like NS_CopySegmentToStream, but also sends the data into an
+// SRICheckDataVerifier.
+nsresult
+CopySegmentToStreamAndSRI(nsIInputStream* aInStr,
+                          void* aClosure,
+                          const char* aBuffer,
+                          uint32_t aOffset,
+                          uint32_t aCount,
+                          uint32_t* aCountWritten)
+{
+  auto holder = static_cast<SRIVerifierAndOutputHolder*>(aClosure);
+  MOZ_DIAGNOSTIC_ASSERT(holder && holder->mVerifier && holder->mOutputStream,
+                        "Bogus holder");
+  nsresult rv =
+    holder->mVerifier->Update(aCount,
+                              reinterpret_cast<const uint8_t*>(aBuffer));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // The rest is just like NS_CopySegmentToStream.
+  *aCountWritten = 0;
+  while (aCount) {
+    uint32_t n = 0;
+    rv = holder->mOutputStream->Write(aBuffer, aCount, &n);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    aBuffer += n;
+    aCount -= n;
+    *aCountWritten += n;
+  }
+  return NS_OK;
+}
+
 } // anonymous namespace
 
 NS_IMETHODIMP
 FetchDriver::OnDataAvailable(nsIRequest* aRequest,
                              nsISupports* aContext,
                              nsIInputStream* aInputStream,
                              uint64_t aOffset,
                              uint32_t aCount)
@@ -687,49 +734,20 @@ FetchDriver::OnDataAvailable(nsIRequest*
   MOZ_ASSERT(mResponse);
   MOZ_ASSERT(mPipeOutputStream);
 
   // From "Main Fetch" step 17: SRI-part2.
   if (mResponse->Type() != ResponseType::Error &&
       !mRequest->GetIntegrity().IsEmpty()) {
     MOZ_ASSERT(mSRIDataVerifier);
 
-    uint32_t aWrite;
-    nsTArray<uint8_t> buffer;
-    nsresult rv;
-    buffer.SetCapacity(aCount);
-    while (aCount > 0) {
-      rv = aInputStream->Read(reinterpret_cast<char*>(buffer.Elements()),
-                              aCount, &aRead);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-
-      rv = mSRIDataVerifier->Update(aRead, (uint8_t*)buffer.Elements());
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      while (aRead > 0) {
-        rv = mPipeOutputStream->Write(reinterpret_cast<char*>(buffer.Elements()),
-                                      aRead, &aWrite);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        if (aRead < aWrite) {
-          return NS_ERROR_FAILURE;
-        }
-
-        aRead -= aWrite;
-      }
-
-
-      aCount -= aWrite;
-    }
-
-    return NS_OK;
+    SRIVerifierAndOutputHolder holder(mSRIDataVerifier, mPipeOutputStream);
+    nsresult rv = aInputStream->ReadSegments(CopySegmentToStreamAndSRI,
+                                             &holder, aCount, &aRead);
+    return rv;
   }
 
   nsresult rv = aInputStream->ReadSegments(NS_CopySegmentToStream,
                                            mPipeOutputStream,
                                            aCount, &aRead);
   return rv;
 }