Backed out changeset 5583ccdfea18
authorChris Double <chris.double@double.co.nz>
Thu, 23 Aug 2012 22:42:14 +1200
changeset 105197 68fc1a8f97d0acbe604c68147c0a20cff1e4a68d
parent 104961 5583ccdfea183a42da2c6fe071ab8352f53f8d79
child 105202 89f96727117692db346acc8faf498f749ec6b4d9
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
milestone17.0a1
backs out5583ccdfea183a42da2c6fe071ab8352f53f8d79
Backed out changeset 5583ccdfea18
content/base/public/Makefile.in
content/base/public/nsBlobProtocolHandler.h
content/base/src/nsBlobProtocolHandler.cpp
content/base/src/nsBlobProtocolHandler.h
content/media/MediaResource.cpp
netwerk/base/public/nsIFileStreams.idl
netwerk/base/src/nsFileStreams.cpp
netwerk/base/src/nsFileStreams.h
xpcom/io/nsMultiplexInputStream.cpp
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -37,17 +37,16 @@ nsContentCID.h \
 nsCopySupport.h \
 nsContentCreatorFunctions.h \
 nsDOMFile.h \
 nsLineBreaker.h \
 nsReferencedElement.h \
 nsTreeSanitizer.h \
 nsXMLNameSpaceMap.h \
 nsIXFormsUtilityService.h \
-nsBlobProtocolHandler.h \
 $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom mozilla
 
 EXPORTS_mozilla/dom = \
 		DirectionalityUtils.h \
 		Element.h \
 		FragmentOrElement.h \
deleted file mode 100644
--- a/content/base/public/nsBlobProtocolHandler.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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 */
--- a/content/base/src/nsBlobProtocolHandler.cpp
+++ b/content/base/src/nsBlobProtocolHandler.cpp
@@ -158,18 +158,18 @@ nsBlobProtocolHandler::NewChannel(nsIURI
 #endif
 
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = info->mFile->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   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);
 
   nsAutoString type;
   rv = info->mFile->GetType(type);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -184,28 +184,8 @@ nsBlobProtocolHandler::NewChannel(nsIURI
 NS_IMETHODIMP 
 nsBlobProtocolHandler::AllowPort(PRInt32 port, const char *scheme,
                                      bool *_retval)
 {
     // don't override anything.  
     *_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);
-}
--- a/content/base/src/nsBlobProtocolHandler.h
+++ b/content/base/src/nsBlobProtocolHandler.h
@@ -1,51 +1,40 @@
 /* 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,
+			       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 */
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -23,17 +23,16 @@
 #include "nsCrossSiteListenerProxy.h"
 #include "nsHTMLMediaElement.h"
 #include "nsError.h"
 #include "nsICachingChannel.h"
 #include "nsURILoader.h"
 #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;
 
 using namespace mozilla;
 
 ChannelMediaResource::ChannelMediaResource(nsMediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI)
@@ -1034,25 +1033,24 @@ nsresult FileMediaResource::Open(nsIStre
   }
 
   nsresult rv = NS_OK;
   if (aStreamListener) {
     // The channel is already open. We need a synchronous stream that
     // implements nsISeekableStream, so we have to find the underlying
     // file and reopen it
     nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(mChannel));
-    if (fc) {
-      nsCOMPtr<nsIFile> file;
-      rv = fc->GetFile(getter_AddRefs(file));
-      NS_ENSURE_SUCCESS(rv, rv);
+    if (!fc)
+      return NS_ERROR_UNEXPECTED;
 
-      rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file);
-    } else if (IsBlobURI(mURI)) {
-      rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput));
-    }
+    nsCOMPtr<nsIFile> file;
+    rv = fc->GetFile(getter_AddRefs(file));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file);
   } else {
     // Ensure that we never load a local file from some page on a
     // web server.
     nsHTMLMediaElement* element = mDecoder->GetMediaElement();
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
 
     rv = nsContentUtils::GetSecurityManager()->
            CheckLoadURIWithPrincipal(element->NodePrincipal(),
@@ -1198,27 +1196,27 @@ PRInt64 FileMediaResource::Tell()
   mSeekable->Tell(&offset);
   return offset;
 }
 
 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:,
   // we want the original URI.
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
-  if (fc || IsBlobURI(uri)) {
+  if (fc) {
     return new FileMediaResource(aDecoder, aChannel, uri);
   }
   return new ChannelMediaResource(aDecoder, aChannel, uri);
 }
 
 void MediaResource::MoveLoadsToBackground() {
   NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?");
   mLoadInBackground = true;
--- a/netwerk/base/public/nsIFileStreams.idl
+++ b/netwerk/base/public/nsIFileStreams.idl
@@ -39,21 +39,19 @@ interface nsIFileInputStream : nsIInputS
 
     /**
      * 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 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.)
+     * 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;
 
     /**
      * If this is set, the file will be opened (i.e., a call to
      * PR_Open done) only when we do an actual operation on the stream,
      * or more specifically, when one of the following is called:
      *   - Seek
--- a/netwerk/base/src/nsFileStreams.cpp
+++ b/netwerk/base/src/nsFileStreams.cpp
@@ -405,24 +405,16 @@ nsFileInputStream::Init(nsIFile* aFile, 
     mPerm = aPerm;
 
     return Open(aFile, aIOFlags, 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();
     if (NS_FAILED(rv)) return rv;
     if (mFile && (mBehaviorFlags & DELETE_ON_CLOSE)) {
         rv = mFile->Remove(false);
         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to delete file");
         // If we don't need to save the file for reopening, free it up
@@ -464,51 +456,28 @@ NS_IMETHODIMP
 nsFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
 {
     nsresult rv = DoPendingOpen();
     NS_ENSURE_SUCCESS(rv, rv);
 
     PR_FREEIF(mLineBuffer); // this invalidates the line buffer
     if (!mFD) {
         if (mBehaviorFlags & REOPEN_ON_REWIND) {
-            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;
+            nsresult rv = Reopen();
+            if (NS_FAILED(rv)) {
+                return rv;
             }
         } else {
             return NS_BASE_STREAM_CLOSED;
         }
     }
 
     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)
 {
     using IPC::ReadParam;
 
     nsCString path;
     bool followLinks;
     PRInt32 flags;
--- a/netwerk/base/src/nsFileStreams.h
+++ b/netwerk/base/src/nsFileStreams.h
@@ -109,38 +109,42 @@ class nsFileInputStream : public nsFileS
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIFILEINPUTSTREAM
     NS_DECL_NSILINEINPUTSTREAM
     NS_DECL_NSIIPCSERIALIZABLEOBSOLETE
     NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
 
     NS_IMETHOD Close();
-    NS_IMETHOD Available(PRUint64* _retval);
+    NS_IMETHOD Available(PRUint64* _retval)
+    {
+        return nsFileStreamBase::Available(_retval);
+    }
     NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32* _retval);
     NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
                             PRUint32 aCount, PRUint32* _retval)
     {
         return nsFileStreamBase::ReadSegments(aWriter, aClosure, aCount,
                                               _retval);
     }
     NS_IMETHOD IsNonBlocking(bool* _retval)
     {
         return nsFileStreamBase::IsNonBlocking(_retval);
     } 
     
     // Overrided from nsFileStreamBase
     NS_IMETHOD Seek(PRInt32 aWhence, PRInt64 aOffset);
-    NS_IMETHOD Tell(PRInt64 *aResult);
 
     nsFileInputStream()
-      : mIOFlags(0), mPerm(0), mCachedPosition(0), mLineBuffer(nullptr)
-    {}
+      : mIOFlags(0), mPerm(0)
+    {
+        mLineBuffer = nullptr;
+    }
 
-    virtual ~nsFileInputStream()
+    virtual ~nsFileInputStream() 
     {
         Close();
     }
 
     static nsresult
     Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
 protected:
@@ -154,27 +158,26 @@ protected:
      * The IO flags passed to Init() for the file open.
      */
     PRInt32 mIOFlags;
     /**
      * The permissions passed to Init() for the file open.
      */
     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); }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
 class nsPartialFileInputStream : public nsFileInputStream,
                                  public nsIPartialFileInputStream
 {
 public:
--- a/xpcom/io/nsMultiplexInputStream.cpp
+++ b/xpcom/io/nsMultiplexInputStream.cpp
@@ -50,17 +50,17 @@ private:
         void* mClosure;
         bool mDone;
     };
 
     static NS_METHOD ReadSegCb(nsIInputStream* aIn, void* aClosure,
                                const char* aFromRawSegment, PRUint32 aToOffset,
                                PRUint32 aCount, PRUint32 *aWriteCount);
     
-    nsTArray<nsCOMPtr<nsIInputStream> > mStreams;
+    nsCOMArray<nsIInputStream> mStreams;
     PRUint32 mCurrentStream;
     bool mStartedReadingCurrent;
     nsresult mStatus;
 };
 
 NS_IMPL_THREADSAFE_ADDREF(nsMultiplexInputStream)
 NS_IMPL_THREADSAFE_RELEASE(nsMultiplexInputStream)
 
@@ -84,72 +84,73 @@ nsMultiplexInputStream::nsMultiplexInput
       mStatus(NS_OK)
 {
 }
 
 /* readonly attribute unsigned long count; */
 NS_IMETHODIMP
 nsMultiplexInputStream::GetCount(PRUint32 *aCount)
 {
-    *aCount = mStreams.Length();
+    *aCount = mStreams.Count();
     return NS_OK;
 }
 
 /* void appendStream (in nsIInputStream stream); */
 NS_IMETHODIMP
 nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
 {
-    return mStreams.AppendElement(aStream) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+    return mStreams.AppendObject(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.InsertElementAt(aIndex, aStream);
+    bool result = mStreams.InsertObjectAt(aStream, aIndex);
     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
     if (mCurrentStream > aIndex ||
         (mCurrentStream == aIndex && mStartedReadingCurrent))
         ++mCurrentStream;
     return NS_OK;
 }
 
 /* void removeStream (in unsigned long index); */
 NS_IMETHODIMP
 nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
 {
-    mStreams.RemoveElementAt(aIndex);
+    bool result = mStreams.RemoveObjectAt(aIndex);
+    NS_ENSURE_TRUE(result, NS_ERROR_NOT_AVAILABLE);
     if (mCurrentStream > aIndex)
         --mCurrentStream;
     else if (mCurrentStream == aIndex)
         mStartedReadingCurrent = false;
 
     return NS_OK;
 }
 
 /* nsIInputStream getStream (in unsigned long index); */
 NS_IMETHODIMP
 nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
 {
-    *_retval = mStreams.SafeElementAt(aIndex, nullptr);
+    *_retval = mStreams.SafeObjectAt(aIndex);
     NS_ENSURE_TRUE(*_retval, NS_ERROR_NOT_AVAILABLE);
 
     NS_ADDREF(*_retval);
     return NS_OK;
 }
 
 /* void close (); */
 NS_IMETHODIMP
 nsMultiplexInputStream::Close()
 {
     mStatus = NS_BASE_STREAM_CLOSED;
 
     nsresult rv = NS_OK;
 
-    PRUint32 len = mStreams.Length();
+    PRUint32 len = mStreams.Count();
     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
         if (NS_FAILED(rv2))
             rv = rv2;
     }
     return rv;
 }
@@ -159,17 +160,17 @@ NS_IMETHODIMP
 nsMultiplexInputStream::Available(PRUint64 *_retval)
 {
     if (NS_FAILED(mStatus))
         return mStatus;
 
     nsresult rv;
     PRUint64 avail = 0;
 
-    PRUint32 len = mStreams.Length();
+    PRUint32 len = mStreams.Count();
     for (PRUint32 i = mCurrentStream; i < len; i++) {
         PRUint64 streamAvail;
         rv = mStreams[i]->Available(&streamAvail);
         NS_ENSURE_SUCCESS(rv, rv);
         avail += streamAvail;
     }
     *_retval = avail;
     return NS_OK;
@@ -187,17 +188,17 @@ nsMultiplexInputStream::Read(char * aBuf
 
     if (mStatus == NS_BASE_STREAM_CLOSED)
         return NS_OK;
     if (NS_FAILED(mStatus))
         return mStatus;
  
     nsresult rv = NS_OK;
 
-    PRUint32 len = mStreams.Length();
+    PRUint32 len = mStreams.Count();
     while (mCurrentStream < len && aCount) {
         PRUint32 read;
         rv = mStreams[mCurrentStream]->Read(aBuf, aCount, &read);
 
         // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
         // (This is a bug in those stream implementations)
         if (rv == NS_BASE_STREAM_CLOSED) {
             NS_NOTREACHED("Input stream's Read method returned NS_BASE_STREAM_CLOSED");
@@ -241,17 +242,17 @@ nsMultiplexInputStream::ReadSegments(nsW
     nsresult rv = NS_OK;
     ReadSegmentsState state;
     state.mThisStream = this;
     state.mOffset = 0;
     state.mWriter = aWriter;
     state.mClosure = aClosure;
     state.mDone = false;
     
-    PRUint32 len = mStreams.Length();
+    PRUint32 len = mStreams.Count();
     while (mCurrentStream < len && aCount) {
         PRUint32 read;
         rv = mStreams[mCurrentStream]->ReadSegments(ReadSegCb, &state, aCount, &read);
 
         // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
         // (This is a bug in those stream implementations)
         if (rv == NS_BASE_STREAM_CLOSED) {
             NS_NOTREACHED("Input stream's Read method returned NS_BASE_STREAM_CLOSED");
@@ -299,17 +300,17 @@ nsMultiplexInputStream::ReadSegCb(nsIInp
         state->mDone = true;
     return rv;
 }
 
 /* readonly attribute boolean nonBlocking; */
 NS_IMETHODIMP
 nsMultiplexInputStream::IsNonBlocking(bool *aNonBlocking)
 {
-    PRUint32 len = mStreams.Length();
+    PRUint32 len = mStreams.Count();
     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,
         // so maybe we should claim to be blocking?  It probably doesn't
         // matter in practice.
         *aNonBlocking = true;
         return NS_OK;
     }
@@ -329,218 +330,30 @@ nsMultiplexInputStream::IsNonBlocking(bo
 NS_IMETHODIMP
 nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
 {
     if (NS_FAILED(mStatus))
         return mStatus;
 
     nsresult rv;
 
-    PRUint32 oldCurrentStream = mCurrentStream;
-    bool oldStartedReadingCurrent = mStartedReadingCurrent;
-
-    if (aWhence == NS_SEEK_SET) {
-        PRInt64 remaining = aOffset;
-        if (aOffset == 0) {
-            mCurrentStream = 0;
-        }
-        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;
-        }
+    // 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);
 
-        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);
+            rv = stream->Seek(NS_SEEK_SET, 0);
             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;
-            }
-        }
-
+        mCurrentStream = 0;
+        mStartedReadingCurrent = false;
         return NS_OK;
     }
 
     // other Seeks not implemented yet
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* PRUint32 tell (); */
@@ -624,43 +437,43 @@ nsMultiplexInputStream::Read(const IPC::
     return true;
 }
 
 void
 nsMultiplexInputStream::Write(IPC::Message *aMsg)
 {
     using IPC::WriteParam;
 
-    PRUint32 count = mStreams.Length();
+    PRUint32 count = mStreams.Count();
     WriteParam(aMsg, count);
 
     for (PRUint32 i = 0; i < count; i++) {
-        IPC::InputStream inputStream(mStreams[i]);
+        IPC::InputStream inputStream(mStreams.ObjectAt(i));
         WriteParam(aMsg, inputStream);
     }
 
     WriteParam(aMsg, mCurrentStream);
     WriteParam(aMsg, mStartedReadingCurrent);
     WriteParam(aMsg, mStatus);
 }
 
 void
 nsMultiplexInputStream::Serialize(InputStreamParams& aParams)
 {
     MultiplexInputStreamParams params;
 
-    PRUint32 streamCount = mStreams.Length();
+    PRUint32 streamCount = mStreams.Count();
 
     if (streamCount) {
         InfallibleTArray<InputStreamParams>& streams = params.streams();
 
         streams.SetCapacity(streamCount);
         for (PRUint32 index = 0; index < streamCount; index++) {
             nsCOMPtr<nsIIPCSerializableInputStream> serializable =
-                do_QueryInterface(mStreams[index]);
+                do_QueryInterface(mStreams.ObjectAt(index));
             NS_ASSERTION(serializable, "Child stream isn't serializable!");
 
             if (serializable) {
                 InputStreamParams childStreamParams;
                 serializable->Serialize(childStreamParams);
 
                 NS_ASSERTION(childStreamParams.type() !=
                                  InputStreamParams::T__None,