зеркало из https://github.com/mozilla/gecko-dev.git
Bug 730765 - Media cache shouldn't be used when loading from blob: urls. r=biesi
This commit is contained in:
Родитель
f2ed1e6d36
Коммит
82b123b5a7
|
@ -42,6 +42,7 @@ nsReferencedElement.h \
|
|||
nsTreeSanitizer.h \
|
||||
nsXMLNameSpaceMap.h \
|
||||
nsIXFormsUtilityService.h \
|
||||
nsBlobProtocolHandler.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/dom mozilla
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef nsBlobProtocolHandler_h
|
||||
#define nsBlobProtocolHandler_h
|
||||
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define BLOBURI_SCHEME "blob"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIPrincipal;
|
||||
class nsIInputStream;
|
||||
|
||||
inline bool IsBlobURI(nsIURI* aUri)
|
||||
{
|
||||
bool isBlob;
|
||||
return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob;
|
||||
}
|
||||
|
||||
extern nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
|
||||
|
||||
class nsBlobProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIProtocolHandler methods:
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
|
||||
// nsBlobProtocolHandler methods:
|
||||
nsBlobProtocolHandler() {}
|
||||
virtual ~nsBlobProtocolHandler() {}
|
||||
|
||||
// Methods for managing uri->file mapping
|
||||
static void AddFileDataEntry(nsACString& aUri,
|
||||
nsIDOMBlob* aFile,
|
||||
nsIPrincipal* aPrincipal);
|
||||
static void RemoveFileDataEntry(nsACString& aUri);
|
||||
static nsIPrincipal* GetFileDataEntryPrincipal(nsACString& aUri);
|
||||
};
|
||||
|
||||
#define NS_BLOBPROTOCOLHANDLER_CID \
|
||||
{ 0xb43964aa, 0xa078, 0x44b2, \
|
||||
{ 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } }
|
||||
|
||||
#endif /* nsBlobProtocolHandler_h */
|
|
@ -163,8 +163,8 @@ nsBlobProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
stream);
|
||||
uri,
|
||||
stream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
|
||||
|
@ -189,3 +189,23 @@ nsBlobProtocolHandler::AllowPort(PRInt32 port, const char *scheme,
|
|||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
|
||||
{
|
||||
NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
|
||||
|
||||
*aStream = nullptr;
|
||||
|
||||
nsCString spec;
|
||||
aURI->GetSpec(spec);
|
||||
|
||||
FileDataInfo* info =
|
||||
GetFileDataInfo(spec);
|
||||
|
||||
if (!info) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
return info->mFile->GetInternalStream(aStream);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,23 @@
|
|||
#define nsBlobProtocolHandler_h
|
||||
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define BLOBURI_SCHEME "blob"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIPrincipal;
|
||||
class nsIInputStream;
|
||||
|
||||
inline bool IsBlobURI(nsIURI* aUri)
|
||||
{
|
||||
bool isBlob;
|
||||
return NS_SUCCEEDED(aUri->SchemeIs(BLOBURI_SCHEME, &isBlob)) && isBlob;
|
||||
}
|
||||
|
||||
extern nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
|
||||
|
||||
class nsBlobProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
|
@ -26,11 +38,10 @@ public:
|
|||
|
||||
// Methods for managing uri->file mapping
|
||||
static void AddFileDataEntry(nsACString& aUri,
|
||||
nsIDOMBlob* aFile,
|
||||
nsIDOMBlob* aFile,
|
||||
nsIPrincipal* aPrincipal);
|
||||
static void RemoveFileDataEntry(nsACString& aUri);
|
||||
static nsIPrincipal* GetFileDataEntryPrincipal(nsACString& aUri);
|
||||
|
||||
};
|
||||
|
||||
#define NS_BLOBPROTOCOLHANDLER_CID \
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/Util.h" // for DebugOnly
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsBlobProtocolHandler.h"
|
||||
|
||||
static const PRUint32 HTTP_OK_CODE = 200;
|
||||
static const PRUint32 HTTP_PARTIAL_RESPONSE_CODE = 206;
|
||||
|
@ -1038,14 +1039,15 @@ nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener)
|
|||
// implements nsISeekableStream, so we have to find the underlying
|
||||
// file and reopen it
|
||||
nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(mChannel));
|
||||
if (!fc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (fc) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = fc->GetFile(getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = fc->GetFile(getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file);
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file);
|
||||
} else if (IsBlobURI(mURI)) {
|
||||
rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput));
|
||||
}
|
||||
} else {
|
||||
// Ensure that we never load a local file from some page on a
|
||||
// web server.
|
||||
|
@ -1201,7 +1203,7 @@ MediaResource*
|
|||
MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"MediaResource::Open called on non-main thread");
|
||||
"MediaResource::Open called on non-main thread");
|
||||
|
||||
// If the channel was redirected, we want the post-redirect URI;
|
||||
// but if the URI scheme was expanded, say from chrome: to jar:file:,
|
||||
|
@ -1211,7 +1213,7 @@ MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)
|
|||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
|
||||
if (fc) {
|
||||
if (fc || IsBlobURI(uri)) {
|
||||
return new FileMediaResource(aDecoder, aChannel, uri);
|
||||
}
|
||||
return new ChannelMediaResource(aDecoder, aChannel, uri);
|
||||
|
|
|
@ -44,9 +44,11 @@ interface nsIFileInputStream : nsIInputStream
|
|||
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.)
|
||||
* If this is set, the file will be reopened whenever we reach the start of
|
||||
* the file, either by doing a Seek(0, NS_SEEK_CUR), or by doing a relative
|
||||
* seek that happen to reach the beginning of the file. 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;
|
||||
|
||||
|
|
|
@ -410,6 +410,14 @@ nsFileInputStream::Init(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm,
|
|||
NS_IMETHODIMP
|
||||
nsFileInputStream::Close()
|
||||
{
|
||||
// Get the cache position at the time the file was close. This allows
|
||||
// NS_SEEK_CUR on a closed file that has been opened with
|
||||
// REOPEN_ON_REWIND.
|
||||
if (mBehaviorFlags & REOPEN_ON_REWIND) {
|
||||
// Get actual position. Not one modified by subclasses
|
||||
nsFileStreamBase::Tell(&mCachedPosition);
|
||||
}
|
||||
|
||||
// null out mLineBuffer in case Close() is called again after failing
|
||||
PR_FREEIF(mLineBuffer);
|
||||
nsresult rv = nsFileStreamBase::Close();
|
||||
|
@ -461,9 +469,15 @@ nsFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
|
|||
PR_FREEIF(mLineBuffer); // this invalidates the line buffer
|
||||
if (!mFD) {
|
||||
if (mBehaviorFlags & REOPEN_ON_REWIND) {
|
||||
nsresult rv = Reopen();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
rv = Open(mFile, mIOFlags, mPerm);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the file was closed, and we do a relative seek, use the
|
||||
// position we cached when we closed the file to seek to the right
|
||||
// location.
|
||||
if (aWhence == NS_SEEK_CUR) {
|
||||
aWhence = NS_SEEK_SET;
|
||||
aOffset += mCachedPosition;
|
||||
}
|
||||
} else {
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
|
@ -473,6 +487,23 @@ nsFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
|
|||
return nsFileStreamBase::Seek(aWhence, aOffset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileInputStream::Tell(PRInt64 *aResult)
|
||||
{
|
||||
return nsFileStreamBase::Tell(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileInputStream::Available(PRUint64 *aResult)
|
||||
{
|
||||
//if (mFD == nullptr && mBehaviorFlags & REOPEN_ON_REWIND) {
|
||||
//*aResult = 0;
|
||||
//return NS_OK;
|
||||
//}
|
||||
|
||||
return nsFileStreamBase::Available(aResult);
|
||||
}
|
||||
|
||||
bool
|
||||
nsFileInputStream::Read(const IPC::Message *aMsg, void **aIter)
|
||||
{
|
||||
|
|
|
@ -114,10 +114,7 @@ public:
|
|||
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
|
||||
|
||||
NS_IMETHOD Close();
|
||||
NS_IMETHOD Available(PRUint64* _retval)
|
||||
{
|
||||
return nsFileStreamBase::Available(_retval);
|
||||
}
|
||||
NS_IMETHOD Available(PRUint64* _retval);
|
||||
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32* _retval);
|
||||
NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
|
||||
PRUint32 aCount, PRUint32* _retval)
|
||||
|
@ -132,14 +129,13 @@ public:
|
|||
|
||||
// Overrided from nsFileStreamBase
|
||||
NS_IMETHOD Seek(PRInt32 aWhence, PRInt64 aOffset);
|
||||
NS_IMETHOD Tell(PRInt64 *aResult);
|
||||
|
||||
nsFileInputStream()
|
||||
: mIOFlags(0), mPerm(0)
|
||||
{
|
||||
mLineBuffer = nullptr;
|
||||
}
|
||||
: mIOFlags(0), mPerm(0), mCachedPosition(0), mLineBuffer(nullptr)
|
||||
{}
|
||||
|
||||
virtual ~nsFileInputStream()
|
||||
virtual ~nsFileInputStream()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
@ -163,16 +159,17 @@ protected:
|
|||
*/
|
||||
PRInt32 mPerm;
|
||||
|
||||
/**
|
||||
* Cached position for Tell for automatically reopening streams.
|
||||
*/
|
||||
PRInt64 mCachedPosition;
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -55,7 +55,7 @@ private:
|
|||
const char* aFromRawSegment, PRUint32 aToOffset,
|
||||
PRUint32 aCount, PRUint32 *aWriteCount);
|
||||
|
||||
nsCOMArray<nsIInputStream> mStreams;
|
||||
nsTArray<nsCOMPtr<nsIInputStream> > mStreams;
|
||||
PRUint32 mCurrentStream;
|
||||
bool mStartedReadingCurrent;
|
||||
nsresult mStatus;
|
||||
|
@ -89,7 +89,7 @@ nsMultiplexInputStream::nsMultiplexInputStream()
|
|||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetCount(PRUint32 *aCount)
|
||||
{
|
||||
*aCount = mStreams.Count();
|
||||
*aCount = mStreams.Length();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -97,14 +97,14 @@ nsMultiplexInputStream::GetCount(PRUint32 *aCount)
|
|||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
|
||||
{
|
||||
return mStreams.AppendObject(aStream) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
return mStreams.AppendElement(aStream) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* void insertStream (in nsIInputStream stream, in unsigned long index); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
|
||||
{
|
||||
bool result = mStreams.InsertObjectAt(aStream, aIndex);
|
||||
bool result = mStreams.InsertElementAt(aIndex, aStream);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (mCurrentStream > aIndex ||
|
||||
(mCurrentStream == aIndex && mStartedReadingCurrent))
|
||||
|
@ -116,8 +116,7 @@ nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
|
|||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
|
||||
{
|
||||
bool result = mStreams.RemoveObjectAt(aIndex);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_NOT_AVAILABLE);
|
||||
mStreams.RemoveElementAt(aIndex);
|
||||
if (mCurrentStream > aIndex)
|
||||
--mCurrentStream;
|
||||
else if (mCurrentStream == aIndex)
|
||||
|
@ -130,7 +129,7 @@ nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
|
|||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
|
||||
{
|
||||
*_retval = mStreams.SafeObjectAt(aIndex);
|
||||
*_retval = mStreams.SafeElementAt(aIndex, nullptr);
|
||||
NS_ENSURE_TRUE(*_retval, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
NS_ADDREF(*_retval);
|
||||
|
@ -145,7 +144,7 @@ nsMultiplexInputStream::Close()
|
|||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 len = mStreams.Count();
|
||||
PRUint32 len = mStreams.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
nsresult rv2 = mStreams[i]->Close();
|
||||
// We still want to close all streams, but we should return an error
|
||||
|
@ -165,7 +164,7 @@ nsMultiplexInputStream::Available(PRUint64 *_retval)
|
|||
nsresult rv;
|
||||
PRUint64 avail = 0;
|
||||
|
||||
PRUint32 len = mStreams.Count();
|
||||
PRUint32 len = mStreams.Length();
|
||||
for (PRUint32 i = mCurrentStream; i < len; i++) {
|
||||
PRUint64 streamAvail;
|
||||
rv = mStreams[i]->Available(&streamAvail);
|
||||
|
@ -193,7 +192,7 @@ nsMultiplexInputStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
|
|||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 len = mStreams.Count();
|
||||
PRUint32 len = mStreams.Length();
|
||||
while (mCurrentStream < len && aCount) {
|
||||
PRUint32 read;
|
||||
rv = mStreams[mCurrentStream]->Read(aBuf, aCount, &read);
|
||||
|
@ -247,7 +246,7 @@ nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
|
|||
state.mClosure = aClosure;
|
||||
state.mDone = false;
|
||||
|
||||
PRUint32 len = mStreams.Count();
|
||||
PRUint32 len = mStreams.Length();
|
||||
while (mCurrentStream < len && aCount) {
|
||||
PRUint32 read;
|
||||
rv = mStreams[mCurrentStream]->ReadSegments(ReadSegCb, &state, aCount, &read);
|
||||
|
@ -305,7 +304,7 @@ nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
|
|||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::IsNonBlocking(bool *aNonBlocking)
|
||||
{
|
||||
PRUint32 len = mStreams.Count();
|
||||
PRUint32 len = mStreams.Length();
|
||||
if (len == 0) {
|
||||
// Claim to be non-blocking, since we won't block the caller.
|
||||
// On the other hand we'll never return NS_BASE_STREAM_WOULD_BLOCK,
|
||||
|
@ -335,20 +334,208 @@ nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// rewinding to start is easy, and should be the most common case
|
||||
if (aWhence == NS_SEEK_SET && aOffset == 0)
|
||||
{
|
||||
PRUint32 i, last;
|
||||
last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
|
||||
for (i = 0; i < last; ++i) {
|
||||
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]);
|
||||
NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
|
||||
PRUint32 oldCurrentStream = mCurrentStream;
|
||||
bool oldStartedReadingCurrent = mStartedReadingCurrent;
|
||||
|
||||
rv = stream->Seek(NS_SEEK_SET, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aWhence == NS_SEEK_SET) {
|
||||
PRInt64 remaining = aOffset;
|
||||
if (aOffset == 0) {
|
||||
mCurrentStream = 0;
|
||||
}
|
||||
mCurrentStream = 0;
|
||||
mStartedReadingCurrent = false;
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
nsCOMPtr<nsISeekableStream> stream =
|
||||
do_QueryInterface(mStreams[i]);
|
||||
if (!stream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// See if all remaining streams should be rewound
|
||||
if (remaining == 0) {
|
||||
if (i < oldCurrentStream ||
|
||||
(i == oldCurrentStream && oldStartedReadingCurrent)) {
|
||||
rv = stream->Seek(NS_SEEK_SET, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get position in current stream
|
||||
PRInt64 streamPos;
|
||||
if (i > oldCurrentStream ||
|
||||
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
|
||||
streamPos = 0;
|
||||
}
|
||||
else {
|
||||
rv = stream->Tell(&streamPos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// See if we need to seek current stream forward or backward
|
||||
if (remaining < streamPos) {
|
||||
rv = stream->Seek(NS_SEEK_SET, remaining);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = remaining != 0;
|
||||
|
||||
remaining = 0;
|
||||
}
|
||||
else if (remaining > streamPos) {
|
||||
if (i < oldCurrentStream) {
|
||||
// We're already at end so no need to seek this stream
|
||||
remaining -= streamPos;
|
||||
}
|
||||
else {
|
||||
PRUint64 avail;
|
||||
rv = mStreams[i]->Available(&avail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 newPos = streamPos +
|
||||
NS_MIN((PRInt64)avail, remaining);
|
||||
|
||||
rv = stream->Seek(NS_SEEK_SET, newPos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = true;
|
||||
|
||||
remaining -= newPos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(remaining == streamPos, "Huh?");
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aWhence == NS_SEEK_CUR && aOffset > 0) {
|
||||
PRInt64 remaining = aOffset;
|
||||
for (PRUint32 i = mCurrentStream; remaining && i < mStreams.Length(); ++i) {
|
||||
nsCOMPtr<nsISeekableStream> stream =
|
||||
do_QueryInterface(mStreams[i]);
|
||||
|
||||
PRUint64 avail;
|
||||
rv = mStreams[i]->Available(&avail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 seek = NS_MIN((PRInt64)avail, remaining);
|
||||
|
||||
rv = stream->Seek(NS_SEEK_CUR, seek);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = true;
|
||||
|
||||
remaining -= seek;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aWhence == NS_SEEK_CUR && aOffset < 0) {
|
||||
PRInt64 remaining = -aOffset;
|
||||
for (PRUint32 i = mCurrentStream; remaining && i != (PRUint32)-1; --i) {
|
||||
nsCOMPtr<nsISeekableStream> stream =
|
||||
do_QueryInterface(mStreams[i]);
|
||||
|
||||
PRInt64 pos;
|
||||
rv = stream->Tell(&pos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 seek = NS_MIN(pos, remaining);
|
||||
|
||||
rv = stream->Seek(NS_SEEK_CUR, -seek);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = seek != -pos;
|
||||
|
||||
remaining -= seek;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aWhence == NS_SEEK_CUR) {
|
||||
NS_ASSERTION(aOffset == 0, "Should have handled all non-zero values");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aWhence == NS_SEEK_END) {
|
||||
if (aOffset > 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
PRInt64 remaining = aOffset;
|
||||
for (PRUint32 i = mStreams.Length() - 1; i != (PRUint32)-1; --i) {
|
||||
nsCOMPtr<nsISeekableStream> stream =
|
||||
do_QueryInterface(mStreams[i]);
|
||||
|
||||
// See if all remaining streams should be seeked to end
|
||||
if (remaining == 0) {
|
||||
if (i >= oldCurrentStream) {
|
||||
rv = stream->Seek(NS_SEEK_END, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get position in current stream
|
||||
PRInt64 streamPos;
|
||||
if (i < oldCurrentStream) {
|
||||
streamPos = 0;
|
||||
} else {
|
||||
PRUint64 avail;
|
||||
rv = mStreams[i]->Available(&avail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
streamPos = avail;
|
||||
}
|
||||
|
||||
// See if we have enough data in the current stream.
|
||||
if (NS_ABS(remaining) < streamPos) {
|
||||
rv = stream->Seek(NS_SEEK_END, remaining);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = true;
|
||||
|
||||
remaining = 0;
|
||||
} else if (NS_ABS(remaining) > streamPos) {
|
||||
if (i > oldCurrentStream ||
|
||||
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
|
||||
// We're already at start so no need to seek this stream
|
||||
remaining += streamPos;
|
||||
} else {
|
||||
PRInt64 avail;
|
||||
rv = stream->Tell(&avail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 newPos = streamPos + NS_MIN(avail, NS_ABS(remaining));
|
||||
|
||||
rv = stream->Seek(NS_SEEK_END, -newPos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentStream = i;
|
||||
mStartedReadingCurrent = true;
|
||||
|
||||
remaining += newPos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(remaining == streamPos, "Huh?");
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -442,11 +629,11 @@ nsMultiplexInputStream::Write(IPC::Message *aMsg)
|
|||
{
|
||||
using IPC::WriteParam;
|
||||
|
||||
PRUint32 count = mStreams.Count();
|
||||
PRUint32 count = mStreams.Length();
|
||||
WriteParam(aMsg, count);
|
||||
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
IPC::InputStream inputStream(mStreams.ObjectAt(i));
|
||||
IPC::InputStream inputStream(mStreams[i]);
|
||||
WriteParam(aMsg, inputStream);
|
||||
}
|
||||
|
||||
|
@ -460,7 +647,7 @@ nsMultiplexInputStream::Serialize(InputStreamParams& aParams)
|
|||
{
|
||||
MultiplexInputStreamParams params;
|
||||
|
||||
PRUint32 streamCount = mStreams.Count();
|
||||
PRUint32 streamCount = mStreams.Length();
|
||||
|
||||
if (streamCount) {
|
||||
InfallibleTArray<InputStreamParams>& streams = params.streams();
|
||||
|
@ -468,7 +655,7 @@ nsMultiplexInputStream::Serialize(InputStreamParams& aParams)
|
|||
streams.SetCapacity(streamCount);
|
||||
for (PRUint32 index = 0; index < streamCount; index++) {
|
||||
nsCOMPtr<nsIIPCSerializableInputStream> serializable =
|
||||
do_QueryInterface(mStreams.ObjectAt(index));
|
||||
do_QueryInterface(mStreams[index]);
|
||||
NS_ASSERTION(serializable, "Child stream isn't serializable!");
|
||||
|
||||
if (serializable) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче