Bug 783878 - Part 2: Allow serializing remote input streams by passing the actor reference over the wire and retrieving the original stream in the parent. r=bent
authorJosh Matthews <josh@joshmatthews.net>
Fri, 21 Sep 2012 13:26:13 -0400
changeset 107907 3c77dfc193d2436e40f9dbe40558b72aa40eda31
parent 107906 e1f3deefa340ec7916607db71979d6478253f61b
child 107908 935b18138954228f73d94e7e393b3cc135616bb4
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersbent
bugs783878
milestone18.0a1
Bug 783878 - Part 2: Allow serializing remote input streams by passing the actor reference over the wire and retrieving the original stream in the parent. r=bent
dom/ipc/Blob.cpp
ipc/glue/InputStreamParams.ipdlh
ipc/glue/InputStreamUtils.cpp
netwerk/protocol/ftp/PFTPChannel.ipdl
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/websocket/PWebSocket.ipdl
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -26,34 +26,61 @@
 
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
 using namespace mozilla::ipc;
 
 namespace {
 
 class RemoteInputStream : public nsIInputStream,
-                          public nsISeekableStream
+                          public nsISeekableStream,
+                          public nsIIPCSerializableInputStream
 {
   mozilla::Monitor mMonitor;
   nsCOMPtr<nsIDOMBlob> mSourceBlob;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
+  ActorFlavorEnum mOrigin;
 
 public:
   NS_DECL_ISUPPORTS
 
-  RemoteInputStream(nsIDOMBlob* aSourceBlob)
-  : mMonitor("RemoteInputStream.mMonitor"), mSourceBlob(aSourceBlob)
+  RemoteInputStream(nsIDOMBlob* aSourceBlob, ActorFlavorEnum aOrigin)
+  : mMonitor("RemoteInputStream.mMonitor"), mSourceBlob(aSourceBlob),
+    mOrigin(aOrigin)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aSourceBlob);
   }
 
   void
+  Serialize(InputStreamParams& aParams)
+  {
+    nsCOMPtr<nsIRemoteBlob> remote = do_QueryInterface(mSourceBlob);
+    MOZ_ASSERT(remote);
+
+    if (mOrigin == Parent) {
+      aParams = RemoteInputStreamParams(
+        static_cast<PBlobParent*>(remote->GetPBlob()), nullptr);
+    } else {
+      aParams = RemoteInputStreamParams(
+        nullptr, static_cast<PBlobChild*>(remote->GetPBlob()));
+    }
+  }
+
+  bool
+  Deserialize(const InputStreamParams& aParams)
+  {
+    // See InputStreamUtils.cpp to see how deserialization of a
+    // RemoteInputStream is special-cased.
+    MOZ_NOT_REACHED("RemoteInputStream should never be deserialized");
+    return false;
+  }
+
+  void
   SetStream(nsIInputStream* aStream)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aStream);
 
     nsCOMPtr<nsIInputStream> stream = aStream;
     nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
 
@@ -229,16 +256,17 @@ private:
   }
 };
 
 NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
 NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
 
 NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
+  NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 template <ActorFlavorEnum ActorFlavor>
 class InputStreamActor : public BlobTraits<ActorFlavor>::StreamType
 {
   nsRefPtr<RemoteInputStream> mRemoteStream;
@@ -416,17 +444,18 @@ private:
     void
     RunInternal(bool aNotify)
     {
       MOZ_ASSERT(NS_IsMainThread());
       MOZ_ASSERT(mActor);
       MOZ_ASSERT(!mInputStream);
       MOZ_ASSERT(!mDone);
 
-      nsRefPtr<RemoteInputStream> stream = new RemoteInputStream(mSourceBlob);
+      nsRefPtr<RemoteInputStream> stream = new RemoteInputStream(mSourceBlob,
+                                                                 ActorFlavor);
 
       StreamActorType* streamActor = new StreamActorType(stream);
       if (mActor->SendPBlobStreamConstructor(streamActor)) {
         stream.swap(mInputStream);
       }
 
       mActor = nullptr;
 
--- a/ipc/glue/InputStreamParams.ipdlh
+++ b/ipc/glue/InputStreamParams.ipdlh
@@ -1,15 +1,16 @@
 /* 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/. */
 
 include "ipc/IPCMessageUtils.h";
 
 using mozilla::void_t;
+include protocol PBlob;
 
 namespace mozilla {
 namespace ipc {
 
 struct StringInputStreamParams
 {
   nsCString data;
 };
@@ -31,24 +32,30 @@ struct PartialFileInputStreamParams
 struct MultiplexInputStreamParams
 {
   InputStreamParams[] streams;
   uint32_t currentStream;
   nsresult status;
   bool startedReadingCurrent;
 };
 
+struct RemoteInputStreamParams
+{
+  PBlob remoteBlob;
+};
+
 union InputStreamParams
 {
   StringInputStreamParams;
   FileInputStreamParams;
   PartialFileInputStreamParams;
   BufferedInputStreamParams;
   MIMEInputStreamParams;
   MultiplexInputStreamParams;
+  RemoteInputStreamParams;
 };
 
 union OptionalInputStreamParams
 {
   void_t;
   InputStreamParams;
 };
 
--- a/ipc/glue/InputStreamUtils.cpp
+++ b/ipc/glue/InputStreamUtils.cpp
@@ -2,26 +2,32 @@
  * 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/. */
 
 #include "InputStreamUtils.h"
 
 #include "nsIIPCSerializableInputStream.h"
 
 #include "mozilla/Assertions.h"
+#include "mozilla/dom/ipc/Blob.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDebug.h"
 #include "nsID.h"
+#include "nsIDOMFile.h"
+#include "nsIXULRuntime.h"
 #include "nsMIMEInputStream.h"
 #include "nsMultiplexInputStream.h"
 #include "nsNetCID.h"
 #include "nsStringStream.h"
 #include "nsThreadUtils.h"
+#include "nsXULAppAPI.h"
 
 using namespace mozilla::ipc;
+using mozilla::dom::BlobChild;
+using mozilla::dom::BlobParent;
 
 namespace {
 
 NS_DEFINE_CID(kStringInputStreamCID, NS_STRINGINPUTSTREAM_CID);
 NS_DEFINE_CID(kFileInputStreamCID, NS_LOCALFILEINPUTSTREAM_CID);
 NS_DEFINE_CID(kPartialFileInputStreamCID, NS_PARTIALLOCALFILEINPUTSTREAM_CID);
 NS_DEFINE_CID(kBufferedInputStreamCID, NS_BUFFEREDINPUTSTREAM_CID);
 NS_DEFINE_CID(kMIMEInputStreamCID, NS_MIMEINPUTSTREAM_CID);
@@ -95,16 +101,39 @@ DeserializeInputStream(const InputStream
     case InputStreamParams::TMIMEInputStreamParams:
       serializable = do_CreateInstance(kMIMEInputStreamCID);
       break;
 
     case InputStreamParams::TMultiplexInputStreamParams:
       serializable = do_CreateInstance(kMultiplexInputStreamCID);
       break;
 
+    // When the input stream already exists in this process, all we need to do
+    // is retrieve the original instead of sending any data over the wire.
+    case InputStreamParams::TRemoteInputStreamParams: {
+      nsCOMPtr<nsIDOMBlob> domBlob;
+      const RemoteInputStreamParams& params =
+          aParams.get_RemoteInputStreamParams();
+
+      domBlob = params.remoteBlobParent() ?
+          static_cast<BlobParent*>(params.remoteBlobParent())->GetBlob() :
+          static_cast<BlobChild*>(params.remoteBlobChild())->GetBlob();
+
+      MOZ_ASSERT(domBlob, "Invalid blob contents");
+
+      // If fetching the internal stream fails, we ignore it and return a
+      // null stream.
+      nsCOMPtr<nsIInputStream> stream;
+      nsresult rv = domBlob->GetInternalStream(getter_AddRefs(stream));
+      if (NS_FAILED(rv) || !stream) {
+        NS_WARNING("Couldn't obtain a valid stream from the blob");
+      }
+      return stream.forget();
+    }
+
     default:
       MOZ_ASSERT(false, "Unknown params!");
       return nullptr;
   }
 
   MOZ_ASSERT(serializable);
 
   if (!serializable->Deserialize(aParams)) {
--- a/netwerk/protocol/ftp/PFTPChannel.ipdl
+++ b/netwerk/protocol/ftp/PFTPChannel.ipdl
@@ -4,16 +4,18 @@
 /* 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/. */
 
 include protocol PNecko;
 include InputStreamParams;
 include URIParams;
 
+include protocol PBlob; //FIXME: bug #792908
+
 include "SerializedLoadContext.h";
 
 using IPC::SerializedLoadContext;
 using PRTime;
 
 namespace mozilla {
 namespace net {
 
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -4,16 +4,18 @@
 /* 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/. */
 
 include protocol PNecko;
 include InputStreamParams;
 include URIParams;
 
+include protocol PBlob; //FIXME: bug #792908
+
 include "mozilla/net/PHttpChannelParams.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "prio.h";
 include "SerializedLoadContext.h";
 
 using RequestHeaderTuples;
 using nsHttpHeaderArray;
 using nsHttpResponseHead;
--- a/netwerk/protocol/websocket/PWebSocket.ipdl
+++ b/netwerk/protocol/websocket/PWebSocket.ipdl
@@ -5,16 +5,18 @@
  * 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/. */
 
 include protocol PNecko;
 include protocol PBrowser;
 include InputStreamParams;
 include URIParams;
 
+include protocol PBlob; //FIXME: bug #792908
+
 include "SerializedLoadContext.h";
 using IPC::SerializedLoadContext;
 
 namespace mozilla {
 namespace net {
 
 async protocol PWebSocket
 {