tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SocketProcessChild.cpp (27601B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "SocketProcessChild.h"
      7 #include "SocketProcessLogging.h"
      8 
      9 #include "base/task.h"
     10 #include "InputChannelThrottleQueueChild.h"
     11 #include "HttpInfo.h"
     12 #include "HttpTransactionChild.h"
     13 #include "HttpConnectionMgrChild.h"
     14 #include "mozilla/Assertions.h"
     15 #include "mozilla/Atomics.h"
     16 #include "mozilla/Components.h"
     17 #include "mozilla/dom/MemoryReportRequest.h"
     18 #include "mozilla/FOGIPC.h"
     19 #include "mozilla/glean/GleanTestsTestMetrics.h"
     20 #include "mozilla/ipc/CrashReporterClient.h"
     21 #include "mozilla/ipc/ProcessChild.h"
     22 #include "mozilla/net/AltSvcTransactionChild.h"
     23 #include "mozilla/net/BackgroundDataBridgeParent.h"
     24 #include "mozilla/net/DNSRequestChild.h"
     25 #include "mozilla/net/DNSRequestParent.h"
     26 #include "mozilla/net/NativeDNSResolverOverrideChild.h"
     27 #include "mozilla/net/ProxyAutoConfigChild.h"
     28 #include "mozilla/net/SocketProcessBackgroundChild.h"
     29 #include "mozilla/net/TRRServiceChild.h"
     30 #include "mozilla/ipc/ProcessUtils.h"
     31 #include "mozilla/Preferences.h"
     32 #include "mozilla/RemoteLazyInputStreamChild.h"
     33 #include "mozilla/StaticPrefs_javascript.h"
     34 #include "mozilla/StaticPrefs_network.h"
     35 #include "mozilla/Telemetry.h"
     36 #include "MockNetworkLayerController.h"
     37 #include "NetworkConnectivityService.h"
     38 #include "nsDebugImpl.h"
     39 #include "nsHttpConnectionInfo.h"
     40 #include "nsHttpHandler.h"
     41 #include "nsIDNSService.h"
     42 #include "nsIHttpActivityObserver.h"
     43 #include "nsIXULRuntime.h"
     44 #include "nsNetAddr.h"
     45 #include "nsNetUtil.h"
     46 #include "nsNSSComponent.h"
     47 #include "nsSocketTransportService2.h"
     48 #include "nsThreadManager.h"
     49 #include "SocketProcessBridgeParent.h"
     50 #include "jsapi.h"
     51 #include "js/Initialization.h"
     52 #include "js/Prefs.h"
     53 #include "XPCSelfHostedShmem.h"
     54 
     55 #if defined(XP_WIN)
     56 #  include <process.h>
     57 
     58 #  include "mozilla/WinDllServices.h"
     59 #else
     60 #  include <unistd.h>
     61 #endif
     62 
     63 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
     64 #  include "mozilla/Sandbox.h"
     65 #  include "mozilla/SandboxProfilerObserver.h"
     66 #endif
     67 
     68 #include "ChildProfilerController.h"
     69 
     70 #ifdef MOZ_WEBRTC
     71 #  include "mozilla/net/WebrtcTCPSocketChild.h"
     72 #endif
     73 
     74 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
     75 #  include "mozilla/SandboxTestingChild.h"
     76 #endif
     77 
     78 namespace TelemetryScalar {
     79 void Set(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
     80 }
     81 
     82 namespace mozilla {
     83 namespace net {
     84 
     85 using namespace ipc;
     86 
     87 static bool sInitializedJS = false;
     88 
     89 static Atomic<SocketProcessChild*> sSocketProcessChild;
     90 
     91 SocketProcessChild::SocketProcessChild() {
     92  LOG(("CONSTRUCT SocketProcessChild::SocketProcessChild\n"));
     93  nsDebugImpl::SetMultiprocessMode("Socket");
     94 
     95  MOZ_COUNT_CTOR(SocketProcessChild);
     96  sSocketProcessChild = this;
     97 }
     98 
     99 SocketProcessChild::~SocketProcessChild() {
    100  LOG(("DESTRUCT SocketProcessChild::SocketProcessChild\n"));
    101  MOZ_COUNT_DTOR(SocketProcessChild);
    102  sSocketProcessChild = nullptr;
    103 }
    104 
    105 /* static */
    106 SocketProcessChild* SocketProcessChild::GetSingleton() {
    107  return sSocketProcessChild;
    108 }
    109 
    110 #if defined(XP_MACOSX)
    111 extern "C" {
    112 void CGSShutdownServerConnections();
    113 };
    114 #endif
    115 
    116 void SocketProcessChild::InitSocketBackground() {
    117  Endpoint<PSocketProcessBackgroundParent> parentEndpoint;
    118  Endpoint<PSocketProcessBackgroundChild> childEndpoint;
    119  if (NS_WARN_IF(NS_FAILED(PSocketProcessBackground::CreateEndpoints(
    120          &parentEndpoint, &childEndpoint)))) {
    121    return;
    122  }
    123 
    124  SocketProcessBackgroundChild::Create(std::move(childEndpoint));
    125 
    126  (void)SendInitSocketBackground(std::move(parentEndpoint));
    127 }
    128 
    129 namespace {
    130 
    131 class NetTeardownObserver final : public nsIObserver {
    132 public:
    133  NetTeardownObserver() = default;
    134 
    135  NS_DECL_ISUPPORTS
    136  NS_DECL_NSIOBSERVER
    137 
    138 private:
    139  ~NetTeardownObserver() = default;
    140 };
    141 
    142 NS_IMPL_ISUPPORTS(NetTeardownObserver, nsIObserver)
    143 
    144 NS_IMETHODIMP
    145 NetTeardownObserver::Observe(nsISupports* aSubject, const char* aTopic,
    146                             const char16_t* aData) {
    147  if (SocketProcessChild* child = SocketProcessChild::GetSingleton()) {
    148    child->CloseIPCClientCertsActor();
    149  }
    150 
    151  return NS_OK;
    152 }
    153 
    154 }  // namespace
    155 
    156 bool SocketProcessChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
    157                              const char* aParentBuildID) {
    158  if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
    159    return false;
    160  }
    161  if (NS_WARN_IF(!aEndpoint.Bind(this))) {
    162    return false;
    163  }
    164  // This must be sent before any IPDL message, which may hit sentinel
    165  // errors due to parent and content processes having different
    166  // versions.
    167  MessageChannel* channel = GetIPCChannel();
    168  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
    169    // We need to quit this process if the buildID doesn't match the parent's.
    170    // This can occur when an update occurred in the background.
    171    ProcessChild::QuickExit();
    172  }
    173 
    174  // Init crash reporter support.
    175  CrashReporterClient::InitSingleton(this);
    176 
    177  if (NS_FAILED(NS_InitMinimalXPCOM())) {
    178    return false;
    179  }
    180 
    181  InitSocketBackground();
    182 
    183  SetThisProcessName("Socket Process");
    184 #if defined(XP_MACOSX)
    185  // Close all current connections to the WindowServer. This ensures that the
    186  // Activity Monitor will not label the socket process as "Not responding"
    187  // because it's not running a native event loop. See bug 1384336.
    188  CGSShutdownServerConnections();
    189 #endif  // XP_MACOSX
    190 
    191  nsresult rv;
    192  nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
    193  if (NS_FAILED(rv)) {
    194    return false;
    195  }
    196 
    197  nsCOMPtr<nsIProtocolHandler> handler;
    198  rv = ios->GetProtocolHandler("http", getter_AddRefs(handler));
    199  if (NS_FAILED(rv)) {
    200    return false;
    201  }
    202 
    203  // Initialize DNS Service here, since it needs to be done in main thread.
    204  mozilla::components::DNS::Service(&rv);
    205  if (NS_FAILED(rv)) {
    206    return false;
    207  }
    208 
    209  if (!EnsureNSSInitializedChromeOrContent()) {
    210    return false;
    211  }
    212 
    213  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
    214  if (obs) {
    215    nsCOMPtr<nsIObserver> observer = new NetTeardownObserver();
    216    (void)obs->AddObserver(observer, "profile-change-net-teardown", false);
    217  }
    218 
    219  mSocketThread = mozilla::components::SocketTransport::Service();
    220  if (!mSocketThread) {
    221    return false;
    222  }
    223 
    224  return true;
    225 }
    226 
    227 void SocketProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
    228  LOG(("SocketProcessChild::ActorDestroy\n"));
    229 
    230  {
    231    MutexAutoLock lock(mMutex);
    232    mShuttingDown = true;
    233  }
    234 
    235 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
    236  DestroySandboxProfiler();
    237 #endif
    238 
    239  if (AbnormalShutdown == aWhy) {
    240    NS_WARNING("Shutting down Socket process early due to a crash!");
    241    ProcessChild::QuickExit();
    242  }
    243 
    244  // Send the last bits of Glean data over to the main process.
    245  glean::FlushFOGData(
    246      [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); });
    247 
    248  if (mProfilerController) {
    249    mProfilerController->Shutdown();
    250    mProfilerController = nullptr;
    251  }
    252 
    253  CrashReporterClient::DestroySingleton();
    254  XRE_ShutdownChildProcess();
    255 }
    256 
    257 void SocketProcessChild::CleanUp() {
    258  LOG(("SocketProcessChild::CleanUp\n"));
    259 
    260  SocketProcessBackgroundChild::Shutdown();
    261 
    262  for (const auto& parent : mSocketProcessBridgeParentMap.Values()) {
    263    if (parent->CanSend()) {
    264      parent->Close();
    265    }
    266  }
    267 
    268  {
    269    MutexAutoLock lock(mMutex);
    270    mBackgroundDataBridgeMap.Clear();
    271  }
    272 
    273  // Normally, the IPC channel should be already closed at this point, but
    274  // sometimes it's not (bug 1788860). When the channel is closed, calling
    275  // Close() again is harmless.
    276  Close();
    277 
    278  NS_ShutdownXPCOM(nullptr);
    279 
    280  if (sInitializedJS) {
    281    JS_ShutDown();
    282  }
    283 }
    284 
    285 mozilla::ipc::IPCResult SocketProcessChild::RecvInit(
    286    const SocketPorcessInitAttributes& aAttributes) {
    287  (void)RecvSetOffline(aAttributes.mOffline());
    288  (void)RecvSetConnectivity(aAttributes.mConnectivity());
    289  if (aAttributes.mInitSandbox()) {
    290    (void)RecvInitLinuxSandbox(aAttributes.mSandboxBroker());
    291  }
    292 
    293 #if defined(XP_WIN)
    294  RefPtr<DllServices> dllSvc(DllServices::Get());
    295  dllSvc->StartUntrustedModulesProcessor(
    296      aAttributes.mIsReadyForBackgroundProcessing());
    297 #endif  // defined(XP_WIN)
    298 
    299  return IPC_OK();
    300 }
    301 
    302 IPCResult SocketProcessChild::RecvPreferenceUpdate(const Pref& aPref) {
    303  Preferences::SetPreference(aPref);
    304  return IPC_OK();
    305 }
    306 
    307 mozilla::ipc::IPCResult SocketProcessChild::RecvRequestMemoryReport(
    308    const uint32_t& aGeneration, const bool& aAnonymize,
    309    const bool& aMinimizeMemoryUsage,
    310    const Maybe<ipc::FileDescriptor>& aDMDFile,
    311    const RequestMemoryReportResolver& aResolver) {
    312  nsPrintfCString processName("Socket (pid %u)", (unsigned)getpid());
    313 
    314  mozilla::dom::MemoryReportRequestClient::Start(
    315      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
    316      [&](const MemoryReport& aReport) {
    317        (void)GetSingleton()->SendAddMemoryReport(aReport);
    318      },
    319      aResolver);
    320  return IPC_OK();
    321 }
    322 
    323 mozilla::ipc::IPCResult SocketProcessChild::RecvSetOffline(
    324    const bool& aOffline) {
    325  LOG(("SocketProcessChild::RecvSetOffline aOffline=%d\n", aOffline));
    326 
    327  nsCOMPtr<nsIIOService> io(do_GetIOService());
    328  NS_ASSERTION(io, "IO Service can not be null");
    329 
    330  io->SetOffline(aOffline);
    331 
    332  return IPC_OK();
    333 }
    334 
    335 mozilla::ipc::IPCResult SocketProcessChild::RecvSetConnectivity(
    336    const bool& aConnectivity) {
    337  nsCOMPtr<nsIIOService> io(do_GetIOService());
    338  nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io));
    339  NS_ASSERTION(ioInternal, "IO Service can not be null");
    340 
    341  ioInternal->SetConnectivity(aConnectivity);
    342 
    343  return IPC_OK();
    344 }
    345 
    346 mozilla::ipc::IPCResult SocketProcessChild::RecvInitLinuxSandbox(
    347    const Maybe<ipc::FileDescriptor>& aBrokerFd) {
    348 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
    349  RegisterProfilerObserversForSandboxProfiler();
    350  SetSocketProcessSandbox(
    351      SocketProcessSandboxParams::ForThisProcess(aBrokerFd));
    352 #endif  // XP_LINUX && MOZ_SANDBOX
    353  return IPC_OK();
    354 }
    355 
    356 mozilla::ipc::IPCResult SocketProcessChild::RecvInitSocketProcessBridgeParent(
    357    const ProcessId& aContentProcessId,
    358    Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) {
    359  MOZ_ASSERT(NS_IsMainThread());
    360  MOZ_ASSERT(!mSocketProcessBridgeParentMap.Contains(aContentProcessId));
    361 
    362  if (NS_WARN_IF(!aEndpoint.IsValid())) {
    363    return IPC_FAIL(this, "invalid endpoint");
    364  }
    365 
    366  auto bridge = MakeRefPtr<SocketProcessBridgeParent>(aContentProcessId);
    367  MOZ_ALWAYS_TRUE(aEndpoint.Bind(bridge));
    368 
    369  mSocketProcessBridgeParentMap.InsertOrUpdate(aContentProcessId,
    370                                               std::move(bridge));
    371  return IPC_OK();
    372 }
    373 
    374 mozilla::ipc::IPCResult SocketProcessChild::RecvInitProfiler(
    375    Endpoint<PProfilerChild>&& aEndpoint) {
    376  mProfilerController =
    377      mozilla::ChildProfilerController::Create(std::move(aEndpoint));
    378  return IPC_OK();
    379 }
    380 
    381 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
    382 mozilla::ipc::IPCResult SocketProcessChild::RecvInitSandboxTesting(
    383    Endpoint<PSandboxTestingChild>&& aEndpoint) {
    384  if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
    385    return IPC_FAIL(
    386        this, "InitSandboxTesting failed to initialise the child process.");
    387  }
    388  return IPC_OK();
    389 }
    390 #endif
    391 
    392 mozilla::ipc::IPCResult SocketProcessChild::RecvSocketProcessTelemetryPing() {
    393  const uint32_t kExpectedUintValue = 42;
    394  TelemetryScalar::Set(Telemetry::ScalarID::TELEMETRY_TEST_SOCKET_ONLY_UINT,
    395                       kExpectedUintValue);
    396  return IPC_OK();
    397 }
    398 
    399 void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) {
    400  MOZ_ASSERT(NS_IsMainThread());
    401 
    402  mSocketProcessBridgeParentMap.Remove(aId);
    403 }
    404 
    405 PWebrtcTCPSocketChild* SocketProcessChild::AllocPWebrtcTCPSocketChild(
    406    const Maybe<TabId>& tabId) {
    407  // We don't allocate here: instead we always use IPDL constructor that takes
    408  // an existing object
    409  MOZ_ASSERT_UNREACHABLE(
    410      "AllocPWebrtcTCPSocketChild should not be called on"
    411      " socket child");
    412  return nullptr;
    413 }
    414 
    415 bool SocketProcessChild::DeallocPWebrtcTCPSocketChild(
    416    PWebrtcTCPSocketChild* aActor) {
    417 #ifdef MOZ_WEBRTC
    418  WebrtcTCPSocketChild* child = static_cast<WebrtcTCPSocketChild*>(aActor);
    419  child->ReleaseIPDLReference();
    420 #endif
    421  return true;
    422 }
    423 
    424 already_AddRefed<PHttpTransactionChild>
    425 SocketProcessChild::AllocPHttpTransactionChild() {
    426  RefPtr<HttpTransactionChild> actor = new HttpTransactionChild();
    427  return actor.forget();
    428 }
    429 
    430 already_AddRefed<PHttpConnectionMgrChild>
    431 SocketProcessChild::AllocPHttpConnectionMgrChild(
    432    const HttpHandlerInitArgs& aArgs) {
    433  LOG(("SocketProcessChild::AllocPHttpConnectionMgrChild \n"));
    434  MOZ_ASSERT(gHttpHandler);
    435  gHttpHandler->SetHttpHandlerInitArgs(aArgs);
    436 
    437  RefPtr<HttpConnectionMgrChild> actor = new HttpConnectionMgrChild();
    438  return actor.forget();
    439 }
    440 
    441 mozilla::ipc::IPCResult SocketProcessChild::RecvUpdateDeviceModelId(
    442    const nsACString& aModelId) {
    443  MOZ_ASSERT(gHttpHandler);
    444  gHttpHandler->SetDeviceModelId(aModelId);
    445  return IPC_OK();
    446 }
    447 
    448 mozilla::ipc::IPCResult
    449 SocketProcessChild::RecvOnHttpActivityDistributorActivated(
    450    const bool& aIsActivated) {
    451  nsCOMPtr<nsIHttpActivityObserver> distributor;
    452  distributor = mozilla::components::HttpActivityDistributor::Service();
    453  if (distributor) {
    454    distributor->SetIsActive(aIsActivated);
    455  }
    456  return IPC_OK();
    457 }
    458 
    459 mozilla::ipc::IPCResult
    460 SocketProcessChild::RecvOnHttpActivityDistributorObserveProxyResponse(
    461    const bool& aIsEnabled) {
    462  nsCOMPtr<nsIHttpActivityDistributor> distributor;
    463  distributor = mozilla::components::HttpActivityDistributor::Service();
    464  if (distributor) {
    465    (void)distributor->SetObserveProxyResponse(aIsEnabled);
    466  }
    467  return IPC_OK();
    468 }
    469 
    470 mozilla::ipc::IPCResult
    471 SocketProcessChild::RecvOnHttpActivityDistributorObserveConnection(
    472    const bool& aIsEnabled) {
    473  nsCOMPtr<nsIHttpActivityDistributor> distributor;
    474  distributor = mozilla::components::HttpActivityDistributor::Service();
    475  if (distributor) {
    476    (void)distributor->SetObserveConnection(aIsEnabled);
    477  }
    478  return IPC_OK();
    479 }
    480 
    481 already_AddRefed<PInputChannelThrottleQueueChild>
    482 SocketProcessChild::AllocPInputChannelThrottleQueueChild(
    483    const uint32_t& aMeanBytesPerSecond, const uint32_t& aMaxBytesPerSecond) {
    484  RefPtr<InputChannelThrottleQueueChild> p =
    485      new InputChannelThrottleQueueChild();
    486  p->Init(aMeanBytesPerSecond, aMaxBytesPerSecond);
    487  return p.forget();
    488 }
    489 
    490 already_AddRefed<PAltSvcTransactionChild>
    491 SocketProcessChild::AllocPAltSvcTransactionChild(
    492    const HttpConnectionInfoCloneArgs& aConnInfo, const uint32_t& aCaps) {
    493  RefPtr<nsHttpConnectionInfo> cinfo =
    494      nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(aConnInfo);
    495  RefPtr<AltSvcTransactionChild> child =
    496      new AltSvcTransactionChild(cinfo, aCaps);
    497  return child.forget();
    498 }
    499 
    500 already_AddRefed<PDNSRequestChild> SocketProcessChild::AllocPDNSRequestChild(
    501    const nsACString& aHost, const nsACString& aTrrServer, const int32_t& aPort,
    502    const uint16_t& aType, const OriginAttributes& aOriginAttributes,
    503    const nsIDNSService::DNSFlags& aFlags) {
    504  RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
    505  RefPtr<DNSRequestChild> actor = new DNSRequestChild(handler);
    506  return actor.forget();
    507 }
    508 
    509 mozilla::ipc::IPCResult SocketProcessChild::RecvPDNSRequestConstructor(
    510    PDNSRequestChild* aActor, const nsACString& aHost,
    511    const nsACString& aTrrServer, const int32_t& aPort, const uint16_t& aType,
    512    const OriginAttributes& aOriginAttributes,
    513    const nsIDNSService::DNSFlags& aFlags) {
    514  RefPtr<DNSRequestChild> actor = static_cast<DNSRequestChild*>(aActor);
    515  RefPtr<DNSRequestHandler> handler =
    516      actor->GetDNSRequest()->AsDNSRequestHandler();
    517  handler->DoAsyncResolve(aHost, aTrrServer, aPort, aType, aOriginAttributes,
    518                          aFlags);
    519  return IPC_OK();
    520 }
    521 
    522 void SocketProcessChild::AddDataBridgeToMap(
    523    uint64_t aChannelId, BackgroundDataBridgeParent* aActor) {
    524  MutexAutoLock lock(mMutex);
    525  mBackgroundDataBridgeMap.InsertOrUpdate(aChannelId, RefPtr{aActor});
    526 }
    527 
    528 void SocketProcessChild::RemoveDataBridgeFromMap(uint64_t aChannelId) {
    529  MutexAutoLock lock(mMutex);
    530  mBackgroundDataBridgeMap.Remove(aChannelId);
    531 }
    532 
    533 Maybe<RefPtr<BackgroundDataBridgeParent>>
    534 SocketProcessChild::GetAndRemoveDataBridge(uint64_t aChannelId) {
    535  MutexAutoLock lock(mMutex);
    536  return mBackgroundDataBridgeMap.Extract(aChannelId);
    537 }
    538 
    539 mozilla::ipc::IPCResult SocketProcessChild::RecvClearSessionCache(
    540    ClearSessionCacheResolver&& aResolve) {
    541  nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
    542  aResolve(void_t{});
    543  return IPC_OK();
    544 }
    545 
    546 already_AddRefed<PTRRServiceChild> SocketProcessChild::AllocPTRRServiceChild(
    547    const bool& aCaptiveIsPassed, const bool& aParentalControlEnabled,
    548    const nsTArray<nsCString>& aDNSSuffixList) {
    549  RefPtr<TRRServiceChild> actor = new TRRServiceChild();
    550  return actor.forget();
    551 }
    552 
    553 mozilla::ipc::IPCResult SocketProcessChild::RecvPTRRServiceConstructor(
    554    PTRRServiceChild* aActor, const bool& aCaptiveIsPassed,
    555    const bool& aParentalControlEnabled, nsTArray<nsCString>&& aDNSSuffixList) {
    556  static_cast<TRRServiceChild*>(aActor)->Init(
    557      aCaptiveIsPassed, aParentalControlEnabled, std::move(aDNSSuffixList));
    558  return IPC_OK();
    559 }
    560 
    561 already_AddRefed<PNativeDNSResolverOverrideChild>
    562 SocketProcessChild::AllocPNativeDNSResolverOverrideChild() {
    563  RefPtr<NativeDNSResolverOverrideChild> actor =
    564      new NativeDNSResolverOverrideChild();
    565  return actor.forget();
    566 }
    567 
    568 mozilla::ipc::IPCResult
    569 SocketProcessChild::RecvPNativeDNSResolverOverrideConstructor(
    570    PNativeDNSResolverOverrideChild* aActor) {
    571  return IPC_OK();
    572 }
    573 
    574 mozilla::ipc::IPCResult SocketProcessChild::RecvNotifyObserver(
    575    const nsACString& aTopic, const nsAString& aData) {
    576  if (nsCOMPtr<nsIObserverService> obs =
    577          mozilla::services::GetObserverService()) {
    578    obs->NotifyObservers(nullptr, PromiseFlatCString(aTopic).get(),
    579                         PromiseFlatString(aData).get());
    580  }
    581  return IPC_OK();
    582 }
    583 
    584 namespace {
    585 
    586 class DataResolverBase {
    587 public:
    588  // This type is threadsafe-refcounted, as it's referenced on the socket
    589  // thread, but must be destroyed on the main thread.
    590  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(
    591      DataResolverBase)
    592 
    593  DataResolverBase() = default;
    594 
    595 protected:
    596  virtual ~DataResolverBase() = default;
    597 };
    598 
    599 template <typename DataType, typename ResolverType>
    600 class DataResolver final : public DataResolverBase {
    601 public:
    602  explicit DataResolver(ResolverType&& aResolve)
    603      : mResolve(std::move(aResolve)) {}
    604 
    605  void OnResolve(DataType&& aData) {
    606    MOZ_ASSERT(OnSocketThread());
    607 
    608    RefPtr<DataResolver<DataType, ResolverType>> self = this;
    609    mData = std::move(aData);
    610    NS_DispatchToMainThread(NS_NewRunnableFunction(
    611        "net::DataResolver::OnResolve",
    612        [self{std::move(self)}]() { self->mResolve(std::move(self->mData)); }));
    613  }
    614 
    615 private:
    616  virtual ~DataResolver() = default;
    617 
    618  ResolverType mResolve;
    619  DataType mData;
    620 };
    621 
    622 }  // anonymous namespace
    623 
    624 mozilla::ipc::IPCResult SocketProcessChild::RecvGetSocketData(
    625    GetSocketDataResolver&& aResolve) {
    626  if (!gSocketTransportService) {
    627    aResolve(SocketDataArgs());
    628    return IPC_OK();
    629  }
    630 
    631  RefPtr<
    632      DataResolver<SocketDataArgs, SocketProcessChild::GetSocketDataResolver>>
    633      resolver = new DataResolver<SocketDataArgs,
    634                                  SocketProcessChild::GetSocketDataResolver>(
    635          std::move(aResolve));
    636  gSocketTransportService->Dispatch(
    637      NS_NewRunnableFunction(
    638          "net::SocketProcessChild::RecvGetSocketData",
    639          [resolver{std::move(resolver)}]() {
    640            SocketDataArgs args;
    641            gSocketTransportService->GetSocketConnections(&args.info());
    642            args.totalSent() = gSocketTransportService->GetSentBytes();
    643            args.totalRecv() = gSocketTransportService->GetReceivedBytes();
    644            resolver->OnResolve(std::move(args));
    645          }),
    646      NS_DISPATCH_NORMAL);
    647  return IPC_OK();
    648 }
    649 
    650 mozilla::ipc::IPCResult SocketProcessChild::RecvGetDNSCacheEntries(
    651    GetDNSCacheEntriesResolver&& aResolve) {
    652  nsresult rv = NS_OK;
    653  nsCOMPtr<nsIDNSService> dns;
    654  dns = mozilla::components::DNS::Service(&rv);
    655  if (NS_FAILED(rv)) {
    656    aResolve(nsTArray<DNSCacheEntries>());
    657    return IPC_OK();
    658  }
    659 
    660  RefPtr<DataResolver<nsTArray<DNSCacheEntries>,
    661                      SocketProcessChild::GetDNSCacheEntriesResolver>>
    662      resolver =
    663          new DataResolver<nsTArray<DNSCacheEntries>,
    664                           SocketProcessChild::GetDNSCacheEntriesResolver>(
    665              std::move(aResolve));
    666  gSocketTransportService->Dispatch(
    667      NS_NewRunnableFunction(
    668          "net::SocketProcessChild::RecvGetDNSCacheEntries",
    669          [resolver{std::move(resolver)}, dns{std::move(dns)}]() {
    670            nsTArray<DNSCacheEntries> entries;
    671            dns->GetDNSCacheEntries(&entries);
    672            resolver->OnResolve(std::move(entries));
    673          }),
    674      NS_DISPATCH_NORMAL);
    675  return IPC_OK();
    676 }
    677 
    678 mozilla::ipc::IPCResult SocketProcessChild::RecvGetHttpConnectionData(
    679    GetHttpConnectionDataResolver&& aResolve) {
    680  if (!gSocketTransportService) {
    681    aResolve(nsTArray<HttpRetParams>());
    682    return IPC_OK();
    683  }
    684 
    685  RefPtr<DataResolver<nsTArray<HttpRetParams>,
    686                      SocketProcessChild::GetHttpConnectionDataResolver>>
    687      resolver =
    688          new DataResolver<nsTArray<HttpRetParams>,
    689                           SocketProcessChild::GetHttpConnectionDataResolver>(
    690              std::move(aResolve));
    691  gSocketTransportService->Dispatch(
    692      NS_NewRunnableFunction(
    693          "net::SocketProcessChild::RecvGetHttpConnectionData",
    694          [resolver{std::move(resolver)}]() {
    695            nsTArray<HttpRetParams> data;
    696            HttpInfo::GetHttpConnectionData(&data);
    697            resolver->OnResolve(std::move(data));
    698          }),
    699      NS_DISPATCH_NORMAL);
    700  return IPC_OK();
    701 }
    702 
    703 mozilla::ipc::IPCResult SocketProcessChild::RecvGetHttp3ConnectionStatsData(
    704    GetHttp3ConnectionStatsDataResolver&& aResolve) {
    705  if (!gSocketTransportService) {
    706    aResolve(nsTArray<Http3ConnectionStatsParams>());
    707    return IPC_OK();
    708  }
    709 
    710  RefPtr<DataResolver<nsTArray<Http3ConnectionStatsParams>,
    711                      SocketProcessChild::GetHttp3ConnectionStatsDataResolver>>
    712      resolver = new DataResolver<
    713          nsTArray<Http3ConnectionStatsParams>,
    714          SocketProcessChild::GetHttp3ConnectionStatsDataResolver>(
    715          std::move(aResolve));
    716  gSocketTransportService->Dispatch(
    717      NS_NewRunnableFunction(
    718          "net::SocketProcessChild::RecvGetHttpConnectionStatsData",
    719          [resolver{std::move(resolver)}]() {
    720            nsTArray<Http3ConnectionStatsParams> data;
    721            HttpInfo::GetHttp3ConnectionStatsData(&data);
    722            resolver->OnResolve(std::move(data));
    723          }),
    724      NS_DISPATCH_NORMAL);
    725  return IPC_OK();
    726 }
    727 
    728 mozilla::ipc::IPCResult SocketProcessChild::RecvInitProxyAutoConfigChild(
    729    Endpoint<PProxyAutoConfigChild>&& aEndpoint) {
    730  // For parsing PAC.
    731  if (!sInitializedJS) {
    732    JS::DisableJitBackend();
    733 
    734    // Set all JS::Prefs.
    735    SET_JS_PREFS_FROM_BROWSER_PREFS;
    736 
    737    const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
    738    if (jsInitFailureReason) {
    739      MOZ_CRASH_UNSAFE(jsInitFailureReason);
    740    }
    741    sInitializedJS = true;
    742 
    743    xpc::SelfHostedShmem::GetSingleton();
    744  }
    745 
    746  (void)ProxyAutoConfigChild::Create(std::move(aEndpoint));
    747  return IPC_OK();
    748 }
    749 
    750 mozilla::ipc::IPCResult SocketProcessChild::RecvRecheckIPConnectivity() {
    751  RefPtr<NetworkConnectivityService> ncs =
    752      NetworkConnectivityService::GetSingleton();
    753  if (ncs) {
    754    ncs->RecheckIPConnectivity();
    755  }
    756  return IPC_OK();
    757 }
    758 
    759 mozilla::ipc::IPCResult SocketProcessChild::RecvRecheckDNS() {
    760  RefPtr<NetworkConnectivityService> ncs =
    761      NetworkConnectivityService::GetSingleton();
    762  if (ncs) {
    763    ncs->RecheckDNS();
    764  }
    765  return IPC_OK();
    766 }
    767 
    768 mozilla::ipc::IPCResult SocketProcessChild::RecvFlushFOGData(
    769    FlushFOGDataResolver&& aResolver) {
    770  glean::FlushFOGData(std::move(aResolver));
    771  return IPC_OK();
    772 }
    773 
    774 mozilla::ipc::IPCResult SocketProcessChild::RecvTestTriggerMetrics(
    775    TestTriggerMetricsResolver&& aResolve) {
    776  mozilla::glean::test_only_ipc::a_counter.Add(
    777      nsIXULRuntime::PROCESS_TYPE_SOCKET);
    778  aResolve(true);
    779  return IPC_OK();
    780 }
    781 
    782 #if defined(XP_WIN)
    783 mozilla::ipc::IPCResult SocketProcessChild::RecvGetUntrustedModulesData(
    784    GetUntrustedModulesDataResolver&& aResolver) {
    785  RefPtr<DllServices> dllSvc(DllServices::Get());
    786  dllSvc->GetUntrustedModulesData()->Then(
    787      GetMainThreadSerialEventTarget(), __func__,
    788      [aResolver](Maybe<UntrustedModulesData>&& aData) {
    789        aResolver(std::move(aData));
    790      },
    791      [aResolver](nsresult aReason) { aResolver(Nothing()); });
    792  return IPC_OK();
    793 }
    794 
    795 mozilla::ipc::IPCResult
    796 SocketProcessChild::RecvUnblockUntrustedModulesThread() {
    797  if (nsCOMPtr<nsIObserverService> obs =
    798          mozilla::services::GetObserverService()) {
    799    obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
    800  }
    801  return IPC_OK();
    802 }
    803 #endif  // defined(XP_WIN)
    804 
    805 bool SocketProcessChild::IsShuttingDown() {
    806  MutexAutoLock lock(mMutex);
    807  return mShuttingDown;
    808 }
    809 
    810 void SocketProcessChild::CloseIPCClientCertsActor() {
    811  LOG(("SocketProcessChild::CloseIPCClientCertsActor"));
    812  MOZ_ASSERT(NS_IsMainThread());
    813 
    814  mSocketThread->Dispatch(NS_NewRunnableFunction(
    815      "CloseIPCClientCertsActor", [self = RefPtr{this}]() {
    816        LOG(("CloseIPCClientCertsActor"));
    817        if (self->mIPCClientCertsChild) {
    818          self->mIPCClientCertsChild->Close();
    819          self->mIPCClientCertsChild = nullptr;
    820        }
    821      }));
    822 }
    823 
    824 already_AddRefed<psm::IPCClientCertsChild>
    825 SocketProcessChild::GetIPCClientCertsActor() {
    826  LOG(("SocketProcessChild::GetIPCClientCertsActor"));
    827  // Only socket thread can access the mIPCClientCertsChild.
    828  if (!OnSocketThread()) {
    829    return nullptr;
    830  }
    831 
    832  {
    833    MutexAutoLock lock(mMutex);
    834    if (mShuttingDown) {
    835      return nullptr;
    836    }
    837  }
    838 
    839  if (mIPCClientCertsChild) {
    840    RefPtr<psm::IPCClientCertsChild> actorChild = mIPCClientCertsChild;
    841    return actorChild.forget();
    842  }
    843 
    844  ipc::Endpoint<psm::PIPCClientCertsParent> parentEndpoint;
    845  ipc::Endpoint<psm::PIPCClientCertsChild> childEndpoint;
    846  psm::PIPCClientCerts::CreateEndpoints(&parentEndpoint, &childEndpoint);
    847 
    848  if (NS_FAILED(SocketProcessBackgroundChild::WithActor(
    849          "SendInitIPCClientCerts",
    850          [endpoint = std::move(parentEndpoint)](
    851              SocketProcessBackgroundChild* aActor) mutable {
    852            (void)aActor->SendInitIPCClientCerts(std::move(endpoint));
    853          }))) {
    854    return nullptr;
    855  }
    856 
    857  RefPtr<psm::IPCClientCertsChild> actor = new psm::IPCClientCertsChild();
    858  if (!childEndpoint.Bind(actor)) {
    859    return nullptr;
    860  }
    861 
    862  mIPCClientCertsChild = actor;
    863  return actor.forget();
    864 }
    865 
    866 mozilla::ipc::IPCResult SocketProcessChild::RecvAddNetAddrOverride(
    867    const NetAddr& aFrom, const NetAddr& aTo) {
    868  nsCOMPtr<nsIMockNetworkLayerController> controller =
    869      MockNetworkLayerController::GetSingleton();
    870  RefPtr<nsNetAddr> from = new nsNetAddr(&aFrom);
    871  RefPtr<nsNetAddr> to = new nsNetAddr(&aTo);
    872  (void)controller->AddNetAddrOverride(from, to);
    873  return IPC_OK();
    874 }
    875 mozilla::ipc::IPCResult SocketProcessChild::RecvClearNetAddrOverrides() {
    876  nsCOMPtr<nsIMockNetworkLayerController> controller =
    877      MockNetworkLayerController::GetSingleton();
    878  (void)controller->ClearNetAddrOverrides();
    879  return IPC_OK();
    880 }
    881 
    882 }  // namespace net
    883 }  // namespace mozilla