Bug 1818305 - Part 2: Add a streamStatus method to nsIInputStream, r=xpcom-reviewers,necko-reviewers,geckoview-reviewers,valentin,jesup,m_kato,mccr8

This is semantically similar to the existing available() method, however will
not block, and doesn't need to do the work to actually determine the number of
available bytes.

As part of this patch, I also fixed one available() implementation which was
incorrectly throwing NS_BASE_STREAM_WOULD_BLOCK.

Differential Revision: https://phabricator.services.mozilla.com/D170697
This commit is contained in:
Nika Layzell 2023-03-15 19:52:34 +00:00
Родитель e61507c3a3
Коммит 3b40268cc1
56 изменённых файлов: 378 добавлений и 5 удалений

20
dom/cache/ReadStream.cpp поставляемый
Просмотреть файл

@ -46,6 +46,8 @@ class ReadStream::Inner final : public ReadStream::Controllable {
nsresult Available(uint64_t* aNumAvailableOut);
nsresult StreamStatus();
nsresult Read(char* aBuf, uint32_t aCount, uint32_t* aNumReadOut);
nsresult ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
@ -266,6 +268,21 @@ nsresult ReadStream::Inner::Available(uint64_t* aNumAvailableOut) {
return rv;
}
nsresult ReadStream::Inner::StreamStatus() {
// stream ops can happen on any thread
nsresult rv = NS_OK;
{
MutexAutoLock lock(mMutex);
rv = EnsureStream()->StreamStatus();
}
if (NS_FAILED(rv)) {
Close();
}
return rv;
}
nsresult ReadStream::Inner::Read(char* aBuf, uint32_t aCount,
uint32_t* aNumReadOut) {
// stream ops can happen on any thread
@ -581,6 +598,9 @@ ReadStream::Available(uint64_t* aNumAvailableOut) {
return mInner->Available(aNumAvailableOut);
}
NS_IMETHODIMP
ReadStream::StreamStatus() { return mInner->StreamStatus(); }
NS_IMETHODIMP
ReadStream::Read(char* aBuf, uint32_t aCount, uint32_t* aNumReadOut) {
return mInner->Read(aBuf, aCount, aNumReadOut);

Просмотреть файл

@ -330,6 +330,36 @@ RemoteLazyInputStream::Available(uint64_t* aLength) {
return stream->Available(aLength);
}
NS_IMETHODIMP
RemoteLazyInputStream::StreamStatus() {
nsCOMPtr<nsIAsyncInputStream> stream;
{
MutexAutoLock lock(mMutex);
// We don't have a remoteStream yet: let's return 0.
if (mState == eInit || mState == ePending) {
return NS_OK;
}
if (mState == eClosed) {
return NS_BASE_STREAM_CLOSED;
}
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mInnerStream || mAsyncInnerStream);
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
stream = mAsyncInnerStream;
}
MOZ_ASSERT(stream);
return stream->StreamStatus();
}
NS_IMETHODIMP
RemoteLazyInputStream::Read(char* aBuffer, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -70,7 +70,27 @@ NS_IMETHODIMP BlobURLInputStream::Available(uint64_t* aLength) {
return mAsyncInputStream->Available(aLength);
}
return NS_BASE_STREAM_WOULD_BLOCK;
return NS_OK;
}
NS_IMETHODIMP BlobURLInputStream::StreamStatus() {
MutexAutoLock lock(mStateMachineMutex);
if (mState == State::ERROR) {
MOZ_ASSERT(NS_FAILED(mError));
return mError;
}
if (mState == State::CLOSED) {
return NS_BASE_STREAM_CLOSED;
}
if (mState == State::READY) {
MOZ_ASSERT(mAsyncInputStream);
return mAsyncInputStream->StreamStatus();
}
return NS_OK;
}
NS_IMETHODIMP BlobURLInputStream::Read(char* aBuffer, uint32_t aCount,

Просмотреть файл

@ -18785,6 +18785,9 @@ ObjectStoreAddOrPutRequestOp::SCInputStream::Available(uint64_t* _retval) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ObjectStoreAddOrPutRequestOp::SCInputStream::StreamStatus() { return NS_OK; }
NS_IMETHODIMP
ObjectStoreAddOrPutRequestOp::SCInputStream::Read(char* aBuf, uint32_t aCount,
uint32_t* _retval) {

Просмотреть файл

@ -329,6 +329,8 @@ nsresult WebrtcTCPSocketTestInputStream::Available(uint64_t* aAvailable) {
return NS_OK;
}
nsresult WebrtcTCPSocketTestInputStream::StreamStatus() { return NS_OK; }
nsresult WebrtcTCPSocketTestInputStream::Read(char* aBuffer, uint32_t aCount,
uint32_t* aRead) {
std::lock_guard<std::mutex> guard(mDataMutex);

Просмотреть файл

@ -107,6 +107,7 @@ class DecryptingInputStream final : public DecryptingInputStreamBase {
NS_IMETHOD Close() override;
NS_IMETHOD Available(uint64_t* _retval) override;
NS_IMETHOD StreamStatus() override;
NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* _retval) override;

Просмотреть файл

@ -104,6 +104,11 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Available(
return NS_OK;
}
template <typename CipherStrategy>
NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::StreamStatus() {
return mBaseStream ? NS_OK : NS_BASE_STREAM_CLOSED;
}
template <typename CipherStrategy>
NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::ReadSegments(
nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,

Просмотреть файл

@ -114,6 +114,11 @@ ArrayBufferInputStream::Available(uint64_t* aCount) {
return NS_OK;
}
NS_IMETHODIMP
ArrayBufferInputStream::StreamStatus() {
return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHODIMP
ArrayBufferInputStream::Read(char* aBuf, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -334,6 +334,12 @@ nsBMPEncoder::Available(uint64_t* _retval) {
return NS_OK;
}
// Obtains the stream's status
NS_IMETHODIMP
nsBMPEncoder::StreamStatus() {
return mImageBufferStart && mImageBufferCurr ? NS_OK : NS_BASE_STREAM_CLOSED;
}
// [noscript] Reads bytes which are available
NS_IMETHODIMP
nsBMPEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {

Просмотреть файл

@ -323,6 +323,12 @@ nsICOEncoder::Available(uint64_t* _retval) {
return NS_OK;
}
// Obtains the stream's status
NS_IMETHODIMP
nsICOEncoder::StreamStatus() {
return mImageBufferStart && mImageBufferCurr ? NS_OK : NS_BASE_STREAM_CLOSED;
}
// [noscript] Reads bytes which are available
NS_IMETHODIMP
nsICOEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {

Просмотреть файл

@ -281,6 +281,11 @@ nsJPEGEncoder::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP
nsJPEGEncoder::StreamStatus() {
return mImageBuffer ? NS_OK : NS_BASE_STREAM_CLOSED;
}
NS_IMETHODIMP
nsJPEGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);

Просмотреть файл

@ -586,6 +586,11 @@ nsPNGEncoder::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP
nsPNGEncoder::StreamStatus() {
return mImageBuffer ? NS_OK : NS_BASE_STREAM_CLOSED;
}
NS_IMETHODIMP
nsPNGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);

Просмотреть файл

@ -229,6 +229,11 @@ nsWebPEncoder::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP
nsWebPEncoder::StreamStatus() {
return mImageBuffer ? NS_OK : NS_BASE_STREAM_CLOSED;
}
NS_IMETHODIMP
nsWebPEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);

Просмотреть файл

@ -53,6 +53,9 @@ ShortReadWrapper::Available(uint64_t* aAvailable) {
return NS_OK;
}
NS_IMETHODIMP
ShortReadWrapper::StreamStatus() { return mBaseStream->StreamStatus(); }
NS_IMETHODIMP
ShortReadWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
if (mShortReadIter != mShortReadEnd) {

Просмотреть файл

@ -612,6 +612,11 @@ NS_IMETHODIMP DataPipeReceiver::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP DataPipeReceiver::StreamStatus() {
data_pipe_detail::DataPipeAutoLock lock(*mMutex);
return CheckStatus(lock);
}
NS_IMETHODIMP DataPipeReceiver::Read(char* aBuf, uint32_t aCount,
uint32_t* aReadCount) {
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount);

Просмотреть файл

@ -154,6 +154,11 @@ nsJARInputThunk::Available(uint64_t* avail) {
return mJarStream->Available(avail);
}
NS_IMETHODIMP
nsJARInputThunk::StreamStatus() {
return mJarStream->StreamStatus();
}
NS_IMETHODIMP
nsJARInputThunk::Read(char* buf, uint32_t count, uint32_t* countRead) {
return mJarStream->Read(buf, count, countRead);

Просмотреть файл

@ -172,6 +172,11 @@ nsJARInputStream::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP
nsJARInputStream::StreamStatus() {
return mMode == MODE_CLOSED ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHODIMP
nsJARInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytesRead) {
NS_ENSURE_ARG_POINTER(aBuffer);

Просмотреть файл

@ -73,6 +73,11 @@ ArrayBufferInputStream::Available(uint64_t* aCount) {
return NS_OK;
}
NS_IMETHODIMP
ArrayBufferInputStream::StreamStatus() {
return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHODIMP
ArrayBufferInputStream::Read(char* aBuf, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -76,6 +76,15 @@ ThrottleInputStream::Available(uint64_t* aResult) {
return mStream->Available(aResult);
}
NS_IMETHODIMP
ThrottleInputStream::StreamStatus() {
if (NS_FAILED(mClosedStatus)) {
return mClosedStatus;
}
return mStream->StreamStatus();
}
NS_IMETHODIMP
ThrottleInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult) {
if (NS_FAILED(mClosedStatus)) {

Просмотреть файл

@ -54,6 +54,9 @@ nsBaseContentStream::Available(uint64_t* result) {
return mStatus;
}
NS_IMETHODIMP
nsBaseContentStream::StreamStatus() { return mStatus; }
NS_IMETHODIMP
nsBaseContentStream::Read(char* buf, uint32_t count, uint32_t* result) {
return ReadSegments(NS_CopySegmentToBuffer, buf, count, result);

Просмотреть файл

@ -400,6 +400,19 @@ nsBufferedInputStream::Available(uint64_t* result) {
return rv;
}
NS_IMETHODIMP
nsBufferedInputStream::StreamStatus() {
if (!mStream) {
return NS_OK;
}
if (mFillPoint - mCursor) {
return NS_OK;
}
return Source()->StreamStatus();
}
NS_IMETHODIMP
nsBufferedInputStream::Read(char* buf, uint32_t count, uint32_t* result) {
if (mBufferDisabled) {

Просмотреть файл

@ -150,6 +150,9 @@ nsDirectoryIndexStream::Available(uint64_t* aLength) {
return NS_OK;
}
NS_IMETHODIMP
nsDirectoryIndexStream::StreamStatus() { return mStatus; }
NS_IMETHODIMP
nsDirectoryIndexStream::Read(char* aBuf, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -567,6 +567,9 @@ nsFileInputStream::Available(uint64_t* aResult) {
return nsFileStreamBase::Available(aResult);
}
NS_IMETHODIMP
nsFileInputStream::StreamStatus() { return nsFileStreamBase::StreamStatus(); }
void nsFileInputStream::SerializedComplexity(uint32_t aMaxSize,
uint32_t* aSizeUsed,
uint32_t* aPipes,

Просмотреть файл

@ -138,6 +138,7 @@ class nsFileInputStream : public nsFileStreamBase,
NS_IMETHOD Close() override;
NS_IMETHOD Tell(int64_t* aResult) override;
NS_IMETHOD Available(uint64_t* _retval) override;
NS_IMETHOD StreamStatus() override;
NS_IMETHOD Read(char* aBuf, uint32_t aCount, uint32_t* _retval) override;
NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* _retval) override {
@ -269,9 +270,6 @@ class nsFileRandomAccessStream : public nsFileStreamBase,
// Can't use NS_FORWARD_NSIOUTPUTSTREAM due to overlapping methods
// Close() and IsNonBlocking()
NS_IMETHOD Flush() override { return nsFileStreamBase::Flush(); }
NS_IMETHOD StreamStatus() override {
return nsFileStreamBase::StreamStatus();
}
NS_IMETHOD Write(const char* aBuf, uint32_t aCount,
uint32_t* _retval) override {
return nsFileStreamBase::Write(aBuf, aCount, _retval);

Просмотреть файл

@ -227,6 +227,10 @@ NS_IMETHODIMP nsMIMEInputStream::Available(uint64_t* _retval) {
INITSTREAMS;
return mStream->Available(_retval);
}
NS_IMETHODIMP nsMIMEInputStream::StreamStatus() {
INITSTREAMS;
return mStream->StreamStatus();
}
NS_IMETHODIMP nsMIMEInputStream::Read(char* buf, uint32_t count,
uint32_t* _retval) {
INITSTREAMS;

Просмотреть файл

@ -43,6 +43,9 @@ nsPreloadedStream::Available(uint64_t* _retval) {
return NS_OK;
}
NS_IMETHODIMP
nsPreloadedStream::StreamStatus() { return mStream->StreamStatus(); }
NS_IMETHODIMP
nsPreloadedStream::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
if (!mLen) return mStream->Read(aBuf, aCount, _retval);

Просмотреть файл

@ -353,6 +353,14 @@ nsSocketInputStream::Available(uint64_t* avail) {
return rv;
}
NS_IMETHODIMP
nsSocketInputStream::StreamStatus() {
SOCKET_LOG(("nsSocketInputStream::StreamStatus [this=%p]\n", this));
MutexAutoLock lock(mTransport->mLock);
return mCondition;
}
NS_IMETHODIMP
nsSocketInputStream::Read(char* buf, uint32_t count, uint32_t* countRead) {
SOCKET_LOG(("nsSocketInputStream::Read [this=%p count=%u]\n", this, count));

Просмотреть файл

@ -165,6 +165,9 @@ nsInputStreamTransport::Available(uint64_t* result) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsInputStreamTransport::StreamStatus() { return mSource->StreamStatus(); }
NS_IMETHODIMP
nsInputStreamTransport::Read(char* buf, uint32_t count, uint32_t* result) {
nsresult rv = mSource->Read(buf, count, result);

Просмотреть файл

@ -121,6 +121,16 @@ nsSyncStreamListener::Available(uint64_t* result) {
return mStatus;
}
NS_IMETHODIMP
nsSyncStreamListener::StreamStatus() {
if (NS_FAILED(mStatus)) {
return mStatus;
}
mStatus = mPipeIn->StreamStatus();
return mStatus;
}
NS_IMETHODIMP
nsSyncStreamListener::Read(char* buf, uint32_t bufLen, uint32_t* result) {
if (mStatus == NS_BASE_STREAM_CLOSED) {

Просмотреть файл

@ -116,6 +116,21 @@ CacheFileInputStream::Available(uint64_t* _retval) {
return rv;
}
NS_IMETHODIMP
CacheFileInputStream::StreamStatus() {
CacheFileAutoLock lock(mFile);
if (mClosed) {
LOG(
("CacheFileInputStream::StreamStatus() - Stream is closed. [this=%p, "
"status=0x%08" PRIx32 "]",
this, static_cast<uint32_t>(mStatus)));
return NS_FAILED(mStatus) ? mStatus : NS_BASE_STREAM_CLOSED;
}
return NS_OK;
}
NS_IMETHODIMP
CacheFileInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) {
LOG(("CacheFileInputStream::Read() [this=%p, count=%d]", this, aCount));

Просмотреть файл

@ -620,6 +620,12 @@ nsGIOInputStream::Available(uint64_t* aResult) {
return NS_OK;
}
/**
* Return the status of the input stream
*/
NS_IMETHODIMP
nsGIOInputStream::StreamStatus() { return mStatus; }
/**
* Trying to read from stream. When location is not available it tries to mount
* it.

Просмотреть файл

@ -559,6 +559,13 @@ InputStreamTunnel::Available(uint64_t* avail) {
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
InputStreamTunnel::StreamStatus() {
LOG(("InputStreamTunnel::StreamStatus [this=%p]\n", this));
return mCondition;
}
NS_IMETHODIMP
InputStreamTunnel::Read(char* buf, uint32_t count, uint32_t* countRead) {
LOG(("InputStreamTunnel::Read [this=%p count=%u]\n", this, count));

Просмотреть файл

@ -48,6 +48,12 @@ NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::Available(
return mSocketIn->Available(avail);
}
NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::StreamStatus() {
LOG(("TLSTransportLayer::InputStreamWrapper::StreamStatus [this=%p]\n",
this));
return mSocketIn->StreamStatus();
}
nsresult TLSTransportLayer::InputStreamWrapper::ReadDirectly(
char* buf, uint32_t count, uint32_t* countRead) {
LOG(("TLSTransportLayer::InputStreamWrapper::ReadDirectly [this=%p]\n",

Просмотреть файл

@ -262,6 +262,10 @@ NS_IMETHODIMP WebTransportStreamProxy::AsyncInputStreamWrapper::Available(
return mStream->Available(aAvailable);
}
NS_IMETHODIMP WebTransportStreamProxy::AsyncInputStreamWrapper::StreamStatus() {
return mStream->StreamStatus();
}
NS_IMETHODIMP WebTransportStreamProxy::AsyncInputStreamWrapper::Read(
char* aBuf, uint32_t aCount, uint32_t* aResult) {
LOG(("WebTransportStreamProxy::AsyncInputStreamWrapper::Read %p", this));

Просмотреть файл

@ -30,6 +30,8 @@ class TestStream final : public nsIInputStream {
return NS_OK;
}
NS_IMETHOD StreamStatus() override { return NS_OK; }
NS_IMETHOD Read(char* aBuffer, uint32_t aCount,
uint32_t* aReadCount) override {
MOZ_CRASH("This should not be called");

Просмотреть файл

@ -47,6 +47,9 @@ class BlockingSyncStream final : public nsIInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);
@ -112,6 +115,9 @@ class BlockingAsyncStream final : public nsIAsyncInputStream {
return NS_OK;
}
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
mPending = !mPending;

Просмотреть файл

@ -91,6 +91,9 @@ class ByteBufferStream final : public nsIInputStream {
return NS_OK;
}
NS_IMETHOD
StreamStatus() override { return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK; }
NS_IMETHOD
Read(char* aBuf, uint32_t aCount, uint32_t* aCountRead) override {
if (mClosed) {

Просмотреть файл

@ -138,6 +138,12 @@ InputStreamLengthWrapper::Available(uint64_t* aLength) {
return mInputStream->Available(aLength);
}
NS_IMETHODIMP
InputStreamLengthWrapper::StreamStatus() {
NS_ENSURE_STATE(mInputStream);
return mInputStream->StreamStatus();
}
NS_IMETHODIMP
InputStreamLengthWrapper::Read(char* aBuffer, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -194,6 +194,11 @@ NonBlockingAsyncInputStream::Available(uint64_t* aLength) {
return NS_OK;
}
NS_IMETHODIMP
NonBlockingAsyncInputStream::StreamStatus() {
return mInputStream->StreamStatus();
}
NS_IMETHODIMP
NonBlockingAsyncInputStream::Read(char* aBuffer, uint32_t aCount,
uint32_t* aReadCount) {

Просмотреть файл

@ -177,6 +177,21 @@ SlicedInputStream::Available(uint64_t* aLength) {
return NS_OK;
}
NS_IMETHODIMP
SlicedInputStream::StreamStatus() {
NS_ENSURE_STATE(mInputStream);
if (mClosed) {
return NS_BASE_STREAM_CLOSED;
}
nsresult rv = mInputStream->StreamStatus();
if (rv == NS_BASE_STREAM_CLOSED) {
mClosed = true;
}
return rv;
}
NS_IMETHODIMP
SlicedInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) {
*aReadCount = 0;

Просмотреть файл

@ -92,6 +92,21 @@ SnappyUncompressInputStream::Available(uint64_t* aLengthOut) {
return NS_OK;
}
NS_IMETHODIMP
SnappyUncompressInputStream::StreamStatus() {
if (!mBaseStream) {
return NS_BASE_STREAM_CLOSED;
}
// If we have uncompressed bytes, then we're still open.
if (UncompressedLength() > 0) {
return NS_OK;
}
// Otherwise we'll need to read from the underlying stream, so check it
return mBaseStream->StreamStatus();
}
NS_IMETHODIMP
SnappyUncompressInputStream::Read(char* aBuf, uint32_t aCount,
uint32_t* aBytesReadOut) {

Просмотреть файл

@ -386,6 +386,14 @@ nsBinaryInputStream::Available(uint64_t* aResult) {
return mInputStream->Available(aResult);
}
NS_IMETHODIMP
nsBinaryInputStream::StreamStatus() {
if (NS_WARN_IF(!mInputStream)) {
return NS_ERROR_UNEXPECTED;
}
return mInputStream->StreamStatus();
}
NS_IMETHODIMP
nsBinaryInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aNumRead) {
if (NS_WARN_IF(!mInputStream)) {

Просмотреть файл

@ -62,7 +62,8 @@ interface nsIInputStream : nsISupports
/**
* Close the stream. This method causes subsequent calls to Read and
* ReadSegments to return 0 bytes read to indicate end-of-file. Any
* subsequent calls to Available should throw NS_BASE_STREAM_CLOSED.
* subsequent calls to Available or StreamStatus should throw
* NS_BASE_STREAM_CLOSED.
*/
void close();
@ -92,6 +93,24 @@ interface nsIInputStream : nsISupports
*/
unsigned long long available();
/**
* Check the current status of the stream. A stream that is closed will
* throw an exception when this method is called. That enables the caller
* to know the condition of the stream before attempting to read from it.
*
* This method will not throw NS_BASE_STREAM_WOULD_BLOCK, even if the stream
* is an non-blocking stream with no data. A non-blocking stream that does
* not yet have any data to read should return NS_OK.
*
* NOTE: Unlike available, his method should not block the calling thread
* (e.g. to query the state of a file descriptor), even when called on a
* blocking stream.
*
* @throws NS_BASE_STREAM_CLOSED if the stream closed normally
* @throws <other-error> if the stream closed with a different status
*/
void streamStatus();
/**
* Read data from the stream.
*

Просмотреть файл

@ -215,6 +215,14 @@ nsInputStreamTee::Available(uint64_t* aAvail) {
return mSource->Available(aAvail);
}
NS_IMETHODIMP
nsInputStreamTee::StreamStatus() {
if (NS_WARN_IF(!mSource)) {
return NS_ERROR_NOT_INITIALIZED;
}
return mSource->StreamStatus();
}
NS_IMETHODIMP
nsInputStreamTee::Read(char* aBuf, uint32_t aCount, uint32_t* aBytesRead) {
if (NS_WARN_IF(!mSource)) {

Просмотреть файл

@ -369,6 +369,12 @@ nsMultiplexInputStream::Available(uint64_t* aResult) {
return rv;
}
NS_IMETHODIMP
nsMultiplexInputStream::StreamStatus() {
MutexAutoLock lock(mLock);
return mStatus;
}
NS_IMETHODIMP
nsMultiplexInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult) {
MutexAutoLock lock(mLock);

Просмотреть файл

@ -1316,6 +1316,12 @@ nsPipeInputStream::Available(uint64_t* aResult) {
return NS_OK;
}
NS_IMETHODIMP
nsPipeInputStream::StreamStatus() {
ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor);
return mReadState.mAvailable ? NS_OK : Status(mon);
}
NS_IMETHODIMP
nsPipeInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* aReadCount) {

Просмотреть файл

@ -430,6 +430,9 @@ nsStorageInputStream::Available(uint64_t* aAvailable) {
return NS_OK;
}
NS_IMETHODIMP
nsStorageInputStream::StreamStatus() { return mStatus; }
NS_IMETHODIMP
nsStorageInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aNumRead) {
return ReadSegments(NS_CopySegmentToBuffer, aBuffer, aCount, aNumRead);

Просмотреть файл

@ -265,6 +265,12 @@ nsStringInputStream::Available(uint64_t* aLength) {
return NS_OK;
}
NS_IMETHODIMP
nsStringInputStream::StreamStatus() {
ReentrantMonitorAutoEnter lock(mMon);
return Closed() ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHODIMP
nsStringInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aReadCount) {
NS_ASSERTION(aBuf, "null ptr");

Просмотреть файл

@ -119,6 +119,9 @@ AsyncStringStream::Available(uint64_t* aLength) {
return mStream->Available(aLength);
}
NS_IMETHODIMP
AsyncStringStream::StreamStatus() { return mStream->StreamStatus(); }
NS_IMETHODIMP
AsyncStringStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) {
return mStream->Read(aBuffer, aCount, aReadCount);

Просмотреть файл

@ -113,6 +113,9 @@ class LengthInputStream : public nsIInputStream,
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);

Просмотреть файл

@ -129,6 +129,11 @@ FakeInputStream::Available(uint64_t* aAvailable) {
return NS_OK;
}
NS_IMETHODIMP
FakeInputStream::StreamStatus() {
return mClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHODIMP
FakeInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aOut) {
return NS_ERROR_NOT_IMPLEMENTED;

Просмотреть файл

@ -52,6 +52,9 @@ class NonCloneableInputStream final : public nsIInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);

Просмотреть файл

@ -75,6 +75,8 @@ class LengthStream final : public nsIInputStreamLength,
return NS_OK;
}
NS_IMETHOD StreamStatus() override { return NS_OK; }
private:
~LengthStream() = default;

Просмотреть файл

@ -414,6 +414,9 @@ class ClosedStream final : public nsIInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return NS_BASE_STREAM_CLOSED; }
NS_IMETHOD
StreamStatus() override { return NS_BASE_STREAM_CLOSED; }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
MOZ_CRASH("This should not be called!");
@ -455,6 +458,11 @@ class AsyncStream final : public nsIAsyncInputStream {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHOD
StreamStatus() override {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_OK;
}
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
MOZ_CRASH("This should not be called!");
@ -508,6 +516,9 @@ class BlockingStream final : public nsIInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return NS_BASE_STREAM_CLOSED; }
NS_IMETHOD
StreamStatus() override { return NS_BASE_STREAM_CLOSED; }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
// We are actually empty.
@ -609,6 +620,9 @@ class NonBufferableStringStream final : public nsIInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);

Просмотреть файл

@ -263,6 +263,7 @@ class QIInputStream final : public nsIInputStream,
// nsIInputStream
NS_IMETHOD Close() override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Available(uint64_t*) override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD StreamStatus() override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD Read(char*, uint32_t, uint32_t*) override {
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -58,6 +58,9 @@ class NonSeekableStringStream final : public nsIAsyncInputStream {
NS_IMETHOD
Available(uint64_t* aLength) override { return mStream->Available(aLength); }
NS_IMETHOD
StreamStatus() override { return mStream->StreamStatus(); }
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override {
return mStream->Read(aBuffer, aCount, aReadCount);