Bug 1600254 - P4: Make HttpActivityObserver work in socket process r=dragana
authorKershaw Chang <kershaw@mozilla.com>
Thu, 30 Jan 2020 13:00:11 +0000
changeset 512154 01e0454d96a4c9adff0b74e717d925c50204b617
parent 512153 cd6bfcd9ae6e56cc2c6cc213abfd40632329a408
child 512155 1d7b2d12113cd3cefe79ab0cfe0a536f3b5c5946
push id106219
push userkjang@mozilla.com
push dateThu, 30 Jan 2020 13:59:40 +0000
treeherderautoland@655675bbf178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1600254
milestone74.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 1600254 - P4: Make HttpActivityObserver work in socket process r=dragana Differential Revision: https://phabricator.services.mozilla.com/D56039
netwerk/ipc/NeckoChannelParams.ipdlh
netwerk/ipc/PSocketProcess.ipdl
netwerk/ipc/SocketProcessChild.cpp
netwerk/ipc/SocketProcessChild.h
netwerk/ipc/SocketProcessParent.cpp
netwerk/ipc/SocketProcessParent.h
netwerk/protocol/http/HttpTransactionChild.cpp
netwerk/protocol/http/HttpTransactionChild.h
netwerk/protocol/http/HttpTransactionParent.cpp
netwerk/protocol/http/HttpTransactionParent.h
netwerk/protocol/http/HttpTransactionShell.h
netwerk/protocol/http/NullHttpTransaction.cpp
netwerk/protocol/http/PHttpTransaction.ipdl
netwerk/protocol/http/nsHttpActivityDistributor.cpp
netwerk/protocol/http/nsHttpActivityDistributor.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
netwerk/protocol/http/nsIHttpActivityObserver.idl
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -481,10 +481,23 @@ struct ResourceTimingStructArgs {
 
   // Not actually part of resource timing, but not part of the transaction
   // timings either. These need to be passed to HttpChannelChild along with
   // the rest of the timings so the timing information in the child is complete.
   TimeStamp cacheReadStart;
   TimeStamp cacheReadEnd;
 };
 
+struct HttpActivity
+{
+  nsCString host;
+  int32_t port;
+  bool endToEndSSL;
+};
+
+union HttpActivityArgs
+{
+  uint64_t;
+  HttpActivity;
+};
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/PSocketProcess.ipdl
+++ b/netwerk/ipc/PSocketProcess.ipdl
@@ -9,28 +9,30 @@ include protocol PProfiler;
 include protocol PWebrtcTCPSocket;
 include protocol PHttpTransaction;
 include protocol PHttpConnectionMgr;
 include protocol PFileDescriptorSet;
 include protocol PChildToParentStream;
 include protocol PParentToChildStream;
 
 include MemoryReportTypes;
+include NeckoChannelParams;
 include PBrowserOrId;
 include PrefsTypes;
 
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::Telemetry::HistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedHistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using base::ProcessId from "base/process.h";
 using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
+using PRTime from "prtime.h";
 
 namespace mozilla {
 namespace net {
 
 protocol PSocketProcess
 {
   manages PDNSRequest;
   manages PWebrtcTCPSocket;
@@ -52,30 +54,38 @@ parent:
   async RecordChildEvents(ChildEventData[] events);
   async RecordDiscardedData(DiscardedData data);
 
   /* tabId is only required for web-proxy support, which isn't always needed */
   async PWebrtcTCPSocket(TabId? tabId);
   async PDNSRequest(nsCString hostName, OriginAttributes originAttributes,
                     uint32_t flags);
   async PChildToParentStream();
+  async ObserveHttpActivity(HttpActivityArgs aActivityArgs,
+                            uint32_t aActivityType,
+                            uint32_t aActivitySubtype,
+                            PRTime   aTimestamp,
+                            uint64_t aExtraSizeData,
+                            nsCString aExtraStringData);
 
 child:
   async PreferenceUpdate(Pref pref);
   async RequestMemoryReport(uint32_t generation,
                             bool anonymize,
                             bool minimizeMemoryUsage,
                             FileDescriptor? DMDFile);
   async SetOffline(bool offline);
   async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
   async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
   // test-only
   async SocketProcessTelemetryPing();
   async PHttpTransaction();
   async PParentToChildStream();
   async PHttpConnectionMgr();
 
+  async OnHttpActivityDistributorActivated(bool aIsActivated);
+
 both:
   async PFileDescriptorSet(FileDescriptor fd);
 };
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.cpp
+++ b/netwerk/ipc/SocketProcessChild.cpp
@@ -16,16 +16,17 @@
 #include "mozilla/ipc/IPCStreamAlloc.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/net/DNSRequestChild.h"
 #include "mozilla/ipc/PChildToParentStreamChild.h"
 #include "mozilla/ipc/PParentToChildStreamChild.h"
 #include "mozilla/Preferences.h"
 #include "nsDebugImpl.h"
 #include "nsIDNSService.h"
+#include "nsIHttpActivityObserver.h"
 #include "nsThreadManager.h"
 #include "ProcessUtils.h"
 #include "SocketProcessBridgeParent.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ChildProfilerController.h"
 #endif
 
@@ -296,10 +297,20 @@ SocketProcessChild::AllocPHttpConnection
 
     RefPtr<HttpConnectionMgrChild> actor = new HttpConnectionMgrChild();
     return actor.forget();
   }
 
   return nullptr;
 }
 
+mozilla::ipc::IPCResult
+SocketProcessChild::RecvOnHttpActivityDistributorActivated(
+    const bool& aIsActivated) {
+  if (nsCOMPtr<nsIHttpActivityObserver> distributor =
+          services::GetActivityDistributor()) {
+    distributor->SetIsActive(aIsActivated);
+  }
+  return IPC_OK();
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.h
+++ b/netwerk/ipc/SocketProcessChild.h
@@ -66,16 +66,19 @@ class SocketProcessChild final
   void DestroySocketProcessBridgeParent(ProcessId aId);
 
   PChildToParentStreamChild* SendPChildToParentStreamConstructor(
       PChildToParentStreamChild* aActor) override;
   PFileDescriptorSetChild* SendPFileDescriptorSetConstructor(
       const FileDescriptor& aFD) override;
   already_AddRefed<PHttpConnectionMgrChild> AllocPHttpConnectionMgrChild();
 
+  mozilla::ipc::IPCResult RecvOnHttpActivityDistributorActivated(
+      const bool& aIsActivated);
+
  private:
   // Mapping of content process id and the SocketProcessBridgeParent.
   // This table keeps SocketProcessBridgeParent alive in socket process.
   nsRefPtrHashtable<nsUint32HashKey, SocketProcessBridgeParent>
       mSocketProcessBridgeParentMap;
 
 #ifdef MOZ_GECKO_PROFILER
   RefPtr<ChildProfilerController> mProfilerController;
--- a/netwerk/ipc/SocketProcessParent.cpp
+++ b/netwerk/ipc/SocketProcessParent.cpp
@@ -6,16 +6,17 @@
 #include "SocketProcessParent.h"
 
 #include "HttpTransactionParent.h"
 #include "SocketProcessHost.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/net/DNSRequestParent.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
+#include "nsIHttpActivityObserver.h"
 #ifdef MOZ_WEBRTC
 #  include "mozilla/dom/ContentProcessManager.h"
 #  include "mozilla/dom/BrowserParent.h"
 #  include "mozilla/net/WebrtcTCPSocketParent.h"
 #endif
 
 namespace mozilla {
 namespace net {
@@ -200,16 +201,30 @@ SocketProcessParent::SendPParentToChildS
 
 PFileDescriptorSetParent*
 SocketProcessParent::SendPFileDescriptorSetConstructor(
     const FileDescriptor& aFD) {
   MOZ_ASSERT(NS_IsMainThread());
   return PSocketProcessParent::SendPFileDescriptorSetConstructor(aFD);
 }
 
+mozilla::ipc::IPCResult SocketProcessParent::RecvObserveHttpActivity(
+    const HttpActivityArgs& aArgs, const uint32_t& aActivityType,
+    const uint32_t& aActivitySubtype, const PRTime& aTimestamp,
+    const uint64_t& aExtraSizeData, const nsCString& aExtraStringData) {
+  nsCOMPtr<nsIHttpActivityDistributor> activityDistributor =
+      services::GetActivityDistributor();
+  MOZ_ASSERT(activityDistributor);
+
+  Unused << activityDistributor->ObserveActivityWithArgs(
+      aArgs, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
+      aExtraStringData);
+  return IPC_OK();
+}
+
 // To ensure that IPDL is finished before SocketParent gets deleted.
 class DeferredDeleteSocketProcessParent : public Runnable {
  public:
   explicit DeferredDeleteSocketProcessParent(
       UniquePtr<SocketProcessParent>&& aParent)
       : Runnable("net::DeferredDeleteSocketProcessParent"),
         mParent(std::move(aParent)) {}
 
--- a/netwerk/ipc/SocketProcessParent.h
+++ b/netwerk/ipc/SocketProcessParent.h
@@ -81,16 +81,21 @@ class SocketProcessParent final
   PParentToChildStreamParent* AllocPParentToChildStreamParent();
   bool DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor);
 
   PParentToChildStreamParent* SendPParentToChildStreamConstructor(
       PParentToChildStreamParent* aActor) override;
   PFileDescriptorSetParent* SendPFileDescriptorSetConstructor(
       const FileDescriptor& aFD) override;
 
+  mozilla::ipc::IPCResult RecvObserveHttpActivity(
+      const HttpActivityArgs& aArgs, const uint32_t& aActivityType,
+      const uint32_t& aActivitySubtype, const PRTime& aTimestamp,
+      const uint64_t& aExtraSizeData, const nsCString& aExtraStringData);
+
  private:
   SocketProcessHost* mHost;
   UniquePtr<dom::MemoryReportRequestHost> mMemoryReportRequest;
 
   static void Destroy(UniquePtr<SocketProcessParent>&& aParent);
 };
 
 }  // namespace net
--- a/netwerk/protocol/http/HttpTransactionChild.cpp
+++ b/netwerk/protocol/http/HttpTransactionChild.cpp
@@ -22,17 +22,17 @@ namespace net {
 NS_IMPL_ISUPPORTS(HttpTransactionChild, nsIRequestObserver, nsIStreamListener,
                   nsITransportEventSink);
 
 //-----------------------------------------------------------------------------
 // HttpTransactionChild <public>
 //-----------------------------------------------------------------------------
 
 HttpTransactionChild::HttpTransactionChild()
-    : mCanceled(false), mStatus(NS_OK) {
+    : mCanceled(false), mStatus(NS_OK), mChannelId(0) {
   LOG(("Creating HttpTransactionChild @%p\n", this));
 }
 
 HttpTransactionChild::~HttpTransactionChild() {
   LOG(("Destroying HttpTransactionChild @%p\n", this));
 }
 
 nsProxyInfo* HttpTransactionChild::ProxyInfoCloneArgsToProxyInfo(
@@ -110,30 +110,30 @@ static already_AddRefed<nsIRequestContex
 }
 
 nsresult HttpTransactionChild::InitInternal(
     uint32_t caps, const HttpConnectionInfoCloneArgs& infoArgs,
     nsHttpRequestHead* requestHead, nsIInputStream* requestBody,
     uint64_t requestContentLength, bool requestBodyHasHeaders,
     uint64_t topLevelOuterContentWindowId, uint8_t httpTrafficCategory,
     uint64_t requestContextID, uint32_t classOfService, uint32_t initialRwin,
-    bool responseTimeoutEnabled) {
+    bool responseTimeoutEnabled, uint64_t channelId) {
   LOG(("HttpTransactionChild::InitInternal [this=%p caps=%x]\n", this, caps));
 
   RefPtr<nsHttpConnectionInfo> cinfo =
       DeserializeHttpConnectionInfoCloneArgs(infoArgs);
   nsCOMPtr<nsIRequestContext> rc = CreateRequestContext(requestContextID);
 
   nsresult rv = mTransaction->Init(
       caps, cinfo, requestHead, requestBody, requestContentLength,
       requestBodyHasHeaders, GetCurrentThreadEventTarget(),
       nullptr,  // TODO: security callback, fix in bug 1512479.
       this, topLevelOuterContentWindowId,
       static_cast<HttpTrafficCategory>(httpTrafficCategory), rc, classOfService,
-      initialRwin, responseTimeoutEnabled);
+      initialRwin, responseTimeoutEnabled, channelId);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mTransaction = nullptr;
     return rv;
   }
 
   Unused << mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
   return rv;
 }
@@ -172,28 +172,30 @@ mozilla::ipc::IPCResult HttpTransactionC
 
 mozilla::ipc::IPCResult HttpTransactionChild::RecvInit(
     const uint32_t& aCaps, const HttpConnectionInfoCloneArgs& aArgs,
     const nsHttpRequestHead& aReqHeaders, const Maybe<IPCStream>& aRequestBody,
     const uint64_t& aReqContentLength, const bool& aReqBodyIncludesHeaders,
     const uint64_t& aTopLevelOuterContentWindowId,
     const uint8_t& aHttpTrafficCategory, const uint64_t& aRequestContextID,
     const uint32_t& aClassOfService, const uint32_t& aInitialRwin,
-    const bool& aResponseTimeoutEnabled) {
+    const bool& aResponseTimeoutEnabled, const uint64_t& aChannelId) {
   mRequestHead = aReqHeaders;
   if (aRequestBody) {
     mUploadStream = mozilla::ipc::DeserializeIPCStream(aRequestBody);
   }
 
   mTransaction = new nsHttpTransaction();
+  mChannelId = aChannelId;
+
   nsresult rv = InitInternal(
       aCaps, aArgs, &mRequestHead, mUploadStream, aReqContentLength,
       aReqBodyIncludesHeaders, aTopLevelOuterContentWindowId,
       aHttpTrafficCategory, aRequestContextID, aClassOfService, aInitialRwin,
-      aResponseTimeoutEnabled);
+      aResponseTimeoutEnabled, aChannelId);
   if (NS_FAILED(rv)) {
     LOG(("HttpTransactionChild::RecvInit: [this=%p] InitInternal failed!\n",
          this));
     mTransaction = nullptr;
     SendOnInitFailed(rv);
   }
   return IPC_OK();
 }
--- a/netwerk/protocol/http/HttpTransactionChild.h
+++ b/netwerk/protocol/http/HttpTransactionChild.h
@@ -40,17 +40,17 @@ class HttpTransactionChild final : publi
   mozilla::ipc::IPCResult RecvInit(
       const uint32_t& aCaps, const HttpConnectionInfoCloneArgs& aArgs,
       const nsHttpRequestHead& aReqHeaders,
       const Maybe<IPCStream>& aRequestBody, const uint64_t& aReqContentLength,
       const bool& aReqBodyIncludesHeaders,
       const uint64_t& aTopLevelOuterContentWindowId,
       const uint8_t& aHttpTrafficCategory, const uint64_t& aRequestContextID,
       const uint32_t& aClassOfService, const uint32_t& aInitialRwin,
-      const bool& aResponseTimeoutEnabled);
+      const bool& aResponseTimeoutEnabled, const uint64_t& aChannelId);
   mozilla::ipc::IPCResult RecvUpdateClassOfService(
       const uint32_t& classOfService);
   mozilla::ipc::IPCResult RecvCancelPump(const nsresult& aStatus);
   mozilla::ipc::IPCResult RecvSuspendPump();
   mozilla::ipc::IPCResult RecvResumePump();
   mozilla::ipc::IPCResult RecvSetDNSWasRefreshed();
   mozilla::ipc::IPCResult RecvDontReuseConnection();
   mozilla::ipc::IPCResult RecvSetH2WSConnRefTaken();
@@ -69,20 +69,21 @@ class HttpTransactionChild final : publi
   // for the parameters.
   MOZ_MUST_USE nsresult InitInternal(
       uint32_t caps, const HttpConnectionInfoCloneArgs& aArgs,
       nsHttpRequestHead* reqHeaders,
       nsIInputStream* reqBody,  // use the trick in bug 1277681
       uint64_t reqContentLength, bool reqBodyIncludesHeaders,
       uint64_t topLevelOuterContentWindowId, uint8_t httpTrafficCategory,
       uint64_t requestContextID, uint32_t classOfService, uint32_t initialRwin,
-      bool responseTimeoutEnabled);
+      bool responseTimeoutEnabled, uint64_t channelId);
 
   bool mCanceled;
   nsresult mStatus;
+  uint64_t mChannelId;
   nsHttpRequestHead mRequestHead;
 
   nsCOMPtr<nsIInputStream> mUploadStream;
   RefPtr<nsHttpTransaction> mTransaction;
   nsCOMPtr<nsIRequest> mTransactionPump;
 };
 
 }  // namespace net
--- a/netwerk/protocol/http/HttpTransactionParent.cpp
+++ b/netwerk/protocol/http/HttpTransactionParent.cpp
@@ -64,17 +64,18 @@ HttpTransactionParent::HttpTransactionPa
       mStatus(NS_OK),
       mSuspendCount(0),
       mResponseHeadTaken(false),
       mResponseTrailersTaken(false),
       mHasStickyConnection(false),
       mOnStartRequestCalled(false),
       mOnStopRequestCalled(false),
       mResolvedByTRR(false),
-      mProxyConnectResponseCode(0) {
+      mProxyConnectResponseCode(0),
+      mChannelId(0) {
   LOG(("Creating HttpTransactionParent @%p\n", this));
 
   this->mSelfAddr.inet = {};
   this->mPeerAddr.inet = {};
 
 #ifdef MOZ_VALGRIND
   memset(&mSelfAddr, 0, sizeof(NetAddr));
   memset(&mPeerAddr, 0, sizeof(NetAddr));
@@ -144,44 +145,47 @@ void HttpTransactionParent::GetStructFro
 // Let socket process init the *real* nsHttpTransaction.
 nsresult HttpTransactionParent::Init(
     uint32_t caps, nsHttpConnectionInfo* cinfo, nsHttpRequestHead* requestHead,
     nsIInputStream* requestBody, uint64_t requestContentLength,
     bool requestBodyHasHeaders, nsIEventTarget* target,
     nsIInterfaceRequestor* callbacks, nsITransportEventSink* eventsink,
     uint64_t topLevelOuterContentWindowId, HttpTrafficCategory trafficCategory,
     nsIRequestContext* requestContext, uint32_t classOfService,
-    uint32_t initialRwin, bool responseTimeoutEnabled) {
+    uint32_t initialRwin, bool responseTimeoutEnabled, uint64_t channelId) {
   LOG(("HttpTransactionParent::Init [this=%p caps=%x]\n", this, caps));
 
   if (!CanSend()) {
     return NS_ERROR_FAILURE;
   }
 
   mEventsink = eventsink;
   mTargetThread = GetCurrentThreadEventTarget();
+  mChannelId = channelId;
 
   HttpConnectionInfoCloneArgs infoArgs;
   GetStructFromInfo(cinfo, infoArgs);
 
   mozilla::ipc::AutoIPCStream autoStream;
   if (requestBody &&
       !autoStream.Serialize(requestBody, SocketProcessParent::GetSingleton())) {
     return NS_ERROR_FAILURE;
   }
 
   uint64_t requestContextID = requestContext ? requestContext->GetID() : 0;
+
   // TODO: Figure out if we have to implement nsIThreadRetargetableRequest in
   // bug 1544378.
   if (!SendInit(caps, infoArgs, *requestHead,
                 requestBody ? Some(autoStream.TakeValue()) : Nothing(),
                 requestContentLength, requestBodyHasHeaders,
                 topLevelOuterContentWindowId,
                 static_cast<uint8_t>(trafficCategory), requestContextID,
-                classOfService, initialRwin, responseTimeoutEnabled)) {
+                classOfService, initialRwin, responseTimeoutEnabled,
+                mChannelId)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult HttpTransactionParent::AsyncRead(nsIStreamListener* listener,
                                           nsIRequest** pump) {
--- a/netwerk/protocol/http/HttpTransactionParent.h
+++ b/netwerk/protocol/http/HttpTransactionParent.h
@@ -99,16 +99,17 @@ class HttpTransactionParent final : publ
   int32_t mSuspendCount;
   bool mResponseHeadTaken;
   bool mResponseTrailersTaken;
   bool mHasStickyConnection;
   bool mOnStartRequestCalled;
   bool mOnStopRequestCalled;
   bool mResolvedByTRR;
   int32_t mProxyConnectResponseCode;
+  uint64_t mChannelId;
 
   NetAddr mSelfAddr;
   NetAddr mPeerAddr;
   TimingStruct mTimings;
   TimeStamp mDomainLookupStart;
   TimeStamp mDomainLookupEnd;
 };
 
--- a/netwerk/protocol/http/HttpTransactionShell.h
+++ b/netwerk/protocol/http/HttpTransactionShell.h
@@ -67,17 +67,17 @@ class HttpTransactionShell : public nsIS
   MOZ_MUST_USE nsresult virtual Init(
       uint32_t caps, nsHttpConnectionInfo* connInfo,
       nsHttpRequestHead* reqHeaders, nsIInputStream* reqBody,
       uint64_t reqContentLength, bool reqBodyIncludesHeaders,
       nsIEventTarget* consumerTarget, nsIInterfaceRequestor* callbacks,
       nsITransportEventSink* eventsink, uint64_t topLevelOuterContentWindowId,
       HttpTrafficCategory trafficCategory, nsIRequestContext* requestContext,
       uint32_t classOfService, uint32_t initialRwin,
-      bool responseTimeoutEnabled) = 0;
+      bool responseTimeoutEnabled, uint64_t channelId) = 0;
 
   // @param aListener
   //        receives notifications.
   // @param pump
   //        the pump that will contain the response data. async wait on this
   //        input stream for data. On first notification, headers should be
   //        available (check transaction status).
   virtual nsresult AsyncRead(nsIStreamListener* listener,
@@ -150,17 +150,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(HttpTransa
   virtual nsresult Init(                                                       \
       uint32_t caps, nsHttpConnectionInfo* connInfo,                           \
       nsHttpRequestHead* reqHeaders, nsIInputStream* reqBody,                  \
       uint64_t reqContentLength, bool reqBodyIncludesHeaders,                  \
       nsIEventTarget* consumerTarget, nsIInterfaceRequestor* callbacks,        \
       nsITransportEventSink* eventsink, uint64_t topLevelOuterContentWindowId, \
       HttpTrafficCategory trafficCategory, nsIRequestContext* requestContext,  \
       uint32_t classOfService, uint32_t initialRwin,                           \
-      bool responseTimeoutEnabled) override;                                   \
+      bool responseTimeoutEnabled, uint64_t channelId) override;               \
   virtual nsresult AsyncRead(nsIStreamListener* listener, nsIRequest** pump)   \
       override;                                                                \
   virtual void SetClassOfService(uint32_t classOfService) override;            \
   virtual nsHttpResponseHead* TakeResponseHead() override;                     \
   virtual nsHttpHeaderArray* TakeResponseTrailers() override;                  \
   virtual nsISupports* SecurityInfo() override;                                \
   virtual void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks)         \
       override;                                                                \
--- a/netwerk/protocol/http/NullHttpTransaction.cpp
+++ b/netwerk/protocol/http/NullHttpTransaction.cpp
@@ -2,90 +2,29 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* 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/. */
 
 // HttpLog.h should generally be included first
 #include "HttpLog.h"
 
+#include "mozilla/net/NeckoChannelParams.h"  // For HttpActivityArgs.
 #include "nsHttp.h"
 #include "NullHttpTransaction.h"
 #include "nsHttpHandler.h"
 #include "nsHttpRequestHead.h"
 #include "nsIHttpActivityObserver.h"
-#include "NullHttpChannel.h"
 #include "nsQueryObject.h"
 #include "nsNetUtil.h"
 #include "TCPFastOpenLayer.h"
 
 namespace mozilla {
 namespace net {
 
-class CallObserveActivity final : public nsIRunnable {
-  ~CallObserveActivity() = default;
-
- public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  CallObserveActivity(nsIHttpActivityObserver* aActivityDistributor,
-                      const nsCString& aHost, int32_t aPort, bool aEndToEndSSL,
-                      uint32_t aActivityType, uint32_t aActivitySubtype,
-                      PRTime aTimestamp, uint64_t aExtraSizeData,
-                      const nsACString& aExtraStringData)
-      : mActivityDistributor(aActivityDistributor),
-        mHost(aHost),
-        mPort(aPort),
-        mEndToEndSSL(aEndToEndSSL),
-        mActivityType(aActivityType),
-        mActivitySubtype(aActivitySubtype),
-        mTimestamp(aTimestamp),
-        mExtraSizeData(aExtraSizeData),
-        mExtraStringData(aExtraStringData) {}
-  NS_IMETHOD Run() override {
-    MOZ_ASSERT(NS_IsMainThread());
-    nsCOMPtr<nsIURI> uri;
-    nsAutoCString port(NS_LITERAL_CSTRING(""));
-    if (mPort != -1 &&
-        ((mEndToEndSSL && mPort != 443) || (!mEndToEndSSL && mPort != 80))) {
-      port.AppendInt(mPort);
-    }
-
-    nsresult rv = NS_NewURI(getter_AddRefs(uri),
-                            (mEndToEndSSL ? NS_LITERAL_CSTRING("https://")
-                                          : NS_LITERAL_CSTRING("http://")) +
-                                mHost + port);
-    if (NS_FAILED(rv)) {
-      return NS_OK;
-    }
-
-    RefPtr<NullHttpChannel> channel = new NullHttpChannel();
-    rv = channel->Init(uri, 0, nullptr, 0, nullptr);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-    rv = mActivityDistributor->ObserveActivity(
-        nsCOMPtr<nsISupports>(do_QueryObject(channel)), mActivityType,
-        mActivitySubtype, mTimestamp, mExtraSizeData, mExtraStringData);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return NS_OK;
-  }
-
- private:
-  nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
-  nsCString mHost;
-  int32_t mPort;
-  bool mEndToEndSSL;
-  uint32_t mActivityType;
-  uint32_t mActivitySubtype;
-  PRTime mTimestamp;
-  uint64_t mExtraSizeData;
-  nsCString mExtraStringData;
-};
-
-NS_IMPL_ISUPPORTS(CallObserveActivity, nsIRunnable)
-
 NS_IMPL_ISUPPORTS(NullHttpTransaction, NullHttpTransaction,
                   nsISupportsWeakReference)
 
 NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo* ci,
                                          nsIInterfaceRequestor* callbacks,
                                          uint32_t caps)
     : mStatus(NS_OK),
       mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE),
@@ -178,21 +117,22 @@ void NullHttpTransaction::OnTransportSta
       mTimings.secureConnectionStart = TimeStamp::Now();
     }
   } else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
     mTimings.connectEnd = TimeStamp::Now();
     ;
   }
 
   if (mActivityDistributor) {
-    NS_DispatchToMainThread(new CallObserveActivity(
-        mActivityDistributor, mConnectionInfo->GetOrigin(),
-        mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(),
+    Unused << mActivityDistributor->ObserveActivityWithArgs(
+        HttpActivity(mConnectionInfo->GetOrigin(),
+                     mConnectionInfo->OriginPort(),
+                     mConnectionInfo->EndToEndSSL()),
         NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT, static_cast<uint32_t>(status),
-        PR_Now(), progress, EmptyCString()));
+        PR_Now(), progress, EmptyCString());
   }
 }
 
 bool NullHttpTransaction::IsDone() { return mIsDone; }
 
 nsresult NullHttpTransaction::Status() { return mStatus; }
 
 uint32_t NullHttpTransaction::Caps() { return mCaps; }
@@ -227,22 +167,22 @@ nsHttpRequestHead* NullHttpTransaction::
         host, mConnectionInfo->OriginPort(), hostHeader);
     if (NS_SUCCEEDED(rv)) {
       rv = mRequestHead->SetHeader(nsHttp::Host, hostHeader);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
       if (mActivityDistributor) {
         // Report request headers.
         nsCString reqHeaderBuf;
         mRequestHead->Flatten(reqHeaderBuf, false);
-        NS_DispatchToMainThread(new CallObserveActivity(
-            mActivityDistributor, mConnectionInfo->GetOrigin(),
-            mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(),
+        Unused << mActivityDistributor->ObserveActivityWithArgs(
+            HttpActivity(mConnectionInfo->GetOrigin(),
+                         mConnectionInfo->OriginPort(),
+                         mConnectionInfo->EndToEndSSL()),
             NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
-            NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0,
-            reqHeaderBuf));
+            NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0, reqHeaderBuf);
       }
     }
 
     // CONNECT tunnels may also want Proxy-Authorization but that is a lot
     // harder to determine, so for now we will let those connections fail in
     // the NullHttpTransaction and let them be retried from the pending queue
     // with a bound transaction
   }
@@ -258,22 +198,23 @@ nsresult NullHttpTransaction::TakeSubTra
 void NullHttpTransaction::SetProxyConnectFailed() {}
 
 void NullHttpTransaction::Close(nsresult reason) {
   mStatus = reason;
   mConnection = nullptr;
   mIsDone = true;
   if (mActivityDistributor) {
     // Report that this transaction is closing.
-    NS_DispatchToMainThread(new CallObserveActivity(
-        mActivityDistributor, mConnectionInfo->GetOrigin(),
-        mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(),
+    Unused << mActivityDistributor->ObserveActivityWithArgs(
+        HttpActivity(mConnectionInfo->GetOrigin(),
+                     mConnectionInfo->OriginPort(),
+                     mConnectionInfo->EndToEndSSL()),
         NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
         NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, PR_Now(), 0,
-        EmptyCString()));
+        EmptyCString());
   }
 }
 
 nsHttpConnectionInfo* NullHttpTransaction::ConnectionInfo() {
   return mConnectionInfo;
 }
 
 }  // namespace net
--- a/netwerk/protocol/http/PHttpTransaction.ipdl
+++ b/netwerk/protocol/http/PHttpTransaction.ipdl
@@ -54,17 +54,18 @@ child:
              IPCStream? requestBody,
              uint64_t reqContentLength,
              bool reqBodyIncludesHeaders,
              uint64_t topLevelOuterContentWindowId,
              uint8_t httpTrafficCategory,
              uint64_t requestContextID,
              uint32_t classOfService,
              uint32_t initialRwin,
-             bool responseTimeoutEnabled);
+             bool responseTimeoutEnabled,
+             uint64_t channelId);
 
   async UpdateClassOfService(uint32_t classOfService);
   async CancelPump(nsresult status);
   async SuspendPump();
   async ResumePump();
 
   async SetDNSWasRefreshed();
   async DontReuseConnection();
--- a/netwerk/protocol/http/nsHttpActivityDistributor.cpp
+++ b/netwerk/protocol/http/nsHttpActivityDistributor.cpp
@@ -1,116 +1,188 @@
 /* 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/. */
 
 // HttpLog.h should generally be included first
 #include "HttpLog.h"
 
+#include "mozilla/net/SocketProcessChild.h"
+#include "mozilla/net/SocketProcessParent.h"
 #include "nsHttpActivityDistributor.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
+#include "nsIOService.h"
 #include "nsThreadUtils.h"
+#include "NullHttpChannel.h"
 
 namespace mozilla {
 namespace net {
 
 typedef nsMainThreadPtrHolder<nsIHttpActivityObserver> ObserverHolder;
 typedef nsMainThreadPtrHandle<nsIHttpActivityObserver> ObserverHandle;
-typedef nsTArray<ObserverHandle> ObserverArray;
-
-class nsHttpActivityEvent : public Runnable {
- public:
-  nsHttpActivityEvent(nsISupports* aHttpChannel, uint32_t aActivityType,
-                      uint32_t aActivitySubtype, PRTime aTimestamp,
-                      uint64_t aExtraSizeData,
-                      const nsACString& aExtraStringData,
-                      ObserverArray* aObservers)
-      : Runnable("net::nsHttpActivityEvent"),
-        mHttpChannel(aHttpChannel),
-        mActivityType(aActivityType),
-        mActivitySubtype(aActivitySubtype),
-        mTimestamp(aTimestamp),
-        mExtraSizeData(aExtraSizeData),
-        mExtraStringData(aExtraStringData),
-        mObservers(*aObservers) {}
-
-  NS_IMETHOD Run() override {
-    for (size_t i = 0; i < mObservers.Length(); i++) {
-      Unused << mObservers[i]->ObserveActivity(
-          mHttpChannel, mActivityType, mActivitySubtype, mTimestamp,
-          mExtraSizeData, mExtraStringData);
-    }
-    return NS_OK;
-  }
-
- private:
-  virtual ~nsHttpActivityEvent() = default;
-
-  nsCOMPtr<nsISupports> mHttpChannel;
-  uint32_t mActivityType;
-  uint32_t mActivitySubtype;
-  PRTime mTimestamp;
-  uint64_t mExtraSizeData;
-  nsCString mExtraStringData;
-
-  ObserverArray mObservers;
-};
 
 NS_IMPL_ISUPPORTS(nsHttpActivityDistributor, nsIHttpActivityDistributor,
                   nsIHttpActivityObserver)
 
 nsHttpActivityDistributor::nsHttpActivityDistributor()
-    : mLock("nsHttpActivityDistributor.mLock") {}
+    : mLock("nsHttpActivityDistributor.mLock"), mActivated(false) {}
 
 NS_IMETHODIMP
 nsHttpActivityDistributor::ObserveActivity(nsISupports* aHttpChannel,
                                            uint32_t aActivityType,
                                            uint32_t aActivitySubtype,
                                            PRTime aTimestamp,
                                            uint64_t aExtraSizeData,
                                            const nsACString& aExtraStringData) {
-  nsCOMPtr<nsIRunnable> event;
-  {
-    MutexAutoLock lock(mLock);
+  MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
+
+  for (size_t i = 0; i < mObservers.Length(); i++) {
+    Unused << mObservers[i]->ObserveActivity(aHttpChannel, aActivityType,
+                                             aActivitySubtype, aTimestamp,
+                                             aExtraSizeData, aExtraStringData);
+  }
+  return NS_OK;
+}
 
-    if (!mObservers.Length()) return NS_OK;
+NS_IMETHODIMP
+nsHttpActivityDistributor::ObserveActivityWithArgs(
+    const HttpActivityArgs& aArgs, uint32_t aActivityType,
+    uint32_t aActivitySubtype, PRTime aTimestamp, uint64_t aExtraSizeData,
+    const nsACString& aExtraStringData) {
+  HttpActivityArgs args(aArgs);
+  nsCString extraStringData(aExtraStringData);
+  if (XRE_IsSocketProcess()) {
+    auto task = [args{std::move(args)}, aActivityType, aActivitySubtype,
+                 aTimestamp, aExtraSizeData,
+                 extraStringData{std::move(extraStringData)}]() {
+      SocketProcessChild::GetSingleton()->SendObserveHttpActivity(
+          args, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
+          extraStringData);
+    };
+
+    if (!NS_IsMainThread()) {
+      return NS_DispatchToMainThread(NS_NewRunnableFunction(
+          "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task));
+    }
+
+    task();
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(XRE_IsParentProcess());
 
-    event = new nsHttpActivityEvent(
-        aHttpChannel, aActivityType, aActivitySubtype, aTimestamp,
-        aExtraSizeData, aExtraStringData, &mObservers);
-  }
-  NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
-  return NS_DispatchToMainThread(event);
+  RefPtr<nsHttpActivityDistributor> self = this;
+  auto task = [args{std::move(args)}, aActivityType, aActivitySubtype,
+               aTimestamp, aExtraSizeData,
+               extraStringData{std::move(extraStringData)},
+               self{std::move(self)}]() {
+    if (args.type() == HttpActivityArgs::Tuint64_t) {
+      nsWeakPtr weakPtr = gHttpHandler->GetWeakHttpChannel(args.get_uint64_t());
+      if (nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtr)) {
+        Unused << self->ObserveActivity(channel, aActivityType,
+                                        aActivitySubtype, aTimestamp,
+                                        aExtraSizeData, extraStringData);
+      }
+    } else if (args.type() == HttpActivityArgs::THttpActivity) {
+      nsCOMPtr<nsIURI> uri;
+      nsAutoCString portStr(NS_LITERAL_CSTRING(""));
+      int32_t port = args.get_HttpActivity().port();
+      bool endToEndSSL = args.get_HttpActivity().endToEndSSL();
+      if (port != -1 &&
+          ((endToEndSSL && port != 443) || (!endToEndSSL && port != 80))) {
+        portStr.AppendInt(port);
+      }
+
+      nsresult rv = NS_NewURI(getter_AddRefs(uri),
+                              (endToEndSSL ? NS_LITERAL_CSTRING("https://")
+                                           : NS_LITERAL_CSTRING("http://")) +
+                                  args.get_HttpActivity().host() + portStr);
+      if (NS_FAILED(rv)) {
+        return;
+      }
+
+      RefPtr<NullHttpChannel> channel = new NullHttpChannel();
+      rv = channel->Init(uri, 0, nullptr, 0, nullptr);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+      Unused << self->ObserveActivity(
+          nsCOMPtr<nsISupports>(do_QueryObject(channel)), aActivityType,
+          aActivitySubtype, aTimestamp, aExtraSizeData, extraStringData);
+    }
+  };
+
+  return NS_DispatchToMainThread(NS_NewRunnableFunction(
+      "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task));
 }
 
 NS_IMETHODIMP
 nsHttpActivityDistributor::GetIsActive(bool* isActive) {
   NS_ENSURE_ARG_POINTER(isActive);
   MutexAutoLock lock(mLock);
+  if (XRE_IsSocketProcess()) {
+    *isActive = mActivated;
+    return NS_OK;
+  }
+
   *isActive = !!mObservers.Length();
   return NS_OK;
 }
 
+NS_IMETHODIMP nsHttpActivityDistributor::SetIsActive(bool aActived) {
+  MOZ_RELEASE_ASSERT(XRE_IsSocketProcess());
+
+  mActivated = aActived;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) {
-  MutexAutoLock lock(mLock);
+  MOZ_ASSERT(XRE_IsParentProcess());
 
   ObserverHandle observer(
       new ObserverHolder("nsIHttpActivityObserver", aObserver));
-  if (!mObservers.AppendElement(observer)) return NS_ERROR_OUT_OF_MEMORY;
+
+  bool wasEmpty = false;
+  {
+    MutexAutoLock lock(mLock);
+    wasEmpty = mObservers.IsEmpty();
+    if (!mObservers.AppendElement(observer)) return NS_ERROR_OUT_OF_MEMORY;
+  }
 
+  if (gIOService->UseSocketProcess() && wasEmpty) {
+    SocketProcessParent* parent = SocketProcessParent::GetSingleton();
+    if (parent && parent->CanSend()) {
+      Unused << parent->SendOnHttpActivityDistributorActivated(true);
+    } else {
+      return NS_ERROR_FAILURE;
+    }
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver* aObserver) {
-  MutexAutoLock lock(mLock);
+  MOZ_ASSERT(XRE_IsParentProcess());
 
   ObserverHandle observer(
       new ObserverHolder("nsIHttpActivityObserver", aObserver));
-  if (!mObservers.RemoveElement(observer)) return NS_ERROR_FAILURE;
+
+  bool isEmpty = false;
+  {
+    MutexAutoLock lock(mLock);
+    if (!mObservers.RemoveElement(observer)) return NS_ERROR_FAILURE;
+    isEmpty = mObservers.IsEmpty();
+  }
 
+  if (gIOService->UseSocketProcess() && isEmpty) {
+    SocketProcessParent* parent = SocketProcessParent::GetSingleton();
+    if (parent && parent->CanSend()) {
+      Unused << parent->SendOnHttpActivityDistributorActivated(false);
+    } else {
+      return NS_ERROR_FAILURE;
+    }
+  }
   return NS_OK;
 }
 
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/protocol/http/nsHttpActivityDistributor.h
+++ b/netwerk/protocol/http/nsHttpActivityDistributor.h
@@ -23,14 +23,15 @@ class nsHttpActivityDistributor : public
 
   nsHttpActivityDistributor();
 
  protected:
   virtual ~nsHttpActivityDistributor() = default;
 
   ObserverArray mObservers;
   Mutex mLock;
+  bool mActivated;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // nsHttpActivityDistributor_h__
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -358,16 +358,19 @@ nsHttpChannel::~nsHttpChannel() {
   LOG(("Destroying nsHttpChannel [this=%p]\n", this));
 
   if (mAuthProvider) {
     DebugOnly<nsresult> rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   ReleaseMainThreadOnlyReferences();
+  if (gHttpHandler) {
+    gHttpHandler->RemoveHttpChannel(mChannelId);
+  }
 }
 
 void nsHttpChannel::ReleaseMainThreadOnlyReferences() {
   if (NS_IsMainThread()) {
     // Already on main thread, let dtor to
     // take care of releasing references
     return;
   }
@@ -1291,16 +1294,20 @@ nsresult nsHttpChannel::SetupTransaction
 
     mTransaction = transParent;
   } else {
     mTransaction = new nsHttpTransaction();
     LOG1(("nsHttpChannel %p created nsHttpTransaction %p\n", this,
           mTransaction.get()));
   }
 
+  // Save the mapping of channel id and the channel. We need this mapping for
+  // nsIHttpActivityObserver.
+  gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
+
   mTransaction->SetTransactionObserver(mTransactionObserver);
   mTransactionObserver = nullptr;
 
   // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
   if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS;
 
   if (mTimingEnabled) mCaps |= NS_HTTP_TIMING_ENABLED;
 
@@ -1331,17 +1338,17 @@ nsresult nsHttpChannel::SetupTransaction
   EnsureRequestContext();
 
   HttpTrafficCategory category = CreateTrafficCategory();
 
   rv = mTransaction->Init(
       mCaps, mConnectionInfo, &mRequestHead, mUploadStream, mReqContentLength,
       mUploadStreamHasHeaders, GetCurrentThreadEventTarget(), callbacks, this,
       mTopLevelOuterContentWindowId, category, mRequestContext, mClassOfService,
-      mInitialRwin, mResponseTimeoutEnabled);
+      mInitialRwin, mResponseTimeoutEnabled, mChannelId);
   if (NS_FAILED(rv)) {
     mTransaction = nullptr;
     return rv;
   }
 
   return rv;
 }
 
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2740,9 +2740,42 @@ void nsHttpHandler::UpdateClassOfService
   mConnMgr->UpdateClassOfServiceOnTransaction(trans, classOfService);
 }
 
 nsresult nsHttpHandler::CancelTransaction(HttpTransactionShell* trans,
                                           nsresult reason) {
   return mConnMgr->CancelTransaction(trans, reason);
 }
 
-}  // namespace mozilla::net
+void nsHttpHandler::AddHttpChannel(uint64_t aId, nsISupports* aChannel) {
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsWeakPtr channel(do_GetWeakReference(aChannel));
+  mIDToHttpChannelMap.Put(aId, std::move(channel));
+}
+
+void nsHttpHandler::RemoveHttpChannel(uint64_t aId) {
+  MOZ_ASSERT(XRE_IsParentProcess());
+  if (!NS_IsMainThread()) {
+    nsCOMPtr<nsIRunnable> idleRunnable(NewCancelableRunnableMethod<uint64_t>(
+        "nsHttpHandler::RemoveHttpChannel", this,
+        &nsHttpHandler::RemoveHttpChannel, aId));
+
+    NS_DispatchToMainThreadQueue(do_AddRef(idleRunnable),
+                                 EventQueuePriority::Idle);
+    return;
+  }
+
+  auto entry = mIDToHttpChannelMap.Lookup(aId);
+  if (entry) {
+    entry.Remove();
+  }
+}
+
+nsWeakPtr nsHttpHandler::GetWeakHttpChannel(uint64_t aId) {
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return mIDToHttpChannelMap.Get(aId);
+}
+
+}  // namespace mozilla::net
\ No newline at end of file
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -20,16 +20,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsWeakReference.h"
 
 #include "nsIHttpProtocolHandler.h"
 #include "nsIObserver.h"
 #include "nsISpeculativeConnect.h"
+#include "nsDataHashtable.h"
 
 class nsIHttpChannel;
 class nsIPrefBranch;
 class nsICancelable;
 class nsICookieService;
 class nsIProcessSwitchRequestor;
 class nsIIOService;
 class nsIRequestContextService;
@@ -772,24 +773,30 @@ class nsHttpHandler final : public nsIHt
   // onstoprequest notification coming from an http channel.
   Mutex mLastActiveTabLoadOptimizationLock;
   TimeStamp mLastActiveTabLoadOptimizationHit;
 
   Mutex mSpdyBlacklistLock;
 
  public:
   MOZ_MUST_USE nsresult NewChannelId(uint64_t& channelId);
+  void AddHttpChannel(uint64_t aId, nsISupports* aChannel);
+  void RemoveHttpChannel(uint64_t aId);
+  nsWeakPtr GetWeakHttpChannel(uint64_t aId);
 
   void BlacklistSpdy(const nsHttpConnectionInfo* ci);
   MOZ_MUST_USE bool IsSpdyBlacklisted(const nsHttpConnectionInfo* ci);
 
  private:
   nsTHashtable<nsCStringHashKey> mBlacklistedSpdyOrigins;
 
   bool mThroughCaptivePortal;
+
+  // The mapping of channel id and the weak pointer of nsHttpChannel.
+  nsDataHashtable<nsUint64HashKey, nsWeakPtr> mIDToHttpChannelMap;
 };
 
 extern StaticRefPtr<nsHttpHandler> gHttpHandler;
 
 //-----------------------------------------------------------------------------
 // nsHttpsHandler - thin wrapper to distinguish the HTTP handler from the
 //                  HTTPS handler (even though they share the same impl).
 //-----------------------------------------------------------------------------
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -62,16 +62,17 @@ namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
 // nsHttpTransaction <public>
 //-----------------------------------------------------------------------------
 
 nsHttpTransaction::nsHttpTransaction()
     : mLock("transaction lock"),
+      mChannelId(0),
       mRequestSize(0),
       mRequestHead(nullptr),
       mResponseHead(nullptr),
       mReader(nullptr),
       mWriter(nullptr),
       mContentLength(-1),
       mContentRead(0),
       mTransferSize(0),
@@ -245,26 +246,27 @@ nsHttpTransaction::~nsHttpTransaction() 
 
 nsresult nsHttpTransaction::Init(
     uint32_t caps, nsHttpConnectionInfo* cinfo, nsHttpRequestHead* requestHead,
     nsIInputStream* requestBody, uint64_t requestContentLength,
     bool requestBodyHasHeaders, nsIEventTarget* target,
     nsIInterfaceRequestor* callbacks, nsITransportEventSink* eventsink,
     uint64_t topLevelOuterContentWindowId, HttpTrafficCategory trafficCategory,
     nsIRequestContext* requestContext, uint32_t classOfService,
-    uint32_t initialRwin, bool responseTimeoutEnabled) {
+    uint32_t initialRwin, bool responseTimeoutEnabled, uint64_t channelId) {
   nsresult rv;
 
   LOG1(("nsHttpTransaction::Init [this=%p caps=%x]\n", this, caps));
 
   MOZ_ASSERT(cinfo);
   MOZ_ASSERT(requestHead);
   MOZ_ASSERT(target);
   MOZ_ASSERT(NS_IsMainThread());
 
+  mChannelId = channelId;
   mTopLevelOuterContentWindowId = topLevelOuterContentWindowId;
   LOG(("  window-id = %" PRIx64, mTopLevelOuterContentWindowId));
 
   mTrafficCategory = trafficCategory;
 
   mActivityDistributor = services::GetActivityDistributor();
   if (!mActivityDistributor) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -347,18 +349,18 @@ nsresult nsHttpTransaction::Init(
 
   // If the request body does not include headers or if there is no request
   // body, then we must add the header/body separator manually.
   if (!requestBodyHasHeaders || !requestBody)
     mReqHeaderBuf.AppendLiteral("\r\n");
 
   // report the request header
   if (mActivityDistributor) {
-    rv = mActivityDistributor->ObserveActivity(
-        mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+    rv = mActivityDistributor->ObserveActivityWithArgs(
+        HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
         NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0, mReqHeaderBuf);
     if (NS_FAILED(rv)) {
       LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
     }
   }
 
   // Create a string stream for the request header buf (the stream holds
   // a non-owning reference to the request header data, so we MUST keep
@@ -648,28 +650,28 @@ void nsHttpTransaction::OnTransportStatu
 
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
   // Need to do this before the STATUS_RECEIVING_FROM check below, to make
   // sure that the activity distributor gets told about all status events.
   if (mActivityDistributor) {
     // upon STATUS_WAITING_FOR; report request body sent
     if ((mHasRequestBody) && (status == NS_NET_STATUS_WAITING_FOR)) {
-      nsresult rv = mActivityDistributor->ObserveActivity(
-          mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+      nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
+          HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
           NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT, PR_Now(), 0,
           EmptyCString());
       if (NS_FAILED(rv)) {
         LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
       }
     }
 
     // report the status and progress
-    nsresult rv = mActivityDistributor->ObserveActivity(
-        mChannel, NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
+    nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
+        HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
         static_cast<uint32_t>(status), PR_Now(), progress, EmptyCString());
     if (NS_FAILED(rv)) {
       LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
     }
   }
 
   // nsHttpChannel synthesizes progress events in OnDataAvailable
   if (status == NS_NET_STATUS_RECEIVING_FROM) return;
@@ -1053,28 +1055,28 @@ void nsHttpTransaction::Close(nsresult r
   if (mTokenBucketCancel) {
     mTokenBucketCancel->Cancel(reason);
     mTokenBucketCancel = nullptr;
   }
 
   if (mActivityDistributor) {
     // report the reponse is complete if not already reported
     if (!mResponseIsComplete) {
-      nsresult rv = mActivityDistributor->ObserveActivity(
-          mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+      nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
+          HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
           NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(),
           static_cast<uint64_t>(mContentRead), EmptyCString());
       if (NS_FAILED(rv)) {
         LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
       }
     }
 
     // report that this transaction is closing
-    nsresult rv = mActivityDistributor->ObserveActivity(
-        mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+    nsresult rv = mActivityDistributor->ObserveActivityWithArgs(
+        HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
         NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, PR_Now(), 0,
         EmptyCString());
     if (NS_FAILED(rv)) {
       LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
     }
   }
 
   // we must no longer reference the connection!  find out if the
@@ -1513,18 +1515,18 @@ nsresult nsHttpTransaction::ParseHead(ch
   // allocate the response head object if necessary
   if (!mResponseHead) {
     mResponseHead = new nsHttpResponseHead();
     if (!mResponseHead) return NS_ERROR_OUT_OF_MEMORY;
 
     // report that we have a least some of the response
     if (mActivityDistributor && !mReportedStart) {
       mReportedStart = true;
-      rv = mActivityDistributor->ObserveActivity(
-          mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+      rv = mActivityDistributor->ObserveActivityWithArgs(
+          HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
           NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START, PR_Now(), 0, EmptyCString());
       if (NS_FAILED(rv)) {
         LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
       }
     }
   }
 
   if (!mHttpResponseMatched) {
@@ -1855,18 +1857,18 @@ nsresult nsHttpTransaction::HandleConten
     ReleaseBlockingTransaction();
 
     if (TimingEnabled()) {
       SetResponseEnd(TimeStamp::Now());
     }
 
     // report the entire response has arrived
     if (mActivityDistributor) {
-      rv = mActivityDistributor->ObserveActivity(
-          mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+      rv = mActivityDistributor->ObserveActivityWithArgs(
+          HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
           NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE, PR_Now(),
           static_cast<uint64_t>(mContentRead), EmptyCString());
       if (NS_FAILED(rv)) {
         LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
       }
     }
   }
 
@@ -1909,18 +1911,18 @@ nsresult nsHttpTransaction::ProcessData(
 
     // report the completed response header
     if (mActivityDistributor && mResponseHead && mHaveAllHeaders &&
         !mReportedResponseHeader) {
       mReportedResponseHeader = true;
       nsAutoCString completeResponseHeaders;
       mResponseHead->Flatten(completeResponseHeaders, false);
       completeResponseHeaders.AppendLiteral("\r\n");
-      rv = mActivityDistributor->ObserveActivity(
-          mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+      rv = mActivityDistributor->ObserveActivityWithArgs(
+          HttpActivityArgs(mChannelId), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
           NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER, PR_Now(), 0,
           completeResponseHeaders);
       if (NS_FAILED(rv)) {
         LOG3(("ObserveActivity failed (%08x)", static_cast<uint32_t>(rv)));
       }
     }
   }
 
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -12,16 +12,17 @@
 #include "nsAHttpConnection.h"
 #include "EventTokenBucket.h"
 #include "nsCOMPtr.h"
 #include "nsThreadUtils.h"
 #include "nsIInterfaceRequestor.h"
 #include "TimingStruct.h"
 #include "Http2Push.h"
 #include "mozilla/net/DNS.h"
+#include "mozilla/net/NeckoChannelParams.h"
 #include "ARefBase.h"
 #include "AlternateServices.h"
 
 //-----------------------------------------------------------------------------
 
 class nsIHttpActivityObserver;
 class nsIEventTarget;
 class nsIInputStream;
@@ -209,16 +210,17 @@ class nsHttpTransaction final : public n
   nsCOMPtr<nsITransportEventSink> mTransportSink;
   nsCOMPtr<nsIEventTarget> mConsumerTarget;
   nsCOMPtr<nsISupports> mSecurityInfo;
   nsCOMPtr<nsIAsyncInputStream> mPipeIn;
   nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
   nsCOMPtr<nsIRequestContext> mRequestContext;
 
   nsCOMPtr<nsISupports> mChannel;
+  uint64_t mChannelId;
   nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
 
   nsCString mReqHeaderBuf;  // flattened request headers
   nsCOMPtr<nsIInputStream> mRequestStream;
   int64_t mRequestSize;
 
   RefPtr<nsAHttpConnection> mConnection;
   RefPtr<nsHttpConnectionInfo> mConnInfo;
--- a/netwerk/protocol/http/nsIHttpActivityObserver.idl
+++ b/netwerk/protocol/http/nsIHttpActivityObserver.idl
@@ -1,14 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+%{ C++
+namespace mozilla {
+namespace net {
+class HttpActivityArgs;
+} // namespace net
+} // namespace mozilla
+%}
+
+[ref] native HttpActivityArgs(const mozilla::net::HttpActivityArgs);
+
 /**
  * nsIHttpActivityObserver
  *
  * This interface provides a way for http activities to be reported
  * to observers.
  */
 [scriptable, uuid(412880C8-6C36-48d8-BF8F-84F91F892503)]
 interface nsIHttpActivityObserver : nsISupports
@@ -55,16 +65,40 @@ interface nsIHttpActivityObserver : nsIS
     /**
      * This attribute is true when this interface is active and should
      * observe http activities. When false, observeActivity() should not
      * be called. It is present for compatibility reasons and should be
      * implemented only by nsHttpActivityDistributor.
      */
     [must_use] readonly attribute boolean isActive;
 
+    /**
+     * This function is for internal use only. Every time a http transaction
+     * is created in socket process, we use this function to set the value of
+     * |isActive|. We need this since the real value of |isActive| is
+     * only available in parent process.
+     */
+    [noscript] void setIsActive(in boolean aActived);
+
+    /**
+     * This function is used when the real http channel is not available.
+     * We use the information in |HttpActivityArgs| to get the http channel or
+     * create a |NullHttpChannel|.
+     *
+     * @param aArgs
+     *        See the definition of |HttpActivityArgs| in PSocketProcess.ipdl.
+     */
+    [noscript, must_use]
+    void observeActivityWithArgs(in HttpActivityArgs aArgs,
+                                 in uint32_t aActivityType,
+                                 in uint32_t aActivitySubtype,
+                                 in PRTime   aTimestamp,
+                                 in uint64_t aExtraSizeData,
+                                 in ACString aExtraStringData);
+
     const unsigned long ACTIVITY_TYPE_SOCKET_TRANSPORT     = 0x0001;
     const unsigned long ACTIVITY_TYPE_HTTP_TRANSACTION     = 0x0002;
 
     const unsigned long ACTIVITY_SUBTYPE_REQUEST_HEADER    = 0x5001;
     const unsigned long ACTIVITY_SUBTYPE_REQUEST_BODY_SENT = 0x5002;
     const unsigned long ACTIVITY_SUBTYPE_RESPONSE_START    = 0x5003;
     const unsigned long ACTIVITY_SUBTYPE_RESPONSE_HEADER   = 0x5004;
     const unsigned long ACTIVITY_SUBTYPE_RESPONSE_COMPLETE = 0x5005;