Bug 1015466 - Part 4, implement OnStartRequestSent/OnStopRequest/OnTransportAndData/OnDiversion on background channel. r=mayhemer draft
authorShih-Chiang Chien <schien@mozilla.com>
Mon, 15 May 2017 18:58:31 +0800
changeset 587451 57b983301453ae37a8a7e18fd206ace7a4cdb62c
parent 587450 0425872587b4c64e80ce16ba2e91a6009a797fac
child 587452 c2cd990ee7162684b5c5f72705adeb9cff555a2a
push id61708
push userschien@mozilla.com
push dateThu, 01 Jun 2017 02:33:54 +0000
reviewersmayhemer
bugs1015466
milestone55.0a1
Bug 1015466 - Part 4, implement OnStartRequestSent/OnStopRequest/OnTransportAndData/OnDiversion on background channel. r=mayhemer OnStartRequestSent is used to ensure the execution order between OnStartRequest and all other messsages sent over PBackground. IPC messages sent before OnStartRequestSent can be processed immediately while received by content process. IPC messages sent after OnSartRequestSent need to be pending until OnStartRequestReceived is called. MozReview-Commit-ID: 5Vbb8SBQmW8
netwerk/protocol/http/HttpBackgroundChannelChild.cpp
netwerk/protocol/http/HttpBackgroundChannelChild.h
netwerk/protocol/http/HttpBackgroundChannelParent.cpp
netwerk/protocol/http/HttpBackgroundChannelParent.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/PHttpChannel.ipdl
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
@@ -9,16 +9,17 @@
 #include "HttpLog.h"
 
 #include "HttpBackgroundChannelChild.h"
 
 #include "HttpChannelChild.h"
 #include "MainThreadUtils.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Unused.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 
 using mozilla::ipc::BackgroundChild;
 using mozilla::ipc::IPCResult;
 
 namespace mozilla {
 namespace net {
@@ -113,16 +114,39 @@ HttpBackgroundChannelChild::OnChannelClo
   LOG(("HttpBackgroundChannelChild::OnChannelClosed [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
 
   // HttpChannelChild is not going to handle any incoming message.
   mChannelChild = nullptr;
 }
 
 void
+HttpBackgroundChannelChild::OnStartRequestReceived()
+{
+  LOG(("HttpBackgroundChannelChild::OnStartRequestReceived [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mChannelChild);
+  MOZ_ASSERT(!mStartReceived); // Should only be called once.
+
+  mStartReceived = true;
+
+  nsTArray<nsCOMPtr<nsIRunnable>> runnables;
+  runnables.SwapElements(mQueuedRunnables);
+
+  for (auto event : runnables) {
+    // Note: these runnables call Recv* methods on HttpBackgroundChannelChild
+    // but not the Process* methods on HttpChannelChild.
+    event->Run();
+  }
+
+  // Ensure no new message is enqueued.
+  MOZ_ASSERT(mQueuedRunnables.IsEmpty());
+}
+
+void
 HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed()
 {
   LOG(("HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed"
        " [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mChannelChild) {
     RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
@@ -137,73 +161,232 @@ HttpBackgroundChannelChild::CreateBackgr
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<BackgroundChannelCreateCallback> callback =
     new BackgroundChannelCreateCallback(this);
 
   return BackgroundChild::GetOrCreateForCurrentThread(callback);
 }
 
+bool
+HttpBackgroundChannelChild::IsWaitingOnStartRequest()
+{
+  // Need to wait for OnStartRequest if it is sent by
+  // parent process but not received by content process.
+  return (mStartSent && !mStartReceived);
+}
+
 // PHttpBackgroundChannelChild
 IPCResult
 HttpBackgroundChannelChild::RecvOnStartRequestSent()
 {
+  LOG(("HttpBackgroundChannelChild::RecvOnStartRequestSent [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mStartSent); // Should only receive this message once.
+
+  mStartSent = true;
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvOnTransportAndData(
                                                const nsresult& aChannelStatus,
                                                const nsresult& aTransportStatus,
                                                const uint64_t& aOffset,
                                                const uint32_t& aCount,
                                                const nsCString& aData)
 {
+  LOG(("HttpBackgroundChannelChild::RecvOnTransportAndData [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest [offset=%" PRIu64 " count=%" PRIu32
+         "]\n", aOffset, aCount));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod<const nsresult, const nsresult, const uint64_t,
+                        const uint32_t, const nsCString>(
+        this, &HttpBackgroundChannelChild::RecvOnTransportAndData,
+        aChannelStatus, aTransportStatus, aOffset,
+        aCount, aData));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessOnTransportAndData(aChannelStatus,
+                                           aTransportStatus,
+                                           aOffset,
+                                           aCount,
+                                           aData);
+
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvOnStopRequest(
                                             const nsresult& aChannelStatus,
                                             const ResourceTimingStruct& aTiming)
 {
+  LOG(("HttpBackgroundChannelChild::RecvOnStopRequest [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest [status=%" PRIx32 "]\n",
+         static_cast<uint32_t>(aChannelStatus)));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod<const nsresult, const ResourceTimingStruct>(
+        this, &HttpBackgroundChannelChild::RecvOnStopRequest,
+        aChannelStatus, aTiming));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessOnStopRequest(aChannelStatus, aTiming);
+
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvOnProgress(const int64_t& aProgress,
                                            const int64_t& aProgressMax)
 {
+  LOG(("HttpBackgroundChannelChild::RecvOnProgress [this=%p progress=%"
+       PRId64 " max=%" PRId64 "]\n", this, aProgress, aProgressMax));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest [progress=%" PRId64 " max=%"
+         PRId64 "]\n", aProgress, aProgressMax));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod<const int64_t, const int64_t>(
+        this, &HttpBackgroundChannelChild::RecvOnProgress,
+        aProgress, aProgressMax));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessOnProgress(aProgress, aProgressMax);
+
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvOnStatus(const nsresult& aStatus)
 {
+  LOG(("HttpBackgroundChannelChild::RecvOnStatus [this=%p status=%"
+       PRIx32 "]\n", this, static_cast<uint32_t>(aStatus)));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest [status=%" PRIx32 "]\n",
+         static_cast<uint32_t>(aStatus)));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod<const nsresult>(
+        this, &HttpBackgroundChannelChild::RecvOnStatus, aStatus));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessOnStatus(aStatus);
+
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvFlushedForDiversion()
 {
+  LOG(("HttpBackgroundChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest\n"));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod(this, &HttpBackgroundChannelChild::RecvFlushedForDiversion));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessFlushedForDiversion();
+
   return IPC_OK();
 }
 
 IPCResult
 HttpBackgroundChannelChild::RecvDivertMessages()
 {
+  LOG(("HttpBackgroundChannelChild::RecvDivertMessages [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_WARN_IF(!mChannelChild)) {
+    return IPC_OK();
+  }
+
+  if (IsWaitingOnStartRequest()) {
+    LOG(("  > pending until OnStartRequest\n"));
+
+    mQueuedRunnables.AppendElement(
+      NewRunnableMethod(this, &HttpBackgroundChannelChild::RecvDivertMessages));
+
+    return IPC_OK();
+  }
+
+  mChannelChild->ProcessDivertMessages();
+
   return IPC_OK();
 }
 
 void
 HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
 
+  // Ensure all IPC messages received before ActorDestroy can be
+  // handled correctly. If there is any pending IPC message, destroyed
+  // mChannelChild until those messages are flushed.
+  if (!mQueuedRunnables.IsEmpty()) {
+    LOG(("  > pending until queued messages are flushed\n"));
+    RefPtr<HttpBackgroundChannelChild> self = this;
+    mQueuedRunnables.AppendElement(
+      NS_NewRunnableFunction([self]() {
+        MOZ_ASSERT(NS_IsMainThread());
+        RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget();
+
+        if (channelChild) {
+          channelChild->OnBackgroundChildDestroyed();
+        }
+      }));
+    return;
+  }
+
   if (mChannelChild) {
     RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
+
     channelChild->OnBackgroundChildDestroyed();
   }
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.h
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.h
@@ -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/. */
 
 #ifndef mozilla_net_HttpBackgroundChannelChild_h
 #define mozilla_net_HttpBackgroundChannelChild_h
 
 #include "mozilla/net/PHttpBackgroundChannelChild.h"
+#include "nsIRunnable.h"
+#include "nsTArray.h"
 
 using mozilla::ipc::IPCResult;
 
 namespace mozilla {
 namespace net {
 
 class HttpChannelChild;
 
@@ -28,16 +30,20 @@ public:
   // Associate this background channel with a HttpChannelChild and
   // initiate the createion of the PBackground IPC channel.
   nsresult Init(HttpChannelChild* aChannelChild);
 
   // Callback while the associated HttpChannelChild is not going to
   // handle any incoming messages over background channel.
   void OnChannelClosed();
 
+  // Callback when OnStartRequest is received and handled by HttpChannelChild.
+  // Enqueued messages in background channel will be flushed.
+  void OnStartRequestReceived();
+
   // Callback while failed to create PBackground IPC channel.
   void OnBackgroundChannelCreationFailed();
 
 protected:
   IPCResult RecvOnTransportAndData(const nsresult& aChannelStatus,
                                    const nsresult& aTransportStatus,
                                    const uint64_t& aOffset,
                                    const uint32_t& aCount,
@@ -61,19 +67,38 @@ protected:
 
 private:
   virtual ~HttpBackgroundChannelChild();
 
   // Initiate the creation of the PBckground IPC channel.
   // Return false if failed.
   bool CreateBackgroundChannel();
 
+  // Check OnStartRequest is sent by parent process over main thread IPC
+  // but not yet received on child process.
+  // return true before RecvOnStartRequestSent is invoked.
+  // return false if RecvOnStartRequestSent is invoked but not
+  // OnStartRequestReceived.
+  // return true after both RecvOnStartRequestSend and OnStartRequestReceived
+  // are invoked.
+  bool IsWaitingOnStartRequest();
+
   // Associated HttpChannelChild for handling the channel events.
   // Will be removed while failed to create background channel,
   // destruction of the background channel, or explicitly dissociation
   // via OnChannelClosed callback.
   RefPtr<HttpChannelChild> mChannelChild;
+
+  // True if OnStartRequest is received by HttpChannelChild.
+  bool mStartReceived = false;
+
+  // True if OnStartRequest is sent by HttpChannelParent.
+  bool mStartSent = false;
+
+  // Store pending messages that require to be handled after OnStartRequest.
+  // Should be flushed after OnStartRequest is received and handled.
+  nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // mozilla_net_HttpBackgroundChannelChild_h
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelParent.cpp
@@ -7,16 +7,17 @@
 
 // HttpLog.h should generally be included first
 #include "HttpLog.h"
 
 #include "HttpBackgroundChannelParent.h"
 
 #include "HttpChannelParent.h"
 #include "mozilla/ipc/BackgroundParent.h"
+#include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Unused.h"
 #include "nsIBackgroundChannelRegistrar.h"
 #include "nsNetCID.h"
 #include "nsQueryObject.h"
 #include "nsThreadUtils.h"
 
 using mozilla::dom::ContentParent;
 using mozilla::ipc::AssertIsInMainProcess;
@@ -131,16 +132,183 @@ HttpBackgroundChannelParent::OnChannelCl
     }
 
     Unused << self->Send__delete__(self);
   }), NS_DISPATCH_NORMAL);
 
   Unused << NS_WARN_IF(NS_FAILED(rv));
 }
 
+bool
+HttpBackgroundChannelParent::OnStartRequestSent()
+{
+  LOG(("HttpBackgroundChannelParent::OnStartRequestSent [this=%p]\n", this));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod(this, &HttpBackgroundChannelParent::OnStartRequestSent),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  return SendOnStartRequestSent();
+}
+
+bool
+HttpBackgroundChannelParent::OnTransportAndData(
+                                               const nsresult& aChannelStatus,
+                                               const nsresult& aTransportStatus,
+                                               const uint64_t& aOffset,
+                                               const uint32_t& aCount,
+                                               const nsCString& aData)
+{
+  LOG(("HttpBackgroundChannelParent::OnTransportAndData [this=%p]\n", this));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod<const nsresult, const nsresult, const uint64_t,
+                        const uint32_t, const nsCString>
+        (this, &HttpBackgroundChannelParent::OnTransportAndData,
+         aChannelStatus, aTransportStatus, aOffset, aCount, aData),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  return SendOnTransportAndData(aChannelStatus, aTransportStatus,
+                                aOffset, aCount, aData);
+}
+
+bool
+HttpBackgroundChannelParent::OnStopRequest(const nsresult& aChannelStatus,
+                                           const ResourceTimingStruct& aTiming)
+{
+  LOG(("HttpBackgroundChannelParent::OnStopRequest [this=%p "
+        "status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus)));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod<const nsresult, const ResourceTimingStruct>
+        (this, &HttpBackgroundChannelParent::OnStopRequest,
+         aChannelStatus, aTiming),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  return SendOnStopRequest(aChannelStatus, aTiming);
+}
+
+bool
+HttpBackgroundChannelParent::OnProgress(const int64_t& aProgress,
+                                        const int64_t& aProgressMax)
+{
+  LOG(("HttpBackgroundChannelParent::OnProgress [this=%p progress=%" PRId64
+       " max=%" PRId64 "]\n", this, aProgress, aProgressMax));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod<const int64_t, const int64_t>
+        (this, &HttpBackgroundChannelParent::OnProgress,
+         aProgress, aProgressMax),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  return SendOnProgress(aProgress, aProgressMax);
+}
+
+bool
+HttpBackgroundChannelParent::OnStatus(const nsresult& aStatus)
+{
+  LOG(("HttpBackgroundChannelParent::OnStatus [this=%p stauts=%" PRIx32
+       "]\n", this, static_cast<uint32_t>(aStatus)));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod<const nsresult>
+        (this, &HttpBackgroundChannelParent::OnStatus, aStatus),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  return SendOnStatus(aStatus);
+}
+
+bool
+HttpBackgroundChannelParent::OnDiversion()
+{
+  LOG(("HttpBackgroundChannelParent::OnDiversion [this=%p]\n", this));
+  AssertIsInMainProcess();
+
+  if (NS_WARN_IF(!mIPCOpened)) {
+    return false;
+  }
+
+  if (!IsOnBackgroundThread()) {
+    nsresult rv = mBackgroundThread->Dispatch(
+      NewRunnableMethod(this, &HttpBackgroundChannelParent::OnDiversion),
+      NS_DISPATCH_NORMAL);
+
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+
+    return NS_SUCCEEDED(rv);
+  }
+
+  if (!SendFlushedForDiversion()) {
+    return false;
+  }
+
+  // The listener chain should now be setup; tell HttpChannelChild to divert
+  // the OnDataAvailables and OnStopRequest to associated HttpChannelParent.
+  if (!SendDivertMessages()) {
+    return false;
+  }
+
+  return true;
+}
+
 void
 HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this));
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
   mIPCOpened = false;
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.h
+++ b/netwerk/protocol/http/HttpBackgroundChannelParent.h
@@ -34,16 +34,41 @@ public:
   // Callbacks for BackgroundChannelRegistrar to notify
   // the associated HttpChannelParent is found.
   void LinkToChannel(HttpChannelParent* aChannelParent);
 
   // Callbacks for HttpChannelParent to close the background
   // IPC channel.
   void OnChannelClosed();
 
+  // To send OnStartRequestSend message over background channel.
+  bool OnStartRequestSent();
+
+  // To send OnTransportAndData message over background channel.
+  bool OnTransportAndData(const nsresult& aChannelStatus,
+                          const nsresult& aTransportStatus,
+                          const uint64_t& aOffset,
+                          const uint32_t& aCount,
+                          const nsCString& aData);
+
+  // To send OnStopRequest message over background channel.
+  bool OnStopRequest(const nsresult& aChannelStatus,
+                     const ResourceTimingStruct& aTiming);
+
+  // To send OnProgress message over background channel.
+  bool OnProgress(const int64_t& aProgress,
+                  const int64_t& aProgressMax);
+
+  // To send OnStatus message over background channel.
+  bool OnStatus(const nsresult& aStatus);
+
+  // To send FlushedForDiversion and DivertMessages messages
+  // over background channel.
+  bool OnDiversion();
+
 protected:
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   virtual ~HttpBackgroundChannelParent();
 
   Atomic<bool> mIPCOpened;
 
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -441,16 +441,22 @@ HttpChannelChild::RecvOnStartRequest(con
   mEventQ->RunOrEnqueue(new StartRequestEvent(this, channelStatus, responseHead,
                                               useResponseHead, requestHeaders,
                                               isFromCache, cacheEntryAvailable,
                                               cacheExpirationTime,
                                               cachedCharset,
                                               securityInfoSerialization,
                                               selfAddr, peerAddr, cacheKey,
                                               altDataType, altDataLen));
+
+  MOZ_ASSERT(mBgChild);
+  if (mBgChild) {
+    mBgChild->OnStartRequestReceived();
+  }
+
   return IPC_OK();
 }
 
 void
 HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
                                  const nsHttpResponseHead& responseHead,
                                  const bool& useResponseHead,
                                  const nsHttpHeaderArray& requestHeaders,
@@ -662,32 +668,31 @@ class TransportAndDataEvent : public Cha
   HttpChannelChild* mChild;
   nsresult mChannelStatus;
   nsresult mTransportStatus;
   nsCString mData;
   uint64_t mOffset;
   uint32_t mCount;
 };
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvOnTransportAndData(const nsresult& channelStatus,
-                                         const nsresult& transportStatus,
-                                         const uint64_t& offset,
-                                         const uint32_t& count,
-                                         const nsCString& data)
+void
+HttpChannelChild::ProcessOnTransportAndData(const nsresult& aChannelStatus,
+                                            const nsresult& aTransportStatus,
+                                            const uint64_t& aOffset,
+                                            const uint32_t& aCount,
+                                            const nsCString& aData)
 {
-  LOG(("HttpChannelChild::RecvOnTransportAndData [this=%p]\n", this));
+  LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
                      "Should not be receiving any more callbacks from parent!");
-
-  mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, channelStatus,
-                                                  transportStatus, data, offset,
-                                                  count),
+  mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, aChannelStatus,
+                                                  aTransportStatus, aData,
+                                                  aOffset, aCount),
                         mDivertingToParent);
-  return IPC_OK();
 }
 
 class MaybeDivertOnDataHttpEvent : public ChannelEvent
 {
  public:
   MaybeDivertOnDataHttpEvent(HttpChannelChild* child,
                              const nsCString& data,
                              const uint64_t& offset,
@@ -905,27 +910,27 @@ class StopRequestEvent : public ChannelE
     return target.forget();
   }
  private:
   HttpChannelChild* mChild;
   nsresult mChannelStatus;
   ResourceTimingStruct mTiming;
 };
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus,
-                                    const ResourceTimingStruct& timing)
+void
+HttpChannelChild::ProcessOnStopRequest(const nsresult& aChannelStatus,
+                                       const ResourceTimingStruct& aTiming)
 {
-  LOG(("HttpChannelChild::RecvOnStopRequest [this=%p]\n", this));
+  LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "Should not be receiving any more callbacks from parent!");
 
-  mEventQ->RunOrEnqueue(new StopRequestEvent(this, channelStatus, timing),
+  mEventQ->RunOrEnqueue(new StopRequestEvent(this, aChannelStatus, aTiming),
                         mDivertingToParent);
-  return IPC_OK();
 }
 
 class MaybeDivertOnStopHttpEvent : public ChannelEvent
 {
  public:
   MaybeDivertOnStopHttpEvent(HttpChannelChild* child,
                              const nsresult& channelStatus)
   : mChild(child)
@@ -1146,22 +1151,23 @@ class ProgressEvent : public ChannelEven
     nsCOMPtr<nsIEventTarget> target = mChild->GetNeckoTarget();
     return target.forget();
   }
  private:
   HttpChannelChild* mChild;
   int64_t mProgress, mProgressMax;
 };
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvOnProgress(const int64_t& progress,
-                                 const int64_t& progressMax)
+void
+HttpChannelChild::ProcessOnProgress(const int64_t& aProgress,
+                                    const int64_t& aProgressMax)
 {
-  mEventQ->RunOrEnqueue(new ProgressEvent(this, progress, progressMax));
-  return IPC_OK();
+  LOG(("HttpChannelChild::ProcessOnProgress [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+  mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax));
 }
 
 void
 HttpChannelChild::OnProgress(const int64_t& progress,
                              const int64_t& progressMax)
 {
   LOG(("HttpChannelChild::OnProgress [this=%p progress=%" PRId64 "/%" PRId64 "]\n",
        this, progress, progressMax));
@@ -1201,21 +1207,22 @@ class StatusEvent : public ChannelEvent
     nsCOMPtr<nsIEventTarget> target = mChild->GetNeckoTarget();
     return target.forget();
   }
  private:
   HttpChannelChild* mChild;
   nsresult mStatus;
 };
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvOnStatus(const nsresult& status)
+void
+HttpChannelChild::ProcessOnStatus(const nsresult& aStatus)
 {
-  mEventQ->RunOrEnqueue(new StatusEvent(this, status));
-  return IPC_OK();
+  LOG(("HttpChannelChild::ProcessOnStatus [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
+  mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus));
 }
 
 void
 HttpChannelChild::OnStatus(const nsresult& status)
 {
   LOG(("HttpChannelChild::OnStatus [this=%p status=%" PRIx32 "]\n",
        this, static_cast<uint32_t>(status)));
 
@@ -1302,18 +1309,18 @@ HttpChannelChild::FailedAsyncOpen(const 
   if (mIPCOpen) {
     TrySendDeletingChannel();
   }
 }
 
 void
 HttpChannelChild::CleanupBackgroundChannel()
 {
-  LOG(("HttpChannelChild::CleanupBackgroundChannel [this=%p]\n", this));
-
+  LOG(("HttpChannelChild::CleanupBackgroundChannel [this=%p bgChild=%p]\n",
+       this, mBgChild.get()));
   if (!mBgChild) {
     return;
   }
 
   RefPtr<HttpBackgroundChannelChild> bgChild = mBgChild.forget();
 
   if (!NS_IsMainThread()) {
     SystemGroup::Dispatch(
@@ -1709,25 +1716,24 @@ class HttpFlushedForDiversionEvent : pub
     MOZ_ASSERT(mChild);
     nsCOMPtr<nsIEventTarget> target = mChild->GetNeckoTarget();
     return target.forget();
   }
  private:
   HttpChannelChild* mChild;
 };
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvFlushedForDiversion()
+void
+HttpChannelChild::ProcessFlushedForDiversion()
 {
-  LOG(("HttpChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
+  LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(mDivertingToParent);
 
   mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true);
-
-  return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 HttpChannelChild::RecvNotifyTrackingProtectionDisabled()
 {
   nsChannelClassifier::NotifyTrackingProtectionDisabled(this);
   return IPC_OK();
 }
@@ -1755,29 +1761,27 @@ HttpChannelChild::FlushedForDiversion()
 
 mozilla::ipc::IPCResult
 HttpChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& aInfo)
 {
   SetMatchedInfo(aInfo.list(), aInfo.provider(), aInfo.prefix());
   return IPC_OK();
 }
 
-
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvDivertMessages()
+void
+HttpChannelChild::ProcessDivertMessages()
 {
-  LOG(("HttpChannelChild::RecvDivertMessages [this=%p]\n", this));
+  LOG(("HttpChannelChild::ProcessDivertMessages [this=%p]\n", this));
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(mDivertingToParent);
   MOZ_RELEASE_ASSERT(mSuspendCount > 0);
 
   // DivertTo() has been called on parent, so we can now start sending queued
   // IPDL messages back to parent listener.
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(Resume()));
-
-  return IPC_OK();
 }
 
 // Returns true if has actually completed the redirect and cleaned up the
 // channel, or false the interception logic kicked in and we need to asyncly
 // call FinishInterceptedRedirect and CleanupRedirectingChannel.
 // The argument is an optional OverrideRunnable that we pass to the redirected
 // channel.
 bool
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -134,37 +134,27 @@ protected:
                                              const nsCString& cachedCharset,
                                              const nsCString& securityInfoSerialization,
                                              const NetAddr& selfAddr,
                                              const NetAddr& peerAddr,
                                              const int16_t& redirectCount,
                                              const uint32_t& cacheKey,
                                              const nsCString& altDataType,
                                              const int64_t& altDataLen) override;
-  mozilla::ipc::IPCResult RecvOnTransportAndData(const nsresult& channelStatus,
-                                                 const nsresult& status,
-                                                 const uint64_t& offset,
-                                                 const uint32_t& count,
-                                                 const nsCString& data) override;
-  mozilla::ipc::IPCResult RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing) override;
-  mozilla::ipc::IPCResult RecvOnProgress(const int64_t& progress, const int64_t& progressMax) override;
-  mozilla::ipc::IPCResult RecvOnStatus(const nsresult& status) override;
   mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override;
   mozilla::ipc::IPCResult RecvRedirect1Begin(const uint32_t& registrarId,
                                              const URIParams& newURI,
                                              const uint32_t& redirectFlags,
                                              const nsHttpResponseHead& responseHead,
                                              const nsCString& securityInfoSerialization,
                                              const uint64_t& channelId,
                                              const NetAddr& oldPeerAddr) override;
   mozilla::ipc::IPCResult RecvRedirect3Complete() override;
   mozilla::ipc::IPCResult RecvAssociateApplicationCache(const nsCString& groupID,
                                                         const nsCString& clientID) override;
-  mozilla::ipc::IPCResult RecvFlushedForDiversion() override;
-  mozilla::ipc::IPCResult RecvDivertMessages() override;
   mozilla::ipc::IPCResult RecvDeleteSelf() override;
   mozilla::ipc::IPCResult RecvFinishInterceptedRedirect() override;
 
   mozilla::ipc::IPCResult RecvReportSecurityMessage(const nsString& messageTag,
                                                     const nsString& messageCategory) override;
 
   mozilla::ipc::IPCResult RecvIssueDeprecationWarning(const uint32_t& warning,
                                                       const bool& asError) override;
@@ -218,16 +208,30 @@ private:
   // Get event target for processing network events.
   already_AddRefed<nsIEventTarget> GetNeckoTarget();
 
   // Get event target for ODA.
   already_AddRefed<nsIEventTarget> GetODATarget();
 
   MOZ_MUST_USE nsresult ContinueAsyncOpen();
 
+  // Callbacks while receiving OnTransportAndData/OnStopRequest/OnProgress/
+  // OnStatus/FlushedForDiversion/DivertMessages on background IPC channel.
+  void ProcessOnTransportAndData(const nsresult& aChannelStatus,
+                                 const nsresult& aStatus,
+                                 const uint64_t& aOffset,
+                                 const uint32_t& aCount,
+                                 const nsCString& aData);
+  void ProcessOnStopRequest(const nsresult& aStatusCode,
+                            const ResourceTimingStruct& aTiming);
+  void ProcessOnProgress(const int64_t& aProgress, const int64_t& aProgressMax);
+  void ProcessOnStatus(const nsresult& aStatus);
+  void ProcessFlushedForDiversion();
+  void ProcessDivertMessages();
+
   void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
   void DoOnStatus(nsIRequest* aRequest, nsresult status);
   void DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax);
   void DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream,
                          uint64_t offset, uint32_t count);
   void DoPreOnStopRequest(nsresult aStatus);
   void DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext);
 
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -1379,16 +1379,17 @@ HttpChannelParent::RecvRemoveCorsPreflig
 // HttpChannelParent::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
   LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n",
        this, aRequest));
+  MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnStartRequest if diverting is set!");
 
   RefPtr<nsHttpChannel> chan = do_QueryObject(aRequest);
   if (!chan) {
     LOG(("  aRequest is not nsHttpChannel"));
     NS_ERROR("Expecting only nsHttpChannel as aRequest in HttpChannelParent::OnStartRequest");
@@ -1487,26 +1488,38 @@ HttpChannelParent::OnStartRequest(nsIReq
                           redirectCount,
                           cacheKeyValue,
                           altDataType,
                           altDataLen))
   {
     rv = NS_ERROR_UNEXPECTED;
   }
   requestHead->Exit();
+
+  // OnStartRequest is sent to content process successfully.
+  // Notify PHttpBackgroundChannelChild that all following IPC mesasges
+  // should be run after OnStartRequest is handled.
+  if (NS_SUCCEEDED(rv)) {
+    MOZ_ASSERT(mBgParent);
+    if (!mBgParent->OnStartRequestSent()) {
+      rv = NS_ERROR_UNEXPECTED;
+    }
+  }
+
   return rv;
 }
 
 NS_IMETHODIMP
 HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
                                  nsISupports *aContext,
                                  nsresult aStatusCode)
 {
   LOG(("HttpChannelParent::OnStopRequest: [this=%p aRequest=%p status=%" PRIx32 "]\n",
        this, aRequest, static_cast<uint32_t>(aStatusCode)));
+  MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnStopRequest if diverting is set!");
   ResourceTimingStruct timing;
   mChannel->GetDomainLookupStart(&timing.domainLookupStart);
   mChannel->GetDomainLookupEnd(&timing.domainLookupEnd);
   mChannel->GetConnectStart(&timing.connectStart);
   mChannel->GetConnectEnd(&timing.connectEnd);
@@ -1520,35 +1533,42 @@ HttpChannelParent::OnStopRequest(nsIRequ
   mChannel->GetEncodedBodySize(&timing.encodedBodySize);
   // decodedBodySize can be computed in the child process so it doesn't need
   // to be passed down.
   mChannel->GetProtocolVersion(timing.protocolVersion);
 
   mChannel->GetCacheReadStart(&timing.cacheReadStart);
   mChannel->GetCacheReadEnd(&timing.cacheReadEnd);
 
-  if (mIPCClosed || !SendOnStopRequest(aStatusCode, timing))
+  // Either IPC channel is closed or background channel
+  // is ready to send OnStopRequest.
+  MOZ_ASSERT(mIPCClosed || mBgParent);
+
+  if (mIPCClosed ||
+      !mBgParent || !mBgParent->OnStopRequest(aStatusCode, timing)) {
     return NS_ERROR_UNEXPECTED;
+  }
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIStreamListener
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
                                    nsISupports *aContext,
                                    nsIInputStream *aInputStream,
                                    uint64_t aOffset,
                                    uint32_t aCount)
 {
-  LOG(("HttpChannelParent::OnDataAvailable [this=%p aRequest=%p]\n",
-       this, aRequest));
+  LOG(("HttpChannelParent::OnDataAvailable [this=%p aRequest=%p offset=%" PRIu64
+       " count=%" PRIu32 "]\n", this, aRequest, aOffset, aCount));
+  MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnDataAvailable if diverting is set!");
 
   nsresult channelStatus = NS_OK;
   mChannel->GetStatus(&channelStatus);
 
   nsresult transportStatus =
@@ -1565,18 +1585,23 @@ HttpChannelParent::OnDataAvailable(nsIRe
   }
 
   while (aCount) {
     nsresult rv = NS_ReadInputStreamToString(aInputStream, data, toRead);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
-    if (mIPCClosed || !SendOnTransportAndData(channelStatus, transportStatus,
-                                              aOffset, toRead, data)) {
+    // Either IPC channel is closed or background channel
+    // is ready to send OnTransportAndData.
+    MOZ_ASSERT(mIPCClosed || mBgParent);
+
+    if (mIPCClosed || !mBgParent ||
+        !mBgParent->OnTransportAndData(channelStatus, transportStatus,
+                                       aOffset, toRead, data)) {
       return NS_ERROR_UNEXPECTED;
     }
 
     aOffset += toRead;
     aCount -= toRead;
     toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
   }
 
@@ -1588,50 +1613,67 @@ HttpChannelParent::OnDataAvailable(nsIRe
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::OnProgress(nsIRequest *aRequest,
                               nsISupports *aContext,
                               int64_t aProgress,
                               int64_t aProgressMax)
 {
+  LOG(("HttpChannelParent::OnStatus [this=%p progress=%" PRId64 "max=%" PRId64
+       "]\n", this, aProgress, aProgressMax));
+  MOZ_ASSERT(NS_IsMainThread());
+
   // If it indicates this precedes OnDataAvailable, child can derive the value in ODA.
   if (mIgnoreProgress) {
     mIgnoreProgress = false;
     return NS_OK;
   }
 
+  // Either IPC channel is closed or background channel
+  // is ready to send OnProgress.
+  MOZ_ASSERT(mIPCClosed || mBgParent);
+
   // Send OnProgress events to the child for data upload progress notifications
   // (i.e. status == NS_NET_STATUS_SENDING_TO) or if the channel has
   // LOAD_BACKGROUND set.
-  if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax)) {
+  if (mIPCClosed || !mBgParent
+      || !mBgParent->OnProgress(aProgress, aProgressMax)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelParent::OnStatus(nsIRequest *aRequest,
                             nsISupports *aContext,
                             nsresult aStatus,
                             const char16_t *aStatusArg)
 {
+  LOG(("HttpChannelParent::OnStatus [this=%p status=%" PRIx32 "]\n",
+       this, static_cast<uint32_t>(aStatus)));
+  MOZ_ASSERT(NS_IsMainThread());
+
   // If this precedes OnDataAvailable, transportStatus will be derived in ODA.
   if (aStatus == NS_NET_STATUS_RECEIVING_FROM ||
       aStatus == NS_NET_STATUS_READING) {
     // The transport status and progress generated by ODA will be coalesced
     // into one IPC message. Therefore, we can ignore the next OnProgress event
     // since it is generated by ODA as well.
     mIgnoreProgress = true;
     return NS_OK;
   }
 
+  // Either IPC channel is closed or background channel
+  // is ready to send OnStatus.
+  MOZ_ASSERT(mIPCClosed || mBgParent);
+
   // Otherwise, send to child now
-  if (mIPCClosed || !SendOnStatus(aStatus)) {
+  if (mIPCClosed || !mBgParent || !mBgParent->OnStatus(aStatus)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIParentChannel
@@ -1958,24 +2000,21 @@ HttpChannelParent::StartDiversion()
     mDivertListener = converterListener.forget();
   }
 
   // Now mParentListener can be diverted to mDivertListener.
   DebugOnly<nsresult> rvdbg = mParentListener->DivertTo(mDivertListener);
   MOZ_ASSERT(NS_SUCCEEDED(rvdbg));
   mDivertListener = nullptr;
 
-  if (NS_WARN_IF(mIPCClosed || !SendFlushedForDiversion())) {
-    FailDiversion(NS_ERROR_UNEXPECTED);
-    return;
-  }
+  // Either IPC channel is closed or background channel
+  // is ready to send FlushedForDiversion and DivertMessages.
+  MOZ_ASSERT(mIPCClosed || mBgParent);
 
-  // The listener chain should now be setup; tell HttpChannelChild to divert
-  // the OnDataAvailables and OnStopRequest to this HttpChannelParent.
-  if (NS_WARN_IF(mIPCClosed || !SendDivertMessages())) {
+  if (NS_WARN_IF(mIPCClosed || !mBgParent || !mBgParent->OnDiversion())) {
     FailDiversion(NS_ERROR_UNEXPECTED);
     return;
   }
 }
 
 class HTTPFailDiversionEvent : public Runnable
 {
 public:
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -104,30 +104,16 @@ child:
                        nsCString           securityInfoSerialization,
                        NetAddr             selfAddr,
                        NetAddr             peerAddr,
                        int16_t             redirectCount,
                        uint32_t            cacheKey,
                        nsCString           altDataType,
                        int64_t             altDataLength);
 
-  // Combines a single OnDataAvailable and its associated OnProgress &
-  // OnStatus calls into one IPDL message
-  async OnTransportAndData(nsresult  channelStatus,
-                           nsresult  transportStatus,
-                           uint64_t  offset,
-                           uint32_t  count,
-                           nsCString data);
-
-  async OnStopRequest(nsresult channelStatus, ResourceTimingStruct timing);
-
-  async OnProgress(int64_t progress, int64_t progressMax);
-
-  async OnStatus(nsresult status);
-
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   async FailedAsyncOpen(nsresult status);
 
   // Called to initiate content channel redirect, starts talking to sinks
   // on the content process and reports result via Redirect2Verify above
   async Redirect1Begin(uint32_t           registrarId,
                        URIParams          newUri,
@@ -146,23 +132,16 @@ child:
 
   // Tell the child that tracking protection was disabled for this load.
   async NotifyTrackingProtectionDisabled();
 
   // Tell the child that the resource being loaded is on the tracking
   // protection list.
   async NotifyTrackingResource();
 
-  // Parent has been suspended for diversion; no more events to be enqueued.
-  async FlushedForDiversion();
-
-  // Child should resume processing the ChannelEventQueue, i.e. diverting any
-  // OnDataAvailable and OnStopRequest messages in the queue back to the parent.
-  async DivertMessages();
-
   // Report a security message to the console associated with this
   // channel.
   async ReportSecurityMessage(nsString messageTag, nsString messageCategory);
 
   // Tell child to delete channel (all IPDL deletes must be done from child to
   // avoid races: see bug 591708).
   async DeleteSelf();