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