Bug 1401171 - Make nsIMultiplexInputStream not inherit from nsIInputStream. r=bkelly

This is a preexisting issue that makes nsMultiplexInputStream multiple-inherit
from nsIInputStream: once via nsIMultipartInputStream and once via
nsIAsyncInputStream.  This causes problems once we end up with more multiplex
streams that are async streams, because then some assingments to
nsCOMPtr<nsIInputStream> start asserting.  This patch just removes the footgun
by getting rid of the multiple inheritance.
This commit is contained in:
Boris Zbarsky 2017-09-19 16:26:21 +02:00
parent 7973633f84
commit 203072cfe1
11 changed files with 51 additions and 28 deletions

View File

@ -85,7 +85,7 @@ MultipartBlobImpl::GetInternalStream(nsIInputStream** aStream,
}
}
stream.forget(aStream);
CallQueryInterface(stream, aStream);
}
already_AddRefed<BlobImpl>

View File

@ -394,8 +394,13 @@ FSMultipartFormData::FSMultipartFormData(NotNull<const Encoding*> aEncoding,
nsIContent* aOriginatingElement)
: EncodingFormSubmission(aEncoding, aOriginatingElement)
{
mPostDataStream =
mPostData =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(mPostData);
MOZ_ASSERT(SameCOMIdentity(mPostData, inputStream));
mPostDataStream = inputStream;
mTotalLength = 0;
mBoundary.AssignLiteral("---------------------------");
@ -600,7 +605,7 @@ FSMultipartFormData::AddDataChunk(const nsACString& aName,
// here, since we're about to add the file input stream
AddPostDataStream();
mPostDataStream->AppendStream(aInputStream);
mPostData->AppendStream(aInputStream);
mTotalLength += aInputStreamSize;
}
@ -640,7 +645,7 @@ FSMultipartFormData::AddPostDataStream()
mPostDataChunk);
NS_ASSERTION(postDataChunkStream, "Could not open a stream for POST!");
if (postDataChunkStream) {
mPostDataStream->AppendStream(postDataChunkStream);
mPostData->AppendStream(postDataChunkStream);
mTotalLength += mPostDataChunk.Length();
}

View File

@ -193,7 +193,13 @@ private:
* chunks--string streams and file streams interleaved to make one big POST
* stream.
*/
nsCOMPtr<nsIMultiplexInputStream> mPostDataStream;
nsCOMPtr<nsIMultiplexInputStream> mPostData;
/**
* The same stream, but as an nsIInputStream.
* Raw pointers because it is just QI of mInputStream.
*/
nsIInputStream* mPostDataStream;
/**
* The current string chunk. When a file is hit, the string chunk gets

View File

@ -210,6 +210,7 @@ TCPSocket::CreateStream()
mMultiplexStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(mMultiplexStream);
mMultiplexStreamCopier = do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -218,7 +219,7 @@ TCPSocket::CreateStream()
do_GetService("@mozilla.org/network/socket-transport-service;1");
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
rv = mMultiplexStreamCopier->Init(mMultiplexStream,
rv = mMultiplexStreamCopier->Init(stream,
mSocketOutputStream,
target,
true, /* source buffered */
@ -596,7 +597,8 @@ TCPSocket::BufferedAmount()
}
if (mMultiplexStream) {
uint64_t available = 0;
mMultiplexStream->Available(&available);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(mMultiplexStream));
stream->Available(&available);
return available;
}
return 0;

View File

@ -240,6 +240,7 @@ PresentationTCPSessionTransport::CreateStream()
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(mMultiplexStream);
mMultiplexStreamCopier = do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -253,7 +254,7 @@ PresentationTCPSessionTransport::CreateStream()
}
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
rv = mMultiplexStreamCopier->Init(mMultiplexStream,
rv = mMultiplexStreamCopier->Init(stream,
mSocketOutputStream,
target,
true, /* source buffered */

View File

@ -232,7 +232,9 @@ FileReaderSync::ReadAsText(Blob& aBlob,
nsAutoCString charset;
encoding->Name(charset);
aRv = ConvertStream(multiplexStream, charset.get(), aResult);
nsCOMPtr<nsIInputStream> multiplex(do_QueryInterface(multiplexStream));
aRv = ConvertStream(multiplex, charset.get(), aResult);
if (NS_WARN_IF(aRv.Failed())) {
return;
}

View File

@ -382,7 +382,8 @@ nsHttpTransaction::Init(uint32_t caps,
// wrap the multiplexed input stream with a buffered input stream, so
// that we write data in the largest chunks possible. this is actually
// necessary to workaround some common server bugs (see bug 137155).
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi,
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), stream,
nsIOService::gDefaultSegmentSize);
if (NS_FAILED(rv)) return rv;
} else {

View File

@ -11,7 +11,7 @@
*/
[scriptable, uuid(a076fd12-1dd1-11b2-b19a-d53b5dffaade)]
interface nsIMultiplexInputStream : nsIInputStream
interface nsIMultiplexInputStream : nsISupports
{
/**
* Number of streams in this multiplex-stream

View File

@ -103,7 +103,7 @@ NS_IMPL_CLASSINFO(nsMultiplexInputStream, nullptr, nsIClassInfo::THREADSAFE,
NS_INTERFACE_MAP_BEGIN(nsMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
IsIPCSerializable())
@ -349,7 +349,7 @@ nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
nsresult rv = NS_OK;
ReadSegmentsState state;
state.mThisStream = static_cast<nsIMultiplexInputStream*>(this);
state.mThisStream = this;
state.mOffset = 0;
state.mWriter = aWriter;
state.mClosure = aClosure;
@ -1048,7 +1048,7 @@ nsMultiplexInputStream::Clone(nsIInputStream** aClone)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIMultiplexInputStream> clone = new nsMultiplexInputStream();
RefPtr<nsMultiplexInputStream> clone = new nsMultiplexInputStream();
nsresult rv;
uint32_t len = mStreams.Length();

View File

@ -116,8 +116,10 @@ TEST(CloneInputStream, NonCloneableInput_Fallback)
TEST(CloneInputStream, CloneMultiplexStream)
{
nsCOMPtr<nsIMultiplexInputStream> stream =
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
ASSERT_TRUE(multiplexStream);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(stream);
nsTArray<char> inputData;
@ -129,7 +131,7 @@ TEST(CloneInputStream, CloneMultiplexStream)
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->AppendStream(base);
rv = multiplexStream->AppendStream(base);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}
@ -156,8 +158,10 @@ TEST(CloneInputStream, CloneMultiplexStream)
TEST(CloneInputStream, CloneMultiplexStreamPartial)
{
nsCOMPtr<nsIMultiplexInputStream> stream =
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
ASSERT_TRUE(multiplexStream);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(stream);
nsTArray<char> inputData;
@ -169,7 +173,7 @@ TEST(CloneInputStream, CloneMultiplexStreamPartial)
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = stream->AppendStream(base);
rv = multiplexStream->AppendStream(base);
ASSERT_TRUE(NS_SUCCEEDED(rv));
}

View File

@ -34,6 +34,8 @@ TEST(MultiplexInputStream, Seek_SET)
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
ASSERT_TRUE(multiplexStream);
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(stream);
rv = multiplexStream->AppendStream(inputStream1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
@ -51,16 +53,16 @@ TEST(MultiplexInputStream, Seek_SET)
// Seek forward in first input stream
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, 1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 1,
length);
// Check read is correct
rv = multiplexStream->Read(readBuf, 3, &count);
rv = stream->Read(readBuf, 3, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)3, count);
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf1.Length() + buf2.Length() + buf3.Length() - 4,
length);
@ -70,15 +72,15 @@ TEST(MultiplexInputStream, Seek_SET)
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET,
buf1.Length() + buf2.Length());
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf3.Length(), length);
// Check read is correct
rv = multiplexStream->Read(readBuf, 5, &count);
rv = stream->Read(readBuf, 5, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)5, count);
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf3.Length() - 5, length);
ASSERT_EQ(0, strncmp(readBuf, "Foo b", count));
@ -86,16 +88,16 @@ TEST(MultiplexInputStream, Seek_SET)
// Seek back to start of second stream (covers bug 1272371)
rv = seekStream->Seek(nsISeekableStream::NS_SEEK_SET, buf1.Length());
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf2.Length() + buf3.Length(), length);
// Check read is correct
rv = multiplexStream->Read(readBuf, 6, &count);
rv = stream->Read(readBuf, 6, &count);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)6, count);
rv = multiplexStream->Available(&length);
rv = stream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ((uint64_t)buf2.Length() - 6 + buf3.Length(), length);
ASSERT_EQ(0, strncmp(readBuf, "The qu", count));
}
}