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"
26 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
27 # include "mozilla/Sandbox.h"
31 # include "mozilla/WinDllServices.h"
34 using namespace mozilla::ipc
;
39 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
40 bool SocketProcessHost::sLaunchWithMacSandbox
= false;
43 SocketProcessHost::SocketProcessHost(Listener
* aListener
)
44 : GeckoChildProcessHost(GeckoProcessType_Socket
),
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
;
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
)) {
76 prefSerializer
.AddSharedPrefCmdLineArgs(*this, extraArgs
);
78 mLaunchPhase
= LaunchPhase::Waiting
;
79 if (!GeckoChildProcessHost::LaunchAndWaitForProcessHandle(extraArgs
)) {
80 mLaunchPhase
= LaunchPhase::Complete
;
87 static void HandleErrorAfterDestroy(
88 RefPtr
<SocketProcessHost::Listener
>&& aListener
) {
93 NS_DispatchToMainThread(NS_NewRunnableFunction(
94 "HandleErrorAfterDestroy", [listener
= std::move(aListener
)]() {
95 listener
->OnProcessLaunchComplete(nullptr, false);
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
106 RefPtr
<Runnable
> runnable
;
108 MonitorAutoLock
lock(mMonitor
);
110 HandleErrorAfterDestroy(std::move(mListener
));
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
;
136 mListener
->OnProcessLaunchComplete(this, false);
141 mSocketProcessParent
= MakeRefPtr
<SocketProcessParent
>(this);
142 DebugOnly
<bool> rv
= TakeInitialEndpoint().Bind(mSocketProcessParent
.get());
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;
156 RefPtr
<DllServices
> dllSvc(DllServices::Get());
157 attributes
.mIsReadyForBackgroundProcessing() =
158 dllSvc
->IsReadyForBackgroundProcessing();
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());
168 SandboxBroker::Create(std::move(policy
), GetActor()->OtherPid(),
169 attributes
.mSandboxBroker().ref());
170 // This is unlikely to fail and probably indicates OS resource
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()));
185 mListener
->OnProcessLaunchComplete(this, true);
189 void SocketProcessHost::Shutdown() {
190 MOZ_ASSERT(!mShutdownRequested
);
191 MOZ_ASSERT(NS_IsMainThread());
195 if (mSocketProcessParent
) {
196 // OnChannelClosed uses this to check if the shutdown was expected or
198 mShutdownRequested
= true;
200 // The channel might already be closed if we got here unexpectedly.
201 if (!mChannelClosed
) {
202 mSocketProcessParent
->Close();
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);
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;
248 MacSandboxType
SocketProcessHost::GetMacSandboxType() {
249 return MacSandboxType_Socket
;
253 //-----------------------------------------------------------------------------
254 // SocketProcessMemoryReporter
255 //-----------------------------------------------------------------------------
257 bool SocketProcessMemoryReporter::IsAlive() const {
258 MOZ_ASSERT(gIOService
);
260 if (!gIOService
->mSocketProcess
) {
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
) {
277 SocketProcessParent
* actor
= gIOService
->mSocketProcess
->GetActor();
282 return actor
->SendRequestMemoryReport(aGeneration
, aAnonymize
,
283 aMinimizeMemoryUsage
, aDMDFile
);
286 int32_t SocketProcessMemoryReporter::Pid() const {
287 MOZ_ASSERT(gIOService
);
288 return gIOService
->SocketProcessPid();
292 } // namespace mozilla