Backed out 10 changesets (bug 1803810) for xpcshell failures on test_import_global...
[gecko.git] / netwerk / ipc / SocketProcessHost.cpp
blob5a09f5200ce624e9f00b6199e5f3570051786086
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/. */
6 #include "SocketProcessHost.h"
8 #include "SocketProcessParent.h"
9 #include "mozilla/dom/ContentParent.h"
10 #include "mozilla/ipc/FileDescriptor.h"
11 #include "mozilla/ipc/ProcessUtils.h"
12 #include "nsAppRunner.h"
13 #include "nsIOService.h"
14 #include "nsIObserverService.h"
15 #include "ProfilerParent.h"
16 #include "nsNetUtil.h"
17 #include "mozilla/ipc/Endpoint.h"
18 #include "mozilla/ipc/ProcessChild.h"
20 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
21 # include "mozilla/SandboxBroker.h"
22 # include "mozilla/SandboxBrokerPolicyFactory.h"
23 # include "mozilla/SandboxSettings.h"
24 #endif
26 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
27 # include "mozilla/Sandbox.h"
28 #endif
30 #if defined(XP_WIN)
31 # include "mozilla/WinDllServices.h"
32 #endif
34 using namespace mozilla::ipc;
36 namespace mozilla {
37 namespace net {
39 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
40 bool SocketProcessHost::sLaunchWithMacSandbox = false;
41 #endif
43 SocketProcessHost::SocketProcessHost(Listener* aListener)
44 : GeckoChildProcessHost(GeckoProcessType_Socket),
45 mListener(aListener),
46 mTaskFactory(Some(this)),
47 mLaunchPhase(LaunchPhase::Unlaunched),
48 mShutdownRequested(false),
49 mChannelClosed(false) {
50 MOZ_ASSERT(NS_IsMainThread());
51 MOZ_COUNT_CTOR(SocketProcessHost);
52 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
53 if (!sLaunchWithMacSandbox) {
54 sLaunchWithMacSandbox =
55 (PR_GetEnv("MOZ_DISABLE_SOCKET_PROCESS_SANDBOX") == nullptr);
57 mDisableOSActivityMode = sLaunchWithMacSandbox;
58 #endif
61 SocketProcessHost::~SocketProcessHost() { MOZ_COUNT_DTOR(SocketProcessHost); }
63 bool SocketProcessHost::Launch() {
64 MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
65 MOZ_ASSERT(!mSocketProcessParent);
66 MOZ_ASSERT(NS_IsMainThread());
68 std::vector<std::string> extraArgs;
69 ProcessChild::AddPlatformBuildID(extraArgs);
71 SharedPreferenceSerializer prefSerializer;
72 if (!prefSerializer.SerializeToSharedMemory(GeckoProcessType_VR,
73 /* remoteType */ ""_ns)) {
74 return false;
76 prefSerializer.AddSharedPrefCmdLineArgs(*this, extraArgs);
78 mLaunchPhase = LaunchPhase::Waiting;
79 if (!GeckoChildProcessHost::LaunchAndWaitForProcessHandle(extraArgs)) {
80 mLaunchPhase = LaunchPhase::Complete;
81 return false;
84 return true;
87 static void HandleErrorAfterDestroy(
88 RefPtr<SocketProcessHost::Listener>&& aListener) {
89 if (!aListener) {
90 return;
93 NS_DispatchToMainThread(NS_NewRunnableFunction(
94 "HandleErrorAfterDestroy", [listener = std::move(aListener)]() {
95 listener->OnProcessLaunchComplete(nullptr, false);
96 }));
99 void SocketProcessHost::OnChannelConnected(base::ProcessId peer_pid) {
100 MOZ_ASSERT(!NS_IsMainThread());
102 GeckoChildProcessHost::OnChannelConnected(peer_pid);
104 // Post a task to the main thread. Take the lock because mTaskFactory is not
105 // thread-safe.
106 RefPtr<Runnable> runnable;
108 MonitorAutoLock lock(mMonitor);
109 if (!mTaskFactory) {
110 HandleErrorAfterDestroy(std::move(mListener));
111 return;
113 runnable =
114 (*mTaskFactory)
115 .NewRunnableMethod(&SocketProcessHost::OnChannelConnectedTask);
117 NS_DispatchToMainThread(runnable);
120 void SocketProcessHost::OnChannelConnectedTask() {
121 MOZ_ASSERT(NS_IsMainThread());
123 if (mLaunchPhase == LaunchPhase::Waiting) {
124 InitAfterConnect(true);
128 void SocketProcessHost::InitAfterConnect(bool aSucceeded) {
129 MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
130 MOZ_ASSERT(!mSocketProcessParent);
131 MOZ_ASSERT(NS_IsMainThread());
133 mLaunchPhase = LaunchPhase::Complete;
134 if (!aSucceeded) {
135 if (mListener) {
136 mListener->OnProcessLaunchComplete(this, false);
138 return;
141 mSocketProcessParent = MakeRefPtr<SocketProcessParent>(this);
142 DebugOnly<bool> rv = TakeInitialEndpoint().Bind(mSocketProcessParent.get());
143 MOZ_ASSERT(rv);
145 SocketPorcessInitAttributes attributes;
146 nsCOMPtr<nsIIOService> ioService(do_GetIOService());
147 MOZ_ASSERT(ioService, "No IO service?");
148 DebugOnly<nsresult> result = ioService->GetOffline(&attributes.mOffline());
149 MOZ_ASSERT(NS_SUCCEEDED(result), "Failed getting offline?");
150 result = ioService->GetConnectivity(&attributes.mConnectivity());
151 MOZ_ASSERT(NS_SUCCEEDED(result), "Failed getting connectivity?");
153 attributes.mInitSandbox() = false;
155 #if defined(XP_WIN)
156 RefPtr<DllServices> dllSvc(DllServices::Get());
157 attributes.mIsReadyForBackgroundProcessing() =
158 dllSvc->IsReadyForBackgroundProcessing();
159 #endif
161 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
162 if (GetEffectiveSocketProcessSandboxLevel() > 0) {
163 auto policy = SandboxBrokerPolicyFactory::GetSocketProcessPolicy(
164 GetActor()->OtherPid());
165 if (policy != nullptr) {
166 attributes.mSandboxBroker() = Some(FileDescriptor());
167 mSandboxBroker =
168 SandboxBroker::Create(std::move(policy), GetActor()->OtherPid(),
169 attributes.mSandboxBroker().ref());
170 // This is unlikely to fail and probably indicates OS resource
171 // exhaustion.
172 Unused << NS_WARN_IF(mSandboxBroker == nullptr);
173 MOZ_ASSERT(attributes.mSandboxBroker().ref().IsValid());
175 attributes.mInitSandbox() = true;
177 #endif // XP_LINUX && MOZ_SANDBOX
179 Unused << GetActor()->SendInit(attributes);
181 Unused << GetActor()->SendInitProfiler(
182 ProfilerParent::CreateForProcess(GetActor()->OtherPid()));
184 if (mListener) {
185 mListener->OnProcessLaunchComplete(this, true);
189 void SocketProcessHost::Shutdown() {
190 MOZ_ASSERT(!mShutdownRequested);
191 MOZ_ASSERT(NS_IsMainThread());
193 mListener = nullptr;
195 if (mSocketProcessParent) {
196 // OnChannelClosed uses this to check if the shutdown was expected or
197 // unexpected.
198 mShutdownRequested = true;
200 // The channel might already be closed if we got here unexpectedly.
201 if (!mChannelClosed) {
202 mSocketProcessParent->Close();
205 return;
208 DestroyProcess();
211 void SocketProcessHost::OnChannelClosed() {
212 MOZ_ASSERT(NS_IsMainThread());
214 mChannelClosed = true;
216 if (!mShutdownRequested && mListener) {
217 // This is an unclean shutdown. Notify our listener that we're going away.
218 mListener->OnProcessUnexpectedShutdown(this);
219 } else {
220 DestroyProcess();
223 // Release the actor.
224 SocketProcessParent::Destroy(std::move(mSocketProcessParent));
225 MOZ_ASSERT(!mSocketProcessParent);
228 void SocketProcessHost::DestroyProcess() {
230 MonitorAutoLock lock(mMonitor);
231 mTaskFactory.reset();
234 GetCurrentSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
235 "DestroySocketProcessRunnable", [this] { Destroy(); }));
238 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
239 bool SocketProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
240 GeckoChildProcessHost::FillMacSandboxInfo(aInfo);
241 if (!aInfo.shouldLog && PR_GetEnv("MOZ_SANDBOX_SOCKET_PROCESS_LOGGING")) {
242 aInfo.shouldLog = true;
244 return true;
247 /* static */
248 MacSandboxType SocketProcessHost::GetMacSandboxType() {
249 return MacSandboxType_Socket;
251 #endif
253 //-----------------------------------------------------------------------------
254 // SocketProcessMemoryReporter
255 //-----------------------------------------------------------------------------
257 bool SocketProcessMemoryReporter::IsAlive() const {
258 MOZ_ASSERT(gIOService);
260 if (!gIOService->mSocketProcess) {
261 return false;
264 return gIOService->mSocketProcess->IsConnected();
267 bool SocketProcessMemoryReporter::SendRequestMemoryReport(
268 const uint32_t& aGeneration, const bool& aAnonymize,
269 const bool& aMinimizeMemoryUsage,
270 const Maybe<ipc::FileDescriptor>& aDMDFile) {
271 MOZ_ASSERT(gIOService);
273 if (!gIOService->mSocketProcess) {
274 return false;
277 SocketProcessParent* actor = gIOService->mSocketProcess->GetActor();
278 if (!actor) {
279 return false;
282 return actor->SendRequestMemoryReport(aGeneration, aAnonymize,
283 aMinimizeMemoryUsage, aDMDFile);
286 int32_t SocketProcessMemoryReporter::Pid() const {
287 MOZ_ASSERT(gIOService);
288 return gIOService->SocketProcessPid();
291 } // namespace net
292 } // namespace mozilla