diff --git a/mozilla/content/html/content/src/nsFormSubmission.cpp b/mozilla/content/html/content/src/nsFormSubmission.cpp
index 11f5a1c61da..4bfe635199c 100644
--- a/mozilla/content/html/content/src/nsFormSubmission.cpp
+++ b/mozilla/content/html/content/src/nsFormSubmission.cpp
@@ -524,16 +524,14 @@ nsFSMultipartFormData::AddNameFilePair(nsIDOMHTMLElement* aSource,
+ NS_LITERAL_CSTRING("Content-Type: ") + aContentType
+ NS_LITERAL_CSTRING(CRLF CRLF);
- //
- // We need to dump the data up to this point into the POST data stream here,
- // since we're about to add the file input stream
- //
- AddPostDataStream();
-
//
// Add the file to the stream
//
if (aStream) {
+ // We need to dump the data up to this point into the POST data stream here,
+ // since we're about to add the file input stream
+ AddPostDataStream();
+
mPostDataStream->AppendStream(aStream);
}
diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp
index 442e1e6d7e5..eec7fc80f62 100644
--- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp
@@ -2220,21 +2220,28 @@ nsHTMLInputElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
//
// Get input stream
//
- nsCOMPtr rawStream;
- rv = NS_NewLocalFileInputStream(getter_AddRefs(rawStream), file);
- if (rawStream) {
+ nsCOMPtr fileStream;
+ rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
+ file, -1, -1,
+ nsIFileInputStream::CLOSE_ON_EOF |
+ nsIFileInputStream::REOPEN_ON_REWIND);
+ if (fileStream) {
+ //
+ // Create buffered stream (for efficiency)
+ //
nsCOMPtr bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
- rawStream, 8192);
+ fileStream, 8192);
NS_ENSURE_SUCCESS(rv, rv);
-
- //
- // Submit
- //
- aFormSubmission->AddNameFilePair(this, name, filename,
- bufferedStream, contentType,
- PR_FALSE);
- return rv;
+ if (bufferedStream) {
+ //
+ // Submit
+ //
+ aFormSubmission->AddNameFilePair(this, name, filename,
+ bufferedStream, contentType,
+ PR_FALSE);
+ return rv;
+ }
}
}
diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp
index 44cb077a920..5b9401fd1ae 100644
--- a/mozilla/docshell/base/nsDocShell.cpp
+++ b/mozilla/docshell/base/nsDocShell.cpp
@@ -4854,7 +4854,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
nsCOMPtr
postDataSeekable(do_QueryInterface(aPostData));
if (postDataSeekable) {
- postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ rv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr uploadChannel(do_QueryInterface(httpChannel));
diff --git a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
index b43b6e5e67f..3ac055c69b9 100644
--- a/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/mozilla/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -1597,7 +1597,8 @@ nsWebBrowserPersist::MakeOutputStreamFromFile(
do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- rv = fileOutputStream->Init(aFile, -1, -1); // brade: get the right flags here! XXX
+ // XXX brade: get the right flags here!
+ rv = fileOutputStream->Init(aFile, -1, -1, 0);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(CallQueryInterface(fileOutputStream, aOutputStream), NS_ERROR_FAILURE);
diff --git a/mozilla/modules/plugin/base/src/nsIPluginHost.h b/mozilla/modules/plugin/base/src/nsIPluginHost.h
index 39430761543..b5e83d62a11 100644
--- a/mozilla/modules/plugin/base/src/nsIPluginHost.h
+++ b/mozilla/modules/plugin/base/src/nsIPluginHost.h
@@ -147,7 +147,7 @@ NS_NewPluginPostDataStream(nsIInputStream **result,
file,
PR_RDONLY,
0600,
- PR_TRUE))
+ nsIFileInputStream::DELETE_ON_CLOSE))
)
{
// wrap the file stream with a buffered input stream
diff --git a/mozilla/netwerk/base/public/nsIFileStreams.idl b/mozilla/netwerk/base/public/nsIFileStreams.idl
index 9a3ed2e3082..456bdca911b 100644
--- a/mozilla/netwerk/base/public/nsIFileStreams.idl
+++ b/mozilla/netwerk/base/public/nsIFileStreams.idl
@@ -41,19 +41,49 @@
interface nsIFile;
+/**
+ * An input stream that allows you to read from a file.
+ */
[scriptable, uuid(e3d56a20-c7ec-11d3-8cda-0060b0fc14a3)]
interface nsIFileInputStream : nsIInputStream
{
/**
- * @param file - file to read from (must QI to nsILocalFile)
- * @param ioFlags - file open flags listed in prio.h
- * @param perm - file mode bits listed in prio.h
- * @param deleteOnClose - if true, the file is deleted from the filesystem
- * after the file stream is closed.
+ * @param file file to read from (must QI to nsILocalFile)
+ * @param ioFlags file open flags listed in prio.h
+ * @param perm file mode bits listed in prio.h
+ * @param behaviorFlags flags specifying various behaviors of the class
+ * (see enumerations in the class)
*/
- void init(in nsIFile file, in long ioFlags, in long perm, in boolean deleteOnClose);
+ void init(in nsIFile file, in long ioFlags, in long perm,
+ in long behaviorFlags);
+
+ /**
+ * If this is set, the file will be deleted by the time the stream is
+ * closed. It may be removed before the stream is closed if it is possible
+ * to delete it and still read from it.
+ *
+ * If OPEN_ON_READ is defined, and the file was recreated after the first
+ * delete, the file will be deleted again when it is closed again.
+ */
+ const long DELETE_ON_CLOSE = 1<<1;
+
+ /**
+ * If this is set, the file will close automatically when the end of the
+ * file is reached.
+ */
+ const long CLOSE_ON_EOF = 1<<2;
+
+ /**
+ * If this is set, the file will be reopened whenever Seek(0) occurs. If
+ * the file is already open and the seek occurs, it will happen naturally.
+ * (The file will only be reopened if it is closed for some reason.)
+ */
+ const long REOPEN_ON_REWIND = 1<<3;
};
+/**
+ * An output stream that lets you stream to a file.
+ */
[scriptable, uuid(e6f68040-c7ec-11d3-8cda-0060b0fc14a3)]
interface nsIFileOutputStream : nsIOutputStream
{
@@ -61,10 +91,17 @@ interface nsIFileOutputStream : nsIOutputStream
* @param file - file to write to (must QI to nsILocalFile)
* @param ioFlags - file open flags listed in prio.h
* @param perm - file mode bits listed in prio.h
+ * @param behaviorFlags flags specifying various behaviors of the class
+ * (currently none supported)
*/
- void init(in nsIFile file, in long ioFlags, in long perm);
+ void init(in nsIFile file, in long ioFlags, in long perm,
+ in long behaviorFlags);
};
+/**
+ * An input stream that reads ahead and keeps a buffer coming from another input
+ * stream so that fewer accesses to the underlying stream are necessary.
+ */
[scriptable, uuid(616f5b48-da09-11d3-8cda-0060b0fc14a3)]
interface nsIBufferedInputStream : nsIInputStream
{
@@ -76,6 +113,11 @@ interface nsIBufferedInputStream : nsIInputStream
in unsigned long bufferSize);
};
+/**
+ * An output stream that stores up data to write out to another output stream
+ * and does the entire write only when the buffer is full, so that fewer writes
+ * to the underlying output stream are necessary.
+ */
[scriptable, uuid(6476378a-da09-11d3-8cda-0060b0fc14a3)]
interface nsIBufferedOutputStream : nsIOutputStream
{
@@ -149,10 +191,10 @@ interface nsIBufferedOutputStream : nsIOutputStream
// This will QI the file argument to an nsILocalFile in the Init method.
inline nsresult
-NS_NewLocalFileChannel(nsIFileChannel **result,
- nsIFile* file,
- PRInt32 ioFlags = -1,
- PRInt32 perm = -1)
+NS_NewLocalFileChannel(nsIFileChannel** aResult,
+ nsIFile* aFile,
+ PRInt32 aIOFlags = -1,
+ PRInt32 aPerm = -1)
{
nsresult rv;
nsCOMPtr channel;
@@ -162,21 +204,21 @@ NS_NewLocalFileChannel(nsIFileChannel **result,
NS_GET_IID(nsIFileChannel),
getter_AddRefs(channel));
if (NS_FAILED(rv)) return rv;
- rv = channel->Init(file, ioFlags, perm);
+ rv = channel->Init(aFile, aIOFlags, aPerm);
if (NS_FAILED(rv)) return rv;
- *result = channel;
- NS_ADDREF(*result);
+ *aResult = channel;
+ NS_ADDREF(*aResult);
return NS_OK;
}
// This will QI the file argument to an nsILocalFile in the Init method.
inline nsresult
-NS_NewLocalFileInputStream(nsIInputStream* *result,
- nsIFile* file,
- PRInt32 ioFlags = -1,
- PRInt32 perm = -1,
- PRBool deleteOnClose = PR_FALSE)
+NS_NewLocalFileInputStream(nsIInputStream** aResult,
+ nsIFile* aFile,
+ PRInt32 aIOFlags = -1,
+ PRInt32 aPerm = -1,
+ PRInt32 aBehaviorFlags = 0)
{
nsresult rv;
nsCOMPtr in;
@@ -186,20 +228,21 @@ NS_NewLocalFileInputStream(nsIInputStream* *result,
NS_GET_IID(nsIFileInputStream),
getter_AddRefs(in));
if (NS_FAILED(rv)) return rv;
- rv = in->Init(file, ioFlags, perm, deleteOnClose);
+ rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
if (NS_FAILED(rv)) return rv;
- *result = in;
- NS_ADDREF(*result);
+ *aResult = in;
+ NS_ADDREF(*aResult);
return NS_OK;
}
// This will QI the file argument to an nsILocalFile in the Init method.
inline nsresult
-NS_NewLocalFileOutputStream(nsIOutputStream* *result,
- nsIFile* file,
- PRInt32 ioFlags = -1,
- PRInt32 perm = -1)
+NS_NewLocalFileOutputStream(nsIOutputStream** aResult,
+ nsIFile* aFile,
+ PRInt32 aIOFlags = -1,
+ PRInt32 aPerm = -1,
+ PRInt32 aBehaviorFlags = 0)
{
nsresult rv;
nsCOMPtr out;
@@ -209,20 +252,20 @@ NS_NewLocalFileOutputStream(nsIOutputStream* *result,
NS_GET_IID(nsIFileOutputStream),
getter_AddRefs(out));
if (NS_FAILED(rv)) return rv;
- rv = out->Init(file, ioFlags, perm);
+ rv = out->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
if (NS_FAILED(rv)) return rv;
- *result = out;
- NS_ADDREF(*result);
+ *aResult = out;
+ NS_ADDREF(*aResult);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
inline nsresult
-NS_NewBufferedInputStream(nsIInputStream* *result,
- nsIInputStream* str,
- PRUint32 bufferSize)
+NS_NewBufferedInputStream(nsIInputStream** aResult,
+ nsIInputStream* aStr,
+ PRUint32 aBufferSize)
{
nsresult rv;
nsCOMPtr in;
@@ -232,18 +275,18 @@ NS_NewBufferedInputStream(nsIInputStream* *result,
NS_GET_IID(nsIBufferedInputStream),
getter_AddRefs(in));
if (NS_FAILED(rv)) return rv;
- rv = in->Init(str, bufferSize);
+ rv = in->Init(aStr, aBufferSize);
if (NS_FAILED(rv)) return rv;
- *result = in;
- NS_ADDREF(*result);
+ *aResult = in;
+ NS_ADDREF(*aResult);
return NS_OK;
}
inline nsresult
-NS_NewBufferedOutputStream(nsIOutputStream* *result,
- nsIOutputStream* str,
- PRUint32 bufferSize)
+NS_NewBufferedOutputStream(nsIOutputStream** aResult,
+ nsIOutputStream* aStr,
+ PRUint32 aBufferSize)
{
nsresult rv;
nsCOMPtr out;
@@ -253,11 +296,11 @@ NS_NewBufferedOutputStream(nsIOutputStream* *result,
NS_GET_IID(nsIBufferedOutputStream),
getter_AddRefs(out));
if (NS_FAILED(rv)) return rv;
- rv = out->Init(str, bufferSize);
+ rv = out->Init(aStr, aBufferSize);
if (NS_FAILED(rv)) return rv;
- *result = out;
- NS_ADDREF(*result);
+ *aResult = out;
+ NS_ADDREF(*aResult);
return NS_OK;
}
diff --git a/mozilla/netwerk/base/src/nsFileStreams.cpp b/mozilla/netwerk/base/src/nsFileStreams.cpp
index ec48f2611b2..4ae1bfda52e 100644
--- a/mozilla/netwerk/base/src/nsFileStreams.cpp
+++ b/mozilla/netwerk/base/src/nsFileStreams.cpp
@@ -533,38 +533,66 @@ nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
return rv;
}
-NS_IMETHODIMP
-nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool deleteOnClose)
+nsresult
+nsFileInputStream::Open(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm)
{
- NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
-
nsresult rv = NS_OK;
- nsCOMPtr localFile = do_QueryInterface(file, &rv);
+
+ // If the previous file is open, close it
+ if (mFD) {
+ rv = Close();
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ // Open the file
+ nsCOMPtr localFile = do_QueryInterface(aFile, &rv);
if (NS_FAILED(rv)) return rv;
- if (ioFlags == -1)
- ioFlags = PR_RDONLY;
- if (perm == -1)
- perm = 0;
+ if (aIOFlags == -1)
+ aIOFlags = PR_RDONLY;
+ if (aPerm == -1)
+ aPerm = 0;
PRFileDesc* fd;
- rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd);
+ rv = localFile->OpenNSPRFileDesc(aIOFlags, aPerm, &fd);
if (NS_FAILED(rv)) return rv;
mFD = fd;
- if (deleteOnClose) {
+ if (mBehaviorFlags & DELETE_ON_CLOSE) {
// POSIX compatible filesystems allow a file to be unlinked while a
// file descriptor is still referencing the file. since we've already
// opened the file descriptor, we'll try to remove the file. if that
// fails, then we'll just remember the nsIFile and remove it after we
// close the file descriptor.
- nsresult rv = file->Remove(PR_FALSE);
- if (NS_FAILED(rv))
- mFileToDelete = file;
+ rv = aFile->Remove(PR_FALSE);
+ if (NS_FAILED(rv) && !(mBehaviorFlags & REOPEN_ON_REWIND)) {
+ // If REOPEN_ON_REWIND is not happenin', we haven't saved the file yet
+ mFile = aFile;
+ }
}
+
return NS_OK;
}
+NS_IMETHODIMP
+nsFileInputStream::Init(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm,
+ PRInt32 aBehaviorFlags)
+{
+ NS_ENSURE_TRUE(!mFD, NS_ERROR_ALREADY_INITIALIZED);
+ NS_ENSURE_TRUE(!mParent, NS_ERROR_ALREADY_INITIALIZED);
+
+ mBehaviorFlags = aBehaviorFlags;
+
+ // If the file will be reopened on rewind, save the info to open the file
+ if (mBehaviorFlags & REOPEN_ON_REWIND) {
+ mFile = aFile;
+ mIOFlags = aIOFlags;
+ mPerm = aPerm;
+ }
+
+ return Open(aFile, aIOFlags, aPerm);
+}
+
NS_IMETHODIMP
nsFileInputStream::Close()
{
@@ -572,70 +600,74 @@ nsFileInputStream::Close()
mLineBuffer = nsnull; // in case Close() is called again after failing
nsresult rv = nsFileStream::Close();
if (NS_FAILED(rv)) return rv;
- if (mFileToDelete) {
- rv = mFileToDelete->Remove(PR_FALSE);
+ if (mFile && (mBehaviorFlags & DELETE_ON_CLOSE)) {
+ rv = mFile->Remove(PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to delete file");
+ // If we don't need to save the file for reopening, free it up
+ if (!(mBehaviorFlags & REOPEN_ON_REWIND)) {
+ mFile = nsnull;
+ }
}
return rv;
}
NS_IMETHODIMP
-nsFileInputStream::Available(PRUint32 *result)
+nsFileInputStream::Available(PRUint32* aResult)
{
- if (mFD == nsnull)
+ if (!mFD) {
return NS_BASE_STREAM_CLOSED;
+ }
PRInt32 avail = PR_Available(mFD);
if (avail == -1) {
return NS_ErrorAccordingToNSPR();
}
- *result = avail;
+ *aResult = avail;
return NS_OK;
}
NS_IMETHODIMP
-nsFileInputStream::Read(char * buf, PRUint32 count, PRUint32 *result)
+nsFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult)
{
- if (mFD == nsnull)
+ if (!mFD) {
return NS_BASE_STREAM_CLOSED;
+ }
- PRInt32 cnt = PR_Read(mFD, buf, count);
- if (cnt == -1) {
+ PRInt32 bytesRead = PR_Read(mFD, aBuf, aCount);
+ if (bytesRead == -1) {
return NS_ErrorAccordingToNSPR();
}
- *result = cnt;
+ // Check if we're at the end of file and need to close
+ if (mBehaviorFlags & CLOSE_ON_EOF) {
+ if (bytesRead == 0) {
+ Close();
+ }
+ }
+
+ *aResult = bytesRead;
return NS_OK;
}
NS_IMETHODIMP
-nsFileInputStream::ReadLine(nsAString & aLine, PRBool *_retval)
+nsFileInputStream::ReadLine(nsAString& aLine, PRBool* aResult)
{
if (!mLineBuffer) {
nsresult rv = NS_InitLineBuffer(&mLineBuffer);
if (NS_FAILED(rv)) return rv;
}
- return NS_ReadLine(this, mLineBuffer, aLine, _retval);
+ return NS_ReadLine(this, mLineBuffer, aLine, aResult);
}
NS_IMETHODIMP
-nsFileInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+nsFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32* aResult)
{
- PRUint32 nBytes;
- char *readBuf = (char *)nsMemory::Alloc(count);
- if (!readBuf)
- return NS_ERROR_OUT_OF_MEMORY;
-
- nsresult rv = Read(readBuf, count, &nBytes);
-
- *_retval = 0;
- if (NS_SUCCEEDED(rv)) {
- rv = writer(this, closure, readBuf, 0, nBytes, _retval);
- NS_ASSERTION(NS_SUCCEEDED(rv) ? nBytes == *_retval : PR_TRUE, "Didn't write all Data.");
- // XXX this assertion is invalid!
- }
-
- nsMemory::Free(readBuf);
- return rv;
+ // ReadSegments is not implemented because it would be inefficient when
+ // the writer does not consume all data. If you want to call ReadSegments,
+ // wrap a BufferedInputStream around the file stream. That will call
+ // Read().
+ NS_NOTREACHED("ReadSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@@ -645,6 +677,23 @@ nsFileInputStream::IsNonBlocking(PRBool *aNonBlocking)
return NS_OK;
}
+NS_IMETHODIMP
+nsFileInputStream::Seek(PRInt32 aWhence, PRInt32 aOffset)
+{
+ if (!mFD) {
+ if (mBehaviorFlags & REOPEN_ON_REWIND) {
+ nsresult rv = Reopen();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ } else {
+ return NS_BASE_STREAM_CLOSED;
+ }
+ }
+
+ return nsFileStream::Seek(aWhence, aOffset);
+}
+
////////////////////////////////////////////////////////////////////////////////
// nsFileOutputStream
@@ -668,7 +717,8 @@ nsFileOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
}
NS_IMETHODIMP
-nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm)
+nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm,
+ PRInt32 behaviorFlags)
{
NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
diff --git a/mozilla/netwerk/base/src/nsFileStreams.h b/mozilla/netwerk/base/src/nsFileStreams.h
index e3425e92c78..efe19ca8a7b 100644
--- a/mozilla/netwerk/base/src/nsFileStreams.h
+++ b/mozilla/netwerk/base/src/nsFileStreams.h
@@ -109,9 +109,13 @@ public:
NS_DECL_NSIFILEINPUTSTREAM
NS_DECL_NSILINEINPUTSTREAM
+ // Overrided from nsFileStream
+ NS_IMETHOD Seek(PRInt32 aWhence, PRInt32 aOffset);
+
nsFileInputStream() : nsFileStream()
{
mLineBuffer = nsnull;
+ mBehaviorFlags = 0;
}
virtual ~nsFileInputStream()
{
@@ -123,7 +127,37 @@ public:
protected:
nsLineBuffer *mLineBuffer;
- nsCOMPtr mFileToDelete;
+
+ /**
+ * The file being opened. Only stored when DELETE_ON_CLOSE or
+ * REOPEN_ON_REWIND are true.
+ */
+ nsCOMPtr mFile;
+ /**
+ * The IO flags passed to Init() for the file open.
+ * Only set for REOPEN_ON_REWIND.
+ */
+ PRInt32 mIOFlags;
+ /**
+ * The permissions passed to Init() for the file open.
+ * Only set for REOPEN_ON_REWIND.
+ */
+ PRInt32 mPerm;
+ /**
+ * Flags describing our behavior. See the IDL file for possible values.
+ */
+ PRInt32 mBehaviorFlags;
+
+protected:
+ /**
+ * Internal, called to open a file. Parameters are the same as their
+ * Init() analogues.
+ */
+ nsresult Open(nsIFile* file, PRInt32 ioFlags, PRInt32 perm);
+ /**
+ * Reopen the file (for OPEN_ON_READ only!)
+ */
+ nsresult Reopen() { return Open(mFile, mIOFlags, mPerm); }
};
////////////////////////////////////////////////////////////////////////////////
diff --git a/mozilla/xpcom/io/nsMultiplexInputStream.cpp b/mozilla/xpcom/io/nsMultiplexInputStream.cpp
index 6efbfc34b8a..9b95d8beb00 100644
--- a/mozilla/xpcom/io/nsMultiplexInputStream.cpp
+++ b/mozilla/xpcom/io/nsMultiplexInputStream.cpp
@@ -240,13 +240,8 @@ nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
while (mCurrentStream < len) {
nsCOMPtr stream(do_QueryElementAt(&mStreams,
mCurrentStream));
- PRUint32 avail, read, count;
- rv = stream->Available(&avail);
- if (NS_FAILED(rv)) return rv;
-
- count = PR_MIN(avail, aCount);
-
- rv = stream->ReadSegments(ReadSegCb, &state, count, &read);
+ PRUint32 read;
+ rv = stream->ReadSegments(ReadSegCb, &state, aCount, &read);
// If we got an NS_BASE_STREAM_WOULD_BLOCK error since the reader
// didn't want any more data. This might not be an error for us if
// data was read from a previous stream in this run
@@ -254,23 +249,32 @@ nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
!read && state.mOffset)
break;
- NS_ENSURE_SUCCESS(rv, rv);
- if (read > count) {
- NS_ERROR("Read more than requested");
- read = count; // truncate and hope for the best...
+ // If the return value is NS_BASE_STREAM_CLOSED, we are done with this
+ // stream.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ continue;
}
+
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ASSERTION(aCount >= read, "Read more than requested");
mStartedReadingCurrent = PR_TRUE;
state.mOffset += read;
- count -= read;
aCount -= read;
if (state.mDone || // writer doesn't want anymore data
- aCount == 0 || // already read total amount requested
- count > 0) // the current stream still has data
+ aCount == 0) // the current stream still has data
break;
- ++mCurrentStream;
- mStartedReadingCurrent = PR_FALSE;
+ // If the writer accepted all data but we didn't read any, this stream
+ // is finished. Go on to the next stream. These aren't the droids
+ // you're looking for.
+ if (read == 0) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ }
}
+
*_retval = state.mOffset;
return NS_OK;
}
@@ -290,7 +294,7 @@ nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
aCount,
aWriteCount);
if (rv == NS_BASE_STREAM_WOULD_BLOCK ||
- (NS_SUCCEEDED(rv) && *aWriteCount == 0 && aCount != 0))
+ (NS_SUCCEEDED(rv) && *aWriteCount < aCount && aCount != 0))
state->mDone = PR_TRUE;
return rv;