Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 "SocketProcessParent.h"
#include "SocketProcessLogging.h"
#include "AltServiceParent.h"
#include "CachePushChecker.h"
#include "HttpTransactionParent.h"
#include "SocketProcessHost.h"
#include "TLSClientAuthCertSelection.h"
#include "mozilla/Components.h"
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/FOGIPC.h"
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/net/ProxyConfigLookupParent.h"
#include "mozilla/RemoteLazyInputStreamParent.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryIPC.h"
#include "nsIAppStartup.h"
#include "nsIConsoleService.h"
#include "nsIHttpActivityObserver.h"
#include "nsIObserverService.h"
#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsIOService.h"
#include "nsHttpHandler.h"
#include "nsHttpConnectionInfo.h"
#include "secerr.h"
#ifdef MOZ_WEBRTC
# include "mozilla/dom/ContentProcessManager.h"
# include "mozilla/dom/BrowserParent.h"
# include "mozilla/net/WebrtcTCPSocketParent.h"
#endif
#if defined(MOZ_WIDGET_ANDROID)
# include "mozilla/java/GeckoProcessManagerWrappers.h"
# include "mozilla/java/GeckoProcessTypeWrappers.h"
#endif // defined(MOZ_WIDGET_ANDROID)
#if defined(XP_WIN)
# include "mozilla/WinDllServices.h"
#endif
namespace mozilla {
namespace net {
static SocketProcessParent* sSocketProcessParent;
SocketProcessParent::SocketProcessParent(SocketProcessHost* aHost)
: mHost(aHost) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mHost);
MOZ_COUNT_CTOR(SocketProcessParent);
sSocketProcessParent = this;
}
SocketProcessParent::~SocketProcessParent() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(SocketProcessParent);
sSocketProcessParent = nullptr;
}
/* static */
SocketProcessParent* SocketProcessParent::GetSingleton() {
MOZ_ASSERT(NS_IsMainThread());
return sSocketProcessParent;
}
void SocketProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
#if defined(MOZ_WIDGET_ANDROID)
nsCOMPtr<nsIEventTarget> launcherThread(ipc::GetIPCLauncher());
MOZ_ASSERT(launcherThread);
auto procType = java::GeckoProcessType::SOCKET();
auto selector =
java::GeckoProcessManager::Selector::New(procType, OtherPid());
launcherThread->Dispatch(NS_NewRunnableFunction(
"SocketProcessParent::ActorDestroy",
[selector = java::GeckoProcessManager::Selector::GlobalRef(selector)]() {
java::GeckoProcessManager::ShutdownProcess(selector);
}));
#endif // defined(MOZ_WIDGET_ANDROID)
if (aWhy == AbnormalShutdown) {
GenerateCrashReport(OtherPid());
if (PR_GetEnv("MOZ_CRASHREPORTER_SHUTDOWN")) {
printf_stderr("Shutting down due to socket process crash.\n");
nsCOMPtr<nsIAppStartup> appService =
do_GetService("@mozilla.org/toolkit/app-startup;1");
if (appService) {
bool userAllowedQuit = true;
appService->Quit(nsIAppStartup::eForceQuit, 1, &userAllowedQuit);
}
}
}
if (mHost) {
mHost->OnChannelClosed();
}
}
bool SocketProcessParent::SendRequestMemoryReport(
const uint32_t& aGeneration, const bool& aAnonymize,
const bool& aMinimizeMemoryUsage,
const Maybe<ipc::FileDescriptor>& aDMDFile) {
mMemoryReportRequest = MakeUnique<dom::MemoryReportRequestHost>(aGeneration);
PSocketProcessParent::SendRequestMemoryReport(
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile,
[&](const uint32_t& aGeneration2) {
MOZ_ASSERT(gIOService);
if (!gIOService->SocketProcess()) {
return;
}
SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
if (!actor) {
return;
}
if (actor->mMemoryReportRequest) {
actor->mMemoryReportRequest->Finish(aGeneration2);
actor->mMemoryReportRequest = nullptr;
}
},
[&](mozilla::ipc::ResponseRejectReason) {
MOZ_ASSERT(gIOService);
if (!gIOService->SocketProcess()) {
return;
}
SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
if (!actor) {
return;
}
actor->mMemoryReportRequest = nullptr;
});
return true;
}
mozilla::ipc::IPCResult SocketProcessParent::RecvAddMemoryReport(
const MemoryReport& aReport) {
if (mMemoryReportRequest) {
mMemoryReportRequest->RecvReport(aReport);
}
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildHistograms(
nsTArray<HistogramAccumulation>&& aAccumulations) {
TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Socket,
aAccumulations);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildKeyedHistograms(
nsTArray<KeyedHistogramAccumulation>&& aAccumulations) {
TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Socket,
aAccumulations);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildScalars(
nsTArray<ScalarAction>&& aScalarActions) {
TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Socket,
aScalarActions);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildKeyedScalars(
nsTArray<KeyedScalarAction>&& aScalarActions) {
TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Socket,
aScalarActions);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvRecordChildEvents(
nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) {
TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Socket, aEvents);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvRecordDiscardedData(
const mozilla::Telemetry::DiscardedData& aDiscardedData) {
TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Socket,
aDiscardedData);
return IPC_OK();
}
PWebrtcTCPSocketParent* SocketProcessParent::AllocPWebrtcTCPSocketParent(
const Maybe<TabId>& aTabId) {
#ifdef MOZ_WEBRTC
WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
parent->AddRef();
return parent;
#else
return nullptr;
#endif
}
bool SocketProcessParent::DeallocPWebrtcTCPSocketParent(
PWebrtcTCPSocketParent* aActor) {
#ifdef MOZ_WEBRTC
WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
parent->Release();
#endif
return true;
}
already_AddRefed<PDNSRequestParent> SocketProcessParent::AllocPDNSRequestParent(
const nsACString& aHost, const nsACString& aTrrServer, const int32_t& port,
const uint16_t& aType, const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags) {
RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
return actor.forget();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvPDNSRequestConstructor(
PDNSRequestParent* aActor, const nsACString& aHost,
const nsACString& aTrrServer, const int32_t& port, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
RefPtr<DNSRequestHandler> handler =
actor->GetDNSRequest()->AsDNSRequestHandler();
handler->DoAsyncResolve(aHost, aTrrServer, port, aType, aOriginAttributes,
aFlags);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvObserveHttpActivity(
const HttpActivityArgs& aArgs, const uint32_t& aActivityType,
const uint32_t& aActivitySubtype, const PRTime& aTimestamp,
const uint64_t& aExtraSizeData, const nsACString& aExtraStringData) {
nsCOMPtr<nsIHttpActivityDistributor> activityDistributor =
components::HttpActivityDistributor::Service();
MOZ_ASSERT(activityDistributor);
Unused << activityDistributor->ObserveActivityWithArgs(
aArgs, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
aExtraStringData);
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvInitBackground(
Endpoint<PBackgroundStarterParent>&& aEndpoint) {
LOG(("SocketProcessParent::RecvInitBackground\n"));
if (!ipc::BackgroundParent::AllocStarter(nullptr, std::move(aEndpoint))) {
return IPC_FAIL(this, "BackgroundParent::Alloc failed");
}
return IPC_OK();
}
already_AddRefed<PAltServiceParent>
SocketProcessParent::AllocPAltServiceParent() {
RefPtr<AltServiceParent> actor = new AltServiceParent();
return actor.forget();
}
already_AddRefed<PProxyConfigLookupParent>
SocketProcessParent::AllocPProxyConfigLookupParent(
nsIURI* aURI, const uint32_t& aProxyResolveFlags) {
RefPtr<ProxyConfigLookupParent> actor =
new ProxyConfigLookupParent(aURI, aProxyResolveFlags);
return actor.forget();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvPProxyConfigLookupConstructor(
PProxyConfigLookupParent* aActor, nsIURI* aURI,
const uint32_t& aProxyResolveFlags) {
static_cast<ProxyConfigLookupParent*>(aActor)->DoProxyLookup();
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvCachePushCheck(
nsIURI* aPushedURL, OriginAttributes&& aOriginAttributes,
nsCString&& aRequestString, CachePushCheckResolver&& aResolver) {
RefPtr<CachePushChecker> checker = new CachePushChecker(
aPushedURL, aOriginAttributes, aRequestString, aResolver);
if (NS_FAILED(checker->DoCheck())) {
aResolver(false);
}
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)) {}
NS_IMETHODIMP Run() override { return NS_OK; }
private:
UniquePtr<SocketProcessParent> mParent;
};
/* static */
void SocketProcessParent::Destroy(UniquePtr<SocketProcessParent>&& aParent) {
NS_DispatchToMainThread(
new DeferredDeleteSocketProcessParent(std::move(aParent)));
}
mozilla::ipc::IPCResult SocketProcessParent::RecvODoHServiceActivated(
const bool& aActivated) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(nullptr, "odoh-service-activated",
aActivated ? u"true" : u"false");
}
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvExcludeHttp2OrHttp3(
const HttpConnectionInfoCloneArgs& aArgs) {
RefPtr<nsHttpConnectionInfo> cinfo =
nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(aArgs);
if (!cinfo) {
MOZ_ASSERT(false, "failed to deserizlize http connection info");
return IPC_OK();
}
if (cinfo->IsHttp3()) {
gHttpHandler->ExcludeHttp3(cinfo);
} else {
gHttpHandler->ExcludeHttp2(cinfo);
}
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvOnConsoleMessage(
const nsString& aMessage) {
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(aMessage.get());
}
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvFOGData(ByteBuf&& aBuf) {
glean::FOGData(std::move(aBuf));
return IPC_OK();
}
#if defined(XP_WIN)
mozilla::ipc::IPCResult SocketProcessParent::RecvGetModulesTrust(
ModulePaths&& aModPaths, bool aRunAtNormalPriority,
GetModulesTrustResolver&& aResolver) {
RefPtr<DllServices> dllSvc(DllServices::Get());
dllSvc->GetModulesTrust(std::move(aModPaths), aRunAtNormalPriority)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[aResolver](ModulesMapResult&& aResult) {
aResolver(Some(ModulesMapResult(std::move(aResult))));
},
[aResolver](nsresult aRv) { aResolver(Nothing()); });
return IPC_OK();
}
#endif // defined(XP_WIN)
} // namespace net
} // namespace mozilla