Bug 1588241 - P2. Add ability to use lambdas for channel event handlers. r=mayhemer
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 15 Nov 2019 02:59:21 +0000
changeset 502103 a00f164555ff94b19f25485908288dcadc563624
parent 502102 2a6684436b37e2dff61a160105790e0a44d1c655
child 502104 2dda521c0591c002217453ea3e8358651ad6a45d
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1588241
milestone72.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 1588241 - P2. Add ability to use lambdas for channel event handlers. r=mayhemer Remove the need to create separate runnable classes. It's far more readable and remove the need to duplicate lots of code. We unfortunately need to capture "this" in a ref counter to get around the static analyzer complaining about capturing this by value, even thouch the ChannelEventQueue guarantees that this will outlive the event. Differential Revision: https://phabricator.services.mozilla.com/D52261
netwerk/ipc/ChannelEventQueue.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
--- a/netwerk/ipc/ChannelEventQueue.h
+++ b/netwerk/ipc/ChannelEventQueue.h
@@ -65,16 +65,68 @@ class NeckoTargetChannelEvent : public C
 
     return mChild->GetNeckoTarget();
   }
 
  protected:
   T* mChild;
 };
 
+class ChannelFunctionEvent : public ChannelEvent {
+ public:
+  ChannelFunctionEvent(
+      std::function<already_AddRefed<nsIEventTarget>()>&& aGetEventTarget,
+      std::function<void()>&& aCallback)
+      : mGetEventTarget(std::move(aGetEventTarget)),
+        mCallback(std::move(aCallback)) {}
+
+  void Run() override { mCallback(); }
+  already_AddRefed<nsIEventTarget> GetEventTarget() override {
+    return mGetEventTarget();
+  }
+
+ private:
+  const std::function<already_AddRefed<nsIEventTarget>()> mGetEventTarget;
+  const std::function<void()> mCallback;
+};
+
+// UnsafePtr is a work-around our static analyzer that requires all
+// ref-counted objects to be captured in lambda via a RefPtr
+// The ChannelEventQueue makes it safe to capture "this" by pointer only.
+// This is required as work-around to prevent cycles until bug 1596295
+// is resolved.
+template <typename T>
+class UnsafePtr {
+ public:
+  explicit UnsafePtr(T* aPtr) : mPtr(aPtr) {}
+
+  T& operator*() const { return *mPtr; }
+  T* operator->() const {
+    MOZ_ASSERT(mPtr, "dereferencing a null pointer");
+    return mPtr;
+  }
+  operator T*() const& { return mPtr; }
+  explicit operator bool() const { return mPtr != nullptr; }
+
+ private:
+  T* const mPtr;
+};
+
+class NeckoTargetChannelFunctionEvent : public ChannelFunctionEvent {
+ public:
+  template <typename T>
+  NeckoTargetChannelFunctionEvent(T* aChild, std::function<void()>&& aCallback)
+      : ChannelFunctionEvent(
+            [child = UnsafePtr<T>(aChild)]() {
+              MOZ_ASSERT(child);
+              return child->GetNeckoTarget();
+            },
+            std::move(aCallback)) {}
+};
+
 // Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a
 // queue if still dispatching previous one(s) to listeners/observers.
 // Otherwise synchronous XMLHttpRequests and/or other code that spins the
 // event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for
 // instance) to be dispatched and called before mListener->OnStartRequest has
 // completed.
 
 class ChannelEventQueue final {
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -340,163 +340,80 @@ void HttpChannelChild::OnBackgroundChild
   }
 
   if (callback) {
     nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
     neckoTarget->Dispatch(callback, NS_DISPATCH_NORMAL);
   }
 }
 
-class AssociateApplicationCacheEvent
-    : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  AssociateApplicationCacheEvent(HttpChannelChild* aChild,
-                                 const nsCString& aGroupID,
-                                 const nsCString& aClientID)
-      : NeckoTargetChannelEvent<HttpChannelChild>(aChild),
-        groupID(aGroupID),
-        clientID(aClientID) {}
-
-  void Run() override { mChild->AssociateApplicationCache(groupID, clientID); }
-
- private:
-  nsCString groupID;
-  nsCString clientID;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvAssociateApplicationCache(
-    const nsCString& groupID, const nsCString& clientID) {
+    const nsCString& aGroupID, const nsCString& aClientID) {
   LOG(("HttpChannelChild::RecvAssociateApplicationCache [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(
-      new AssociateApplicationCacheEvent(this, groupID, clientID));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this), aGroupID, aClientID]() {
+        self->AssociateApplicationCache(aGroupID, aClientID);
+      }));
   return IPC_OK();
 }
 
-void HttpChannelChild::AssociateApplicationCache(const nsCString& groupID,
-                                                 const nsCString& clientID) {
+void HttpChannelChild::AssociateApplicationCache(const nsCString& aGroupID,
+                                                 const nsCString& aClientID) {
   LOG(("HttpChannelChild::AssociateApplicationCache [this=%p]\n", this));
   mApplicationCache = new nsApplicationCache();
 
   mLoadedFromApplicationCache = true;
-  mApplicationCache->InitAsHandle(groupID, clientID);
+  mApplicationCache->InitAsHandle(aGroupID, aClientID);
 }
 
-class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  StartRequestEvent(
-      HttpChannelChild* aChild, const nsresult& aChannelStatus,
-      const nsHttpResponseHead& aResponseHead, const bool& aUseResponseHead,
-      const nsHttpHeaderArray& aRequestHeaders,
-      const ParentLoadInfoForwarderArgs& loadInfoForwarder,
-      const bool& aIsFromCache, const bool& aIsRacing,
-      const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId,
-      const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime,
-      const nsCString& aCachedCharset,
-      const nsCString& aSecurityInfoSerialization, const NetAddr& aSelfAddr,
-      const NetAddr& aPeerAddr, const uint32_t& aCacheKey,
-      const nsCString& altDataType, const int64_t& altDataLen,
-      const bool& deliveringAltData, const bool& aApplyConversion,
-      const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming,
-      const bool& aAllRedirectsSameOrigin)
-      : NeckoTargetChannelEvent<HttpChannelChild>(aChild),
-        mChannelStatus(aChannelStatus),
-        mResponseHead(aResponseHead),
-        mRequestHeaders(aRequestHeaders),
-        mUseResponseHead(aUseResponseHead),
-        mApplyConversion(aApplyConversion),
-        mIsFromCache(aIsFromCache),
-        mIsRacing(aIsRacing),
-        mCacheEntryAvailable(aCacheEntryAvailable),
-        mCacheEntryId(aCacheEntryId),
-        mCacheFetchCount(aCacheFetchCount),
-        mCacheExpirationTime(aCacheExpirationTime),
-        mCachedCharset(aCachedCharset),
-        mSecurityInfoSerialization(aSecurityInfoSerialization),
-        mSelfAddr(aSelfAddr),
-        mPeerAddr(aPeerAddr),
-        mCacheKey(aCacheKey),
-        mAltDataType(altDataType),
-        mAltDataLen(altDataLen),
-        mDeliveringAltData(deliveringAltData),
-        mLoadInfoForwarder(loadInfoForwarder),
-        mIsResolvedByTRR(aIsResolvedByTRR),
-        mTiming(aTiming),
-        mAllRedirectsSameOrigin(aAllRedirectsSameOrigin) {}
-
-  void Run() override {
-    LOG(("StartRequestEvent [this=%p]\n", mChild));
-    mChild->OnStartRequest(
-        mChannelStatus, mResponseHead, mUseResponseHead, mRequestHeaders,
-        mLoadInfoForwarder, mIsFromCache, mIsRacing, mCacheEntryAvailable,
-        mCacheEntryId, mCacheFetchCount, mCacheExpirationTime, mCachedCharset,
-        mSecurityInfoSerialization, mSelfAddr, mPeerAddr, mCacheKey,
-        mAltDataType, mAltDataLen, mDeliveringAltData, mApplyConversion,
-        mIsResolvedByTRR, mTiming, mAllRedirectsSameOrigin);
-  }
-
- private:
-  nsresult mChannelStatus;
-  nsHttpResponseHead mResponseHead;
-  nsHttpHeaderArray mRequestHeaders;
-  bool mUseResponseHead;
-  bool mApplyConversion;
-  bool mIsFromCache;
-  bool mIsRacing;
-  bool mCacheEntryAvailable;
-  uint64_t mCacheEntryId;
-  int32_t mCacheFetchCount;
-  uint32_t mCacheExpirationTime;
-  nsCString mCachedCharset;
-  nsCString mSecurityInfoSerialization;
-  NetAddr mSelfAddr;
-  NetAddr mPeerAddr;
-  uint32_t mCacheKey;
-  nsCString mAltDataType;
-  int64_t mAltDataLen;
-  bool mDeliveringAltData;
-  ParentLoadInfoForwarderArgs mLoadInfoForwarder;
-  bool mIsResolvedByTRR;
-  ResourceTimingStruct mTiming;
-  bool mAllRedirectsSameOrigin;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvOnStartRequest(
-    const nsresult& channelStatus, const nsHttpResponseHead& responseHead,
-    const bool& useResponseHead, const nsHttpHeaderArray& requestHeaders,
-    const ParentLoadInfoForwarderArgs& loadInfoForwarder,
-    const bool& isFromCache, const bool& isRacing,
-    const bool& cacheEntryAvailable, const uint64_t& cacheEntryId,
-    const int32_t& cacheFetchCount, const uint32_t& cacheExpirationTime,
-    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,
-    const bool& deliveringAltData, const bool& aApplyConversion,
+    const nsresult& aChannelStatus, const nsHttpResponseHead& aResponseHead,
+    const bool& aUseResponseHead, const nsHttpHeaderArray& aRequestHeaders,
+    const ParentLoadInfoForwarderArgs& aLoadInfoForwarder,
+    const bool& aIsFromCache, const bool& aIsRacing,
+    const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId,
+    const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime,
+    const nsCString& aCachedCharset, const nsCString& aSecurityInfoSerialization,
+    const NetAddr& aSelfAddr, const NetAddr& aPeerAddr,
+    const int16_t& aRedirectCount, const uint32_t& aCacheKey,
+    const nsCString& aAltDataType, const int64_t& aAltDataLen,
+    const bool& aDeliveringAltData, const bool& aApplyConversion,
     const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming,
     const bool& aAllRedirectsSameOrigin) {
   AUTO_PROFILER_LABEL("HttpChannelChild::RecvOnStartRequest", NETWORK);
   LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   // stage, as they are set in the listener's OnStartRequest.
   MOZ_RELEASE_ASSERT(
       !mFlushedForDiversion,
       "mFlushedForDiversion should be unset before OnStartRequest!");
   MOZ_RELEASE_ASSERT(
       !mDivertingToParent,
       "mDivertingToParent should be unset before OnStartRequest!");
 
-  mRedirectCount = redirectCount;
-
-  mEventQ->RunOrEnqueue(new StartRequestEvent(
-      this, channelStatus, responseHead, useResponseHead, requestHeaders,
-      loadInfoForwarder, isFromCache, isRacing, cacheEntryAvailable,
-      cacheEntryId, cacheFetchCount, cacheExpirationTime, cachedCharset,
-      securityInfoSerialization, selfAddr, peerAddr, cacheKey, altDataType,
-      altDataLen, deliveringAltData, aApplyConversion, aIsResolvedByTRR,
-      aTiming, aAllRedirectsSameOrigin));
+  mRedirectCount = aRedirectCount;
+
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this,
+      [self = UnsafePtr<HttpChannelChild>(this), aChannelStatus, aResponseHead,
+       aUseResponseHead, aRequestHeaders, aLoadInfoForwarder, aIsFromCache,
+       aIsRacing, aCacheEntryAvailable, aCacheEntryId, aCacheFetchCount,
+       aCacheExpirationTime, aCachedCharset, aSecurityInfoSerialization,
+       aSelfAddr, aPeerAddr, aCacheKey, aAltDataType, aAltDataLen,
+       aDeliveringAltData, aApplyConversion, aIsResolvedByTRR, aTiming,
+       aAllRedirectsSameOrigin]() {
+        self->OnStartRequest(
+            aChannelStatus, aResponseHead, aUseResponseHead, aRequestHeaders,
+            aLoadInfoForwarder, aIsFromCache, aIsRacing, aCacheEntryAvailable,
+            aCacheEntryId, aCacheFetchCount, aCacheExpirationTime,
+            aCachedCharset, aSecurityInfoSerialization, aSelfAddr, aPeerAddr,
+            aCacheKey, aAltDataType, aAltDataLen, aDeliveringAltData,
+            aApplyConversion, aIsResolvedByTRR, aTiming,
+            aAllRedirectsSameOrigin);
+      }));
 
   {
     // Child's mEventQ is to control the execution order of the IPC messages
     // from both main thread IPDL and PBackground IPDL.
     // To guarantee the ordering, PBackground IPC messages that are sent after
     // OnStartRequest will be throttled until OnStartRequest hits the Child's
     // mEventQ.
     MutexAutoLock lock(mBgChildMutex);
@@ -510,26 +427,26 @@ mozilla::ipc::IPCResult HttpChannelChild
           NS_DISPATCH_NORMAL);
     }
   }
 
   return IPC_OK();
 }
 
 void HttpChannelChild::OnStartRequest(
-    const nsresult& channelStatus, const nsHttpResponseHead& responseHead,
-    const bool& useResponseHead, const nsHttpHeaderArray& requestHeaders,
-    const ParentLoadInfoForwarderArgs& loadInfoForwarder,
-    const bool& isFromCache, const bool& isRacing,
-    const bool& cacheEntryAvailable, const uint64_t& cacheEntryId,
-    const int32_t& cacheFetchCount, const uint32_t& cacheExpirationTime,
-    const nsCString& cachedCharset, const nsCString& securityInfoSerialization,
-    const NetAddr& selfAddr, const NetAddr& peerAddr, const uint32_t& cacheKey,
-    const nsCString& altDataType, const int64_t& altDataLen,
-    const bool& deliveringAltData, const bool& aApplyConversion,
+    const nsresult& aChannelStatus, const nsHttpResponseHead& aResponseHead,
+    const bool& aUseResponseHead, const nsHttpHeaderArray& aRequestHeaders,
+    const ParentLoadInfoForwarderArgs& aLoadInfoForwarder,
+    const bool& aIsFromCache, const bool& aIsRacing,
+    const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId,
+    const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime,
+    const nsCString& aCachedCharset, const nsCString& aSecurityInfoSerialization,
+    const NetAddr& aSelfAddr, const NetAddr& aPeerAddr, const uint32_t& aCacheKey,
+    const nsCString& aAltDataType, const int64_t& aAltDataLen,
+    const bool& aDeliveringAltData, const bool& aApplyConversion,
     const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming,
     const bool& aAllRedirectsSameOrigin) {
   LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
 
   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   // stage, as they are set in the listener's OnStartRequest.
   MOZ_RELEASE_ASSERT(
       !mFlushedForDiversion,
@@ -542,61 +459,61 @@ void HttpChannelChild::OnStartRequest(
   // OnStartRequest/OnStopRequest/OnDataAvailable IPC messages that need to
   // be handled. In that case we just ignore them to avoid calling the listener
   // twice.
   if (mOnStartRequestCalled && mIPCActorDeleted) {
     return;
   }
 
   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
-    mStatus = channelStatus;
+    mStatus = aChannelStatus;
   }
 
   // Cookies headers should not be visible to the child process
-  MOZ_ASSERT(!requestHeaders.HasHeader(nsHttp::Cookie));
-  MOZ_ASSERT(!nsHttpResponseHead(responseHead).HasHeader(nsHttp::Set_Cookie));
-
-  if (useResponseHead && !mCanceled)
-    mResponseHead = new nsHttpResponseHead(responseHead);
-
-  if (!securityInfoSerialization.IsEmpty()) {
-    nsresult rv = NS_DeserializeObject(securityInfoSerialization,
+  MOZ_ASSERT(!aRequestHeaders.HasHeader(nsHttp::Cookie));
+  MOZ_ASSERT(!nsHttpResponseHead(aResponseHead).HasHeader(nsHttp::Set_Cookie));
+
+  if (aUseResponseHead && !mCanceled)
+    mResponseHead = new nsHttpResponseHead(aResponseHead);
+
+  if (!aSecurityInfoSerialization.IsEmpty()) {
+    nsresult rv = NS_DeserializeObject(aSecurityInfoSerialization,
                                        getter_AddRefs(mSecurityInfo));
     MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
                           "Deserializing security info should not fail");
     Unused << rv;  // So we don't get an unused error in release builds.
   }
 
-  ipc::MergeParentLoadInfoForwarder(loadInfoForwarder, mLoadInfo);
-
-  mIsFromCache = isFromCache;
-  mIsRacing = isRacing;
-  mCacheEntryAvailable = cacheEntryAvailable;
-  mCacheEntryId = cacheEntryId;
-  mCacheFetchCount = cacheFetchCount;
-  mCacheExpirationTime = cacheExpirationTime;
-  mCachedCharset = cachedCharset;
-  mSelfAddr = selfAddr;
-  mPeerAddr = peerAddr;
-
-  mAvailableCachedAltDataType = altDataType;
-  mDeliveringAltData = deliveringAltData;
-  mAltDataLength = altDataLen;
+  ipc::MergeParentLoadInfoForwarder(aLoadInfoForwarder, mLoadInfo);
+
+  mIsFromCache = aIsFromCache;
+  mIsRacing = aIsRacing;
+  mCacheEntryAvailable = aCacheEntryAvailable;
+  mCacheEntryId = aCacheEntryId;
+  mCacheFetchCount = aCacheFetchCount;
+  mCacheExpirationTime = aCacheExpirationTime;
+  mCachedCharset = aCachedCharset;
+  mSelfAddr = aSelfAddr;
+  mPeerAddr = aPeerAddr;
+
+  mAvailableCachedAltDataType = aAltDataType;
+  mDeliveringAltData = aDeliveringAltData;
+  mAltDataLength = aAltDataLen;
   mResolvedByTRR = aIsResolvedByTRR;
 
   SetApplyConversion(aApplyConversion);
 
   mAfterOnStartRequestBegun = true;
 
   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
-  mCacheKey = cacheKey;
+  mCacheKey = aCacheKey;
 
   // replace our request headers with what actually got sent in the parent
-  mRequestHead.SetHeaders(requestHeaders);
+  mRequestHead.SetHeaders(aRequestHeaders);
 
   // Note: this is where we would notify "http-on-examine-response" observers.
   // We have deliberately disabled this for child processes (see bug 806753)
   //
   // gHttpHandler->OnExamineResponse(this);
 
   mTracingEnabled = false;
 
@@ -713,176 +630,138 @@ void HttpChannelChild::DoOnStartRequest(
   if (NS_FAILED(rv)) {
     Cancel(rv);
   } else if (listener) {
     mListener = listener;
     mCompressListener = listener;
   }
 }
 
-class TransportAndDataEvent : public ChannelEvent {
- public:
-  TransportAndDataEvent(HttpChannelChild* child, const nsresult& channelStatus,
-                        const nsresult& transportStatus, const nsCString& data,
-                        const uint64_t& offset, const uint32_t& count)
-      : mChild(child),
-        mChannelStatus(channelStatus),
-        mTransportStatus(transportStatus),
-        mData(data),
-        mOffset(offset),
-        mCount(count) {}
-
-  void Run() override {
-    mChild->OnTransportAndData(mChannelStatus, mTransportStatus, mOffset,
-                               mCount, mData);
-  }
-
-  already_AddRefed<nsIEventTarget> GetEventTarget() override {
-    MOZ_ASSERT(mChild);
-    nsCOMPtr<nsIEventTarget> target = mChild->GetODATarget();
-    return target.forget();
-  }
-
- private:
-  HttpChannelChild* mChild;
-  nsresult mChannelStatus;
-  nsresult mTransportStatus;
-  nsCString mData;
-  uint64_t mOffset;
-  uint32_t mCount;
-};
-
 void HttpChannelChild::ProcessOnTransportAndData(
     const nsresult& aChannelStatus, const nsresult& aTransportStatus,
     const uint64_t& aOffset, const uint32_t& aCount, const nsCString& aData) {
   LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this));
   MOZ_ASSERT(OnSocketThread());
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
                      "Should not be receiving any more callbacks from parent!");
   mEventQ->RunOrEnqueue(
-      new TransportAndDataEvent(this, aChannelStatus, aTransportStatus, aData,
-                                aOffset, aCount),
+      new ChannelFunctionEvent([self = UnsafePtr<HttpChannelChild>(
+                                    this)]() { return self->GetODATarget(); },
+                               [self = UnsafePtr<HttpChannelChild>(this),
+                                aChannelStatus, aTransportStatus, aOffset,
+                                aCount, aData]() {
+                                 self->OnTransportAndData(
+                                     aChannelStatus, aTransportStatus, aOffset,
+                                     aCount, aData);
+                               }),
       mDivertingToParent);
 }
 
-class MaybeDivertOnDataHttpEvent
-    : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  MaybeDivertOnDataHttpEvent(HttpChannelChild* child, const nsCString& data,
-                             const uint64_t& offset, const uint32_t& count)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child),
-        mData(data),
-        mOffset(offset),
-        mCount(count) {}
-
-  void Run() override { mChild->MaybeDivertOnData(mData, mOffset, mCount); }
-
- private:
-  nsCString mData;
-  uint64_t mOffset;
-  uint32_t mCount;
-};
-
-void HttpChannelChild::MaybeDivertOnData(const nsCString& data,
-                                         const uint64_t& offset,
-                                         const uint32_t& count) {
+void HttpChannelChild::MaybeDivertOnData(const nsCString& aData,
+                                         const uint64_t& aOffset,
+                                         const uint32_t& aCount) {
   LOG(("HttpChannelChild::MaybeDivertOnData [this=%p]", this));
 
   if (mDivertingToParent) {
-    SendDivertOnDataAvailable(data, offset, count);
+    SendDivertOnDataAvailable(aData, aOffset, aCount);
   }
 }
 
-void HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
-                                          const nsresult& transportStatus,
-                                          const uint64_t& offset,
-                                          const uint32_t& count,
-                                          const nsCString& data) {
+void HttpChannelChild::OnTransportAndData(const nsresult& aChannelStatus,
+                                          const nsresult& aTransportStatus,
+                                          const uint64_t& aOffset,
+                                          const uint32_t& aCount,
+                                          const nsCString& aData) {
   LOG(("HttpChannelChild::OnTransportAndData [this=%p]\n", this));
 
   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
-    mStatus = channelStatus;
+    mStatus = aChannelStatus;
   }
 
   // For diversion to parent, just SendDivertOnDataAvailable.
   if (mDivertingToParent) {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_RELEASE_ASSERT(
         !mFlushedForDiversion,
         "Should not be processing any more callbacks from parent!");
 
-    SendDivertOnDataAvailable(data, offset, count);
+    SendDivertOnDataAvailable(aData, aOffset, aCount);
     return;
   }
 
-  if (mCanceled) return;
+  if (mCanceled) {
+    return;
+  }
 
   if (mUnknownDecoderInvolved) {
     LOG(("UnknownDecoder is involved queue OnDataAvailable call. [this=%p]",
          this));
     MOZ_ASSERT(NS_IsMainThread());
     mUnknownDecoderEventQ.AppendElement(
-        MakeUnique<MaybeDivertOnDataHttpEvent>(this, data, offset, count));
+        MakeUnique<NeckoTargetChannelFunctionEvent>(
+            this,
+            [self = UnsafePtr<HttpChannelChild>(this), aData, aOffset,
+             aCount]() { self->MaybeDivertOnData(aData, aOffset, aCount); }));
   }
 
   // Hold queue lock throughout all three calls, else we might process a later
   // necko msg in between them.
   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
   int64_t progressMax;
   if (NS_FAILED(GetContentLength(&progressMax))) {
     progressMax = -1;
   }
 
-  const int64_t progress = offset + count;
+  const int64_t progress = aOffset + aCount;
 
   // OnTransportAndData will be run on retargeted thread if applicable, however
   // OnStatus/OnProgress event can only be fired on main thread. We need to
   // dispatch the status/progress event handling back to main thread with the
   // appropriate event target for networking.
   if (NS_IsMainThread()) {
-    DoOnStatus(this, transportStatus);
+    DoOnStatus(this, aTransportStatus);
     DoOnProgress(this, progress, progressMax);
   } else {
     RefPtr<HttpChannelChild> self = this;
     nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
     MOZ_ASSERT(neckoTarget);
 
     DebugOnly<nsresult> rv = neckoTarget->Dispatch(
         NS_NewRunnableFunction(
             "net::HttpChannelChild::OnTransportAndData",
-            [self, transportStatus, progress, progressMax]() {
-              self->DoOnStatus(self, transportStatus);
+            [self, aTransportStatus, progress, progressMax]() {
+              self->DoOnStatus(self, aTransportStatus);
               self->DoOnProgress(self, progress, progressMax);
             }),
         NS_DISPATCH_NORMAL);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   // OnDataAvailable
   //
   // NOTE: the OnDataAvailable contract requires the client to read all the data
   // in the inputstream.  This code relies on that ('data' will go away after
   // this function).  Apparently the previous, non-e10s behavior was to actually
   // support only reading part of the data, allowing later calls to read the
   // rest.
   nsCOMPtr<nsIInputStream> stringStream;
   nsresult rv =
       NS_NewByteInputStream(getter_AddRefs(stringStream),
-                            MakeSpan(data).To(count), NS_ASSIGNMENT_DEPEND);
+                            MakeSpan(aData).To(aCount), NS_ASSIGNMENT_DEPEND);
   if (NS_FAILED(rv)) {
     Cancel(rv);
     return;
   }
 
-  DoOnDataAvailable(this, nullptr, stringStream, offset, count);
+  DoOnDataAvailable(this, nullptr, stringStream, aOffset, aCount);
   stringStream->Close();
 
   if (NeedToReportBytesRead()) {
-    mUnreportBytesRead += count;
+    mUnreportBytesRead += aCount;
     if (mUnreportBytesRead >= gHttpHandler->SendWindowSize() >> 2) {
       if (NS_IsMainThread()) {
         Unused << SendBytesRead(mUnreportBytesRead);
       } else {
         // PHttpChannel connects to the main thread
         RefPtr<HttpChannelChild> self = this;
         int32_t bytesRead = mUnreportBytesRead;
         nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
@@ -962,172 +841,146 @@ void HttpChannelChild::DoOnProgress(nsIR
       mProgressSink->OnProgress(aRequest, nullptr, progress, progressMax);
     }
   }
 }
 
 void HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest,
                                          nsISupports* aContext,
                                          nsIInputStream* aStream,
-                                         uint64_t offset, uint32_t count) {
+                                         uint64_t aOffset, uint32_t aCount) {
   AUTO_PROFILER_LABEL("HttpChannelChild::DoOnDataAvailable", NETWORK);
   LOG(("HttpChannelChild::DoOnDataAvailable [this=%p]\n", this));
   if (mCanceled) return;
 
   if (mListener) {
     nsCOMPtr<nsIStreamListener> listener(mListener);
-    nsresult rv = listener->OnDataAvailable(aRequest, aStream, offset, count);
+    nsresult rv = listener->OnDataAvailable(aRequest, aStream, aOffset, aCount);
     if (NS_FAILED(rv)) {
       CancelOnMainThread(rv);
     }
   }
 }
 
-class StopRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  StopRequestEvent(HttpChannelChild* child, const nsresult& channelStatus,
-                   const ResourceTimingStruct& timing,
-                   const nsHttpHeaderArray& aResponseTrailers)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child),
-        mChannelStatus(channelStatus),
-        mTiming(timing),
-        mResponseTrailers(aResponseTrailers) {}
-
-  void Run() override {
-    mChild->OnStopRequest(mChannelStatus, mTiming, mResponseTrailers);
-  }
-
- private:
-  nsresult mChannelStatus;
-  ResourceTimingStruct mTiming;
-  nsHttpHeaderArray mResponseTrailers;
-};
-
 void HttpChannelChild::ProcessOnStopRequest(
     const nsresult& aChannelStatus, const ResourceTimingStruct& aTiming,
     const nsHttpHeaderArray& aResponseTrailers) {
   LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this));
   MOZ_ASSERT(OnSocketThread());
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
                      "Should not be receiving any more callbacks from parent!");
 
-  mEventQ->RunOrEnqueue(
-      new StopRequestEvent(this, aChannelStatus, aTiming, aResponseTrailers),
-      mDivertingToParent);
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+                            this,
+                            [self = UnsafePtr<HttpChannelChild>(this),
+                             aChannelStatus, aTiming, aResponseTrailers]() {
+                              self->OnStopRequest(aChannelStatus, aTiming,
+                                                  aResponseTrailers);
+                            }),
+                        mDivertingToParent);
 }
 
-class MaybeDivertOnStopHttpEvent
-    : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  MaybeDivertOnStopHttpEvent(HttpChannelChild* child,
-                             const nsresult& channelStatus)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child),
-        mChannelStatus(channelStatus) {}
-
-  void Run() override { mChild->MaybeDivertOnStop(mChannelStatus); }
-
- private:
-  nsresult mChannelStatus;
-};
-
 void HttpChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus) {
   LOG(
       ("HttpChannelChild::MaybeDivertOnStop [this=%p, "
        "mDivertingToParent=%d status=%" PRIx32 "]",
        this, static_cast<bool>(mDivertingToParent),
        static_cast<uint32_t>(aChannelStatus)));
   if (mDivertingToParent) {
     SendDivertOnStopRequest(aChannelStatus);
   }
 }
 
 void HttpChannelChild::OnStopRequest(
-    const nsresult& channelStatus, const ResourceTimingStruct& timing,
+    const nsresult& aChannelStatus, const ResourceTimingStruct& aTiming,
     const nsHttpHeaderArray& aResponseTrailers) {
   LOG(("HttpChannelChild::OnStopRequest [this=%p status=%" PRIx32 "]\n", this,
-       static_cast<uint32_t>(channelStatus)));
+       static_cast<uint32_t>(aChannelStatus)));
   MOZ_ASSERT(NS_IsMainThread());
 
   // If this channel was aborted by ActorDestroy, then there may be other
   // OnStartRequest/OnStopRequest/OnDataAvailable IPC messages that need to
   // be handled. In that case we just ignore them to avoid calling the listener
   // twice.
   if (mOnStopRequestCalled && mIPCActorDeleted) {
     return;
   }
 
   if (mDivertingToParent) {
     MOZ_RELEASE_ASSERT(
         !mFlushedForDiversion,
         "Should not be processing any more callbacks from parent!");
 
-    SendDivertOnStopRequest(channelStatus);
+    SendDivertOnStopRequest(aChannelStatus);
     return;
   }
 
   if (mUnknownDecoderInvolved) {
     LOG(("UnknownDecoder is involved queue OnStopRequest call. [this=%p]",
          this));
     MOZ_ASSERT(NS_IsMainThread());
     mUnknownDecoderEventQ.AppendElement(
-        MakeUnique<MaybeDivertOnStopHttpEvent>(this, channelStatus));
+        MakeUnique<NeckoTargetChannelFunctionEvent>(
+            this, [self = UnsafePtr<HttpChannelChild>(this), aChannelStatus]() {
+              self->MaybeDivertOnStop(aChannelStatus);
+            }));
   }
 
   nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
   if (conv) {
     conv->GetDecodedDataLength(&mDecodedBodySize);
   }
 
-  mTransactionTimings.domainLookupStart = timing.domainLookupStart;
-  mTransactionTimings.domainLookupEnd = timing.domainLookupEnd;
-  mTransactionTimings.connectStart = timing.connectStart;
-  mTransactionTimings.tcpConnectEnd = timing.tcpConnectEnd;
-  mTransactionTimings.secureConnectionStart = timing.secureConnectionStart;
-  mTransactionTimings.connectEnd = timing.connectEnd;
-  mTransactionTimings.requestStart = timing.requestStart;
-  mTransactionTimings.responseStart = timing.responseStart;
-  mTransactionTimings.responseEnd = timing.responseEnd;
+  mTransactionTimings.domainLookupStart = aTiming.domainLookupStart;
+  mTransactionTimings.domainLookupEnd = aTiming.domainLookupEnd;
+  mTransactionTimings.connectStart = aTiming.connectStart;
+  mTransactionTimings.tcpConnectEnd = aTiming.tcpConnectEnd;
+  mTransactionTimings.secureConnectionStart = aTiming.secureConnectionStart;
+  mTransactionTimings.connectEnd = aTiming.connectEnd;
+  mTransactionTimings.requestStart = aTiming.requestStart;
+  mTransactionTimings.responseStart = aTiming.responseStart;
+  mTransactionTimings.responseEnd = aTiming.responseEnd;
 
   // Do not overwrite or adjust the original mAsyncOpenTime by timing.fetchStart
   // We must use the original child process time in order to account for child
   // side work and IPC transit overhead.
   // XXX: This depends on TimeStamp being equivalent across processes.
   // This is true for modern hardware but for older platforms it is not always
   // true.
 
-  mRedirectStartTimeStamp = timing.redirectStart;
-  mRedirectEndTimeStamp = timing.redirectEnd;
-  mTransferSize = timing.transferSize;
-  mEncodedBodySize = timing.encodedBodySize;
-  mProtocolVersion = timing.protocolVersion;
-
-  mCacheReadStart = timing.cacheReadStart;
-  mCacheReadEnd = timing.cacheReadEnd;
+  mRedirectStartTimeStamp = aTiming.redirectStart;
+  mRedirectEndTimeStamp = aTiming.redirectEnd;
+  mTransferSize = aTiming.transferSize;
+  mEncodedBodySize = aTiming.encodedBodySize;
+  mProtocolVersion = aTiming.protocolVersion;
+
+  mCacheReadStart = aTiming.cacheReadStart;
+  mCacheReadEnd = aTiming.cacheReadEnd;
 
 #ifdef MOZ_GECKO_PROFILER
   if (profiler_can_accept_markers()) {
     int32_t priority = PRIORITY_NORMAL;
     GetPriority(&priority);
     profiler_add_network_marker(
         mURI, priority, mChannelId, NetworkLoadType::LOAD_STOP,
         mLastStatusReported, TimeStamp::Now(), mTransferSize, kCacheUnknown,
         &mTransactionTimings, nullptr, std::move(mSource));
   }
 #endif
 
   mResponseTrailers = new nsHttpHeaderArray(aResponseTrailers);
 
-  DoPreOnStopRequest(channelStatus);
+  DoPreOnStopRequest(aChannelStatus);
 
   {  // We must flush the queue before we Send__delete__
     // (although we really shouldn't receive any msgs after OnStop),
     // so make sure this goes out of scope before then.
     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
-    DoOnStopRequest(this, channelStatus, nullptr);
+    DoOnStopRequest(this, aChannelStatus, nullptr);
     // DoOnStopRequest() calls ReleaseListeners()
   }
 
   // If unknownDecoder is involved and the received content is short we will
   // know whether we need to divert to parent only after OnStopRequest of the
   // listeners chain is called in DoOnStopRequest. At that moment
   // unknownDecoder will call OnStartRequest of the real listeners of the
   // channel including the OnStopRequest of UrlLoader which decides whether we
@@ -1142,17 +995,17 @@ void HttpChannelChild::OnStopRequest(
 
   CleanupBackgroundChannel();
 
   // If there is a possibility we might want to write alt data to the cache
   // entry, we keep the channel alive. We still send the DocumentChannelCleanup
   // message but request the cache entry to be kept by the parent.
   // If the channel has failed, the cache entry is in a non-writtable state and
   // we want to release it to not block following consumers.
-  if (NS_SUCCEEDED(channelStatus) && !mPreferredCachedAltDataTypes.IsEmpty()) {
+  if (NS_SUCCEEDED(aChannelStatus) && !mPreferredCachedAltDataTypes.IsEmpty()) {
     mKeptAlive = true;
     SendDocumentChannelCleanup(false);  // don't clear cache entry
     return;
   }
 
   if (mLoadFlags & LOAD_DOCUMENT_URI) {
     // Keep IPDL channel open, but only for updating security info.
     // If IPDL is already closed, then do nothing.
@@ -1260,76 +1113,46 @@ void HttpChannelChild::DoOnStopRequest(n
   if (!mPreferredCachedAltDataTypes.IsEmpty()) {
     mAltDataCacheEntryAvailable = mCacheEntryAvailable;
   }
   mCacheEntryAvailable = false;
 
   if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
 }
 
-class ProgressEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  ProgressEvent(HttpChannelChild* child, const int64_t& progress,
-                const int64_t& progressMax)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child),
-        mProgress(progress),
-        mProgressMax(progressMax) {}
-
-  void Run() override {
-    AutoEventEnqueuer ensureSerialDispatch(mChild->mEventQ);
-    mChild->DoOnProgress(mChild, mProgress, mProgressMax);
-  }
-
- private:
-  int64_t mProgress, mProgressMax;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvOnProgress(
     const int64_t& aProgress, const int64_t& aProgressMax) {
   LOG(("HttpChannelChild::RecvOnProgress [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this,
+      [self = UnsafePtr<HttpChannelChild>(this), aProgress, aProgressMax]() {
+        AutoEventEnqueuer ensureSerialDispatch(self->mEventQ);
+        self->DoOnProgress(self, aProgress, aProgressMax);
+      }));
   return IPC_OK();
 }
 
-class StatusEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  StatusEvent(HttpChannelChild* child, const nsresult& status)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child), mStatus(status) {}
-
-  void Run() override {
-    AutoEventEnqueuer ensureSerialDispatch(mChild->mEventQ);
-    mChild->DoOnStatus(mChild, mStatus);
-  }
-
- private:
-  nsresult mStatus;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvOnStatus(
     const nsresult& aStatus) {
   LOG(("HttpChannelChild::RecvOnStatus [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this), aStatus]() {
+        AutoEventEnqueuer ensureSerialDispatch(self->mEventQ);
+        self->DoOnStatus(self, aStatus);
+      }));
   return IPC_OK();
 }
 
-class FailedAsyncOpenEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  FailedAsyncOpenEvent(HttpChannelChild* child, const nsresult& status)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child), mStatus(status) {}
-
-  void Run() override { mChild->FailedAsyncOpen(mStatus); }
-
- private:
-  nsresult mStatus;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvFailedAsyncOpen(
-    const nsresult& status) {
+    const nsresult& aStatus) {
   LOG(("HttpChannelChild::RecvFailedAsyncOpen [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new FailedAsyncOpenEvent(this, status));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this), aStatus]() {
+        self->FailedAsyncOpen(aStatus);
+      }));
   return IPC_OK();
 }
 
 // We need to have an implementation of this function just so that we can keep
 // all references to mCallOnResume of type HttpChannelChild:  it's not OK in C++
 // to set a member function ptr to a base class function.
 void HttpChannelChild::HandleAsyncAbort() {
   HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort();
@@ -1399,26 +1222,21 @@ void HttpChannelChild::DoNotifyListenerC
 
   MaybeCallSynthesizedCallback();
 }
 
 void HttpChannelChild::DoAsyncAbort(nsresult aStatus) {
   Unused << AsyncAbort(aStatus);
 }
 
-class DeleteSelfEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  explicit DeleteSelfEvent(HttpChannelChild* child)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child) {}
-  void Run() override { mChild->DeleteSelf(); }
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvDeleteSelf() {
   LOG(("HttpChannelChild::RecvDeleteSelf [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new DeleteSelfEvent(this));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this,
+      [self = UnsafePtr<HttpChannelChild>(this)]() { self->DeleteSelf(); }));
   return IPC_OK();
 }
 
 HttpChannelChild::OverrideRunnable::OverrideRunnable(
     HttpChannelChild* aChannel, HttpChannelChild* aNewChannel,
     InterceptStreamListener* aListener, nsIInputStream* aInput,
     nsIInterceptedBodyCallback* aCallback, nsAutoPtr<nsHttpResponseHead>& aHead,
     nsICacheInfoChannel* aCacheInfo)
@@ -1492,24 +1310,16 @@ mozilla::ipc::IPCResult HttpChannelChild
                         this, &HttpChannelChild::FinishInterceptedRedirect),
       NS_DISPATCH_NORMAL);
 
   return IPC_OK();
 }
 
 void HttpChannelChild::DeleteSelf() { Send__delete__(this); }
 
-class ContinueDoNotifyListenerEvent
-    : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  explicit ContinueDoNotifyListenerEvent(HttpChannelChild* child)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child) {}
-  void Run() override { mChild->ContinueDoNotifyListener(); }
-};
-
 void HttpChannelChild::DoNotifyListener() {
   LOG(("HttpChannelChild::DoNotifyListener this=%p", this));
   MOZ_ASSERT(NS_IsMainThread());
 
   // In case nsHttpChannel::OnStartRequest wasn't called (e.g. due to flag
   // LOAD_ONLY_IF_MODIFIED) we want to set mAfterOnStartRequestBegun to true
   // before notifying listener.
   if (!mAfterOnStartRequestBegun) {
@@ -1518,17 +1328,20 @@ void HttpChannelChild::DoNotifyListener(
 
   if (mListener && !mOnStartRequestCalled) {
     nsCOMPtr<nsIStreamListener> listener = mListener;
     mOnStartRequestCalled = true;  // avoid reentrancy bugs by setting this now
     listener->OnStartRequest(this);
   }
   mOnStartRequestCalled = true;
 
-  mEventQ->RunOrEnqueue(new ContinueDoNotifyListenerEvent(this));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this)] {
+        self->ContinueDoNotifyListener();
+      }));
 }
 
 void HttpChannelChild::ContinueDoNotifyListener() {
   LOG(("HttpChannelChild::ContinueDoNotifyListener this=%p", this));
   MOZ_ASSERT(NS_IsMainThread());
 
   // Make sure mIsPending is set to false. At this moment we are done from
   // the point of view of our consumer and we have to report our self
@@ -1592,73 +1405,40 @@ void HttpChannelChild::FinishIntercepted
 
 mozilla::ipc::IPCResult HttpChannelChild::RecvReportSecurityMessage(
     const nsString& messageTag, const nsString& messageCategory) {
   DebugOnly<nsresult> rv = AddSecurityMessage(messageTag, messageCategory);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   return IPC_OK();
 }
 
-class Redirect1Event : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  Redirect1Event(HttpChannelChild* child, const uint32_t& registrarId,
-                 const URIParams& newURI, const uint32_t& newLoadFlags,
-                 const uint32_t& redirectFlags,
-                 const ParentLoadInfoForwarderArgs& loadInfoForwarder,
-                 const nsHttpResponseHead& responseHead,
-                 const nsACString& securityInfoSerialization,
-                 const uint64_t& channelId, const ResourceTimingStruct& timing)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child),
-        mRegistrarId(registrarId),
-        mNewURI(newURI),
-        mNewLoadFlags(newLoadFlags),
-        mRedirectFlags(redirectFlags),
-        mResponseHead(responseHead),
-        mSecurityInfoSerialization(securityInfoSerialization),
-        mChannelId(channelId),
-        mLoadInfoForwarder(loadInfoForwarder),
-        mTiming(timing) {}
-
-  void Run() override {
-    mChild->Redirect1Begin(mRegistrarId, mNewURI, mNewLoadFlags, mRedirectFlags,
-                           mLoadInfoForwarder, mResponseHead,
-                           mSecurityInfoSerialization, mChannelId, mTiming);
-  }
-
- private:
-  uint32_t mRegistrarId;
-  URIParams mNewURI;
-  uint32_t mNewLoadFlags;
-  uint32_t mRedirectFlags;
-  nsHttpResponseHead mResponseHead;
-  nsCString mSecurityInfoSerialization;
-  uint64_t mChannelId;
-  ParentLoadInfoForwarderArgs mLoadInfoForwarder;
-  ResourceTimingStruct mTiming;
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvRedirect1Begin(
-    const uint32_t& registrarId, const URIParams& newUri,
-    const uint32_t& newLoadFlags, const uint32_t& redirectFlags,
-    const ParentLoadInfoForwarderArgs& loadInfoForwarder,
-    const nsHttpResponseHead& responseHead,
-    const nsCString& securityInfoSerialization, const uint64_t& channelId,
-    const NetAddr& oldPeerAddr, const ResourceTimingStruct& timing) {
+    const uint32_t& aRegistrarId, const URIParams& aNewUri,
+    const uint32_t& aNewLoadFlags, const uint32_t& aRedirectFlags,
+    const ParentLoadInfoForwarderArgs& aLoadInfoForwarder,
+    const nsHttpResponseHead& aResponseHead,
+    const nsCString& aSecurityInfoSerialization, const uint64_t& aChannelId,
+    const NetAddr& aOldPeerAddr, const ResourceTimingStruct& aTiming) {
   // TODO: handle security info
   LOG(("HttpChannelChild::RecvRedirect1Begin [this=%p]\n", this));
   // We set peer address of child to the old peer,
   // Then it will be updated to new peer in OnStartRequest
-  mPeerAddr = oldPeerAddr;
+  mPeerAddr = aOldPeerAddr;
 
   // Cookies headers should not be visible to the child process
-  MOZ_ASSERT(!nsHttpResponseHead(responseHead).HasHeader(nsHttp::Set_Cookie));
-
-  mEventQ->RunOrEnqueue(new Redirect1Event(
-      this, registrarId, newUri, newLoadFlags, redirectFlags, loadInfoForwarder,
-      responseHead, securityInfoSerialization, channelId, timing));
+  MOZ_ASSERT(!nsHttpResponseHead(aResponseHead).HasHeader(nsHttp::Set_Cookie));
+
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this), aRegistrarId, aNewUri,
+             aNewLoadFlags, aRedirectFlags, aLoadInfoForwarder, aResponseHead,
+             aSecurityInfoSerialization, aChannelId, aTiming]() {
+        self->Redirect1Begin(aRegistrarId, aNewUri, aNewLoadFlags,
+                             aRedirectFlags, aLoadInfoForwarder, aResponseHead,
+                             aSecurityInfoSerialization, aChannelId, aTiming);
+      }));
   return IPC_OK();
 }
 
 nsresult HttpChannelChild::SetupRedirect(nsIURI* uri,
                                          const nsHttpResponseHead* responseHead,
                                          const uint32_t& redirectFlags,
                                          nsIChannel** outChannel) {
   LOG(("HttpChannelChild::SetupRedirect [this=%p]\n", this));
@@ -1833,46 +1613,36 @@ void HttpChannelChild::BeginNonIPCRedire
 
 void HttpChannelChild::OverrideSecurityInfoForNonIPCRedirect(
     nsISupports* securityInfo) {
   mResponseCouldBeSynthesized = true;
   DebugOnly<nsresult> rv = OverrideSecurityInfo(securityInfo);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
-class Redirect3Event : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  explicit Redirect3Event(HttpChannelChild* child)
-      : NeckoTargetChannelEvent<HttpChannelChild>(child) {}
-  void Run() override { mChild->Redirect3Complete(nullptr); }
-};
-
 mozilla::ipc::IPCResult HttpChannelChild::RecvRedirect3Complete() {
   LOG(("HttpChannelChild::RecvRedirect3Complete [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new Redirect3Event(this));
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+      this, [self = UnsafePtr<HttpChannelChild>(this)]() {
+        self->Redirect3Complete(nullptr);
+      }));
   return IPC_OK();
 }
 
-class HttpFlushedForDiversionEvent
-    : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  explicit HttpFlushedForDiversionEvent(HttpChannelChild* aChild)
-      : NeckoTargetChannelEvent<HttpChannelChild>(aChild) {
-    MOZ_RELEASE_ASSERT(aChild);
-  }
-
-  void Run() override { mChild->FlushedForDiversion(); }
-};
-
 void HttpChannelChild::ProcessFlushedForDiversion() {
   LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this));
   MOZ_ASSERT(OnSocketThread());
   MOZ_RELEASE_ASSERT(mDivertingToParent);
 
-  mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true);
+  mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
+                            this,
+                            [self = UnsafePtr<HttpChannelChild>(this)]() {
+                              self->FlushedForDiversion();
+                            }),
+                        true);
 }
 
 void HttpChannelChild::ProcessNotifyChannelClassifierProtectionDisabled(
     uint32_t aAcceptedReason) {
   LOG(
       ("HttpChannelChild::ProcessNotifyChannelClassifierProtectionDisabled "
        "[this=%p aAcceptedReason=%" PRIu32 "]\n",
        this, aAcceptedReason));
@@ -2156,17 +1926,17 @@ HttpChannelChild::ConnectParent(uint32_t
 
     mBgChild = bgChild.forget();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HttpChannelChild::CompleteRedirectSetup(nsIStreamListener* listener,
+HttpChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener,
                                         nsISupports* aContext) {
   LOG(("HttpChannelChild::FinishRedirectSetup [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
   if (mShouldParentIntercept) {
@@ -2178,17 +1948,17 @@ HttpChannelChild::CompleteRedirectSetup(
     // Since this method is called from RecvRedirect3Complete which itself is
     // called from either OnRedirectVerifyCallback via OverrideRunnable, or from
     // RecvRedirect3Complete. The order of events must always be:
     //  1. Teardown the IPDL connection
     //  2. AsyncOpen the connection again
     //  3. Cleanup the redirecting channel (the one calling Redirect3Complete)
     //  4. [optional] Call OverrideWithSynthesizedResponse on the redirected
     //  channel if the call came from OverrideRunnable.
-    mInterceptedRedirectListener = listener;
+    mInterceptedRedirectListener = aListener;
     mInterceptedRedirectContext = aContext;
 
     // This will send a message to the parent notifying it that we are closing
     // down. After closing the IPC channel, we will proceed to execute
     // FinishInterceptedRedirect() which AsyncOpen's the channel again.
     SendFinishInterceptedRedirect();
 
     // XXX valentin: The interception logic should be rewritten to avoid
@@ -2205,50 +1975,50 @@ HttpChannelChild::CompleteRedirectSetup(
 
   mLastStatusReported = TimeStamp::Now();
   PROFILER_ADD_NETWORK_MARKER(mURI, mPriority, mChannelId,
                               NetworkLoadType::LOAD_START,
                               mChannelCreationTimestamp, mLastStatusReported, 0,
                               kCacheUnknown, nullptr, nullptr);
   mIsPending = true;
   mWasOpened = true;
-  mListener = listener;
+  mListener = aListener;
 
   // add ourselves to the load group.
   if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
 
   // We already have an open IPDL connection to the parent. If on-modify-request
   // listeners or load group observers canceled us, let the parent handle it
   // and send it back to us naturally.
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsIAsyncVerifyRedirectCallback
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-HttpChannelChild::OnRedirectVerifyCallback(nsresult result) {
+HttpChannelChild::OnRedirectVerifyCallback(nsresult aResult) {
   LOG(("HttpChannelChild::OnRedirectVerifyCallback [this=%p]\n", this));
   MOZ_ASSERT(NS_IsMainThread());
   Maybe<URIParams> redirectURI;
   nsresult rv;
 
   nsCOMPtr<nsIHttpChannel> newHttpChannel =
       do_QueryInterface(mRedirectChannelChild);
 
-  if (NS_SUCCEEDED(result) && !mRedirectChannelChild) {
+  if (NS_SUCCEEDED(aResult) && !mRedirectChannelChild) {
     // mRedirectChannelChild doesn't exist means we're redirecting to a protocol
     // that doesn't implement nsIChildChannel. The redirect result should be set
     // as failed by veto listeners and shouldn't enter this condition. As the
     // last resort, we synthesize the error result as NS_ERROR_DOM_BAD_URI here
     // to let nsHttpChannel::ContinueProcessResponse2 know it's redirecting to
     // another protocol and throw an error.
     LOG(("  redirecting to a protocol that doesn't implement nsIChildChannel"));
-    result = NS_ERROR_DOM_BAD_URI;
+    aResult = NS_ERROR_DOM_BAD_URI;
   }
 
   nsCOMPtr<nsIReferrerInfo> referrerInfo;
   if (newHttpChannel) {
     // Must not be called until after redirect observers called.
     newHttpChannel->SetOriginalURI(mOriginalURI);
     referrerInfo = newHttpChannel->GetReferrerInfo();
   }
@@ -2281,29 +2051,29 @@ HttpChannelChild::OnRedirectVerifyCallba
 
   RequestHeaderTuples emptyHeaders;
   RequestHeaderTuples* headerTuples = &emptyHeaders;
   nsLoadFlags loadFlags = 0;
   Maybe<CorsPreflightArgs> corsPreflightArgs;
 
   nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
       do_QueryInterface(mRedirectChannelChild);
-  if (newHttpChannelChild && NS_SUCCEEDED(result)) {
+  if (newHttpChannelChild && NS_SUCCEEDED(aResult)) {
     rv = newHttpChannelChild->AddCookiesToRequest();
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     rv = newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     newHttpChannelChild->GetClientSetCorsPreflightParameters(corsPreflightArgs);
   }
 
   /* If the redirect was canceled, bypass OMR and send an empty API
    * redirect URI */
   SerializeURI(nullptr, redirectURI);
 
-  if (NS_SUCCEEDED(result)) {
+  if (NS_SUCCEEDED(aResult)) {
     // Note: this is where we would notify "http-on-modify-response" observers.
     // We have deliberately disabled this for child processes (see bug 806753)
     //
     // After we verify redirect, nsHttpChannel may hit the network: must give
     // "http-on-modify-request" observers the chance to cancel before that.
     // base->CallOnModifyRequestObservers();
 
     nsCOMPtr<nsIHttpChannelInternal> newHttpChannelInternal =
@@ -2345,56 +2115,56 @@ HttpChannelChild::OnRedirectVerifyCallba
     newChannelLoadInfo = newChannel->LoadInfo();
   }
 
   ChildLoadInfoForwarderArgs targetLoadInfoForwarder;
   LoadInfoToChildLoadInfoForwarder(newChannelLoadInfo,
                                    &targetLoadInfoForwarder);
 
   if (CanSend())
-    SendRedirect2Verify(result, *headerTuples, sourceRequestBlockingReason,
+    SendRedirect2Verify(aResult, *headerTuples, sourceRequestBlockingReason,
                         targetLoadInfoForwarder, loadFlags, referrerInfo,
                         redirectURI, corsPreflightArgs, chooseAppcache);
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-HttpChannelChild::Cancel(nsresult status) {
+HttpChannelChild::Cancel(nsresult aStatus) {
   LOG(("HttpChannelChild::Cancel [this=%p, status=%" PRIx32 "]\n", this,
-       static_cast<uint32_t>(status)));
+       static_cast<uint32_t>(aStatus)));
   LogCallingScriptLocation(this);
 
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mCanceled) {
     // If this cancel occurs before nsHttpChannel has been set up, AsyncOpen
     // is responsible for cleaning up.
     mCanceled = true;
-    mStatus = status;
+    mStatus = aStatus;
     if (RemoteChannelExists()) {
-      SendCancel(status);
+      SendCancel(aStatus);
     }
 
     // If the channel is intercepted and already pumping, then just
     // cancel the pump.  This will call OnStopRequest().
     if (mSynthesizedResponsePump) {
-      mSynthesizedResponsePump->Cancel(status);
+      mSynthesizedResponsePump->Cancel(aStatus);
     }
 
     // If we are canceled while intercepting, but not yet pumping, then
     // we must call AsyncAbort() to trigger OnStopRequest().
     else if (mInterceptListener) {
       mInterceptListener->Cleanup();
       mInterceptListener = nullptr;
-      Unused << AsyncAbort(status);
+      Unused << AsyncAbort(aStatus);
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelChild::Suspend() {
   LOG(("HttpChannelChild::Suspend [this=%p, mSuspendCount=%" PRIu32 ", "
@@ -3743,46 +3513,32 @@ nsresult HttpChannelChild::SetReferrerHe
             mClientSetRequestHeaders[i].mHeader)) {
       mClientSetRequestHeaders.RemoveElementAt(i);
     }
   }
 
   return HttpBaseChannel::SetReferrerHeader(aReferrer, aRespectBeforeConnect);
 }
 
-class CancelEvent final : public NeckoTargetChannelEvent<HttpChannelChild> {
- public:
-  CancelEvent(HttpChannelChild* aChild, nsresult aRv)
-      : NeckoTargetChannelEvent<HttpChannelChild>(aChild), mRv(aRv) {
-    MOZ_ASSERT(!NS_IsMainThread());
-    MOZ_ASSERT(aChild);
-  }
-
-  void Run() override {
-    MOZ_ASSERT(NS_IsMainThread());
-    mChild->Cancel(mRv);
-  }
-
- private:
-  const nsresult mRv;
-};
-
 void HttpChannelChild::CancelOnMainThread(nsresult aRv) {
   LOG(("HttpChannelChild::CancelOnMainThread [this=%p]", this));
 
   if (NS_IsMainThread()) {
     Cancel(aRv);
     return;
   }
 
   mEventQ->Suspend();
   // Cancel is expected to preempt any other channel events, thus we put this
   // event in the front of mEventQ to make sure nsIStreamListener not receiving
   // any ODA/OnStopRequest callbacks.
-  mEventQ->PrependEvent(MakeUnique<CancelEvent>(this, aRv));
+  mEventQ->PrependEvent(MakeUnique<NeckoTargetChannelFunctionEvent>(
+      this, [self = UnsafePtr<HttpChannelChild>(this), aRv]() {
+        self->Cancel(aRv);
+      }));
   mEventQ->Resume();
 }
 
 void HttpChannelChild::OverrideWithSynthesizedResponse(
     nsAutoPtr<nsHttpResponseHead>& aResponseHead,
     nsIInputStream* aSynthesizedInput,
     nsIInterceptedBodyCallback* aSynthesizedCallback,
     InterceptStreamListener* aStreamListener,
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -518,36 +518,21 @@ class HttpChannelChild final : public PH
                            bool responseRedirected);
 
   // Override the default security info pointer during a non-IPC redirection.
   void OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo);
 
   // Collect telemetry for the successful rate of OMT.
   void CollectOMTTelemetry();
 
-  friend class AssociateApplicationCacheEvent;
-  friend class StartRequestEvent;
-  friend class StopRequestEvent;
-  friend class TransportAndDataEvent;
-  friend class MaybeDivertOnDataHttpEvent;
-  friend class MaybeDivertOnStopHttpEvent;
-  friend class ProgressEvent;
-  friend class StatusEvent;
-  friend class FailedAsyncOpenEvent;
-  friend class Redirect1Event;
-  friend class Redirect3Event;
-  friend class DeleteSelfEvent;
-  friend class HttpFlushedForDiversionEvent;
-  friend class CancelEvent;
   friend class HttpAsyncAborter<HttpChannelChild>;
   friend class InterceptStreamListener;
   friend class InterceptedChannelContent;
   friend class HttpBackgroundChannelChild;
-  friend class NeckoTargetChannelEvent<HttpChannelChild>;
-  friend class ContinueDoNotifyListenerEvent;
+  friend class NeckoTargetChannelFunctionEvent;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelChild, HTTP_CHANNEL_CHILD_IID)
 
 // A stream listener interposed between the nsInputStreamPump used for
 // intercepted channels and this channel's original listener. This is only used
 // to ensure the original listener sees the channel as the request object, and
 // to synthesize OnStatus and OnProgress notifications.