author | Andrea Marchesini <amarchesini@mozilla.com> |
Thu, 18 Oct 2018 13:35:35 +0200 | |
changeset 497666 | 2da6504c901e9474566aa1663d907bd58bed9edb |
parent 497665 | 0162bb225b88cfda9b702d88464d48fbf1f372ee |
child 497667 | 4a22c1051967e4edef65c5c68305e72618eb2c0d |
push id | 10002 |
push user | archaeopteryx@coole-files.de |
push date | Fri, 19 Oct 2018 23:09:29 +0000 |
treeherder | mozilla-beta@01378c910610 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froydnj |
bugs | 1496581, 1494176 |
milestone | 64.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
|
--- a/dom/file/MemoryBlobImpl.h +++ b/dom/file/MemoryBlobImpl.h @@ -120,16 +120,17 @@ public: uint32_t aLength, nsIInputStream** _retval); NS_DECL_THREADSAFE_ISUPPORTS // These are mandatory. NS_FORWARD_NSIINPUTSTREAM(mStream->) NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->) + NS_FORWARD_NSITELLABLESTREAM(mSeekableStream->) NS_FORWARD_NSICLONEABLEINPUTSTREAM(mCloneableInputStream->) // This is optional. We use a conditional QI to keep it from being called // if the underlying stream doesn't support it. NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->) private: ~DataOwnerAdapter() {}
--- a/netwerk/base/PartiallySeekableInputStream.cpp +++ b/netwerk/base/PartiallySeekableInputStream.cpp @@ -12,16 +12,17 @@ namespace mozilla { namespace net { NS_IMPL_ADDREF(PartiallySeekableInputStream); NS_IMPL_RELEASE(PartiallySeekableInputStream); NS_INTERFACE_MAP_BEGIN(PartiallySeekableInputStream) NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY(nsISeekableStream) + NS_INTERFACE_MAP_ENTRY(nsITellableStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, mWeakCloneableInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mWeakIPCSerializableInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mWeakAsyncInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, mWeakAsyncInputStream)
--- a/netwerk/base/PartiallySeekableInputStream.h +++ b/netwerk/base/PartiallySeekableInputStream.h @@ -29,16 +29,17 @@ class PartiallySeekableInputStream final , public nsIInputStreamLength , public nsIAsyncInputStreamLength , public nsIInputStreamLengthCallback { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINPUTSTREAMLENGTH NS_DECL_NSIASYNCINPUTSTREAMLENGTH NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK
--- a/netwerk/base/ThrottleQueue.cpp +++ b/netwerk/base/ThrottleQueue.cpp @@ -21,33 +21,35 @@ class ThrottleInputStream final { public: ThrottleInputStream(nsIInputStream* aStream, ThrottleQueue* aQueue); NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIASYNCINPUTSTREAM void AllowInput(); private: ~ThrottleInputStream(); nsCOMPtr<nsIInputStream> mStream; RefPtr<ThrottleQueue> mQueue; nsresult mClosedStatus; nsCOMPtr<nsIInputStreamCallback> mCallback; nsCOMPtr<nsIEventTarget> mEventTarget; }; -NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, nsISeekableStream) +NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, + nsITellableStream, nsISeekableStream) ThrottleInputStream::ThrottleInputStream(nsIInputStream *aStream, ThrottleQueue* aQueue) : mStream(aStream) , mQueue(aQueue) , mClosedStatus(NS_OK) { MOZ_ASSERT(aQueue != nullptr); } @@ -155,17 +157,17 @@ ThrottleInputStream::Seek(int32_t aWhenc NS_IMETHODIMP ThrottleInputStream::Tell(int64_t* aResult) { if (NS_FAILED(mClosedStatus)) { return mClosedStatus; } - nsCOMPtr<nsISeekableStream> sstream = do_QueryInterface(mStream); + nsCOMPtr<nsITellableStream> sstream = do_QueryInterface(mStream); if (!sstream) { return NS_ERROR_FAILURE; } return sstream->Tell(aResult); } NS_IMETHODIMP
--- a/netwerk/base/nsBufferedStreams.cpp +++ b/netwerk/base/nsBufferedStreams.cpp @@ -58,17 +58,17 @@ nsBufferedStream::nsBufferedStream() { } nsBufferedStream::~nsBufferedStream() { Close(); } -NS_IMPL_ISUPPORTS(nsBufferedStream, nsISeekableStream) +NS_IMPL_ISUPPORTS(nsBufferedStream, nsITellableStream, nsISeekableStream) nsresult nsBufferedStream::Init(nsISupports* stream, uint32_t bufferSize) { NS_ASSERTION(stream, "need to supply a stream"); NS_ASSERTION(mStream == nullptr, "already inited"); mStream = stream; NS_IF_ADDREF(mStream); @@ -300,16 +300,17 @@ NS_INTERFACE_MAP_BEGIN(nsBufferedInputSt NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLengthCallback, mIsAsyncInputStreamLength) NS_IMPL_QUERY_CLASSINFO(nsBufferedInputStream) NS_INTERFACE_MAP_END_INHERITING(nsBufferedStream) NS_IMPL_CI_INTERFACE_GETTER(nsBufferedInputStream, nsIInputStream, nsIBufferedInputStream, nsISeekableStream, + nsITellableStream, nsIStreamBufferAccess) nsBufferedInputStream::nsBufferedInputStream() : nsBufferedStream() , mMutex("nsBufferedInputStream::mMutex") , mIsIPCSerializable(true) , mIsAsyncInputStream(false) , mIsCloneableInputStream(false)
--- a/netwerk/base/nsBufferedStreams.h +++ b/netwerk/base/nsBufferedStreams.h @@ -21,16 +21,17 @@ //////////////////////////////////////////////////////////////////////////////// class nsBufferedStream : public nsISeekableStream { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM nsBufferedStream(); nsresult Close(); protected: virtual ~nsBufferedStream();
--- a/netwerk/base/nsFileStreams.cpp +++ b/netwerk/base/nsFileStreams.cpp @@ -56,16 +56,17 @@ nsFileStreamBase::~nsFileStreamBase() // We don't want to try to rewrind the stream when shutting down. mBehaviorFlags &= ~nsIFileInputStream::REOPEN_ON_REWIND; Close(); } NS_IMPL_ISUPPORTS(nsFileStreamBase, nsISeekableStream, + nsITellableStream, nsIFileMetadata) NS_IMETHODIMP nsFileStreamBase::Seek(int32_t whence, int64_t offset) { nsresult rv = DoPendingOpen(); NS_ENSURE_SUCCESS(rv, rv); @@ -437,16 +438,17 @@ NS_INTERFACE_MAP_BEGIN(nsFileInputStream NS_IMPL_QUERY_CLASSINFO(nsFileInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, IsCloneable()) NS_INTERFACE_MAP_END_INHERITING(nsFileStreamBase) NS_IMPL_CI_INTERFACE_GETTER(nsFileInputStream, nsIInputStream, nsIFileInputStream, nsISeekableStream, + nsITellableStream, nsILineInputStream) nsresult nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) { NS_ENSURE_NO_AGGREGATION(aOuter); RefPtr<nsFileInputStream> stream = new nsFileInputStream();
--- a/netwerk/base/nsFileStreams.h +++ b/netwerk/base/nsFileStreams.h @@ -26,16 +26,17 @@ class nsFileStreamBase : public nsISeekableStream, public nsIFileMetadata { public: // Record refcount changes to ensure that streams are destroyed on // consistent threads when recording/replaying. NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(mozilla::recordreplay::Behavior::Preserve) NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIFILEMETADATA nsFileStreamBase(); protected: virtual ~nsFileStreamBase(); nsresult Close();
--- a/netwerk/base/nsInputStreamPump.cpp +++ b/netwerk/base/nsInputStreamPump.cpp @@ -569,20 +569,20 @@ nsInputStreamPump::OnStateTransfer() // however, many do not... mailnews... stream converters... // cough, cough. the input stream pump is fairly tolerant // in this regard; however, if an ODA does not consume any // data from the stream, then we could potentially end up in // an infinite loop. we do our best here to try to catch // such an error. (see bug 189672) // in most cases this QI will succeed (mAsyncStream is almost always - // a nsPipeInputStream, which implements nsISeekableStream::Tell). + // a nsPipeInputStream, which implements nsITellableStream::Tell). int64_t offsetBefore; - nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mAsyncStream); - if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))) { + nsCOMPtr<nsITellableStream> tellable = do_QueryInterface(mAsyncStream); + if (tellable && NS_FAILED(tellable->Tell(&offsetBefore))) { MOZ_ASSERT_UNREACHABLE("Tell failed on readable stream"); offsetBefore = 0; } uint32_t odaAvail = avail > UINT32_MAX ? UINT32_MAX : uint32_t(avail); @@ -597,21 +597,21 @@ nsInputStreamPump::OnStateTransfer() rv = mListener->OnDataAvailable(this, mListenerContext, mAsyncStream, mStreamOffset, odaAvail); } // don't enter this code if ODA failed or called Cancel if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mStatus)) { // test to see if this ODA failed to consume data - if (seekable) { + if (tellable) { // NOTE: if Tell fails, which can happen if the stream is // now closed, then we assume that everything was read. int64_t offsetAfter; - if (NS_FAILED(seekable->Tell(&offsetAfter))) + if (NS_FAILED(tellable->Tell(&offsetAfter))) offsetAfter = offsetBefore + odaAvail; if (offsetAfter > offsetBefore) mStreamOffset += (offsetAfter - offsetBefore); else if (mSuspendCount == 0) { // // possible infinite loop if we continue pumping data! // // NOTE: although not allowed by nsIStreamListener, we
--- a/netwerk/base/nsMIMEInputStream.cpp +++ b/netwerk/base/nsMIMEInputStream.cpp @@ -42,16 +42,17 @@ class nsMIMEInputStream : public nsIMIME public: nsMIMEInputStream(); NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIMIMEINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINPUTSTREAMLENGTH NS_DECL_NSIASYNCINPUTSTREAMLENGTH NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK NS_DECL_NSICLONEABLEINPUTSTREAM @@ -93,16 +94,17 @@ NS_IMPL_RELEASE(nsMIMEInputStream) NS_IMPL_CLASSINFO(nsMIMEInputStream, nullptr, nsIClassInfo::THREADSAFE, NS_MIMEINPUTSTREAM_CID) NS_INTERFACE_MAP_BEGIN(nsMIMEInputStream) NS_INTERFACE_MAP_ENTRY(nsIMIMEInputStream) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIMIMEInputStream) NS_INTERFACE_MAP_ENTRY(nsISeekableStream) + NS_INTERFACE_MAP_ENTRY(nsITellableStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, IsIPCSerializable()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, IsAsyncInputStream()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, IsAsyncInputStream()) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMIMEInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength, @@ -115,17 +117,18 @@ NS_INTERFACE_MAP_BEGIN(nsMIMEInputStream IsCloneableInputStream()) NS_IMPL_QUERY_CLASSINFO(nsMIMEInputStream) NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER(nsMIMEInputStream, nsIMIMEInputStream, nsIAsyncInputStream, nsIInputStream, - nsISeekableStream) + nsISeekableStream, + nsITellableStream) nsMIMEInputStream::nsMIMEInputStream() : mStartedReading(false) , mMutex("nsMIMEInputStream::mMutex") { } NS_IMETHODIMP @@ -307,23 +310,25 @@ nsMIMEInputStream::OnInputStreamReady(ns callback.swap(mAsyncWaitCallback); } MOZ_ASSERT(callback); return callback->OnInputStreamReady(this); } -// nsISeekableStream +// nsITellableStream NS_IMETHODIMP nsMIMEInputStream::Tell(int64_t *_retval) { INITSTREAMS; - nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream); + nsCOMPtr<nsITellableStream> stream = do_QueryInterface(mStream); return stream->Tell(_retval); } + +// nsISeekableStream NS_IMETHODIMP nsMIMEInputStream::SetEOF(void) { INITSTREAMS; nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream); return stream->SetEOF(); } /**
--- a/netwerk/cache2/CacheFileInputStream.cpp +++ b/netwerk/cache2/CacheFileInputStream.cpp @@ -33,16 +33,17 @@ CacheFileInputStream::Release() return count; } NS_INTERFACE_MAP_BEGIN(CacheFileInputStream) NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream) NS_INTERFACE_MAP_ENTRY(nsISeekableStream) + NS_INTERFACE_MAP_ENTRY(nsITellableStream) NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END CacheFileInputStream::CacheFileInputStream(CacheFile *aFile, nsISupports *aEntry, bool aAlternativeData) : mFile(aFile) @@ -384,16 +385,24 @@ CacheFileInputStream::Seek(int32_t whenc mPos = newPos; EnsureCorrectChunk(false); LOG(("CacheFileInputStream::Seek() [this=%p, pos=%" PRId64 "]", this, mPos)); return NS_OK; } NS_IMETHODIMP +CacheFileInputStream::SetEOF() +{ + MOZ_ASSERT(false, "Don't call SetEOF on cache input stream"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +// nsITellableStream +NS_IMETHODIMP CacheFileInputStream::Tell(int64_t *_retval) { CacheFileAutoLock lock(mFile); if (mClosed) { LOG(("CacheFileInputStream::Tell() - Stream is closed. [this=%p]", this)); return NS_BASE_STREAM_CLOSED; } @@ -403,23 +412,16 @@ CacheFileInputStream::Tell(int64_t *_ret if (mAlternativeData) { *_retval -= mFile->mAltDataOffset; } LOG(("CacheFileInputStream::Tell() [this=%p, retval=%" PRId64 "]", this, *_retval)); return NS_OK; } -NS_IMETHODIMP -CacheFileInputStream::SetEOF() -{ - MOZ_ASSERT(false, "Don't call SetEOF on cache input stream"); - return NS_ERROR_NOT_IMPLEMENTED; -} - // CacheFileChunkListener nsresult CacheFileInputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) { MOZ_CRASH("CacheFileInputStream::OnChunkRead should not be called!"); return NS_ERROR_UNEXPECTED; }
--- a/netwerk/cache2/CacheFileInputStream.h +++ b/netwerk/cache2/CacheFileInputStream.h @@ -19,16 +19,17 @@ class CacheFile; class CacheFileInputStream : public nsIAsyncInputStream , public nsISeekableStream , public CacheFileChunkListener { NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM public: explicit CacheFileInputStream(CacheFile *aFile, nsISupports *aEntry, bool aAlternativeData); NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) override; NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) override; NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx,
--- a/netwerk/cache2/CacheFileOutputStream.cpp +++ b/netwerk/cache2/CacheFileOutputStream.cpp @@ -35,16 +35,17 @@ CacheFileOutputStream::Release() return count; } NS_INTERFACE_MAP_BEGIN(CacheFileOutputStream) NS_INTERFACE_MAP_ENTRY(nsIOutputStream) NS_INTERFACE_MAP_ENTRY(nsIAsyncOutputStream) NS_INTERFACE_MAP_ENTRY(nsISeekableStream) + NS_INTERFACE_MAP_ENTRY(nsITellableStream) NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream) NS_INTERFACE_MAP_END CacheFileOutputStream::CacheFileOutputStream(CacheFile *aFile, CacheOutputCloseListener *aCloseListener, bool aAlternativeData) : mFile(aFile) @@ -284,16 +285,27 @@ CacheFileOutputStream::Seek(int32_t when mPos = newPos; EnsureCorrectChunk(true); LOG(("CacheFileOutputStream::Seek() [this=%p, pos=%" PRId64 "]", this, mPos)); return NS_OK; } NS_IMETHODIMP +CacheFileOutputStream::SetEOF() +{ + MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented"); + // Right now we don't use SetEOF(). If we ever need this method, we need + // to think about what to do with input streams that already points beyond + // new EOF. + return NS_ERROR_NOT_IMPLEMENTED; +} + +// nsITellableStream +NS_IMETHODIMP CacheFileOutputStream::Tell(int64_t *_retval) { CacheFileAutoLock lock(mFile); if (mClosed) { LOG(("CacheFileOutputStream::Tell() - Stream is closed. [this=%p]", this)); return NS_BASE_STREAM_CLOSED; } @@ -303,26 +315,16 @@ CacheFileOutputStream::Tell(int64_t *_re if (mAlternativeData) { *_retval -= mFile->mAltDataOffset; } LOG(("CacheFileOutputStream::Tell() [this=%p, retval=%" PRId64 "]", this, *_retval)); return NS_OK; } -NS_IMETHODIMP -CacheFileOutputStream::SetEOF() -{ - MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented"); - // Right now we don't use SetEOF(). If we ever need this method, we need - // to think about what to do with input streams that already points beyond - // new EOF. - return NS_ERROR_NOT_IMPLEMENTED; -} - // CacheFileChunkListener nsresult CacheFileOutputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) { MOZ_CRASH("CacheFileOutputStream::OnChunkRead should not be called!"); return NS_ERROR_UNEXPECTED; }
--- a/netwerk/cache2/CacheFileOutputStream.h +++ b/netwerk/cache2/CacheFileOutputStream.h @@ -21,16 +21,17 @@ class CacheOutputCloseListener; class CacheFileOutputStream : public nsIAsyncOutputStream , public nsISeekableStream , public CacheFileChunkListener { NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOUTPUTSTREAM NS_DECL_NSIASYNCOUTPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM public: CacheFileOutputStream(CacheFile *aFile, CacheOutputCloseListener *aCloseListener, bool aAlternativeData); NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) override; NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) override;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -915,24 +915,20 @@ HttpBaseChannel::EnsureUploadStreamIsClo NS_ENSURE_FALSE(mUploadCloneableCallback, NS_ERROR_UNEXPECTED); // We can immediately exec the callback if we don't have an upload stream. if (!mUploadStream) { aCallback->Run(); return NS_OK; } - // Some nsSeekableStreams do not implement ::Seek() (see nsPipeInputStream). - // In this case, we must clone the uploadStream into a memory stream in order - // to have it seekable. If the CloneUploadStream() will succeed, then - // synchronously invoke the callback to indicate we're already cloneable. + // Upload nsIInputStream must be cloneable and seekable in order to be + // processed by devtools network inspector. nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream); - if (seekable && - NS_SUCCEEDED(seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0)) && - NS_InputStreamIsCloneable(mUploadStream)) { + if (seekable && NS_InputStreamIsCloneable(mUploadStream)) { aCallback->Run(); return NS_OK; } nsCOMPtr<nsIStorageStream> storageStream; nsresult rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storageStream)); NS_ENSURE_SUCCESS(rv, rv);
--- a/xpcom/io/InputStreamLengthWrapper.cpp +++ b/xpcom/io/InputStreamLengthWrapper.cpp @@ -19,16 +19,18 @@ NS_IMPL_RELEASE(InputStreamLengthWrapper NS_INTERFACE_MAP_BEGIN(InputStreamLengthWrapper) NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, mWeakCloneableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mWeakIPCSerializableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mWeakSeekableInputStream || !mInputStream) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, + mWeakTellableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mWeakAsyncInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, mWeakAsyncInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END @@ -58,31 +60,33 @@ InputStreamLengthWrapper::MaybeWrap(alre return inputStream.forget(); } InputStreamLengthWrapper::InputStreamLengthWrapper(already_AddRefed<nsIInputStream> aInputStream, int64_t aLength) : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) , mWeakSeekableInputStream(nullptr) + , mWeakTellableInputStream(nullptr) , mWeakAsyncInputStream(nullptr) , mLength(aLength) , mConsumed(false) , mMutex("InputStreamLengthWrapper::mMutex") { MOZ_ASSERT(mLength >= 0); nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream); SetSourceStream(inputStream.forget()); } InputStreamLengthWrapper::InputStreamLengthWrapper() : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) , mWeakSeekableInputStream(nullptr) + , mWeakTellableInputStream(nullptr) , mWeakAsyncInputStream(nullptr) , mLength(-1) , mConsumed(false) , mMutex("InputStreamLengthWrapper::mMutex") {} InputStreamLengthWrapper::~InputStreamLengthWrapper() = default; @@ -107,16 +111,22 @@ InputStreamLengthWrapper::SetSourceStrea } nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mInputStream); if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) { mWeakSeekableInputStream = seekableStream; } + nsCOMPtr<nsITellableStream> tellableStream = + do_QueryInterface(mInputStream); + if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) { + mWeakTellableInputStream = tellableStream; + } + nsCOMPtr<nsIAsyncInputStream> asyncInputStream = do_QueryInterface(mInputStream); if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) { mWeakAsyncInputStream = asyncInputStream; } } // nsIInputStream interface @@ -326,34 +336,36 @@ InputStreamLengthWrapper::Seek(int32_t a NS_ENSURE_STATE(mInputStream); NS_ENSURE_STATE(mWeakSeekableInputStream); mConsumed = true; return mWeakSeekableInputStream->Seek(aWhence, aOffset); } NS_IMETHODIMP -InputStreamLengthWrapper::Tell(int64_t *aResult) -{ - NS_ENSURE_STATE(mInputStream); - NS_ENSURE_STATE(mWeakSeekableInputStream); - - return mWeakSeekableInputStream->Tell(aResult); -} - -NS_IMETHODIMP InputStreamLengthWrapper::SetEOF() { NS_ENSURE_STATE(mInputStream); NS_ENSURE_STATE(mWeakSeekableInputStream); mConsumed = true; return mWeakSeekableInputStream->SetEOF(); } +// nsITellableStream + +NS_IMETHODIMP +InputStreamLengthWrapper::Tell(int64_t *aResult) +{ + NS_ENSURE_STATE(mInputStream); + NS_ENSURE_STATE(mWeakTellableInputStream); + + return mWeakTellableInputStream->Tell(aResult); +} + // nsIInputStreamLength NS_IMETHODIMP InputStreamLengthWrapper::Length(int64_t* aLength) { NS_ENSURE_STATE(mInputStream); *aLength = mLength; return NS_OK;
--- a/xpcom/io/InputStreamLengthWrapper.h +++ b/xpcom/io/InputStreamLengthWrapper.h @@ -31,16 +31,17 @@ class InputStreamLengthWrapper final : p { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINPUTSTREAMLENGTH // This method creates a InputStreamLengthWrapper around aInputStream if // this doesn't implement nsIInputStreamLength or // nsIInputStreamAsyncLength interface, but it implements // nsIAsyncInputStream. For this kind of streams, // InputStreamLengthHelper is not able to retrieve the length. This @@ -64,16 +65,17 @@ private: SetSourceStream(already_AddRefed<nsIInputStream> aInputStream); nsCOMPtr<nsIInputStream> mInputStream; // Raw pointers because these are just QI of mInputStream. nsICloneableInputStream* mWeakCloneableInputStream; nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream; nsISeekableStream* mWeakSeekableInputStream; + nsITellableStream* mWeakTellableInputStream; nsIAsyncInputStream* mWeakAsyncInputStream; int64_t mLength; bool mConsumed; mozilla::Mutex mMutex; // This is used for AsyncWait and it's protected by mutex.
--- a/xpcom/io/NonBlockingAsyncInputStream.cpp +++ b/xpcom/io/NonBlockingAsyncInputStream.cpp @@ -46,16 +46,18 @@ NS_INTERFACE_MAP_BEGIN(NonBlockingAsyncI NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, mWeakCloneableInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mWeakIPCSerializableInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mWeakSeekableInputStream) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, + mWeakTellableInputStream) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END /* static */ nsresult NonBlockingAsyncInputStream::Create(already_AddRefed<nsIInputStream> aInputStream, nsIAsyncInputStream** aResult) { MOZ_DIAGNOSTIC_ASSERT(aResult); @@ -83,16 +85,17 @@ NonBlockingAsyncInputStream::Create(alre return NS_OK; } NonBlockingAsyncInputStream::NonBlockingAsyncInputStream(already_AddRefed<nsIInputStream> aInputStream) : mInputStream(std::move(aInputStream)) , mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) , mWeakSeekableInputStream(nullptr) + , mWeakTellableInputStream(nullptr) , mLock("NonBlockingAsyncInputStream::mLock") , mClosed(false) { MOZ_ASSERT(mInputStream); nsCOMPtr<nsICloneableInputStream> cloneableStream = do_QueryInterface(mInputStream); if (cloneableStream && SameCOMIdentity(mInputStream, cloneableStream)) { @@ -106,16 +109,22 @@ NonBlockingAsyncInputStream::NonBlocking mWeakIPCSerializableInputStream = serializableStream; } nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mInputStream); if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) { mWeakSeekableInputStream = seekableStream; } + + nsCOMPtr<nsITellableStream> tellableStream = + do_QueryInterface(mInputStream); + if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) { + mWeakTellableInputStream = tellableStream; + } } NonBlockingAsyncInputStream::~NonBlockingAsyncInputStream() {} NS_IMETHODIMP NonBlockingAsyncInputStream::Close() { @@ -346,29 +355,31 @@ NonBlockingAsyncInputStream::ExpectedSer NS_IMETHODIMP NonBlockingAsyncInputStream::Seek(int32_t aWhence, int64_t aOffset) { NS_ENSURE_STATE(mWeakSeekableInputStream); return mWeakSeekableInputStream->Seek(aWhence, aOffset); } NS_IMETHODIMP -NonBlockingAsyncInputStream::Tell(int64_t* aResult) -{ - NS_ENSURE_STATE(mWeakSeekableInputStream); - return mWeakSeekableInputStream->Tell(aResult); -} - -NS_IMETHODIMP NonBlockingAsyncInputStream::SetEOF() { NS_ENSURE_STATE(mWeakSeekableInputStream); return NS_ERROR_NOT_IMPLEMENTED; } +// nsITellableStream + +NS_IMETHODIMP +NonBlockingAsyncInputStream::Tell(int64_t* aResult) +{ + NS_ENSURE_STATE(mWeakTellableInputStream); + return mWeakTellableInputStream->Tell(aResult); +} + void NonBlockingAsyncInputStream::RunAsyncWaitCallback(NonBlockingAsyncInputStream::AsyncWaitRunnable* aRunnable, already_AddRefed<nsIInputStreamCallback> aCallback) { nsCOMPtr<nsIInputStreamCallback> callback = std::move(aCallback); { MutexAutoLock lock(mLock);
--- a/xpcom/io/NonBlockingAsyncInputStream.h +++ b/xpcom/io/NonBlockingAsyncInputStream.h @@ -29,16 +29,17 @@ class NonBlockingAsyncInputStream final { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM // |aInputStream| must be a non-blocking, non-async inputSteam. static nsresult Create(already_AddRefed<nsIInputStream> aInputStream, nsIAsyncInputStream** aAsyncInputStream); private: explicit NonBlockingAsyncInputStream(already_AddRefed<nsIInputStream> aInputStream); @@ -51,16 +52,17 @@ private: already_AddRefed<nsIInputStreamCallback> aCallback); nsCOMPtr<nsIInputStream> mInputStream; // Raw pointers because these are just QI of mInputStream. nsICloneableInputStream* MOZ_NON_OWNING_REF mWeakCloneableInputStream; nsIIPCSerializableInputStream* MOZ_NON_OWNING_REF mWeakIPCSerializableInputStream; nsISeekableStream* MOZ_NON_OWNING_REF mWeakSeekableInputStream; + nsITellableStream* MOZ_NON_OWNING_REF mWeakTellableInputStream; Mutex mLock; struct WaitClosureOnly { WaitClosureOnly(AsyncWaitRunnable* aRunnable, nsIEventTarget* aEventTarget); RefPtr<AsyncWaitRunnable> mRunnable;
--- a/xpcom/io/SlicedInputStream.cpp +++ b/xpcom/io/SlicedInputStream.cpp @@ -21,16 +21,18 @@ NS_IMPL_RELEASE(SlicedInputStream); NS_INTERFACE_MAP_BEGIN(SlicedInputStream) NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, mWeakCloneableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mWeakIPCSerializableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mWeakSeekableInputStream || !mInputStream) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, + mWeakTellableInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mWeakAsyncInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, mWeakAsyncInputStream || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamLength, mWeakInputStreamLength || !mInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStreamLength, mWeakAsyncInputStreamLength || !mInputStream) @@ -39,16 +41,17 @@ NS_INTERFACE_MAP_BEGIN(SlicedInputStream NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END SlicedInputStream::SlicedInputStream(already_AddRefed<nsIInputStream> aInputStream, uint64_t aStart, uint64_t aLength) : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) , mWeakSeekableInputStream(nullptr) + , mWeakTellableInputStream(nullptr) , mWeakAsyncInputStream(nullptr) , mWeakInputStreamLength(nullptr) , mWeakAsyncInputStreamLength(nullptr) , mStart(aStart) , mLength(aLength) , mCurPos(0) , mClosed(false) , mAsyncWaitFlags(0) @@ -58,16 +61,17 @@ SlicedInputStream::SlicedInputStream(alr nsCOMPtr<nsIInputStream> inputStream = std::move(aInputStream); SetSourceStream(inputStream.forget()); } SlicedInputStream::SlicedInputStream() : mWeakCloneableInputStream(nullptr) , mWeakIPCSerializableInputStream(nullptr) , mWeakSeekableInputStream(nullptr) + , mWeakTellableInputStream(nullptr) , mWeakAsyncInputStream(nullptr) , mStart(0) , mLength(0) , mCurPos(0) , mClosed(false) , mAsyncWaitFlags(0) , mAsyncWaitRequestedCount(0) , mMutex("SlicedInputStream::mMutex") @@ -97,16 +101,22 @@ SlicedInputStream::SetSourceStream(alrea } nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mInputStream); if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) { mWeakSeekableInputStream = seekableStream; } + nsCOMPtr<nsITellableStream> tellableStream = + do_QueryInterface(mInputStream); + if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) { + mWeakTellableInputStream = tellableStream; + } + nsCOMPtr<nsIAsyncInputStream> asyncInputStream = do_QueryInterface(mInputStream); if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) { mWeakAsyncInputStream = asyncInputStream; } nsCOMPtr<nsIInputStreamLength> streamLength = do_QueryInterface(mInputStream); if (streamLength && @@ -539,24 +549,36 @@ SlicedInputStream::Seek(int32_t aWhence, return rv; } mCurPos = offset; return NS_OK; } NS_IMETHODIMP -SlicedInputStream::Tell(int64_t *aResult) +SlicedInputStream::SetEOF() { NS_ENSURE_STATE(mInputStream); NS_ENSURE_STATE(mWeakSeekableInputStream); + mClosed = true; + return mWeakSeekableInputStream->SetEOF(); +} + +// nsITellableStream + +NS_IMETHODIMP +SlicedInputStream::Tell(int64_t *aResult) +{ + NS_ENSURE_STATE(mInputStream); + NS_ENSURE_STATE(mWeakTellableInputStream); + int64_t tell = 0; - nsresult rv = mWeakSeekableInputStream->Tell(&tell); + nsresult rv = mWeakTellableInputStream->Tell(&tell); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (tell < (int64_t)mStart) { *aResult = 0; return NS_OK; } @@ -564,26 +586,16 @@ SlicedInputStream::Tell(int64_t *aResult *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(); -} - // nsIInputStreamLength NS_IMETHODIMP SlicedInputStream::Length(int64_t* aLength) { NS_ENSURE_STATE(mInputStream); NS_ENSURE_STATE(mWeakInputStreamLength);
--- a/xpcom/io/SlicedInputStream.h +++ b/xpcom/io/SlicedInputStream.h @@ -31,16 +31,17 @@ class SlicedInputStream final : public n { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINPUTSTREAMLENGTH NS_DECL_NSIASYNCINPUTSTREAMLENGTH NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK // Create an input stream whose data comes from a slice of aInputStream. The // slice begins at aStart bytes beyond aInputStream's current position, and // extends for a maximum of aLength bytes. If aInputStream contains fewer @@ -68,16 +69,17 @@ private: AdjustRange(uint64_t aRange); nsCOMPtr<nsIInputStream> mInputStream; // Raw pointers because these are just QI of mInputStream. nsICloneableInputStream* mWeakCloneableInputStream; nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream; nsISeekableStream* mWeakSeekableInputStream; + nsITellableStream* mWeakTellableInputStream; nsIAsyncInputStream* mWeakAsyncInputStream; nsIInputStreamLength* mWeakInputStreamLength; nsIAsyncInputStreamLength* mWeakAsyncInputStreamLength; uint64_t mStart; uint64_t mLength; uint64_t mCurPos;
--- a/xpcom/io/moz.build +++ b/xpcom/io/moz.build @@ -28,16 +28,17 @@ XPIDL_SOURCES += [ 'nsIPipe.idl', 'nsISafeOutputStream.idl', 'nsIScriptableBase64Encoder.idl', 'nsIScriptableInputStream.idl', 'nsISeekableStream.idl', 'nsIStorageStream.idl', 'nsIStreamBufferAccess.idl', 'nsIStringStream.idl', + 'nsITellableStream.idl', 'nsIUnicharInputStream.idl', 'nsIUnicharLineInputStream.idl', 'nsIUnicharOutputStream.idl', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': XPIDL_SOURCES += [ 'nsILocalFileMac.idl',
--- a/xpcom/io/nsISeekableStream.idl +++ b/xpcom/io/nsISeekableStream.idl @@ -1,25 +1,27 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsITellableStream.idl" + /* * nsISeekableStream * * Note that a stream might not implement all methods (e.g., a readonly stream * won't implement setEOF) */ #include "nsISupports.idl" [scriptable, uuid(8429d350-1040-4661-8b71-f2a6ba455980)] -interface nsISeekableStream : nsISupports +interface nsISeekableStream : nsITellableStream { /* * Sets the stream pointer to the value of the 'offset' parameter */ const int32_t NS_SEEK_SET = 0; /* * Sets the stream pointer to its current location plus the value @@ -48,27 +50,16 @@ interface nsISeekableStream : nsISupport * implementing stream. A negative value causes seeking in * the reverse direction. * * @throws NS_BASE_STREAM_CLOSED if called on a closed stream. */ void seek(in long whence, in long long offset); /** - * tell - * - * This method reports the current offset, in bytes, from the start of the - * stream. - * - * @throws NS_BASE_STREAM_CLOSED if called on a closed stream. - */ - long long tell(); - - - /** * setEOF * * This method truncates the stream at the current offset. * * @throws NS_BASE_STREAM_CLOSED if called on a closed stream. */ void setEOF(); };
new file mode 100644 --- /dev/null +++ b/xpcom/io/nsITellableStream.idl @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/* + * nsITellableStream + * + * This class is separate from nsISeekableStream in order to let streams to + * implement ::Tell() without implementing the whole nsISeekableStream + * interface. Callers can QI the stream to know what is implemented. This is + * mainly done for nsPipeInputStream. + * + * + * Implementing this interface, streams are able to expose the current offset + * via ::tell(). + */ + +#include "nsISupports.idl" + +[scriptable, uuid(ee942946-4538-45d2-bf05-ffdbf5932621)] +interface nsITellableStream : nsISupports +{ + /** + * tell + * + * This method reports the current offset, in bytes, from the start of the + * stream. + * + * @throws NS_BASE_STREAM_CLOSED if called on a closed stream. + */ + long long tell(); +};
--- a/xpcom/io/nsMultiplexInputStream.cpp +++ b/xpcom/io/nsMultiplexInputStream.cpp @@ -51,16 +51,17 @@ class nsMultiplexInputStream final { public: nsMultiplexInputStream(); NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSIMULTIPLEXINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINPUTSTREAMLENGTH NS_DECL_NSIASYNCINPUTSTREAMLENGTH // This is used for nsIAsyncInputStream::AsyncWait @@ -72,25 +73,28 @@ public: struct StreamData { void Initialize(nsIInputStream* aStream, bool aBuffered) { mStream = aStream; mAsyncStream = do_QueryInterface(aStream); mSeekableStream = do_QueryInterface(aStream); + mTellableStream = do_QueryInterface(aStream); mBuffered = aBuffered; } nsCOMPtr<nsIInputStream> mStream; // This can be null. nsCOMPtr<nsIAsyncInputStream> mAsyncStream; // This can be null. nsCOMPtr<nsISeekableStream> mSeekableStream; + // This can be null. + nsCOMPtr<nsITellableStream> mTellableStream; // True if the stream is wrapped with nsIBufferedInputStream. bool mBuffered; }; Mutex& GetLock() { return mLock; @@ -99,34 +103,35 @@ public: private: ~nsMultiplexInputStream() { } nsresult AsyncWaitInternal(); - // This method updates mSeekableStreams, mIPCSerializableStreams, - // mCloneableStreams and mAsyncInputStreams values. + // This method updates mSeekableStreams, mTellableStreams, + // mIPCSerializableStreams, mCloneableStreams and mAsyncInputStreams values. void UpdateQIMap(StreamData& aStream, int32_t aCount); struct MOZ_STACK_CLASS ReadSegmentsState { nsCOMPtr<nsIInputStream> mThisStream; uint32_t mOffset; nsWriteSegmentFun mWriter; void* mClosure; bool mDone; }; static nsresult ReadSegCb(nsIInputStream* aIn, void* aClosure, const char* aFromRawSegment, uint32_t aToOffset, uint32_t aCount, uint32_t* aWriteCount); bool IsSeekable() const; + bool IsTellable() const; bool IsIPCSerializable() const; bool IsCloneable() const; bool IsAsyncInputStream() const; bool IsInputStreamLength() const; bool IsAsyncInputStreamLength() const; Mutex mLock; // Protects access to all data members. @@ -140,16 +145,17 @@ private: uint32_t mAsyncWaitRequestedCount; nsCOMPtr<nsIEventTarget> mAsyncWaitEventTarget; nsCOMPtr<nsIInputStreamLengthCallback> mAsyncWaitLengthCallback; class AsyncWaitLengthHelper; RefPtr<AsyncWaitLengthHelper> mAsyncWaitLengthHelper; uint32_t mSeekableStreams; + uint32_t mTellableStreams; uint32_t mIPCSerializableStreams; uint32_t mCloneableStreams; uint32_t mAsyncInputStreams; uint32_t mInputStreamLengths; uint32_t mAsyncInputStreamLengths; }; NS_IMPL_ADDREF(nsMultiplexInputStream) @@ -157,16 +163,17 @@ NS_IMPL_RELEASE(nsMultiplexInputStream) NS_IMPL_CLASSINFO(nsMultiplexInputStream, nullptr, nsIClassInfo::THREADSAFE, NS_MULTIPLEXINPUTSTREAM_CID) NS_INTERFACE_MAP_BEGIN(nsMultiplexInputStream) NS_INTERFACE_MAP_ENTRY(nsIMultiplexInputStream) NS_INTERFACE_MAP_ENTRY(nsIInputStream) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekable()) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, IsTellable()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, IsIPCSerializable()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, IsCloneable()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, IsAsyncInputStream()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback, IsAsyncInputStream()) @@ -176,17 +183,18 @@ NS_INTERFACE_MAP_BEGIN(nsMultiplexInputS IsAsyncInputStreamLength()) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMultiplexInputStream) NS_IMPL_QUERY_CLASSINFO(nsMultiplexInputStream) NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER(nsMultiplexInputStream, nsIMultiplexInputStream, nsIInputStream, - nsISeekableStream) + nsISeekableStream, + nsITellableStream) static nsresult AvailableMaybeSeek(nsMultiplexInputStream::StreamData& aStream, uint64_t* aResult) { nsresult rv = aStream.mStream->Available(aResult); if (rv == NS_BASE_STREAM_CLOSED) { // Blindly seek to the current position if Available() returns @@ -200,40 +208,42 @@ AvailableMaybeSeek(nsMultiplexInputStrea rv = aStream.mStream->Available(aResult); } } } return rv; } static nsresult -TellMaybeSeek(nsISeekableStream* aSeekable, int64_t* aResult) +TellMaybeSeek(nsITellableStream* aTellable, nsISeekableStream* aSeekable, + int64_t* aResult) { - nsresult rv = aSeekable->Tell(aResult); - if (rv == NS_BASE_STREAM_CLOSED) { + nsresult rv = aTellable->Tell(aResult); + if (rv == NS_BASE_STREAM_CLOSED && aSeekable) { // Blindly seek to the current position if Tell() returns // NS_BASE_STREAM_CLOSED. // If nsIFileInputStream is closed in Read() due to CLOSE_ON_EOF flag, // Seek() could reopen the file if REOPEN_ON_REWIND flag is set. nsresult rvSeek = aSeekable->Seek(nsISeekableStream::NS_SEEK_CUR, 0); if (NS_SUCCEEDED(rvSeek)) { - rv = aSeekable->Tell(aResult); + rv = aTellable->Tell(aResult); } } return rv; } nsMultiplexInputStream::nsMultiplexInputStream() : mLock("nsMultiplexInputStream lock") , mCurrentStream(0) , mStartedReadingCurrent(false) , mStatus(NS_OK) , mAsyncWaitFlags(0) , mAsyncWaitRequestedCount(0) , mSeekableStreams(0) + , mTellableStreams(0) , mIPCSerializableStreams(0) , mCloneableStreams(0) , mAsyncInputStreams(0) , mInputStreamLengths(0) , mAsyncInputStreamLengths(0) {} NS_IMETHODIMP @@ -574,16 +584,18 @@ nsMultiplexInputStream::Seek(int32_t aWh mCurrentStream = 0; } for (uint32_t i = 0; i < mStreams.Length(); ++i) { nsCOMPtr<nsISeekableStream> stream = mStreams[i].mSeekableStream; if (!stream) { return NS_ERROR_FAILURE; } + MOZ_ASSERT(mStreams[i].mTellableStream); + // See if all remaining streams should be rewound if (remaining == 0) { if (i < oldCurrentStream || (i == oldCurrentStream && oldStartedReadingCurrent)) { rv = stream->Seek(NS_SEEK_SET, 0); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -594,17 +606,17 @@ nsMultiplexInputStream::Seek(int32_t aWh } // Get position in current stream int64_t streamPos; if (i > oldCurrentStream || (i == oldCurrentStream && !oldStartedReadingCurrent)) { streamPos = 0; } else { - rv = TellMaybeSeek(stream, &streamPos); + rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &streamPos); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } // See if we need to seek current stream forward or backward if (remaining < streamPos) { rv = stream->Seek(NS_SEEK_SET, remaining); @@ -677,17 +689,18 @@ nsMultiplexInputStream::Seek(int32_t aWh return NS_OK; } if (aWhence == NS_SEEK_CUR && aOffset < 0) { int64_t remaining = -aOffset; for (uint32_t i = mCurrentStream; remaining && i != (uint32_t)-1; --i) { int64_t pos; - rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos); + rv = TellMaybeSeek(mStreams[i].mTellableStream, + mStreams[i].mSeekableStream, &pos); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } int64_t seek = XPCOM_MIN(pos, remaining); rv = mStreams[i].mSeekableStream->Seek(NS_SEEK_CUR, -seek); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -756,17 +769,17 @@ nsMultiplexInputStream::Seek(int32_t aWh remaining = 0; } else if (DeprecatedAbs(remaining) > streamPos) { if (i > oldCurrentStream || (i == oldCurrentStream && !oldStartedReadingCurrent)) { // We're already at start so no need to seek this stream remaining += streamPos; } else { int64_t avail; - rv = TellMaybeSeek(stream, &avail); + rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &avail); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } int64_t newPos = streamPos + XPCOM_MIN(avail, DeprecatedAbs(remaining)); rv = stream->Seek(NS_SEEK_END, -newPos); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -800,22 +813,23 @@ nsMultiplexInputStream::Tell(int64_t* aR return mStatus; } nsresult rv; int64_t ret64 = 0; uint32_t i, last; last = mStartedReadingCurrent ? mCurrentStream + 1 : mCurrentStream; for (i = 0; i < last; ++i) { - if (NS_WARN_IF(!mStreams[i].mSeekableStream)) { + if (NS_WARN_IF(!mStreams[i].mTellableStream)) { return NS_ERROR_NO_INTERFACE; } int64_t pos; - rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos); + rv = TellMaybeSeek(mStreams[i].mTellableStream, mStreams[i].mSeekableStream, + &pos); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } ret64 += pos; } *aResult = ret64; return NS_OK; @@ -1510,32 +1524,39 @@ nsMultiplexInputStream::AsyncWaitComplet } void nsMultiplexInputStream::UpdateQIMap(StreamData& aStream, int32_t aCount) { MOZ_ASSERT(aCount == -1 || aCount == 1); MAYBE_UPDATE_VALUE_REAL(mSeekableStreams, aStream.mSeekableStream) + MAYBE_UPDATE_VALUE_REAL(mTellableStreams, aStream.mTellableStream) MAYBE_UPDATE_VALUE(mIPCSerializableStreams, nsIIPCSerializableInputStream) MAYBE_UPDATE_VALUE(mCloneableStreams, nsICloneableInputStream) MAYBE_UPDATE_VALUE_REAL(mAsyncInputStreams, aStream.mAsyncStream) MAYBE_UPDATE_VALUE(mInputStreamLengths, nsIInputStreamLength) MAYBE_UPDATE_VALUE(mAsyncInputStreamLengths, nsIAsyncInputStreamLength) } #undef MAYBE_UPDATE_VALUE bool nsMultiplexInputStream::IsSeekable() const { return mStreams.Length() == mSeekableStreams; } bool +nsMultiplexInputStream::IsTellable() const +{ + return mStreams.Length() == mTellableStreams; +} + +bool nsMultiplexInputStream::IsIPCSerializable() const { return mStreams.Length() == mIPCSerializableStreams; } bool nsMultiplexInputStream::IsCloneable() const {
--- a/xpcom/io/nsPipe3.cpp +++ b/xpcom/io/nsPipe3.cpp @@ -7,17 +7,17 @@ #include <algorithm> #include "mozilla/Attributes.h" #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/ReentrantMonitor.h" #include "nsIBufferedStreams.h" #include "nsICloneableInputStream.h" #include "nsIPipe.h" #include "nsIEventTarget.h" -#include "nsISeekableStream.h" +#include "nsITellableStream.h" #include "mozilla/RefPtr.h" #include "nsSegmentedBuffer.h" #include "nsStreamUtils.h" #include "nsCOMPtr.h" #include "nsCRT.h" #include "mozilla/Logging.h" #include "nsIClassInfoImpl.h" #include "nsAlgorithm.h" @@ -137,30 +137,30 @@ struct nsPipeReadState bool mNeedDrain; }; //----------------------------------------------------------------------------- // an input end of a pipe (maintained as a list of refs within the pipe) class nsPipeInputStream final : public nsIAsyncInputStream - , public nsISeekableStream + , public nsITellableStream , public nsISearchableInputStream , public nsICloneableInputStream , public nsIClassInfo , public nsIBufferedInputStream { public: // Pipe input streams preserve their refcount changes when record/replaying, // as otherwise the thread which destroys the stream may vary between // recording and replaying. NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(recordreplay::Behavior::Preserve) NS_DECL_NSIINPUTSTREAM NS_DECL_NSIASYNCINPUTSTREAM - NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSISEARCHABLEINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM NS_DECL_NSICLASSINFO NS_DECL_NSIBUFFEREDINPUTSTREAM explicit nsPipeInputStream(nsPipe* aPipe) : mPipe(aPipe) , mLogicalOffset(0) @@ -1245,32 +1245,32 @@ nsPipeEvents::~nsPipeEvents() //----------------------------------------------------------------------------- NS_IMPL_ADDREF(nsPipeInputStream); NS_IMPL_RELEASE(nsPipeInputStream); NS_INTERFACE_TABLE_HEAD(nsPipeInputStream) NS_INTERFACE_TABLE_BEGIN NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIAsyncInputStream) - NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISeekableStream) + NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsITellableStream) NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISearchableInputStream) NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsICloneableInputStream) NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIBufferedInputStream) NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIClassInfo) NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsPipeInputStream, nsIInputStream, nsIAsyncInputStream) NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsPipeInputStream, nsISupports, nsIAsyncInputStream) NS_INTERFACE_TABLE_END NS_INTERFACE_TABLE_TAIL NS_IMPL_CI_INTERFACE_GETTER(nsPipeInputStream, nsIInputStream, nsIAsyncInputStream, - nsISeekableStream, + nsITellableStream, nsISearchableInputStream, nsICloneableInputStream, nsIBufferedInputStream) NS_IMPL_THREADSAFE_CI(nsPipeInputStream) NS_IMETHODIMP nsPipeInputStream::Init(nsIInputStream*, uint32_t) @@ -1521,42 +1521,29 @@ nsPipeInputStream::AsyncWait(nsIInputStr mCallback = aCallback; mCallbackFlags = aFlags; } } return NS_OK; } NS_IMETHODIMP -nsPipeInputStream::Seek(int32_t aWhence, int64_t aOffset) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP nsPipeInputStream::Tell(int64_t* aOffset) { ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor); // return error if closed if (!mReadState.mAvailable && NS_FAILED(Status(mon))) { return Status(mon); } *aOffset = mLogicalOffset; return NS_OK; } -NS_IMETHODIMP -nsPipeInputStream::SetEOF() -{ - MOZ_ASSERT_UNREACHABLE("nsPipeInputStream::SetEOF"); - return NS_ERROR_NOT_IMPLEMENTED; -} - static bool strings_equal(bool aIgnoreCase, const char* aS1, const char* aS2, uint32_t aLen) { return aIgnoreCase ? !nsCRT::strncasecmp(aS1, aS2, aLen) : !strncmp(aS1, aS2, aLen); } NS_IMETHODIMP
--- a/xpcom/io/nsStorageStream.cpp +++ b/xpcom/io/nsStorageStream.cpp @@ -344,16 +344,17 @@ public: mSegmentSize(aSegmentSize), mLogicalCursor(0), mStatus(NS_OK) { } NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM private: ~nsStorageInputStream() { } @@ -379,16 +380,17 @@ private: { return aPosition & (mSegmentSize - 1); } }; NS_IMPL_ISUPPORTS(nsStorageInputStream, nsIInputStream, nsISeekableStream, + nsITellableStream, nsIIPCSerializableInputStream, nsICloneableInputStream) NS_IMETHODIMP nsStorageStream::NewInputStream(int32_t aStartingOffset, nsIInputStream** aInputStream) { if (NS_WARN_IF(!mSegmentedBuffer)) {
--- a/xpcom/io/nsStringStream.cpp +++ b/xpcom/io/nsStringStream.cpp @@ -39,16 +39,17 @@ class nsStringInputStream final , public nsIIPCSerializableInputStream , public nsICloneableInputStream { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM NS_DECL_NSISTRINGINPUTSTREAM NS_DECL_NSISEEKABLESTREAM + NS_DECL_NSITELLABLESTREAM NS_DECL_NSISUPPORTSPRIMITIVE NS_DECL_NSISUPPORTSCSTRING NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM nsStringInputStream() : mOffset(0) { @@ -104,23 +105,25 @@ NS_IMPL_RELEASE(nsStringInputStream) NS_IMPL_CLASSINFO(nsStringInputStream, nullptr, nsIClassInfo::THREADSAFE, NS_STRINGINPUTSTREAM_CID) NS_IMPL_QUERY_INTERFACE_CI(nsStringInputStream, nsIStringInputStream, nsIInputStream, nsISupportsCString, nsISeekableStream, + nsITellableStream, nsIIPCSerializableInputStream, nsICloneableInputStream) NS_IMPL_CI_INTERFACE_GETTER(nsStringInputStream, nsIStringInputStream, nsIInputStream, nsISupportsCString, nsISeekableStream, + nsITellableStream, nsICloneableInputStream) ///////// // nsISupportsCString implementation ///////// NS_IMETHODIMP nsStringInputStream::GetType(uint16_t* aType) @@ -318,37 +321,41 @@ nsStringInputStream::Seek(int32_t aWhenc return NS_ERROR_INVALID_ARG; } mOffset = (uint32_t)newPos; return NS_OK; } NS_IMETHODIMP +nsStringInputStream::SetEOF() +{ + if (Closed()) { + return NS_BASE_STREAM_CLOSED; + } + + mOffset = Length(); + return NS_OK; +} + +///////// +// nsITellableStream implementation +///////// + +NS_IMETHODIMP nsStringInputStream::Tell(int64_t* aOutWhere) { if (Closed()) { return NS_BASE_STREAM_CLOSED; } *aOutWhere = mOffset; return NS_OK; } -NS_IMETHODIMP -nsStringInputStream::SetEOF() -{ - if (Closed()) { - return NS_BASE_STREAM_CLOSED; - } - - mOffset = Length(); - return NS_OK; -} - ///////// // nsIIPCSerializableInputStream implementation ///////// void nsStringInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& /* aFDs */) {
--- a/xpcom/io/nsStringStream.h +++ b/xpcom/io/nsStringStream.h @@ -11,30 +11,31 @@ #include "nsString.h" #include "nsMemory.h" /** * Implements: * nsIStringInputStream * nsIInputStream * nsISeekableStream + * nsITellableStream * nsISupportsCString */ #define NS_STRINGINPUTSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1" #define NS_STRINGINPUTSTREAM_CID \ { /* 0abb0835-5000-4790-af28-61b3ba17c295 */ \ 0x0abb0835, \ 0x5000, \ 0x4790, \ {0xaf, 0x28, 0x61, 0xb3, 0xba, 0x17, 0xc2, 0x95} \ } /** * Factory method to get an nsInputStream from a byte buffer. Result will - * implement nsIStringInputStream and nsISeekableStream. + * implement nsIStringInputStream, nsITellableStream and nsISeekableStream. * * If aAssignment is NS_ASSIGNMENT_COPY, then the resulting stream holds a copy * of the given buffer (aStringToRead), and the caller is free to discard * aStringToRead after this function returns. * * If aAssignment is NS_ASSIGNMENT_DEPEND, then the resulting stream refers * directly to the given buffer (aStringToRead), so the caller must ensure that * the buffer remains valid for the lifetime of the stream object. Use with @@ -49,17 +50,17 @@ */ extern nsresult NS_NewByteInputStream(nsIInputStream** aStreamResult, const char* aStringToRead, int32_t aLength = -1, nsAssignmentType aAssignment = NS_ASSIGNMENT_DEPEND); /** * Factory method to get an nsInputStream from an nsACString. Result will - * implement nsIStringInputStream and nsISeekableStream. + * implement nsIStringInputStream, nsTellableStream and nsISeekableStream. */ extern nsresult NS_NewCStringInputStream(nsIInputStream** aStreamResult, const nsACString& aStringToRead); extern nsresult NS_NewCStringInputStream(nsIInputStream** aStreamResult, nsCString&& aStringToRead);
--- a/xpcom/tests/gtest/TestPipes.cpp +++ b/xpcom/tests/gtest/TestPipes.cpp @@ -14,17 +14,17 @@ #include "nsIAsyncInputStream.h" #include "nsIAsyncOutputStream.h" #include "nsIBufferedStreams.h" #include "nsIClassInfo.h" #include "nsICloneableInputStream.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" #include "nsIPipe.h" -#include "nsISeekableStream.h" +#include "nsITellableStream.h" #include "nsIThread.h" #include "nsIRunnable.h" #include "nsStreamUtils.h" #include "nsString.h" #include "nsThreadUtils.h" #include "prinrval.h" using namespace mozilla; @@ -1073,17 +1073,17 @@ TEST(Pipes, Interfaces) nsCOMPtr<nsIOutputStream> writer; nsresult rv = NS_NewPipe(getter_AddRefs(reader), getter_AddRefs(writer)); ASSERT_TRUE(NS_SUCCEEDED(rv)); nsCOMPtr<nsIAsyncInputStream> readerType1 = do_QueryInterface(reader); ASSERT_TRUE(readerType1); - nsCOMPtr<nsISeekableStream> readerType2 = do_QueryInterface(reader); + nsCOMPtr<nsITellableStream> readerType2 = do_QueryInterface(reader); ASSERT_TRUE(readerType2); nsCOMPtr<nsISearchableInputStream> readerType3 = do_QueryInterface(reader); ASSERT_TRUE(readerType3); nsCOMPtr<nsICloneableInputStream> readerType4 = do_QueryInterface(reader); ASSERT_TRUE(readerType4);