Bug 1181863 (Part 1) - Add support for reading from nsIInputStreams directly to SourceBuffer. r=tn

This commit is contained in:
Seth Fowler
2015-07-31 18:10:29 -07:00
parent 4052837f6a
commit a2a1d92123
4 changed files with 53 additions and 47 deletions

View File

@@ -1188,20 +1188,16 @@ RasterImage::NotifyForLoadEvent(Progress aProgress)
nsresult
RasterImage::OnImageDataAvailable(nsIRequest*,
nsISupports*,
nsIInputStream* aInStr,
uint64_t aOffset,
nsIInputStream* aInputStream,
uint64_t,
uint32_t aCount)
{
nsresult rv;
nsresult rv = mSourceBuffer->AppendFromInputStream(aInputStream, aCount);
MOZ_ASSERT(rv == NS_OK || rv == NS_ERROR_OUT_OF_MEMORY);
// WriteToSourceBuffer always consumes everything it gets if it doesn't run
// out of memory.
uint32_t bytesRead;
rv = aInStr->ReadSegments(WriteToSourceBuffer, this, aCount, &bytesRead);
MOZ_ASSERT(bytesRead == aCount || HasError() || NS_FAILED(rv),
"WriteToSourceBuffer should consume everything if ReadSegments succeeds or "
"the image must be in error!");
if (MOZ_UNLIKELY(rv == NS_ERROR_OUT_OF_MEMORY)) {
DoError();
}
return rv;
}
@@ -1902,36 +1898,6 @@ RasterImage::HandleErrorWorker::Run()
return NS_OK;
}
// nsIInputStream callback to copy the incoming image data directly to the
// RasterImage without processing. The RasterImage is passed as the closure.
// Always reads everything it gets, even if the data is erroneous.
NS_METHOD
RasterImage::WriteToSourceBuffer(nsIInputStream* /* unused */,
void* aClosure,
const char* aFromRawSegment,
uint32_t /* unused */,
uint32_t aCount,
uint32_t* aWriteCount)
{
// Retrieve the RasterImage
RasterImage* image = static_cast<RasterImage*>(aClosure);
// Copy the source data. Unless we hit OOM, we squelch the return value
// here, because returning an error means that ReadSegments stops
// reading data, violating our invariant that we read everything we get.
// If we hit OOM then we fail and the load is aborted.
nsresult rv = image->mSourceBuffer->Append(aFromRawSegment, aCount);
if (rv == NS_ERROR_OUT_OF_MEMORY) {
image->DoError();
return rv;
}
// We wrote everything we got
*aWriteCount = aCount;
return NS_OK;
}
bool
RasterImage::ShouldAnimate()
{

View File

@@ -170,12 +170,6 @@ public:
// Methods inherited from Image
virtual void OnSurfaceDiscarded() override;
// Raster-specific methods
static NS_METHOD WriteToSourceBuffer(nsIInputStream* aIn, void* aClosure,
const char* aFromRawSegment,
uint32_t aToOffset, uint32_t aCount,
uint32_t* aWriteCount);
/* The total number of frames in this image. */
uint32_t GetNumFrames() const { return mFrameCount; }

View File

@@ -9,6 +9,7 @@
#include <cmath>
#include <cstring>
#include "mozilla/Likely.h"
#include "nsIInputStream.h"
#include "MainThreadUtils.h"
#include "SurfaceCache.h"
@@ -354,6 +355,46 @@ SourceBuffer::Append(const char* aData, size_t aLength)
return NS_OK;
}
static NS_METHOD
AppendToSourceBuffer(nsIInputStream*,
void* aClosure,
const char* aFromRawSegment,
uint32_t,
uint32_t aCount,
uint32_t* aWriteCount)
{
SourceBuffer* sourceBuffer = static_cast<SourceBuffer*>(aClosure);
// Copy the source data. Unless we hit OOM, we squelch the return value here,
// because returning an error means that ReadSegments stops reading data, and
// we want to ensure that we read everything we get. If we hit OOM then we
// return a failed status to the caller.
nsresult rv = sourceBuffer->Append(aFromRawSegment, aCount);
if (rv == NS_ERROR_OUT_OF_MEMORY) {
return rv;
}
// Report that we wrote everything we got.
*aWriteCount = aCount;
return NS_OK;
}
nsresult
SourceBuffer::AppendFromInputStream(nsIInputStream* aInputStream,
uint32_t aCount)
{
uint32_t bytesRead;
nsresult rv = aInputStream->ReadSegments(AppendToSourceBuffer, this,
aCount, &bytesRead);
MOZ_ASSERT(bytesRead == aCount || rv == NS_ERROR_OUT_OF_MEMORY,
"AppendToSourceBuffer should consume everything unless "
"we run out of memory");
return rv;
}
void
SourceBuffer::Complete(nsresult aStatus)
{

View File

@@ -21,6 +21,8 @@
#include "mozilla/nsRefPtr.h"
#include "nsTArray.h"
class nsIInputStream;
namespace mozilla {
namespace image {
@@ -229,6 +231,9 @@ public:
/// Append the provided data to the buffer.
nsresult Append(const char* aData, size_t aLength);
/// Append the data available on the provided nsIInputStream to the buffer.
nsresult AppendFromInputStream(nsIInputStream* aInputStream, uint32_t aCount);
/**
* Mark the buffer complete, with a status that will be available to
* consumers. Further calls to Append() are forbidden after Complete().