diff --git a/xpcom/io/SlicedInputStream.cpp b/xpcom/io/SlicedInputStream.cpp index afd00fe2da49..abb623137424 100644 --- a/xpcom/io/SlicedInputStream.cpp +++ b/xpcom/io/SlicedInputStream.cpp @@ -20,6 +20,8 @@ NS_INTERFACE_MAP_BEGIN(SlicedInputStream) mWeakCloneableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mWeakIPCSerializableInputStream || !mInputStream) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, + mWeakSeekableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END @@ -27,6 +29,7 @@ SlicedInputStream::SlicedInputStream(nsIInputStream* aInputStream, uint64_t aStart, uint64_t aLength) : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) + , mWeakSeekableInputStream(nullptr) , mStart(aStart) , mLength(aLength) , mCurPos(0) @@ -39,6 +42,7 @@ SlicedInputStream::SlicedInputStream(nsIInputStream* aInputStream, SlicedInputStream::SlicedInputStream() : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) + , mWeakSeekableInputStream(nullptr) , mStart(0) , mLength(0) , mCurPos(0) @@ -68,6 +72,12 @@ SlicedInputStream::SetSourceStream(nsIInputStream* aInputStream) SameCOMIdentity(aInputStream, serializableStream)) { mWeakIPCSerializableInputStream = serializableStream; } + + nsCOMPtr seekableStream = + do_QueryInterface(aInputStream); + if (seekableStream && SameCOMIdentity(aInputStream, seekableStream)) { + mWeakSeekableInputStream = seekableStream; + } } NS_IMETHODIMP @@ -325,3 +335,75 @@ SlicedInputStream::ExpectedSerializedLength() return mWeakIPCSerializableInputStream->ExpectedSerializedLength(); } + +// nsISeekableStream + +NS_IMETHODIMP +SlicedInputStream::Seek(int32_t aWhence, int64_t aOffset) +{ + NS_ENSURE_STATE(mInputStream); + NS_ENSURE_STATE(mWeakSeekableInputStream); + + int64_t offset; + switch (aWhence) { + case NS_SEEK_SET: + offset = mStart + aOffset; + break; + case NS_SEEK_CUR: + offset = mStart + mCurPos + aOffset; + break; + case NS_SEEK_END: + offset = mStart + mLength + aOffset; + break; + default: + return NS_ERROR_ILLEGAL_VALUE; + } + + if (offset < (int64_t)mStart || offset > (int64_t)(mStart + mLength)) { + return NS_ERROR_INVALID_ARG; + } + + nsresult rv = mWeakSeekableInputStream->Seek(NS_SEEK_SET, offset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + mCurPos = offset - mStart; + return NS_OK; +} + +NS_IMETHODIMP +SlicedInputStream::Tell(int64_t *aResult) +{ + NS_ENSURE_STATE(mInputStream); + NS_ENSURE_STATE(mWeakSeekableInputStream); + + int64_t tell = 0; + + nsresult rv = mWeakSeekableInputStream->Tell(&tell); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (tell < (int64_t)mStart) { + *aResult = 0; + return NS_OK; + } + + *aResult = tell - mStart; + if (*aResult > (int64_t)mLength) { + *aResult = mLength; + } + + return NS_OK; +} + +NS_IMETHODIMP +SlicedInputStream::SetEOF() +{ + NS_ENSURE_STATE(mInputStream); + NS_ENSURE_STATE(mWeakSeekableInputStream); + + mClosed = true; + return mWeakSeekableInputStream->SetEOF(); +} diff --git a/xpcom/io/SlicedInputStream.h b/xpcom/io/SlicedInputStream.h index d9df2b1020e9..7864d4477e5e 100644 --- a/xpcom/io/SlicedInputStream.h +++ b/xpcom/io/SlicedInputStream.h @@ -11,12 +11,14 @@ #include "nsIAsyncInputStream.h" #include "nsICloneableInputStream.h" #include "nsIIPCSerializableInputStream.h" +#include "nsISeekableStream.h" // A wrapper for a slice of an underlying input stream. class SlicedInputStream final : public nsIAsyncInputStream , public nsICloneableInputStream , public nsIIPCSerializableInputStream + , public nsISeekableStream { public: NS_DECL_THREADSAFE_ISUPPORTS @@ -24,6 +26,7 @@ public: NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM + NS_DECL_NSISEEKABLESTREAM // Create an input stream whose data comes from a slice of aInputStream. The // slice begins at aStart bytes beyond aInputStream's current position, and @@ -53,6 +56,7 @@ private: // Raw pointers because these are just QI of mInputStream. nsICloneableInputStream* mWeakCloneableInputStream; nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream; + nsISeekableStream* mWeakSeekableInputStream; uint64_t mStart; uint64_t mLength;