Bug 832419 - 'Clean up IPC blobs'. r=sicking.
authorBen Turner <bent.mozilla@gmail.com>
Thu, 17 Jan 2013 12:17:33 -0800
changeset 130780 88c2a0a35a65800e24341cc1f6b99a12e7569974
parent 130779 47c28fd47df9d66dc72351095a7379f6597b2e40
child 130781 36e03cf9cb413b2a92f2f9cf4368d90ae26a3dda
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs832419
milestone21.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
Bug 832419 - 'Clean up IPC blobs'. r=sicking.
content/base/public/nsDOMFile.h
content/base/src/nsDOMBlobBuilder.cpp
content/base/src/nsDOMBlobBuilder.h
dom/ipc/Blob.cpp
dom/ipc/Blob.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/DOMTypes.ipdlh
dom/ipc/PBlob.ipdl
dom/ipc/PContent.ipdl
dom/ipc/nsIRemoteBlob.h
dom/workers/File.cpp
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -43,18 +43,16 @@ public:
 
   virtual already_AddRefed<nsIDOMBlob>
   CreateSlice(uint64_t aStart, uint64_t aLength,
               const nsAString& aContentType) = 0;
 
   virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
   GetSubBlobs() const { return nullptr; }
 
-  virtual bool IsMemoryBacked() const { return false; }
-
   NS_DECL_NSIDOMBLOB
   NS_DECL_NSIDOMFILE
   NS_DECL_NSIXHRSENDABLE
   NS_DECL_NSIMUTABLE
 
   void
   SetLazyData(const nsAString& aName, const nsAString& aContentType,
               uint64_t aLength, uint64_t aLastModifiedDate)
@@ -347,19 +345,18 @@ protected:
 
 class nsDOMMemoryFile : public nsDOMFile
 {
 public:
   // Create as file
   nsDOMMemoryFile(void *aMemoryBuffer,
                   uint64_t aLength,
                   const nsAString& aName,
-                  const nsAString& aContentType,
-                  uint64_t aModDate = UINT64_MAX)
-    : nsDOMFile(aName, aContentType, aLength, aModDate),
+                  const nsAString& aContentType)
+    : nsDOMFile(aName, aContentType, aLength, UINT64_MAX),
       mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   // Create as blob
   nsDOMMemoryFile(void *aMemoryBuffer,
                   uint64_t aLength,
@@ -367,20 +364,16 @@ public:
     : nsDOMFile(aContentType, aLength),
       mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
-  virtual bool IsMemoryBacked() const { return true; }
-  void* GetData() const { return mDataOwner->mData; }
-  uint64_t GetLength() const { return mDataOwner->mLength; }
-
 protected:
   // Create slice
   nsDOMMemoryFile(const nsDOMMemoryFile* aOther, uint64_t aStart,
                   uint64_t aLength, const nsAString& aContentType)
     : nsDOMFile(aContentType, aOther->mStart + aStart, aLength),
       mDataOwner(aOther->mDataOwner)
   {
     NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -141,25 +141,25 @@ nsDOMMultipartFile::CreateSlice(uint64_t
   nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartFile(blobs, aContentType);
   return blob.forget();
 }
 
 /* static */ nsresult
 nsDOMMultipartFile::NewFile(const nsAString& aName, nsISupports* *aNewObject)
 {
   nsCOMPtr<nsISupports> file =
-    do_QueryObject(new nsDOMMultipartFile(aName, EmptyString()));
+    do_QueryObject(new nsDOMMultipartFile(aName));
   file.forget(aNewObject);
   return NS_OK;
 }
 
 /* static */ nsresult
 nsDOMMultipartFile::NewBlob(nsISupports* *aNewObject)
 {
-  nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMMultipartFile(EmptyString()));
+  nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMMultipartFile());
   file.forget(aNewObject);
   return NS_OK;
 }
 
 static nsIDOMBlob*
 GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
   nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
     nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -12,42 +12,41 @@
 #include "mozilla/Attributes.h"
 #include <algorithm>
 
 class nsDOMMultipartFile : public nsDOMFile,
                            public nsIJSNativeInitializer
 {
 public:
   // Create as a file
-  nsDOMMultipartFile(nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
+  nsDOMMultipartFile(nsTArray<nsCOMPtr<nsIDOMBlob> > aBlobs,
                      const nsAString& aName,
                      const nsAString& aContentType)
     : nsDOMFile(aName, aContentType, UINT64_MAX),
       mBlobs(aBlobs)
   {
   }
 
   // Create as a blob
   nsDOMMultipartFile(nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
                      const nsAString& aContentType)
     : nsDOMFile(aContentType, UINT64_MAX),
       mBlobs(aBlobs)
   {
   }
 
   // Create as a file to be later initialized
-  nsDOMMultipartFile(const nsAString& aName,
-                     const nsAString& aContentType)
-    : nsDOMFile(aName, aContentType, UINT64_MAX)
+  nsDOMMultipartFile(const nsAString& aName)
+    : nsDOMFile(aName, EmptyString(), UINT64_MAX)
   {
   }
 
   // Create as a blob to be later initialized
-  nsDOMMultipartFile(const nsAString& aContentType)
-    : nsDOMFile(aContentType, UINT64_MAX)
+  nsDOMMultipartFile()
+    : nsDOMFile(EmptyString(), UINT64_MAX)
   {
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner,
                         JSContext* aCx,
@@ -85,22 +84,16 @@ public:
     // Initialization will set the filename, so we can pass in an empty string
     // for now.
     return NewFile(EmptyString(), aNewObject);
   }
 
   virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
   GetSubBlobs() const { return &mBlobs; }
 
-  void
-  AddBlob(nsIDOMBlob* aBlob)
-  {
-    mBlobs.AppendElement(aBlob);
-  }
-
 protected:
   nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
 };
 
 class BlobSet {
 public:
   BlobSet()
     : mData(nullptr), mDataLen(0), mDataBufferLen(0)
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -16,17 +16,16 @@
 #include "nsIIPCSerializableInputStream.h"
 #include "nsIRemoteBlob.h"
 #include "nsISeekableStream.h"
 
 #include "mozilla/Monitor.h"
 #include "mozilla/unused.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "nsDOMFile.h"
-#include "nsDOMBlobBuilder.h"
 #include "nsThreadUtils.h"
 
 #include "ContentChild.h"
 #include "ContentParent.h"
 
 #define PRIVATE_REMOTE_INPUT_STREAM_IID \
   {0x30c7699f, 0x51d2, 0x48c8, {0xad, 0x56, 0xc0, 0x16, 0xd7, 0x6f, 0x71, 0x27}}
 
@@ -626,61 +625,42 @@ BlobTraits<Parent>::BaseType::NoteRunnab
       return;
     }
   }
 
   MOZ_NOT_REACHED("Runnable not in our array!");
 }
 
 template <ActorFlavorEnum ActorFlavor>
-class RemoteBlobBase : public nsIRemoteBlob
+struct RemoteBlobBase;
+
+template <>
+struct RemoteBlobBase<Parent>
+{
+  InputStreamParams mInputStreamParams;
+};
+
+template <>
+struct RemoteBlobBase<Child>
+{ };
+
+template <ActorFlavorEnum ActorFlavor>
+class RemoteBlob : public RemoteBlobBase<ActorFlavor>,
+                   public nsDOMFile,
+                   public nsIRemoteBlob
 {
 public:
   typedef RemoteBlob<ActorFlavor> SelfType;
   typedef Blob<ActorFlavor> ActorType;
   typedef InputStreamActor<ActorFlavor> StreamActorType;
-
-  void
-  SetPBlob(void* aActor) MOZ_OVERRIDE
-  {
-    MOZ_ASSERT(!aActor || !mActor);
-    mActor = static_cast<ActorType*>(aActor);
-  }
-
-  virtual void*
-  GetPBlob() MOZ_OVERRIDE
-  {
-    return static_cast<typename ActorType::ProtocolType*>(mActor);
-  }
+  typedef typename ActorType::ConstructorParamsType ConstructorParamsType;
 
 private:
   ActorType* mActor;
 
-protected:
-  RemoteBlobBase()
-  : mActor(nullptr)
-  { }
-
-  virtual
-  ~RemoteBlobBase()
-  {
-    if (mActor) {
-      mActor->NoteDyingRemoteBlob();
-    }
-  }
-
-  ActorType* Actor() const { return mActor; }
-};
-
-template <ActorFlavorEnum ActorFlavor>
-class RemoteBlob : public nsDOMFile,
-                   public RemoteBlobBase<ActorFlavor>
-{
-  typedef Blob<ActorFlavor> ActorType;
-public:
   class StreamHelper : public nsRunnable
   {
     typedef Blob<ActorFlavor> ActorType;
     typedef InputStreamActor<ActorFlavor> StreamActorType;
 
     mozilla::Monitor mMonitor;
     ActorType* mActor;
     nsCOMPtr<nsIDOMBlob> mSourceBlob;
@@ -787,17 +767,16 @@ public:
 
   public:
     SliceHelper(ActorType* aActor)
     : mMonitor("RemoteBlob::SliceHelper::mMonitor"), mActor(aActor), mStart(0),
       mLength(0), mDone(false)
     {
       // This may be created on any thread.
       MOZ_ASSERT(aActor);
-      MOZ_ASSERT(aActor->HasManager());
     }
 
     nsresult
     GetSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
              nsIDOMBlob** aSlice)
     {
       // This may be called on any thread.
       MOZ_ASSERT(aSlice);
@@ -854,30 +833,33 @@ public:
       MOZ_ASSERT(mActor);
       MOZ_ASSERT(!mSlice);
       MOZ_ASSERT(!mDone);
 
       NormalBlobConstructorParams normalParams;
       normalParams.contentType() = mContentType;
       normalParams.length() = mLength;
 
-      BlobConstructorNoMultipartParams params(normalParams);
+      typename ActorType::ConstructorParamsType params;
+      ActorType::BaseType::SetBlobConstructorParams(params, normalParams);
 
       ActorType* newActor = ActorType::Create(params);
       MOZ_ASSERT(newActor);
-      mActor->PropagateManager(newActor);
 
       SlicedBlobConstructorParams slicedParams;
       slicedParams.contentType() = mContentType;
       slicedParams.begin() = mStart;
       slicedParams.end() = mStart + mLength;
       SetBlobOnParams(mActor, slicedParams);
 
-      BlobConstructorNoMultipartParams params2(slicedParams);
-      if (mActor->ConstructPBlobOnManager(newActor, params2)) {
+      typename ActorType::OtherSideConstructorParamsType otherSideParams;
+      ActorType::BaseType::SetBlobConstructorParams(otherSideParams,
+                                                    slicedParams);
+
+      if (mActor->Manager()->SendPBlobConstructor(newActor, otherSideParams)) {
         mSlice = newActor->GetBlob();
       }
 
       mActor = nullptr;
 
       if (aNotify) {
         MonitorAutoLock lock(mMonitor);
         mDone = true;
@@ -889,156 +871,76 @@ public:
     }
   };
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   RemoteBlob(const nsAString& aName, const nsAString& aContentType,
              uint64_t aLength, uint64_t aModDate)
-  : nsDOMFile(aName, aContentType, aLength, aModDate)
-  {
-    mImmutable = true;
-  }
-
-  RemoteBlob(const nsAString& aName, const nsAString& aContentType,
-             uint64_t aLength)
-  : nsDOMFile(aName, aContentType, aLength)
+  : nsDOMFile(aName, aContentType, aLength, aModDate), mActor(nullptr)
   {
     mImmutable = true;
   }
 
   RemoteBlob(const nsAString& aContentType, uint64_t aLength)
-  : nsDOMFile(aContentType, aLength)
+  : nsDOMFile(aContentType, aLength), mActor(nullptr)
   {
     mImmutable = true;
   }
 
   RemoteBlob()
   : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
+  , mActor(nullptr)
   {
     mImmutable = true;
   }
 
+  virtual ~RemoteBlob()
+  {
+    if (mActor) {
+      mActor->NoteDyingRemoteBlob();
+    }
+  }
+
+  void
+  SetActor(ActorType* aActor)
+  {
+    MOZ_ASSERT(!aActor || !mActor);
+    mActor = aActor;
+  }
+
+  void
+  MaybeSetInputStream(const ConstructorParamsType& aParams);
+
   virtual already_AddRefed<nsIDOMBlob>
   CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType)
               MOZ_OVERRIDE
   {
-    ActorType* actor = RemoteBlobBase<ActorFlavor>::Actor();
-    if (!actor) {
+    if (!mActor) {
       return nullptr;
     }
 
-    nsRefPtr<SliceHelper> helper = new SliceHelper(actor);
+    nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
 
     nsCOMPtr<nsIDOMBlob> slice;
     nsresult rv =
       helper->GetSlice(aStart, aLength, aContentType, getter_AddRefs(slice));
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return slice.forget();
   }
 
   NS_IMETHOD
-  GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE
-  {
-    ActorType* actor = RemoteBlobBase<ActorFlavor>::Actor();
-    if (!actor) {
-      return NS_ERROR_UNEXPECTED;
-    }
-
-    nsRefPtr<StreamHelper> helper = new StreamHelper(actor, this);
-    return helper->GetStream(aStream);
-  }
-
-  NS_IMETHOD
-  GetLastModifiedDate(JSContext* cx, JS::Value* aLastModifiedDate)
-  {
-    if (IsDateUnknown()) {
-      aLastModifiedDate->setNull();
-    } else {
-      JSObject* date = JS_NewDateObjectMsec(cx, mLastModificationDate);
-      if (!date) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-      aLastModifiedDate->setObject(*date);
-    }
-    return NS_OK;
-  }
-};
-
-template <ActorFlavorEnum ActorFlavor>
-class RemoteMemoryBlob : public nsDOMMemoryFile,
-                         public RemoteBlobBase<ActorFlavor>
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  RemoteMemoryBlob(void* aMemoryBuffer,
-                   uint64_t aLength,
-                   const nsAString& aName,
-                   const nsAString& aContentType,
-                   uint64_t aModDate)
-  : nsDOMMemoryFile(aMemoryBuffer, aLength, aName, aContentType, aModDate)
-  {
-    mImmutable = true;
-  }
+  GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
 
-  RemoteMemoryBlob(void* aMemoryBuffer,
-                   uint64_t aLength,
-                   const nsAString& aName,
-                   const nsAString& aContentType)
-  : nsDOMMemoryFile(aMemoryBuffer, aLength, aName, aContentType)
-  {
-    mImmutable = true;
-  }
-
-  RemoteMemoryBlob(void* aMemoryBuffer,
-                   uint64_t aLength,
-                   const nsAString& aContentType)
-  : nsDOMMemoryFile(aMemoryBuffer, aLength, EmptyString(), aContentType)
-  {
-    mImmutable = true;
-  }
-
-  NS_IMETHOD
-  GetLastModifiedDate(JSContext* cx, JS::Value* aLastModifiedDate)
+  virtual void*
+  GetPBlob() MOZ_OVERRIDE
   {
-    if (IsDateUnknown()) {
-      aLastModifiedDate->setNull();
-    } else {
-      JSObject* date = JS_NewDateObjectMsec(cx, mLastModificationDate);
-      if (!date) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-      aLastModifiedDate->setObject(*date);
-    }
-    return NS_OK;
-  }
-};
-
-template <ActorFlavorEnum ActorFlavor>
-class RemoteMultipartBlob : public nsDOMMultipartFile,
-                            public RemoteBlobBase<ActorFlavor>
-{
-
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  RemoteMultipartBlob(const nsAString& aName,
-                      const nsAString& aContentType)
-  : nsDOMMultipartFile(aName, aContentType)
-  {
-    mImmutable = true;
-  }
-
-  RemoteMultipartBlob(const nsAString& aName)
-  : nsDOMMultipartFile(aName)
-  {
-    mImmutable = true;
+    return static_cast<typename ActorType::ProtocolType*>(mActor);
   }
 
   NS_IMETHOD
   GetLastModifiedDate(JSContext* cx, JS::Value* aLastModifiedDate)
   {
     if (IsDateUnknown()) {
       aLastModifiedDate->setNull();
     } else {
@@ -1047,255 +949,138 @@ public:
         return NS_ERROR_OUT_OF_MEMORY;
       }
       aLastModifiedDate->setObject(*date);
     }
     return NS_OK;
   }
 };
 
+template <>
+void
+RemoteBlob<Parent>::MaybeSetInputStream(const ConstructorParamsType& aParams)
+{
+  if (aParams.optionalInputStreamParams().type() ==
+      OptionalInputStreamParams::TInputStreamParams) {
+    mInputStreamParams =
+      aParams.optionalInputStreamParams().get_InputStreamParams();
+  }
+  else {
+    MOZ_ASSERT(aParams.blobParams().type() ==
+               ChildBlobConstructorParams::TMysteryBlobConstructorParams);
+  }
+}
+
+template <>
+void
+RemoteBlob<Child>::MaybeSetInputStream(const ConstructorParamsType& aParams)
+{
+  // Nothing needed on the child side!
+}
+
+template <>
+NS_IMETHODIMP
+RemoteBlob<Parent>::GetInternalStream(nsIInputStream** aStream)
+{
+  if (mInputStreamParams.type() != InputStreamParams::T__None) {
+    nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(mInputStreamParams);
+    if (!stream) {
+      NS_WARNING("Failed to deserialize stream!");
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    stream.forget(aStream);
+    return NS_OK;
+  }
+
+  if (!mActor) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
+  return helper->GetStream(aStream);
+}
+
+template <>
+NS_IMETHODIMP
+RemoteBlob<Child>::GetInternalStream(nsIInputStream** aStream)
+{
+  if (!mActor) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
+  return helper->GetStream(aStream);
+}
+
 template <ActorFlavorEnum ActorFlavor>
 Blob<ActorFlavor>::Blob(nsIDOMBlob* aBlob)
-: mBlob(aBlob), mRemoteBlob(nullptr), mRemoteMemoryBlob(nullptr),
-  mRemoteMultipartBlob(nullptr), mContentManager(nullptr),
-  mBlobManager(nullptr), mOwnsBlob(true), mBlobIsFile(false)
+: mBlob(aBlob), mRemoteBlob(nullptr), mOwnsBlob(true), mBlobIsFile(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aBlob);
   aBlob->AddRef();
 
   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
   mBlobIsFile = !!file;
 }
 
 template <ActorFlavorEnum ActorFlavor>
-Blob<ActorFlavor>::Blob(nsRefPtr<RemoteBlobType>& aBlob,
-                        bool aBlobIsFile)
-: mBlob(nullptr), mRemoteBlob(nullptr), mRemoteMemoryBlob(nullptr),
-  mRemoteMultipartBlob(nullptr), mContentManager(nullptr),
-  mBlobManager(nullptr), mOwnsBlob(true), mBlobIsFile(aBlobIsFile)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mBlob);
-  MOZ_ASSERT(!mRemoteBlob);
-  MOZ_ASSERT(aBlob);
-
-  if (NS_FAILED(aBlob->SetMutable(false))) {
-    MOZ_NOT_REACHED("Failed to make remote blob immutable!");
-  }
-
-  aBlob->SetPBlob(this);
-  aBlob.forget(&mRemoteBlob);
-
-  mBlob = mRemoteBlob;
-}
-
-template <ActorFlavorEnum ActorFlavor>
-Blob<ActorFlavor>::Blob(nsRefPtr<RemoteMemoryBlobType>& aBlob,
-                        bool aBlobIsFile)
-: mBlob(nullptr), mRemoteBlob(nullptr), mRemoteMemoryBlob(nullptr),
-  mRemoteMultipartBlob(nullptr), mContentManager(nullptr),
-  mBlobManager(nullptr), mOwnsBlob(true), mBlobIsFile(aBlobIsFile)
+Blob<ActorFlavor>::Blob(const ConstructorParamsType& aParams)
+: mBlob(nullptr), mRemoteBlob(nullptr), mOwnsBlob(false), mBlobIsFile(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mBlob);
-  MOZ_ASSERT(!mRemoteMemoryBlob);
-  MOZ_ASSERT(aBlob);
+
+  ChildBlobConstructorParams::Type paramType =
+    BaseType::GetBlobConstructorParams(aParams).type();
 
-  if (NS_FAILED(aBlob->SetMutable(false))) {
-    MOZ_NOT_REACHED("Failed to make remote blob immutable!");
-  }
-
-  aBlob->SetPBlob(this);
-  aBlob.forget(&mRemoteMemoryBlob);
-
-  mBlob = mRemoteMemoryBlob;
-}
+  mBlobIsFile =
+    paramType == ChildBlobConstructorParams::TFileBlobConstructorParams ||
+    paramType == ChildBlobConstructorParams::TMysteryBlobConstructorParams;
 
-template <ActorFlavorEnum ActorFlavor>
-Blob<ActorFlavor>::Blob(nsRefPtr<RemoteMultipartBlobType>& aBlob,
-                        bool aBlobIsFile)
-: mBlob(nullptr), mRemoteBlob(nullptr), mRemoteMemoryBlob(nullptr),
-  mRemoteMultipartBlob(nullptr), mContentManager(nullptr),
-  mBlobManager(nullptr), mOwnsBlob(true), mBlobIsFile(aBlobIsFile)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mBlob);
-  MOZ_ASSERT(!mRemoteMultipartBlob);
-  MOZ_ASSERT(aBlob);
+  nsRefPtr<RemoteBlobType> remoteBlob = CreateRemoteBlob(aParams);
+  MOZ_ASSERT(remoteBlob);
 
-  if (NS_FAILED(aBlob->SetMutable(false))) {
-    MOZ_NOT_REACHED("Failed to make remote blob immutable!");
-  }
+  remoteBlob->SetActor(this);
+  remoteBlob->MaybeSetInputStream(aParams);
+  remoteBlob.forget(&mRemoteBlob);
 
-  aBlob->SetPBlob(this);
-  aBlob.forget(&mRemoteMultipartBlob);
-
-  mBlob = mRemoteMultipartBlob;
+  mBlob = mRemoteBlob;
+  mOwnsBlob = true;
 }
 
 template <ActorFlavorEnum ActorFlavor>
 Blob<ActorFlavor>*
-Blob<ActorFlavor>::Create(const BlobConstructorParams& aParams)
+Blob<ActorFlavor>::Create(const ConstructorParamsType& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  switch (aParams.type()) {
-    case BlobConstructorParams::TBlobConstructorNoMultipartParams: {
-      const BlobConstructorNoMultipartParams& params =
-        aParams.get_BlobConstructorNoMultipartParams();
-
-      switch (params.type()) {
-        case BlobConstructorNoMultipartParams::TBlobOrFileConstructorParams: {
-          const BlobOrFileConstructorParams& fileParams =
-            params.get_BlobOrFileConstructorParams();
-          nsRefPtr<RemoteBlobType> remoteBlob;
-          bool isFile = false;
-
-          switch (fileParams.type()) {
-            case BlobOrFileConstructorParams::TNormalBlobConstructorParams: {
-              const NormalBlobConstructorParams& normalParams =
-                fileParams.get_NormalBlobConstructorParams();
-              remoteBlob = new RemoteBlobType(normalParams.contentType(),
-                                              normalParams.length());
-              break;
-            }
-
-            case BlobOrFileConstructorParams::TFileBlobConstructorParams: {
-              const FileBlobConstructorParams& fbParams =
-                fileParams.get_FileBlobConstructorParams();
-              remoteBlob =
-                new RemoteBlobType(fbParams.name(), fbParams.contentType(),
-                                   fbParams.length(), fbParams.modDate());
-              isFile = true;
-              break;
-            }
-
-            default:
-              MOZ_NOT_REACHED("Unknown params!");
-          }
+  const ChildBlobConstructorParams& blobParams =
+    BaseType::GetBlobConstructorParams(aParams);
 
-          return new Blob<ActorFlavor>(remoteBlob, isFile);
-        }
-        case BlobConstructorNoMultipartParams::TMemoryBlobOrFileConstructorParams: {
-          const MemoryBlobOrFileConstructorParams& memoryParams =
-            params.get_MemoryBlobOrFileConstructorParams();
-          const BlobOrFileConstructorParams& internalParams =
-            memoryParams.constructorParams();
-          nsRefPtr<RemoteMemoryBlobType> remoteMemoryBlob;
-          bool isFile = false;
-
-          switch (internalParams.type()) {
-            case BlobOrFileConstructorParams::TNormalBlobConstructorParams: {
-              const NormalBlobConstructorParams& normalParams =
-                internalParams.get_NormalBlobConstructorParams();
-              MOZ_ASSERT(normalParams.length() == memoryParams.data().Length());
-
-              void* data =
-                BlobTraits<ActorFlavor>::Allocate(memoryParams.data().Length());
-              if (!data) {
-                return nullptr;
-              }
-              memcpy(data,
-                     memoryParams.data().Elements(),
-                     memoryParams.data().Length());
-              remoteMemoryBlob =
-                new RemoteMemoryBlobType(data,
-                                         memoryParams.data().Length(),
-                                         normalParams.contentType());
-              break;
-            }
-
-            case BlobOrFileConstructorParams::TFileBlobConstructorParams: {
-              const FileBlobConstructorParams& fbParams =
-                internalParams.get_FileBlobConstructorParams();
-              MOZ_ASSERT(fbParams.length() == memoryParams.data().Length());
+  switch (blobParams.type()) {
+    case ChildBlobConstructorParams::TNormalBlobConstructorParams:
+    case ChildBlobConstructorParams::TFileBlobConstructorParams:
+    case ChildBlobConstructorParams::TMysteryBlobConstructorParams:
+      return new Blob<ActorFlavor>(aParams);
 
-              void* data =
-                BlobTraits<ActorFlavor>::Allocate(memoryParams.data().Length());
-              if (!data) {
-                return nullptr;
-              }
-              memcpy(data,
-                     memoryParams.data().Elements(),
-                     memoryParams.data().Length());
-              remoteMemoryBlob =
-                new RemoteMemoryBlobType(data,
-                                         memoryParams.data().Length(),
-                                         fbParams.name(),
-                                         fbParams.contentType(),
-                                         fbParams.modDate());
-              isFile = true;
-              break;
-            }
+    case ChildBlobConstructorParams::TSlicedBlobConstructorParams: {
+      const SlicedBlobConstructorParams& params =
+        blobParams.get_SlicedBlobConstructorParams();
 
-            default:
-              MOZ_NOT_REACHED("Unknown params!");
-          }
-
-          return new Blob<ActorFlavor>(remoteMemoryBlob, isFile);
-        }
-        case BlobConstructorNoMultipartParams::TMysteryBlobConstructorParams: {
-          nsRefPtr<RemoteBlobType> remoteBlob = new RemoteBlobType();
-          return new Blob<ActorFlavor>(remoteBlob, true);
-        }
-
-        case BlobConstructorNoMultipartParams::TSlicedBlobConstructorParams: {
-          const SlicedBlobConstructorParams& slicedParams =
-            params.get_SlicedBlobConstructorParams();
-
-          nsCOMPtr<nsIDOMBlob> source =
-            GetBlobFromParams<ActorFlavor>(slicedParams);
-          MOZ_ASSERT(source);
+      nsCOMPtr<nsIDOMBlob> source = GetBlobFromParams<ActorFlavor>(params);
+      MOZ_ASSERT(source);
 
-          nsCOMPtr<nsIDOMBlob> slice;
-          nsresult rv =
-            source->Slice(slicedParams.begin(), slicedParams.end(),
-                          slicedParams.contentType(), 3,
-                          getter_AddRefs(slice));
-          NS_ENSURE_SUCCESS(rv, nullptr);
-
-          return new Blob<ActorFlavor>(slice);
-        }
-
-        default:
-          MOZ_NOT_REACHED("Unknown params!");
-      }
-    }
-
-    case BlobConstructorParams::TMultipartBlobOrFileConstructorParams: {
-      const MultipartBlobOrFileConstructorParams& params =
-        aParams.get_MultipartBlobOrFileConstructorParams();
+      nsCOMPtr<nsIDOMBlob> slice;
+      nsresult rv =
+        source->Slice(params.begin(), params.end(), params.contentType(), 3,
+                      getter_AddRefs(slice));
+      NS_ENSURE_SUCCESS(rv, nullptr);
 
-      nsRefPtr<RemoteMultipartBlobType> file;
-      bool isFile = false;
-      const BlobOrFileConstructorParams& internalParams =
-        params.constructorParams();
-      switch (internalParams.type()) {
-        case BlobOrFileConstructorParams::TNormalBlobConstructorParams: {
-          const NormalBlobConstructorParams& normalParams =
-            internalParams.get_NormalBlobConstructorParams();
-          file = new RemoteMultipartBlobType(normalParams.contentType());
-          break;
-        }
-
-        case BlobOrFileConstructorParams::TFileBlobConstructorParams: {
-          const FileBlobConstructorParams& fbParams =
-            internalParams.get_FileBlobConstructorParams();
-          file = new RemoteMultipartBlobType(fbParams.name(),
-                                             fbParams.contentType());
-          isFile = true;
-          break;
-        }
-
-        default:
-          MOZ_NOT_REACHED("Unknown params!");
-      }
-
-      return new Blob<ActorFlavor>(file, isFile);
+      return new Blob<ActorFlavor>(slice);
     }
 
     default:
       MOZ_NOT_REACHED("Unknown params!");
   }
 
   return nullptr;
 }
@@ -1307,18 +1092,17 @@ Blob<ActorFlavor>::GetBlob()
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
 
   nsCOMPtr<nsIDOMBlob> blob;
 
   // Remote blobs are held alive until the first call to GetBlob. Thereafter we
   // only hold a weak reference. Normal blobs are held alive until the actor is
   // destroyed.
-  if (mOwnsBlob &&
-      (mRemoteBlob || mRemoteMemoryBlob || mRemoteMultipartBlob)) {
+  if (mRemoteBlob && mOwnsBlob) {
     blob = dont_AddRef(mBlob);
     mOwnsBlob = false;
   }
   else {
     blob = mBlob;
   }
 
   MOZ_ASSERT(blob);
@@ -1363,71 +1147,67 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(co
   ToConcreteBlob(mBlob)->SetLazyData(voidString, aContentType,
                                      aLength, UINT64_MAX);
 
   NormalBlobConstructorParams params(aContentType, aLength);
   return ProtocolType::SendResolveMystery(params);
 }
 
 template <ActorFlavorEnum ActorFlavor>
-typename Blob<ActorFlavor>::ProtocolType*
-Blob<ActorFlavor>::ConstructPBlobOnManager(ProtocolType* aActor,
-                                           const BlobConstructorParams& aParams)
+already_AddRefed<typename Blob<ActorFlavor>::RemoteBlobType>
+Blob<ActorFlavor>::CreateRemoteBlob(const ConstructorParamsType& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(HasManager());
+
+  const ChildBlobConstructorParams& blobParams =
+    BaseType::GetBlobConstructorParams(aParams);
+
+  nsRefPtr<RemoteBlobType> remoteBlob;
+
+  switch (blobParams.type()) {
+    case ChildBlobConstructorParams::TNormalBlobConstructorParams: {
+      const NormalBlobConstructorParams& params =
+        blobParams.get_NormalBlobConstructorParams();
+      remoteBlob = new RemoteBlobType(params.contentType(), params.length());
+      break;
+    }
 
-  if (mContentManager) {
-    return mContentManager->SendPBlobConstructor(aActor, aParams);
-  }
+    case ChildBlobConstructorParams::TFileBlobConstructorParams: {
+      const FileBlobConstructorParams& params =
+        blobParams.get_FileBlobConstructorParams();
+      remoteBlob =
+        new RemoteBlobType(params.name(), params.contentType(),
+                           params.length(), params.modDate());
+      break;
+    }
 
-  if (mBlobManager) {
-    return mBlobManager->SendPBlobConstructor(aActor, aParams);
+    case ChildBlobConstructorParams::TMysteryBlobConstructorParams: {
+      remoteBlob = new RemoteBlobType();
+      break;
+    }
+
+    default:
+      MOZ_NOT_REACHED("Unknown params!");
   }
 
-  MOZ_NOT_REACHED("Why don't I have a manager?!");
-  return nullptr;
-}
-
-template <ActorFlavorEnum ActorFlavor>
-void
-Blob<ActorFlavor>::SetManager(ContentManagerType* aManager)
-{
-  MOZ_ASSERT(!mContentManager && !mBlobManager);
-  MOZ_ASSERT(aManager);
-
-  mContentManager = aManager;
-}
+  MOZ_ASSERT(remoteBlob);
 
-template <ActorFlavorEnum ActorFlavor>
-void
-Blob<ActorFlavor>::SetManager(BlobManagerType* aManager)
-{
-  MOZ_ASSERT(!mContentManager && !mBlobManager);
-  MOZ_ASSERT(aManager);
+  if (NS_FAILED(remoteBlob->SetMutable(false))) {
+    MOZ_NOT_REACHED("Failed to make remote blob immutable!");
+  }
 
-  mBlobManager = aManager;
-}
-
-template <ActorFlavorEnum ActorFlavor>
-void
-Blob<ActorFlavor>::PropagateManager(Blob<ActorFlavor>* aActor) const
-{
-  MOZ_ASSERT(HasManager());
-
-  aActor->mContentManager = mContentManager;
-  aActor->mBlobManager = mBlobManager;
+  return remoteBlob.forget();
 }
 
 template <ActorFlavorEnum ActorFlavor>
 void
 Blob<ActorFlavor>::NoteDyingRemoteBlob()
 {
   MOZ_ASSERT(mBlob);
-  MOZ_ASSERT(mRemoteBlob || mRemoteMemoryBlob || mRemoteMultipartBlob);
+  MOZ_ASSERT(mRemoteBlob);
   MOZ_ASSERT(!mOwnsBlob);
 
   // This may be called on any thread due to the fact that RemoteBlob is
   // designed to be passed between threads. We must start the shutdown process
   // on the main thread, so we proxy here if necessary.
   if (!NS_IsMainThread()) {
     nsCOMPtr<nsIRunnable> runnable =
       NS_NewNonOwningRunnableMethod(this,
@@ -1437,55 +1217,43 @@ Blob<ActorFlavor>::NoteDyingRemoteBlob()
     }
 
     return;
   }
 
   // Must do this before calling Send__delete__ or we'll crash there trying to
   // access a dangling pointer.
   mRemoteBlob = nullptr;
-  mRemoteMemoryBlob = nullptr;
-  mRemoteMultipartBlob = nullptr;
 
   mozilla::unused << ProtocolType::Send__delete__(this);
 }
 
 template <ActorFlavorEnum ActorFlavor>
 void
 Blob<ActorFlavor>::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
 
   if (mRemoteBlob) {
-    mRemoteBlob->SetPBlob(nullptr);
-  }
-
-  if (mRemoteMemoryBlob) {
-    mRemoteMemoryBlob->SetPBlob(nullptr);
-  }
-
-  if (mRemoteMultipartBlob) {
-    mRemoteMultipartBlob->SetPBlob(nullptr);
+    mRemoteBlob->SetActor(nullptr);
   }
 
   if (mOwnsBlob) {
     mBlob->Release();
   }
 }
 
 template <ActorFlavorEnum ActorFlavor>
 bool
 Blob<ActorFlavor>::RecvResolveMystery(const ResolveMysteryParams& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
   MOZ_ASSERT(!mRemoteBlob);
-  MOZ_ASSERT(!mRemoteMemoryBlob);
-  MOZ_ASSERT(!mRemoteMultipartBlob);
   MOZ_ASSERT(mOwnsBlob);
 
   if (!mBlobIsFile) {
     MOZ_ASSERT(false, "Must always be a file!");
     return false;
   }
 
   nsDOMFileBase* blob = ToConcreteBlob(mBlob);
@@ -1518,18 +1286,16 @@ Blob<ActorFlavor>::RecvResolveMystery(co
 
 template <>
 bool
 Blob<Parent>::RecvPBlobStreamConstructor(StreamType* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
   MOZ_ASSERT(!mRemoteBlob);
-  MOZ_ASSERT(!mRemoteMemoryBlob);
-  MOZ_ASSERT(!mRemoteMultipartBlob);
 
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<nsIIPCSerializableInputStream> serializableStream;
 
   nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(mBlob);
@@ -1575,18 +1341,16 @@ Blob<Parent>::RecvPBlobStreamConstructor
 
 template <>
 bool
 Blob<Child>::RecvPBlobStreamConstructor(StreamType* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
   MOZ_ASSERT(!mRemoteBlob);
-  MOZ_ASSERT(!mRemoteMemoryBlob);
-  MOZ_ASSERT(!mRemoteMultipartBlob);
 
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<nsIIPCSerializableInputStream> serializable =
     do_QueryInterface(stream);
   if (!serializable) {
@@ -1598,35 +1362,16 @@ Blob<Child>::RecvPBlobStreamConstructor(
   serializable->Serialize(params);
 
   MOZ_ASSERT(params.type() != InputStreamParams::T__None);
 
   return aActor->Send__delete__(aActor, params);
 }
 
 template <ActorFlavorEnum ActorFlavor>
-bool
-Blob<ActorFlavor>::RecvPBlobConstructor(ProtocolType* aActor,
-                                        const BlobConstructorParams& aParams)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  Blob<ActorFlavor>* subBlobActor = static_cast<Blob<ActorFlavor>*>(aActor);
-
-  if (!subBlobActor->ManagerIs(this)) {
-    // Somebody screwed up!
-    return false;
-  }
-
-  nsCOMPtr<nsIDOMBlob> blob = subBlobActor->GetBlob();
-  static_cast<nsDOMMultipartFile*>(mBlob)->AddBlob(blob);
-  return true;
-}
-
-template <ActorFlavorEnum ActorFlavor>
 typename Blob<ActorFlavor>::StreamType*
 Blob<ActorFlavor>::AllocPBlobStream()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return new InputStreamActor<ActorFlavor>();
 }
 
 template <ActorFlavorEnum ActorFlavor>
@@ -1634,61 +1379,24 @@ bool
 Blob<ActorFlavor>::DeallocPBlobStream(StreamType* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
   delete aActor;
   return true;
 }
 
 template <ActorFlavorEnum ActorFlavor>
-typename Blob<ActorFlavor>::ProtocolType*
-Blob<ActorFlavor>::AllocPBlob(const BlobConstructorParams& aParams)
-{
-  Blob<ActorFlavor>* actor = Blob<ActorFlavor>::Create(aParams);
-  actor->SetManager(this);
-  return actor;
-}
-
-template <ActorFlavorEnum ActorFlavor>
-bool
-Blob<ActorFlavor>::DeallocPBlob(ProtocolType* aActor)
-{
-  delete aActor;
-  return true;
-}
-
-template <ActorFlavorEnum ActorFlavor>
 NS_IMPL_ADDREF_INHERITED(RemoteBlob<ActorFlavor>, nsDOMFile)
 
 template <ActorFlavorEnum ActorFlavor>
 NS_IMPL_RELEASE_INHERITED(RemoteBlob<ActorFlavor>, nsDOMFile)
 
 template <ActorFlavorEnum ActorFlavor>
 NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteBlob<ActorFlavor>, nsDOMFile,
                                                             nsIRemoteBlob)
 
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_ADDREF_INHERITED(RemoteMemoryBlob<ActorFlavor>, nsDOMMemoryFile)
-
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_RELEASE_INHERITED(RemoteMemoryBlob<ActorFlavor>, nsDOMMemoryFile)
-
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteMemoryBlob<ActorFlavor>, nsDOMMemoryFile,
-                                                                  nsIRemoteBlob)
-
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_ADDREF_INHERITED(RemoteMultipartBlob<ActorFlavor>, nsDOMMultipartFile)
-
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_RELEASE_INHERITED(RemoteMultipartBlob<ActorFlavor>, nsDOMMultipartFile)
-
-template <ActorFlavorEnum ActorFlavor>
-NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteMultipartBlob<ActorFlavor>, nsDOMMultipartFile,
-                                                                     nsIRemoteBlob)
-
 // Explicit instantiation of both classes.
 template class Blob<Parent>;
 template class Blob<Child>;
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/Blob.h
+++ b/dom/ipc/Blob.h
@@ -33,229 +33,204 @@ namespace ipc {
 
 enum ActorFlavorEnum
 {
   Parent = 0,
   Child
 };
 
 template <ActorFlavorEnum>
-struct BlobTraits
-{ };
+struct BlobTraits;
 
 template <>
 struct BlobTraits<Parent>
 {
   typedef mozilla::dom::PBlobParent ProtocolType;
   typedef mozilla::dom::PBlobStreamParent StreamType;
-  typedef mozilla::dom::PContentParent ContentManagerType;
+  typedef mozilla::dom::ParentBlobConstructorParams ConstructorParamsType;
+  typedef mozilla::dom::ChildBlobConstructorParams
+          OtherSideConstructorParamsType;
   typedef mozilla::dom::ContentParent ConcreteContentManagerType;
-  typedef ProtocolType BlobManagerType;
 
   // BaseType on the parent side is a bit more complicated than for the child
   // side. In the case of nsIInputStreams backed by files we need to ensure that
   // the files are actually opened and closed on a background thread before we
   // can send their file handles across to the child. The child process could
   // crash during this process so we need to make sure we cancel the intended
   // response in such a case. We do that by holding an array of
   // nsRevocableEventPtr. If the child crashes then this actor will be destroyed
   // and the nsRevocableEventPtr destructor will cancel any stream events that
   // are currently in flight.
   class BaseType : public ProtocolType
   {
+  public:
+    static const ChildBlobConstructorParams&
+    GetBlobConstructorParams(const ConstructorParamsType& aParams)
+    {
+      return aParams.blobParams();
+    }
+
+    static void
+    SetBlobConstructorParams(ConstructorParamsType& aParams,
+                             const ChildBlobConstructorParams& aBlobParams)
+    {
+      aParams.blobParams() = aBlobParams;
+      aParams.optionalInputStreamParams() = mozilla::void_t();
+    }
+
+    static void
+    SetBlobConstructorParams(OtherSideConstructorParamsType& aParams,
+                             const ChildBlobConstructorParams& aBlobParams)
+    {
+      aParams = aBlobParams;
+    }
+
   protected:
     BaseType();
     virtual ~BaseType();
 
     class OpenStreamRunnable;
     friend class OpenStreamRunnable;
 
     void
     NoteRunnableCompleted(OpenStreamRunnable* aRunnable);
 
     nsTArray<nsRevocableEventPtr<OpenStreamRunnable> > mOpenStreamRunnables;
   };
-
-  static void*
-  Allocate(size_t aSize)
-  {
-    // We want fallible allocation in the parent.
-    return moz_malloc(aSize);
-  }
 };
 
 template <>
 struct BlobTraits<Child>
 {
   typedef mozilla::dom::PBlobChild ProtocolType;
   typedef mozilla::dom::PBlobStreamChild StreamType;
-  typedef mozilla::dom::PContentChild ContentManagerType;
+  typedef mozilla::dom::ChildBlobConstructorParams ConstructorParamsType;
+  typedef mozilla::dom::ParentBlobConstructorParams
+          OtherSideConstructorParamsType;
   typedef mozilla::dom::ContentChild ConcreteContentManagerType;
-  typedef ProtocolType BlobManagerType;
+
 
   class BaseType : public ProtocolType
   {
+  public:
+    static const ChildBlobConstructorParams&
+    GetBlobConstructorParams(const ConstructorParamsType& aParams)
+    {
+      return aParams;
+    }
+
+    static void
+    SetBlobConstructorParams(ConstructorParamsType& aParams,
+                             const ChildBlobConstructorParams& aBlobParams)
+    {
+      aParams = aBlobParams;
+    }
+
+    static void
+    SetBlobConstructorParams(OtherSideConstructorParamsType& aParams,
+                             const ChildBlobConstructorParams& aBlobParams)
+    {
+      aParams.blobParams() = aBlobParams;
+      aParams.optionalInputStreamParams() = mozilla::void_t();
+    }
+
   protected:
     BaseType()
     { }
 
     virtual ~BaseType()
     { }
   };
-
-  static void*
-  Allocate(size_t aSize)
-  {
-    // We want infallible allocation in the child.
-    return moz_xmalloc(aSize);
-  }
 };
 
 template <ActorFlavorEnum>
-class RemoteBlobBase;
-template <ActorFlavorEnum>
 class RemoteBlob;
-template <ActorFlavorEnum>
-class RemoteMemoryBlob;
-template <ActorFlavorEnum>
-class RemoteMultipartBlob;
 
 template <ActorFlavorEnum ActorFlavor>
 class Blob : public BlobTraits<ActorFlavor>::BaseType
 {
-  friend class RemoteBlobBase<ActorFlavor>;
+  friend class RemoteBlob<ActorFlavor>;
 
 public:
   typedef typename BlobTraits<ActorFlavor>::ProtocolType ProtocolType;
   typedef typename BlobTraits<ActorFlavor>::StreamType StreamType;
+  typedef typename BlobTraits<ActorFlavor>::ConstructorParamsType
+          ConstructorParamsType;
+  typedef typename BlobTraits<ActorFlavor>::OtherSideConstructorParamsType
+          OtherSideConstructorParamsType;
   typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
-  typedef typename BlobTraits<ActorFlavor>::ContentManagerType ContentManagerType;
-  typedef typename BlobTraits<ActorFlavor>::BlobManagerType BlobManagerType;
   typedef RemoteBlob<ActorFlavor> RemoteBlobType;
-  typedef RemoteMemoryBlob<ActorFlavor> RemoteMemoryBlobType;
-  typedef RemoteMultipartBlob<ActorFlavor> RemoteMultipartBlobType;
   typedef mozilla::ipc::IProtocolManager<
                       mozilla::ipc::RPCChannel::RPCListener>::ActorDestroyReason
           ActorDestroyReason;
-  typedef mozilla::dom::BlobConstructorParams BlobConstructorParams;
 
 protected:
   nsIDOMBlob* mBlob;
   RemoteBlobType* mRemoteBlob;
-  RemoteMemoryBlobType* mRemoteMemoryBlob;
-  RemoteMultipartBlobType* mRemoteMultipartBlob;
-
-  ContentManagerType* mContentManager;
-  BlobManagerType* mBlobManager;
-
   bool mOwnsBlob;
   bool mBlobIsFile;
 
 public:
   // This create function is called on the sending side.
   static Blob*
   Create(nsIDOMBlob* aBlob)
   {
     return new Blob(aBlob);
   }
 
   // This create function is called on the receiving side.
   static Blob*
-  Create(const BlobConstructorParams& aParams);
+  Create(const ConstructorParamsType& aParams);
 
   // Get the blob associated with this actor. This may always be called on the
   // sending side. It may also be called on the receiving side unless this is a
   // "mystery" blob that has not yet received a SetMysteryBlobInfo() call.
   already_AddRefed<nsIDOMBlob>
   GetBlob();
 
   // Use this for files.
   bool
   SetMysteryBlobInfo(const nsString& aName, const nsString& aContentType,
                      uint64_t aLength, uint64_t aLastModifiedDate);
 
   // Use this for non-file blobs.
   bool
   SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength);
 
-  ProtocolType*
-  ConstructPBlobOnManager(ProtocolType* aActor,
-                          const BlobConstructorParams& aParams);
-
-  bool
-  ManagerIs(const ContentManagerType* aManager) const
-  {
-    return aManager == mContentManager;
-  }
-
-  bool
-  ManagerIs(const BlobManagerType* aManager) const
-  {
-    return aManager == mBlobManager;
-  }
-
-#ifdef DEBUG
-  bool
-  HasManager() const
-  {
-    return !!mContentManager || !!mBlobManager;
-  }
-#endif
-
-  void
-  SetManager(ContentManagerType* aManager);
-  void
-  SetManager(BlobManagerType* aManager);
-
-  void
-  PropagateManager(Blob<ActorFlavor>* aActor) const;
-
 private:
   // This constructor is called on the sending side.
   Blob(nsIDOMBlob* aBlob);
 
-  // These constructors are called on the receiving side.
-  Blob(nsRefPtr<RemoteBlobType>& aBlob,
-       bool aIsFile);
-  Blob(nsRefPtr<RemoteMemoryBlobType>& aBlob,
-       bool aIsFile);
-  Blob(nsRefPtr<RemoteMultipartBlobType>& aBlob,
-       bool aIsFile);
+  // This constructor is called on the receiving side.
+  Blob(const ConstructorParamsType& aParams);
+
+  static already_AddRefed<RemoteBlobType>
+  CreateRemoteBlob(const ConstructorParamsType& aParams);
 
   void
   NoteDyingRemoteBlob();
 
   // These methods are only called by the IPDL message machinery.
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvResolveMystery(const ResolveMysteryParams& aParams) MOZ_OVERRIDE;
 
   virtual bool
   RecvPBlobStreamConstructor(StreamType* aActor) MOZ_OVERRIDE;
 
-  virtual bool
-  RecvPBlobConstructor(ProtocolType* aActor,
-                       const BlobConstructorParams& aParams) MOZ_OVERRIDE;
-
   virtual StreamType*
   AllocPBlobStream() MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBlobStream(StreamType* aActor) MOZ_OVERRIDE;
-
-  virtual ProtocolType*
-  AllocPBlob(const BlobConstructorParams& params) MOZ_OVERRIDE;
-
-  virtual bool
-  DeallocPBlob(ProtocolType* actor) MOZ_OVERRIDE;
 };
 
 } // namespace ipc
 
 typedef mozilla::dom::ipc::Blob<mozilla::dom::ipc::Child> BlobChild;
 typedef mozilla::dom::ipc::Blob<mozilla::dom::ipc::Parent> BlobParent;
 
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_ipc_Blob_h
+#endif // mozilla_dom_ipc_Blob_h
\ No newline at end of file
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -86,16 +86,17 @@
 #ifdef ACCESSIBILITY
 #include "nsIAccessibilityService.h"
 #endif
 
 #include "mozilla/dom/indexedDB/PIndexedDBChild.h"
 #include "mozilla/dom/sms/SmsChild.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
+#include "mozilla/ipc/InputStreamUtils.h"
 
 #include "nsDOMFile.h"
 #include "nsIRemoteBlob.h"
 #include "ProcessUtils.h"
 #include "StructuredCloneUtils.h"
 #include "URIUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
@@ -557,114 +558,36 @@ ContentChild::DeallocPBrowser(PBrowserCh
     TabChild* child = static_cast<TabChild*>(iframe);
     NS_RELEASE(child);
     return true;
 }
 
 PBlobChild*
 ContentChild::AllocPBlob(const BlobConstructorParams& aParams)
 {
-  BlobChild* actor = BlobChild::Create(aParams);
-  actor->SetManager(this);
-  return actor;
+  return BlobChild::Create(aParams);
 }
 
 bool
 ContentChild::DeallocPBlob(PBlobChild* aActor)
 {
   delete aActor;
   return true;
 }
 
-bool
-ContentChild::GetParamsForBlob(nsDOMFileBase* aBlob,
-                               BlobConstructorParams* aOutParams)
-{
-  BlobConstructorParams resultParams;
-
-  if (!(aBlob->IsMemoryBacked() || aBlob->GetSubBlobs()) &&
-      (aBlob->IsSizeUnknown() || aBlob->IsDateUnknown())) {
-    // We don't want to call GetSize or GetLastModifiedDate
-    // yet since that may stat a file on the main thread
-    // here. Instead we'll learn the size lazily from the
-    // other process.
-    resultParams = MysteryBlobConstructorParams();
-  }
-  else {
-    BlobOrFileConstructorParams params;
-
-    nsString contentType;
-    nsresult rv = aBlob->GetType(contentType);
-    NS_ENSURE_SUCCESS(rv, false);
-
-    uint64_t length;
-    rv = aBlob->GetSize(&length);
-    NS_ENSURE_SUCCESS(rv, false);
-
-    nsCOMPtr<nsIDOMFile> file;
-    static_cast<nsIDOMBlob*>(aBlob)->QueryInterface(NS_GET_IID(nsIDOMFile),
-                                          (void**)getter_AddRefs(file));
-    if (file) {
-      FileBlobConstructorParams fileParams;
-
-      rv = file->GetName(fileParams.name());
-      NS_ENSURE_SUCCESS(rv, false);
-
-      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
-      NS_ENSURE_SUCCESS(rv, false);
-
-      fileParams.contentType() = contentType;
-      fileParams.length() = length;
-
-      params = fileParams;
-    } else {
-      NormalBlobConstructorParams blobParams;
-      blobParams.contentType() = contentType;
-      blobParams.length() = length;
-      params = blobParams;
-    }
-
-    MOZ_ASSERT(!(aBlob->IsMemoryBacked() &&
-                 aBlob->GetSubBlobs()), "Can't be both!");
-
-    if (aBlob->IsMemoryBacked()) {
-      const nsDOMMemoryFile* memoryBlob =
-        static_cast<const nsDOMMemoryFile*>(aBlob);
-
-      InfallibleTArray<uint8_t> data;
-      data.SetLength(memoryBlob->GetLength());
-      memcpy(data.Elements(), memoryBlob->GetData(), memoryBlob->GetLength());
-
-      MemoryBlobOrFileConstructorParams memoryParams(params, data);
-      resultParams = memoryParams;
-    }
-    else if (aBlob->GetSubBlobs()) {
-      MultipartBlobOrFileConstructorParams multipartParams(params);
-      resultParams = multipartParams;
-    }
-    else {
-      resultParams = BlobConstructorNoMultipartParams(params);
-    }
-  }
-
-  *aOutParams = resultParams;
-
-  return true;
-}
-
 BlobChild*
 ContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aBlob, "Null pointer!");
 
   // XXX This is only safe so long as all blob implementations in our tree
   //     inherit nsDOMFileBase. If that ever changes then this will need to grow
   //     a real interface or something.
-  nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
+  const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
 
   // All blobs shared between processes must be immutable.
   nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
   if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
     NS_WARNING("Failed to make blob immutable!");
     return nullptr;
   }
 
@@ -672,44 +595,73 @@ ContentChild::GetOrCreateActorForBlob(ns
   if (remoteBlob) {
     BlobChild* actor =
       static_cast<BlobChild*>(static_cast<PBlobChild*>(remoteBlob->GetPBlob()));
     NS_ASSERTION(actor, "Null actor?!");
 
     return actor;
   }
 
-  BlobConstructorParams params;
-  if (!GetParamsForBlob(blob, &params)) {
-    return nullptr;
+  ParentBlobConstructorParams params;
+
+  if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
+    // We don't want to call GetSize or GetLastModifiedDate
+    // yet since that may stat a file on the main thread
+    // here. Instead we'll learn the size lazily from the
+    // other process.
+    params.blobParams() = MysteryBlobConstructorParams();
+    params.optionalInputStreamParams() = void_t();
   }
+  else {
+    nsString contentType;
+    nsresult rv = aBlob->GetType(contentType);
+    NS_ENSURE_SUCCESS(rv, nullptr);
+
+    uint64_t length;
+    rv = aBlob->GetSize(&length);
+    NS_ENSURE_SUCCESS(rv, nullptr);
+
+    nsCOMPtr<nsIInputStream> stream;
+    rv = aBlob->GetInternalStream(getter_AddRefs(stream));
+    NS_ENSURE_SUCCESS(rv, nullptr);
+
+    InputStreamParams inputStreamParams;
+    SerializeInputStream(stream, inputStreamParams);
+
+    params.optionalInputStreamParams() = inputStreamParams;
+
+    nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
+    if (file) {
+      FileBlobConstructorParams fileParams;
+
+      rv = file->GetName(fileParams.name());
+      NS_ENSURE_SUCCESS(rv, nullptr);
+
+      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
+      NS_ENSURE_SUCCESS(rv, nullptr);
+
+      fileParams.contentType() = contentType;
+      fileParams.length() = length;
+
+      params.blobParams() = fileParams;
+    } else {
+      NormalBlobConstructorParams blobParams;
+      blobParams.contentType() = contentType;
+      blobParams.length() = length;
+      params.blobParams() = blobParams;
+    }
+    }
 
   BlobChild* actor = BlobChild::Create(aBlob);
   NS_ENSURE_TRUE(actor, nullptr);
 
-  SendPBlobConstructor(actor, params);
-
-  actor->SetManager(this);
-
-  if (const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs()) {
-    for (uint32_t i = 0; i < subBlobs->Length(); ++i) {
-      BlobConstructorParams subParams;
-      nsDOMFileBase* subBlob =
-        static_cast<nsDOMFileBase*>(subBlobs->ElementAt(i).get());
-      if (!GetParamsForBlob(subBlob, &subParams)) {
+  if (!SendPBlobConstructor(actor, params)) {
         return nullptr;
       }
 
-      BlobChild* subActor = BlobChild::Create(aBlob);
-      actor->SendPBlobConstructor(subActor, subParams);
-
-      subActor->SetManager(actor);
-    }
-  }
-
   return actor;
 }
 
 PCrashReporterChild*
 ContentChild::AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
                                   const uint32_t& processType)
 {
 #ifdef MOZ_CRASHREPORTER
@@ -1180,9 +1132,9 @@ ContentChild::RecvFileSystemUpdate(const
     unused << aName;
     unused << aState;
     unused << aMountGeneration;
 #endif
     return true;
 }
 
 } // namespace dom
-} // namespace mozilla
+} // namespace mozilla
\ No newline at end of file
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -12,17 +12,16 @@
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/dom/ipc/Blob.h"
 
 #include "nsTArray.h"
 #include "nsIConsoleListener.h"
 
 struct ChromePackage;
 class nsIDOMBlob;
-class nsDOMFileBase;
 class nsIObserver;
 struct ResourceMapping;
 struct OverrideMapping;
 
 namespace mozilla {
 
 namespace ipc {
 class OptionalURIParams;
@@ -198,18 +197,16 @@ public:
     // cache the value
     nsString &GetIndexedDBPath();
 
     uint64_t GetID() { return mID; }
 
     bool IsForApp() { return mIsForApp; }
     bool IsForBrowser() { return mIsForBrowser; }
 
-    bool GetParamsForBlob(nsDOMFileBase* aBlob,
-                          BlobConstructorParams* aOutParams);
     BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
 private:
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     /**
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1455,168 +1455,103 @@ ContentParent::DeallocPDeviceStorageRequ
   DeviceStorageRequestParent *parent = static_cast<DeviceStorageRequestParent*>(doomed);
   NS_RELEASE(parent);
   return true;
 }
 
 PBlobParent*
 ContentParent::AllocPBlob(const BlobConstructorParams& aParams)
 {
-  BlobParent* actor = BlobParent::Create(aParams);
-  actor->SetManager(this);
-  return actor;
+  return BlobParent::Create(aParams);
 }
 
 bool
 ContentParent::DeallocPBlob(PBlobParent* aActor)
 {
   delete aActor;
   return true;
 }
 
-bool
-ContentParent::GetParamsForBlob(nsDOMFileBase* aBlob,
-                                BlobConstructorParams* aOutParams)
-{
-  BlobConstructorParams resultParams;
-
-  if (!(aBlob->IsMemoryBacked() || aBlob->GetSubBlobs()) &&
-      (aBlob->IsSizeUnknown() || aBlob->IsDateUnknown())) {
-    // We don't want to call GetSize or GetLastModifiedDate
-    // yet since that may stat a file on the main thread
-    // here. Instead we'll learn the size lazily from the
-    // other process.
-    resultParams = MysteryBlobConstructorParams();
-  }
-  else {
-    BlobOrFileConstructorParams params;
-
-    nsString contentType;
-    nsresult rv = aBlob->GetType(contentType);
-    NS_ENSURE_SUCCESS(rv, false);
-
-    uint64_t length;
-    rv = aBlob->GetSize(&length);
-    NS_ENSURE_SUCCESS(rv, false);
-
-    nsCOMPtr<nsIDOMFile> file;
-    static_cast<nsIDOMBlob*>(aBlob)->QueryInterface(NS_GET_IID(nsIDOMFile),
-                                          (void**)getter_AddRefs(file));
-    if (file) {
-      FileBlobConstructorParams fileParams;
-
-      rv = file->GetName(fileParams.name());
-      NS_ENSURE_SUCCESS(rv, false);
-
-      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
-      NS_ENSURE_SUCCESS(rv, false);
-
-      fileParams.contentType() = contentType;
-      fileParams.length() = length;
-
-      params = fileParams;
-    } else {
-      NormalBlobConstructorParams blobParams;
-      blobParams.contentType() = contentType;
-      blobParams.length() = length;
-      params = blobParams;
-    }
-
-    MOZ_ASSERT(!(aBlob->IsMemoryBacked() &&
-                 aBlob->GetSubBlobs()), "Can't be both!");
-
-    if (aBlob->IsMemoryBacked()) {
-      const nsDOMMemoryFile* memoryBlob =
-        static_cast<const nsDOMMemoryFile*>(aBlob);
-
-      FallibleTArray<uint8_t> data;
-      if (!data.SetLength(memoryBlob->GetLength())) {
-        return false;
-      }
-      memcpy(data.Elements(), memoryBlob->GetData(), memoryBlob->GetLength());
-
-      MemoryBlobOrFileConstructorParams memoryParams(params, data);
-      resultParams = memoryParams;
-    }
-    else if (aBlob->GetSubBlobs()) {
-      MultipartBlobOrFileConstructorParams multipartParams(params);
-      resultParams = multipartParams;
-    }
-    else {
-      resultParams = BlobConstructorNoMultipartParams(params);
-    }
-  }
-
-  *aOutParams = resultParams;
-
-  return true;
-}
-
 BlobParent*
 ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aBlob, "Null pointer!");
 
   // XXX This is only safe so long as all blob implementations in our tree
   //     inherit nsDOMFileBase. If that ever changes then this will need to grow
   //     a real interface or something.
-  nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
+  const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob);
 
   // All blobs shared between processes must be immutable.
   nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob);
   if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) {
     NS_WARNING("Failed to make blob immutable!");
     return nullptr;
   }
 
   nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob);
   if (remoteBlob) {
     BlobParent* actor =
       static_cast<BlobParent*>(
         static_cast<PBlobParent*>(remoteBlob->GetPBlob()));
     NS_ASSERTION(actor, "Null actor?!");
 
-    if (actor->ManagerIs(this)) {
+    if (static_cast<ContentParent*>(actor->Manager()) == this) {
       return actor;
     }
   }
 
-  BlobConstructorParams params;
-  if (!GetParamsForBlob(blob, &params)) {
-    return nullptr;
+  ChildBlobConstructorParams params;
+
+  if (blob->IsSizeUnknown() || blob->IsDateUnknown()) {
+    // We don't want to call GetSize or GetLastModifiedDate
+    // yet since that may stat a file on the main thread
+    // here. Instead we'll learn the size lazily from the
+    // other process.
+    params = MysteryBlobConstructorParams();
   }
+  else {
+    nsString contentType;
+    nsresult rv = aBlob->GetType(contentType);
+    NS_ENSURE_SUCCESS(rv, nullptr);
+
+    uint64_t length;
+    rv = aBlob->GetSize(&length);
+    NS_ENSURE_SUCCESS(rv, nullptr);
+
+    nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
+    if (file) {
+      FileBlobConstructorParams fileParams;
+
+      rv = file->GetMozLastModifiedDate(&fileParams.modDate());
+      NS_ENSURE_SUCCESS(rv, nullptr);
+
+      rv = file->GetName(fileParams.name());
+      NS_ENSURE_SUCCESS(rv, nullptr);
+
+      fileParams.contentType() = contentType;
+      fileParams.length() = length;
+
+      params = fileParams;
+    } else {
+      NormalBlobConstructorParams blobParams;
+      blobParams.contentType() = contentType;
+      blobParams.length() = length;
+      params = blobParams;
+    }
+      }
 
   BlobParent* actor = BlobParent::Create(aBlob);
   NS_ENSURE_TRUE(actor, nullptr);
 
   if (!SendPBlobConstructor(actor, params)) {
     return nullptr;
   }
 
-  actor->SetManager(this);
-
-  if (const nsTArray<nsCOMPtr<nsIDOMBlob> >* subBlobs = blob->GetSubBlobs()) {
-    for (uint32_t i = 0; i < subBlobs->Length(); ++i) {
-      BlobConstructorParams subParams;
-      nsDOMFileBase* subBlob =
-        static_cast<nsDOMFileBase*>(subBlobs->ElementAt(i).get());
-      if (!GetParamsForBlob(subBlob, &subParams)) {
-        return nullptr;
-      }
-
-      BlobParent* subActor = BlobParent::Create(aBlob);
-      if (!actor->SendPBlobConstructor(subActor, subParams)) {
-        return nullptr;
-      }
-
-      subActor->SetManager(actor);
-    }
-  }
-
   return actor;
 }
 
 void
 ContentParent::KillHard()
 {
     mForceKillTask = nullptr;
     // This ensures the process is eventually killed, but doesn't
@@ -2333,9 +2268,9 @@ ContentParent::CheckManifestURL(const ns
 
 bool
 ContentParent::CheckAppHasPermission(const nsAString& aPermission)
 {
   return AssertAppHasPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
 }
 
 } // namespace dom
-} // namespace mozilla
+} // namespace mozilla
\ No newline at end of file
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -31,17 +31,16 @@
 #define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
 
 #define CONTENT_PARENT_NO_CHILD_ID 0
 #define CONTENT_PARENT_UNKNOWN_CHILD_ID -1
 
 class mozIApplication;
 class nsConsoleService;
 class nsIDOMBlob;
-class nsDOMFileBase;
 
 namespace mozilla {
 
 namespace ipc {
 class OptionalURIParams;
 class URIParams;
 class TestShellParent;
 } // namespace ipc
@@ -128,19 +127,18 @@ public:
     GeckoChildProcessHost* Process() {
         return mSubprocess;
     }
 
     bool NeedsPermissionsUpdate() {
         return mSendPermissionUpdates;
     }
 
-    bool GetParamsForBlob(nsDOMFileBase* aBlob,
-                          BlobConstructorParams* aOutParams);
     BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
+
     /**
      * Kill our subprocess and make sure it dies.  Should only be used
      * in emergency situations since it bypasses the normal shutdown
      * process.
      */
     void KillHard();
 
     uint64_t ChildID() { return mChildID; }
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -26,54 +26,10 @@ struct NormalBlobConstructorParams
 struct FileBlobConstructorParams
 {
   nsString name;
   nsString contentType;
   uint64_t length;
   uint64_t modDate;
 };
 
-union BlobOrFileConstructorParams
-{
-  NormalBlobConstructorParams;
-  FileBlobConstructorParams;
-};
-
-struct MemoryBlobOrFileConstructorParams
-{
-  BlobOrFileConstructorParams constructorParams;
-  uint8_t[] data;
-};
-
-struct SlicedBlobConstructorParams
-{
-  PBlob source;
-  uint64_t begin;
-  uint64_t end;
-  nsString contentType;
-};
-
-struct MysteryBlobConstructorParams
-{
-  // Nothing is known about this type of blob.
-};
-
-union BlobConstructorNoMultipartParams
-{
-  BlobOrFileConstructorParams;
-  MemoryBlobOrFileConstructorParams;
-  SlicedBlobConstructorParams;
-  MysteryBlobConstructorParams;
-};
-
-struct MultipartBlobOrFileConstructorParams
-{
-  BlobOrFileConstructorParams constructorParams;
-};
-
-union BlobConstructorParams
-{
-  BlobConstructorNoMultipartParams;
-  MultipartBlobOrFileConstructorParams;
-};
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PBlob.ipdl
+++ b/dom/ipc/PBlob.ipdl
@@ -13,23 +13,21 @@ namespace dom {
 union ResolveMysteryParams
 {
   NormalBlobConstructorParams;
   FileBlobConstructorParams;
 };
 
 protocol PBlob
 {
-  manager PContent or PBlob;
+  manager PContent;
   manages PBlobStream;
-  manages PBlob;
 
 both:
   __delete__();
 
-  PBlob(BlobConstructorParams params);
   PBlobStream();
 
   ResolveMystery(ResolveMysteryParams params);
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -15,16 +15,17 @@ include protocol PHal;
 include protocol PImageBridge;
 include protocol PIndexedDB;
 include protocol PMemoryReportRequest;
 include protocol PNecko;
 include protocol PSms;
 include protocol PStorage;
 include protocol PTestShell;
 include DOMTypes;
+include InputStreamParams;
 include URIParams;
 
 include "mozilla/chrome/RegistryMessageUtils.h";
 include "mozilla/dom/PermissionMessageUtils.h";
 include "mozilla/dom/TabMessageUtils.h";
 include "mozilla/layout/RenderFrameUtils.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "nsGeoPositionIPCSerialiser.h";
@@ -126,16 +127,49 @@ union DeviceStorageParams
   DeviceStorageGetParams;
   DeviceStorageDeleteParams;
   DeviceStorageEnumerationParams;
   DeviceStorageFreeSpaceParams;
   DeviceStorageUsedSpaceParams;
   DeviceStorageAvailableParams;
 };
 
+struct SlicedBlobConstructorParams
+{
+  PBlob source;
+  uint64_t begin;
+  uint64_t end;
+  nsString contentType;
+};
+
+struct MysteryBlobConstructorParams
+{
+  // Nothing is known about this type of blob.
+};
+
+union ChildBlobConstructorParams
+{
+  NormalBlobConstructorParams;
+  FileBlobConstructorParams;
+  SlicedBlobConstructorParams;
+  MysteryBlobConstructorParams;
+};
+
+struct ParentBlobConstructorParams
+{
+  ChildBlobConstructorParams blobParams;
+  OptionalInputStreamParams optionalInputStreamParams;
+};
+
+union BlobConstructorParams
+{
+  ChildBlobConstructorParams;
+  ParentBlobConstructorParams;
+};
+
 // An IPCTabContext which corresponds to a PBrowser opened by a child when it
 // receives window.open().
 //
 // If isBrowserElement is false, this PopupIPCTabContext corresponds to an app
 // frame, and the frame's app-id and app-frame-owner-app-id will be equal to the
 // opener's values.
 //
 // If isBrowserElement is true, the frame's browserFrameOwnerAppId will be equal
--- a/dom/ipc/nsIRemoteBlob.h
+++ b/dom/ipc/nsIRemoteBlob.h
@@ -7,24 +7,22 @@
 
 #include "nsISupports.h"
 
 #ifndef NS_NO_VTABLE
 #define NS_NO_VTABLE
 #endif
 
 #define NS_IREMOTEBLOB_IID \
-  {0x1f569fbc, 0xf588, 0x41c5, {0xa0, 0x73, 0x92, 0x0d, 0xf5, 0x9f, 0x1b, 0xdb}}
+  {0x74ce3cdd, 0xbfc9, 0x4edb, {0x98, 0x26, 0x50, 0xcf, 0x00, 0x26, 0x58, 0x70}}
 
 class NS_NO_VTABLE nsIRemoteBlob : public nsISupports
 {
 public: 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IREMOTEBLOB_IID)
 
   // This will either return a PBlobChild or PBlobParent.
   virtual void* GetPBlob() = 0;
-
-  virtual void SetPBlob(void* aActor) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIRemoteBlob, NS_IREMOTEBLOB_IID)
 
 #endif // mozilla_dom_ipc_nsIRemoteBlob_h
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -82,17 +82,17 @@ private:
   Unwrap(JSContext* aCx, JSObject* aObj)
   {
     return GetPrivate(aObj);
   }
 
   static JSBool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile(EmptyString());
+    nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
     nsresult rv = file->InitBlob(aCx, aArgc, JS_ARGV(aCx, aVp), Unwrap);
     if (NS_FAILED(rv)) {
       ThrowDOMExceptionForNSResult(aCx, rv);
       return false;
     }
 
     JSObject* obj = file::CreateBlob(aCx, file);
     if (!obj) {