Bug 1399466 - IPCBlobInputStream should not use STS to read from the remote Stream, but DOMFile thread instead, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 14 Sep 2017 14:28:29 +0200
changeset 430439 7822d49cfd5974f2aebb7fe0ed3a5b75c8471158
parent 430438 75a18fd2dd49e226409ac5f2117c9cc592db8be5
child 430440 e19ae0bc0563f92b18a295acc6f0ec5c152d5b49
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1399466
milestone57.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 1399466 - IPCBlobInputStream should not use STS to read from the remote Stream, but DOMFile thread instead, r=smaug
dom/file/ipc/IPCBlobInputStream.cpp
dom/file/ipc/IPCBlobInputStreamChild.cpp
dom/file/ipc/IPCBlobInputStreamThread.cpp
dom/file/ipc/IPCBlobInputStreamThread.h
--- a/dom/file/ipc/IPCBlobInputStream.cpp
+++ b/dom/file/ipc/IPCBlobInputStream.cpp
@@ -3,30 +3,29 @@
 /* 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 "IPCBlobInputStream.h"
 #include "IPCBlobInputStreamChild.h"
 #include "IPCBlobInputStreamStorage.h"
 #include "mozilla/ipc/InputStreamParams.h"
+#include "IPCBlobInputStreamThread.h"
 #include "nsIAsyncInputStream.h"
-#include "nsIStreamTransportService.h"
-#include "nsITransport.h"
-#include "nsNetCID.h"
+#include "nsIAsyncOutputStream.h"
+#include "nsIPipe.h"
+#include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "SlicedInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
-static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
-
 class InputStreamCallbackRunnable final : public CancelableRunnable
 {
 public:
   // Note that the execution can be synchronous in case the event target is
   // null.
   static void
   Execute(nsIInputStreamCallback* aCallback,
           nsIEventTarget* aEventTarget,
@@ -506,17 +505,17 @@ IPCBlobInputStream::OnInputStreamReady(n
     return NS_OK;
   }
 
   nsCOMPtr<nsIInputStreamCallback> callback;
   callback.swap(mInputStreamCallback);
 
   nsCOMPtr<nsIEventTarget> callbackEventTarget;
   callbackEventTarget.swap(mInputStreamCallbackEventTarget);
- 
+
   // This must be the last operation because the execution of the callback can
   // be synchronous.
   InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
   return NS_OK;
 }
 
 // nsIIPCSerializableInputStream
 
@@ -646,42 +645,40 @@ IPCBlobInputStream::EnsureAsyncRemoteStr
   bool nonBlocking = false;
   nsresult rv = mRemoteStream->IsNonBlocking(&nonBlocking);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
   if (!asyncStream || !nonBlocking) {
-    nsCOMPtr<nsIStreamTransportService> sts =
-      do_GetService(kStreamTransportServiceCID, &rv);
+    // Let's make the stream async using the DOMFile thread.
+    nsCOMPtr<nsIAsyncInputStream> pipeIn;
+    nsCOMPtr<nsIAsyncOutputStream> pipeOut;
+    rv = NS_NewPipe2(getter_AddRefs(pipeIn),
+                     getter_AddRefs(pipeOut),
+                     true, true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    nsCOMPtr<nsITransport> transport;
-    rv = sts->CreateInputTransport(mRemoteStream,
-                                   /* aStartOffset */ 0,
-                                   /* aReadLimit */ -1,
-                                   /* aCloseWhenDone */ true,
-                                   getter_AddRefs(transport));
+    RefPtr<IPCBlobInputStreamThread> thread =
+      IPCBlobInputStreamThread::GetOrCreate();
+    if (NS_WARN_IF(!thread)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    nsCOMPtr<nsIEventTarget> target = thread->EventTarget();
+    rv = NS_AsyncCopy(mRemoteStream, pipeOut, target,
+                      NS_ASYNCCOPY_VIA_WRITESEGMENTS);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    nsCOMPtr<nsIInputStream> wrapper;
-    rv = transport->OpenInputStream(/* aFlags */ 0,
-                                    /* aSegmentSize */ 0,
-                                    /* aSegmentCount */ 0,
-                                    getter_AddRefs(wrapper));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    asyncStream = do_QueryInterface(wrapper);
+    asyncStream = pipeIn;
   }
 
   MOZ_ASSERT(asyncStream);
   mAsyncRemoteStream = asyncStream;
   mRemoteStream = nullptr;
 
   return NS_OK;
 }
--- a/dom/file/ipc/IPCBlobInputStreamChild.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp
@@ -182,16 +182,18 @@ IPCBlobInputStreamChild::ActorDestroy(IP
     mState = migrating ? eInactiveMigrating : eInactive;
   }
 
   if (migrating) {
     // We were waiting for this! Now we can migrate the actor in the correct
     // thread.
     RefPtr<IPCBlobInputStreamThread> thread =
       IPCBlobInputStreamThread::GetOrCreate();
+    MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
+
     ResetManager();
     thread->MigrateActor(this);
     return;
   }
 
   // Let's cleanup the workerHolder and the pending operation queue.
   Shutdown();
 }
--- a/dom/file/ipc/IPCBlobInputStreamThread.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamThread.cpp
@@ -31,17 +31,17 @@ class ThreadInitializeRunnable final : p
 public:
   ThreadInitializeRunnable() : Runnable("dom::ThreadInitializeRunnable") {}
 
   NS_IMETHOD
   Run() override
   {
      mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
      MOZ_ASSERT(gIPCBlobThread);
-     gIPCBlobThread->Initialize();
+     gIPCBlobThread->InitializeOnMainThread();
      return NS_OK;
   }
 };
 
 class MigrateActorRunnable final : public Runnable
                                  , public nsIIPCBackgroundChildCreateCallback
 {
 public:
@@ -110,57 +110,74 @@ IPCBlobInputStreamThread::GetOrCreate()
   mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
 
   if (gShutdownHasStarted) {
     return nullptr;
   }
 
   if (!gIPCBlobThread) {
     gIPCBlobThread = new IPCBlobInputStreamThread();
-    gIPCBlobThread->Initialize();
+    if (!gIPCBlobThread->Initialize()) {
+      return nullptr;
+    }
   }
 
   return gIPCBlobThread;
 }
 
-void
+bool
 IPCBlobInputStreamThread::Initialize()
 {
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  mThread = thread;
+
+  if (!mPendingActors.IsEmpty()) {
+    for (uint32_t i = 0; i < mPendingActors.Length(); ++i) {
+      MigrateActorInternal(mPendingActors[i]);
+    }
+
+    mPendingActors.Clear();
+  }
+
   if (!NS_IsMainThread()) {
     RefPtr<Runnable> runnable = new ThreadInitializeRunnable();
     SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
-    return;
+    return true;
   }
 
+  InitializeOnMainThread();
+  return true;
+}
+
+void
+IPCBlobInputStreamThread::InitializeOnMainThread()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (NS_WARN_IF(!obs)) {
     return;
   }
 
   nsresult rv =
     obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
-
-  nsCOMPtr<nsIThread> thread;
-  rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return;
-  }
+}
 
-  mThread = thread;
-
-  if (!mPendingActors.IsEmpty()) {
-    for (uint32_t i = 0; i < mPendingActors.Length(); ++i) {
-      MigrateActorInternal(mPendingActors[i]);
-    }
-
-    mPendingActors.Clear();
-  }
+nsIEventTarget*
+IPCBlobInputStreamThread::EventTarget() const
+{
+  return mThread;
 }
 
 NS_IMETHODIMP
 IPCBlobInputStreamThread::Observe(nsISupports* aSubject,
                                   const char* aTopic,
                                   const char16_t* aData)
 {
   MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
--- a/dom/file/ipc/IPCBlobInputStreamThread.h
+++ b/dom/file/ipc/IPCBlobInputStreamThread.h
@@ -26,18 +26,24 @@ public:
   IsOnFileEventTarget(nsIEventTarget* aEventTarget);
 
   static IPCBlobInputStreamThread*
   GetOrCreate();
 
   void
   MigrateActor(IPCBlobInputStreamChild* aActor);
 
+  bool
+  Initialize();
+
   void
-  Initialize();
+  InitializeOnMainThread();
+
+  nsIEventTarget*
+  EventTarget() const;
 
 private:
   ~IPCBlobInputStreamThread() = default;
 
   void
   MigrateActorInternal(IPCBlobInputStreamChild* aActor);
 
   nsCOMPtr<nsIThread> mThread;