diff options
Diffstat (limited to 'netwerk/ipc/SocketProcessChild.cpp')
-rw-r--r-- | netwerk/ipc/SocketProcessChild.cpp | 833 |
1 files changed, 833 insertions, 0 deletions
diff --git a/netwerk/ipc/SocketProcessChild.cpp b/netwerk/ipc/SocketProcessChild.cpp new file mode 100644 index 0000000000..000ebde2fd --- /dev/null +++ b/netwerk/ipc/SocketProcessChild.cpp @@ -0,0 +1,833 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "SocketProcessChild.h" +#include "SocketProcessLogging.h" + +#include "base/task.h" +#include "InputChannelThrottleQueueChild.h" +#include "HttpInfo.h" +#include "HttpTransactionChild.h" +#include "HttpConnectionMgrChild.h" +#include "mozilla/Assertions.h" +#include "mozilla/Atomics.h" +#include "mozilla/Components.h" +#include "mozilla/dom/MemoryReportRequest.h" +#include "mozilla/FOGIPC.h" +#include "mozilla/glean/GleanMetrics.h" +#include "mozilla/ipc/CrashReporterClient.h" +#include "mozilla/ipc/ProcessChild.h" +#include "mozilla/net/AltSvcTransactionChild.h" +#include "mozilla/net/BackgroundDataBridgeParent.h" +#include "mozilla/net/DNSRequestChild.h" +#include "mozilla/net/DNSRequestParent.h" +#include "mozilla/net/NativeDNSResolverOverrideChild.h" +#include "mozilla/net/ProxyAutoConfigChild.h" +#include "mozilla/net/SocketProcessBackgroundChild.h" +#include "mozilla/net/TRRServiceChild.h" +#include "mozilla/ipc/ProcessUtils.h" +#include "mozilla/Preferences.h" +#include "mozilla/RemoteLazyInputStreamChild.h" +#include "mozilla/StaticPrefs_javascript.h" +#include "mozilla/StaticPrefs_network.h" +#include "mozilla/Telemetry.h" +#include "NetworkConnectivityService.h" +#include "nsDebugImpl.h" +#include "nsHttpConnectionInfo.h" +#include "nsHttpHandler.h" +#include "nsIDNSService.h" +#include "nsIHttpActivityObserver.h" +#include "nsIXULRuntime.h" +#include "nsNetUtil.h" +#include "nsNSSComponent.h" +#include "nsSocketTransportService2.h" +#include "nsThreadManager.h" +#include "SocketProcessBridgeParent.h" +#include "jsapi.h" +#include "js/Initialization.h" +#include "js/Prefs.h" +#include "XPCSelfHostedShmem.h" + +#if defined(XP_WIN) +# include <process.h> + +# include "mozilla/WinDllServices.h" +#else +# include <unistd.h> +#endif + +#if defined(XP_LINUX) && defined(MOZ_SANDBOX) +# include "mozilla/Sandbox.h" +#endif + +#include "ChildProfilerController.h" + +#ifdef MOZ_WEBRTC +# include "mozilla/net/WebrtcTCPSocketChild.h" +#endif + +#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) +# include "mozilla/SandboxTestingChild.h" +#endif + +namespace mozilla { +namespace net { + +using namespace ipc; + +static bool sInitializedJS = false; + +static Atomic<SocketProcessChild*> sSocketProcessChild; + +SocketProcessChild::SocketProcessChild() { + LOG(("CONSTRUCT SocketProcessChild::SocketProcessChild\n")); + nsDebugImpl::SetMultiprocessMode("Socket"); + + MOZ_COUNT_CTOR(SocketProcessChild); + sSocketProcessChild = this; +} + +SocketProcessChild::~SocketProcessChild() { + LOG(("DESTRUCT SocketProcessChild::SocketProcessChild\n")); + MOZ_COUNT_DTOR(SocketProcessChild); + sSocketProcessChild = nullptr; +} + +/* static */ +SocketProcessChild* SocketProcessChild::GetSingleton() { + return sSocketProcessChild; +} + +#if defined(XP_MACOSX) +extern "C" { +void CGSShutdownServerConnections(); +}; +#endif + +void SocketProcessChild::InitSocketBackground() { + Endpoint<PSocketProcessBackgroundParent> parentEndpoint; + Endpoint<PSocketProcessBackgroundChild> childEndpoint; + if (NS_WARN_IF(NS_FAILED(PSocketProcessBackground::CreateEndpoints( + &parentEndpoint, &childEndpoint)))) { + return; + } + + SocketProcessBackgroundChild::Create(std::move(childEndpoint)); + + Unused << SendInitSocketBackground(std::move(parentEndpoint)); +} + +namespace { + +class NetTeardownObserver final : public nsIObserver { + public: + NetTeardownObserver() = default; + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + private: + ~NetTeardownObserver() = default; +}; + +NS_IMPL_ISUPPORTS(NetTeardownObserver, nsIObserver) + +NS_IMETHODIMP +NetTeardownObserver::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + if (SocketProcessChild* child = SocketProcessChild::GetSingleton()) { + child->CloseIPCClientCertsActor(); + } + + return NS_OK; +} + +} // namespace + +bool SocketProcessChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint, + const char* aParentBuildID) { + if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) { + return false; + } + if (NS_WARN_IF(!aEndpoint.Bind(this))) { + return false; + } + // This must be sent before any IPDL message, which may hit sentinel + // errors due to parent and content processes having different + // versions. + MessageChannel* channel = GetIPCChannel(); + if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) { + // We need to quit this process if the buildID doesn't match the parent's. + // This can occur when an update occurred in the background. + ProcessChild::QuickExit(); + } + + // Init crash reporter support. + CrashReporterClient::InitSingleton(this); + + if (NS_FAILED(NS_InitMinimalXPCOM())) { + return false; + } + + InitSocketBackground(); + + SetThisProcessName("Socket Process"); +#if defined(XP_MACOSX) + // Close all current connections to the WindowServer. This ensures that the + // Activity Monitor will not label the socket process as "Not responding" + // because it's not running a native event loop. See bug 1384336. + CGSShutdownServerConnections(); +#endif // XP_MACOSX + + nsresult rv; + nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv); + if (NS_FAILED(rv)) { + return false; + } + + nsCOMPtr<nsIProtocolHandler> handler; + rv = ios->GetProtocolHandler("http", getter_AddRefs(handler)); + if (NS_FAILED(rv)) { + return false; + } + + // Initialize DNS Service here, since it needs to be done in main thread. + nsCOMPtr<nsIDNSService> dns = + do_GetService("@mozilla.org/network/dns-service;1", &rv); + if (NS_FAILED(rv)) { + return false; + } + + if (!EnsureNSSInitializedChromeOrContent()) { + return false; + } + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (obs) { + nsCOMPtr<nsIObserver> observer = new NetTeardownObserver(); + Unused << obs->AddObserver(observer, "profile-change-net-teardown", false); + } + + mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID); + if (!mSocketThread) { + return false; + } + + return true; +} + +void SocketProcessChild::ActorDestroy(ActorDestroyReason aWhy) { + LOG(("SocketProcessChild::ActorDestroy\n")); + + { + MutexAutoLock lock(mMutex); + mShuttingDown = true; + } + + if (AbnormalShutdown == aWhy) { + NS_WARNING("Shutting down Socket process early due to a crash!"); + ProcessChild::QuickExit(); + } + + // Send the last bits of Glean data over to the main process. + glean::FlushFOGData( + [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); }); + + if (mProfilerController) { + mProfilerController->Shutdown(); + mProfilerController = nullptr; + } + + CrashReporterClient::DestroySingleton(); + XRE_ShutdownChildProcess(); +} + +void SocketProcessChild::CleanUp() { + LOG(("SocketProcessChild::CleanUp\n")); + + SocketProcessBackgroundChild::Shutdown(); + + for (const auto& parent : mSocketProcessBridgeParentMap.Values()) { + if (parent->CanSend()) { + parent->Close(); + } + } + + { + MutexAutoLock lock(mMutex); + mBackgroundDataBridgeMap.Clear(); + } + + // Normally, the IPC channel should be already closed at this point, but + // sometimes it's not (bug 1788860). When the channel is closed, calling + // Close() again is harmless. + Close(); + + NS_ShutdownXPCOM(nullptr); + + if (sInitializedJS) { + JS_ShutDown(); + } +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvInit( + const SocketPorcessInitAttributes& aAttributes) { + Unused << RecvSetOffline(aAttributes.mOffline()); + Unused << RecvSetConnectivity(aAttributes.mConnectivity()); + if (aAttributes.mInitSandbox()) { + Unused << RecvInitLinuxSandbox(aAttributes.mSandboxBroker()); + } + +#if defined(XP_WIN) + RefPtr<DllServices> dllSvc(DllServices::Get()); + dllSvc->StartUntrustedModulesProcessor( + aAttributes.mIsReadyForBackgroundProcessing()); +#endif // defined(XP_WIN) + + return IPC_OK(); +} + +IPCResult SocketProcessChild::RecvPreferenceUpdate(const Pref& aPref) { + Preferences::SetPreference(aPref); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvRequestMemoryReport( + const uint32_t& aGeneration, const bool& aAnonymize, + const bool& aMinimizeMemoryUsage, + const Maybe<ipc::FileDescriptor>& aDMDFile, + const RequestMemoryReportResolver& aResolver) { + nsPrintfCString processName("Socket (pid %u)", (unsigned)getpid()); + + mozilla::dom::MemoryReportRequestClient::Start( + aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName, + [&](const MemoryReport& aReport) { + Unused << GetSingleton()->SendAddMemoryReport(aReport); + }, + aResolver); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvSetOffline( + const bool& aOffline) { + LOG(("SocketProcessChild::RecvSetOffline aOffline=%d\n", aOffline)); + + nsCOMPtr<nsIIOService> io(do_GetIOService()); + NS_ASSERTION(io, "IO Service can not be null"); + + io->SetOffline(aOffline); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvSetConnectivity( + const bool& aConnectivity) { + nsCOMPtr<nsIIOService> io(do_GetIOService()); + nsCOMPtr<nsIIOServiceInternal> ioInternal(do_QueryInterface(io)); + NS_ASSERTION(ioInternal, "IO Service can not be null"); + + ioInternal->SetConnectivity(aConnectivity); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvInitLinuxSandbox( + const Maybe<ipc::FileDescriptor>& aBrokerFd) { +#if defined(XP_LINUX) && defined(MOZ_SANDBOX) + int fd = -1; + if (aBrokerFd.isSome()) { + fd = aBrokerFd.value().ClonePlatformHandle().release(); + } + SetSocketProcessSandbox(fd); +#endif // XP_LINUX && MOZ_SANDBOX + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvInitSocketProcessBridgeParent( + const ProcessId& aContentProcessId, + Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mSocketProcessBridgeParentMap.Contains(aContentProcessId)); + + if (NS_WARN_IF(!aEndpoint.IsValid())) { + return IPC_FAIL(this, "invalid endpoint"); + } + + auto bridge = MakeRefPtr<SocketProcessBridgeParent>(aContentProcessId); + MOZ_ALWAYS_TRUE(aEndpoint.Bind(bridge)); + + mSocketProcessBridgeParentMap.InsertOrUpdate(aContentProcessId, + std::move(bridge)); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvInitProfiler( + Endpoint<PProfilerChild>&& aEndpoint) { + mProfilerController = + mozilla::ChildProfilerController::Create(std::move(aEndpoint)); + return IPC_OK(); +} + +#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) +mozilla::ipc::IPCResult SocketProcessChild::RecvInitSandboxTesting( + Endpoint<PSandboxTestingChild>&& aEndpoint) { + if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) { + return IPC_FAIL( + this, "InitSandboxTesting failed to initialise the child process."); + } + return IPC_OK(); +} +#endif + +mozilla::ipc::IPCResult SocketProcessChild::RecvSocketProcessTelemetryPing() { + const uint32_t kExpectedUintValue = 42; + Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_SOCKET_ONLY_UINT, + kExpectedUintValue); + return IPC_OK(); +} + +void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) { + MOZ_ASSERT(NS_IsMainThread()); + + mSocketProcessBridgeParentMap.Remove(aId); +} + +PWebrtcTCPSocketChild* SocketProcessChild::AllocPWebrtcTCPSocketChild( + const Maybe<TabId>& tabId) { + // We don't allocate here: instead we always use IPDL constructor that takes + // an existing object + MOZ_ASSERT_UNREACHABLE( + "AllocPWebrtcTCPSocketChild should not be called on" + " socket child"); + return nullptr; +} + +bool SocketProcessChild::DeallocPWebrtcTCPSocketChild( + PWebrtcTCPSocketChild* aActor) { +#ifdef MOZ_WEBRTC + WebrtcTCPSocketChild* child = static_cast<WebrtcTCPSocketChild*>(aActor); + child->ReleaseIPDLReference(); +#endif + return true; +} + +already_AddRefed<PHttpTransactionChild> +SocketProcessChild::AllocPHttpTransactionChild() { + RefPtr<HttpTransactionChild> actor = new HttpTransactionChild(); + return actor.forget(); +} + +already_AddRefed<PHttpConnectionMgrChild> +SocketProcessChild::AllocPHttpConnectionMgrChild( + const HttpHandlerInitArgs& aArgs) { + LOG(("SocketProcessChild::AllocPHttpConnectionMgrChild \n")); + MOZ_ASSERT(gHttpHandler); + gHttpHandler->SetHttpHandlerInitArgs(aArgs); + + RefPtr<HttpConnectionMgrChild> actor = new HttpConnectionMgrChild(); + return actor.forget(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvUpdateDeviceModelId( + const nsACString& aModelId) { + MOZ_ASSERT(gHttpHandler); + gHttpHandler->SetDeviceModelId(aModelId); + return IPC_OK(); +} + +mozilla::ipc::IPCResult +SocketProcessChild::RecvOnHttpActivityDistributorActivated( + const bool& aIsActivated) { + if (nsCOMPtr<nsIHttpActivityObserver> distributor = + components::HttpActivityDistributor::Service()) { + distributor->SetIsActive(aIsActivated); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult +SocketProcessChild::RecvOnHttpActivityDistributorObserveProxyResponse( + const bool& aIsEnabled) { + nsCOMPtr<nsIHttpActivityDistributor> distributor = + do_GetService("@mozilla.org/network/http-activity-distributor;1"); + if (distributor) { + Unused << distributor->SetObserveProxyResponse(aIsEnabled); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult +SocketProcessChild::RecvOnHttpActivityDistributorObserveConnection( + const bool& aIsEnabled) { + nsCOMPtr<nsIHttpActivityDistributor> distributor = + do_GetService("@mozilla.org/network/http-activity-distributor;1"); + if (distributor) { + Unused << distributor->SetObserveConnection(aIsEnabled); + } + return IPC_OK(); +} + +already_AddRefed<PInputChannelThrottleQueueChild> +SocketProcessChild::AllocPInputChannelThrottleQueueChild( + const uint32_t& aMeanBytesPerSecond, const uint32_t& aMaxBytesPerSecond) { + RefPtr<InputChannelThrottleQueueChild> p = + new InputChannelThrottleQueueChild(); + p->Init(aMeanBytesPerSecond, aMaxBytesPerSecond); + return p.forget(); +} + +already_AddRefed<PAltSvcTransactionChild> +SocketProcessChild::AllocPAltSvcTransactionChild( + const HttpConnectionInfoCloneArgs& aConnInfo, const uint32_t& aCaps) { + RefPtr<nsHttpConnectionInfo> cinfo = + nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(aConnInfo); + RefPtr<AltSvcTransactionChild> child = + new AltSvcTransactionChild(cinfo, aCaps); + return child.forget(); +} + +already_AddRefed<PDNSRequestChild> SocketProcessChild::AllocPDNSRequestChild( + const nsACString& aHost, const nsACString& aTrrServer, const int32_t& aPort, + const uint16_t& aType, const OriginAttributes& aOriginAttributes, + const nsIDNSService::DNSFlags& aFlags) { + RefPtr<DNSRequestHandler> handler = new DNSRequestHandler(); + RefPtr<DNSRequestChild> actor = new DNSRequestChild(handler); + return actor.forget(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvPDNSRequestConstructor( + PDNSRequestChild* aActor, const nsACString& aHost, + const nsACString& aTrrServer, const int32_t& aPort, const uint16_t& aType, + const OriginAttributes& aOriginAttributes, + const nsIDNSService::DNSFlags& aFlags) { + RefPtr<DNSRequestChild> actor = static_cast<DNSRequestChild*>(aActor); + RefPtr<DNSRequestHandler> handler = + actor->GetDNSRequest()->AsDNSRequestHandler(); + handler->DoAsyncResolve(aHost, aTrrServer, aPort, aType, aOriginAttributes, + aFlags); + return IPC_OK(); +} + +void SocketProcessChild::AddDataBridgeToMap( + uint64_t aChannelId, BackgroundDataBridgeParent* aActor) { + MutexAutoLock lock(mMutex); + mBackgroundDataBridgeMap.InsertOrUpdate(aChannelId, RefPtr{aActor}); +} + +void SocketProcessChild::RemoveDataBridgeFromMap(uint64_t aChannelId) { + MutexAutoLock lock(mMutex); + mBackgroundDataBridgeMap.Remove(aChannelId); +} + +Maybe<RefPtr<BackgroundDataBridgeParent>> +SocketProcessChild::GetAndRemoveDataBridge(uint64_t aChannelId) { + MutexAutoLock lock(mMutex); + return mBackgroundDataBridgeMap.Extract(aChannelId); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvClearSessionCache( + ClearSessionCacheResolver&& aResolve) { + nsNSSComponent::DoClearSSLExternalAndInternalSessionCache(); + aResolve(void_t{}); + return IPC_OK(); +} + +already_AddRefed<PTRRServiceChild> SocketProcessChild::AllocPTRRServiceChild( + const bool& aCaptiveIsPassed, const bool& aParentalControlEnabled, + const nsTArray<nsCString>& aDNSSuffixList) { + RefPtr<TRRServiceChild> actor = new TRRServiceChild(); + return actor.forget(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvPTRRServiceConstructor( + PTRRServiceChild* aActor, const bool& aCaptiveIsPassed, + const bool& aParentalControlEnabled, nsTArray<nsCString>&& aDNSSuffixList) { + static_cast<TRRServiceChild*>(aActor)->Init( + aCaptiveIsPassed, aParentalControlEnabled, std::move(aDNSSuffixList)); + return IPC_OK(); +} + +already_AddRefed<PNativeDNSResolverOverrideChild> +SocketProcessChild::AllocPNativeDNSResolverOverrideChild() { + RefPtr<NativeDNSResolverOverrideChild> actor = + new NativeDNSResolverOverrideChild(); + return actor.forget(); +} + +mozilla::ipc::IPCResult +SocketProcessChild::RecvPNativeDNSResolverOverrideConstructor( + PNativeDNSResolverOverrideChild* aActor) { + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvNotifyObserver( + const nsACString& aTopic, const nsAString& aData) { + if (nsCOMPtr<nsIObserverService> obs = + mozilla::services::GetObserverService()) { + obs->NotifyObservers(nullptr, PromiseFlatCString(aTopic).get(), + PromiseFlatString(aData).get()); + } + return IPC_OK(); +} + +namespace { + +class DataResolverBase { + public: + // This type is threadsafe-refcounted, as it's referenced on the socket + // thread, but must be destroyed on the main thread. + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( + DataResolverBase) + + DataResolverBase() = default; + + protected: + virtual ~DataResolverBase() = default; +}; + +template <typename DataType, typename ResolverType> +class DataResolver final : public DataResolverBase { + public: + explicit DataResolver(ResolverType&& aResolve) + : mResolve(std::move(aResolve)) {} + + void OnResolve(DataType&& aData) { + MOZ_ASSERT(OnSocketThread()); + + RefPtr<DataResolver<DataType, ResolverType>> self = this; + mData = std::move(aData); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "net::DataResolver::OnResolve", + [self{std::move(self)}]() { self->mResolve(std::move(self->mData)); })); + } + + private: + virtual ~DataResolver() = default; + + ResolverType mResolve; + DataType mData; +}; + +} // anonymous namespace + +mozilla::ipc::IPCResult SocketProcessChild::RecvGetSocketData( + GetSocketDataResolver&& aResolve) { + if (!gSocketTransportService) { + aResolve(SocketDataArgs()); + return IPC_OK(); + } + + RefPtr< + DataResolver<SocketDataArgs, SocketProcessChild::GetSocketDataResolver>> + resolver = new DataResolver<SocketDataArgs, + SocketProcessChild::GetSocketDataResolver>( + std::move(aResolve)); + gSocketTransportService->Dispatch( + NS_NewRunnableFunction( + "net::SocketProcessChild::RecvGetSocketData", + [resolver{std::move(resolver)}]() { + SocketDataArgs args; + gSocketTransportService->GetSocketConnections(&args.info()); + args.totalSent() = gSocketTransportService->GetSentBytes(); + args.totalRecv() = gSocketTransportService->GetReceivedBytes(); + resolver->OnResolve(std::move(args)); + }), + NS_DISPATCH_NORMAL); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvGetDNSCacheEntries( + GetDNSCacheEntriesResolver&& aResolve) { + nsresult rv = NS_OK; + nsCOMPtr<nsIDNSService> dns = + do_GetService("@mozilla.org/network/dns-service;1", &rv); + if (NS_FAILED(rv)) { + aResolve(nsTArray<DNSCacheEntries>()); + return IPC_OK(); + } + + RefPtr<DataResolver<nsTArray<DNSCacheEntries>, + SocketProcessChild::GetDNSCacheEntriesResolver>> + resolver = + new DataResolver<nsTArray<DNSCacheEntries>, + SocketProcessChild::GetDNSCacheEntriesResolver>( + std::move(aResolve)); + gSocketTransportService->Dispatch( + NS_NewRunnableFunction( + "net::SocketProcessChild::RecvGetDNSCacheEntries", + [resolver{std::move(resolver)}, dns{std::move(dns)}]() { + nsTArray<DNSCacheEntries> entries; + dns->GetDNSCacheEntries(&entries); + resolver->OnResolve(std::move(entries)); + }), + NS_DISPATCH_NORMAL); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvGetHttpConnectionData( + GetHttpConnectionDataResolver&& aResolve) { + if (!gSocketTransportService) { + aResolve(nsTArray<HttpRetParams>()); + return IPC_OK(); + } + + RefPtr<DataResolver<nsTArray<HttpRetParams>, + SocketProcessChild::GetHttpConnectionDataResolver>> + resolver = + new DataResolver<nsTArray<HttpRetParams>, + SocketProcessChild::GetHttpConnectionDataResolver>( + std::move(aResolve)); + gSocketTransportService->Dispatch( + NS_NewRunnableFunction( + "net::SocketProcessChild::RecvGetHttpConnectionData", + [resolver{std::move(resolver)}]() { + nsTArray<HttpRetParams> data; + HttpInfo::GetHttpConnectionData(&data); + resolver->OnResolve(std::move(data)); + }), + NS_DISPATCH_NORMAL); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvInitProxyAutoConfigChild( + Endpoint<PProxyAutoConfigChild>&& aEndpoint) { + // For parsing PAC. + if (!sInitializedJS) { + JS::DisableJitBackend(); + + // Set all JS::Prefs. + SET_JS_PREFS_FROM_BROWSER_PREFS; + + const char* jsInitFailureReason = JS_InitWithFailureDiagnostic(); + if (jsInitFailureReason) { + MOZ_CRASH_UNSAFE(jsInitFailureReason); + } + sInitializedJS = true; + + xpc::SelfHostedShmem::GetSingleton(); + } + + Unused << ProxyAutoConfigChild::Create(std::move(aEndpoint)); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvRecheckIPConnectivity() { + RefPtr<NetworkConnectivityService> ncs = + NetworkConnectivityService::GetSingleton(); + if (ncs) { + ncs->RecheckIPConnectivity(); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvRecheckDNS() { + RefPtr<NetworkConnectivityService> ncs = + NetworkConnectivityService::GetSingleton(); + if (ncs) { + ncs->RecheckDNS(); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvFlushFOGData( + FlushFOGDataResolver&& aResolver) { + glean::FlushFOGData(std::move(aResolver)); + return IPC_OK(); +} + +mozilla::ipc::IPCResult SocketProcessChild::RecvTestTriggerMetrics( + TestTriggerMetricsResolver&& aResolve) { + mozilla::glean::test_only_ipc::a_counter.Add( + nsIXULRuntime::PROCESS_TYPE_SOCKET); + aResolve(true); + return IPC_OK(); +} + +#if defined(XP_WIN) +mozilla::ipc::IPCResult SocketProcessChild::RecvGetUntrustedModulesData( + GetUntrustedModulesDataResolver&& aResolver) { + RefPtr<DllServices> dllSvc(DllServices::Get()); + dllSvc->GetUntrustedModulesData()->Then( + GetMainThreadSerialEventTarget(), __func__, + [aResolver](Maybe<UntrustedModulesData>&& aData) { + aResolver(std::move(aData)); + }, + [aResolver](nsresult aReason) { aResolver(Nothing()); }); + return IPC_OK(); +} + +mozilla::ipc::IPCResult +SocketProcessChild::RecvUnblockUntrustedModulesThread() { + if (nsCOMPtr<nsIObserverService> obs = + mozilla::services::GetObserverService()) { + obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr); + } + return IPC_OK(); +} +#endif // defined(XP_WIN) + +bool SocketProcessChild::IsShuttingDown() { + MutexAutoLock lock(mMutex); + return mShuttingDown; +} + +void SocketProcessChild::CloseIPCClientCertsActor() { + LOG(("SocketProcessChild::CloseIPCClientCertsActor")); + MOZ_ASSERT(NS_IsMainThread()); + + mSocketThread->Dispatch(NS_NewRunnableFunction( + "CloseIPCClientCertsActor", [self = RefPtr{this}]() { + LOG(("CloseIPCClientCertsActor")); + if (self->mIPCClientCertsChild) { + self->mIPCClientCertsChild->Close(); + self->mIPCClientCertsChild = nullptr; + } + })); +} + +already_AddRefed<psm::IPCClientCertsChild> +SocketProcessChild::GetIPCClientCertsActor() { + LOG(("SocketProcessChild::GetIPCClientCertsActor")); + // Only socket thread can access the mIPCClientCertsChild. + if (!OnSocketThread()) { + return nullptr; + } + + { + MutexAutoLock lock(mMutex); + if (mShuttingDown) { + return nullptr; + } + } + + if (mIPCClientCertsChild) { + RefPtr<psm::IPCClientCertsChild> actorChild = mIPCClientCertsChild; + return actorChild.forget(); + } + + ipc::Endpoint<psm::PIPCClientCertsParent> parentEndpoint; + ipc::Endpoint<psm::PIPCClientCertsChild> childEndpoint; + psm::PIPCClientCerts::CreateEndpoints(&parentEndpoint, &childEndpoint); + + if (NS_FAILED(SocketProcessBackgroundChild::WithActor( + "SendInitIPCClientCerts", + [endpoint = std::move(parentEndpoint)]( + SocketProcessBackgroundChild* aActor) mutable { + Unused << aActor->SendInitIPCClientCerts(std::move(endpoint)); + }))) { + return nullptr; + } + + RefPtr<psm::IPCClientCertsChild> actor = new psm::IPCClientCertsChild(); + if (!childEndpoint.Bind(actor)) { + return nullptr; + } + + mIPCClientCertsChild = actor; + return actor.forget(); +} + +} // namespace net +} // namespace mozilla |