1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "GeckoChildProcessHost.h"
9 #include "base/command_line.h"
10 #include "base/process.h"
11 #include "base/process_util.h"
12 #include "base/string_util.h"
13 #include "base/task.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/process_watcher.h"
17 # include <mach/mach_traps.h>
18 # include "SharedMemory.h"
19 # include "base/rand_util.h"
20 # include "chrome/common/mach_ipc_mac.h"
21 # include "mozilla/StaticPrefs_media.h"
23 #ifdef MOZ_WIDGET_COCOA
24 # include <bsm/libbsm.h>
25 # include <servers/bootstrap.h>
26 # include "nsILocalFileMac.h"
29 #include "GeckoProfiler.h"
30 #include "MainThreadUtils.h"
31 #include "mozilla/Preferences.h"
32 #include "mozilla/Sprintf.h"
33 #include "nsXPCOMPrivate.h"
37 #if defined(MOZ_SANDBOX)
38 # include "mozilla/SandboxSettings.h"
39 # include "nsAppDirectoryServiceDefs.h"
44 #include "ProtocolUtils.h"
45 #include "mozilla/LinkedList.h"
46 #include "mozilla/Logging.h"
47 #include "mozilla/Maybe.h"
48 #include "mozilla/GeckoArgs.h"
49 #include "mozilla/Omnijar.h"
50 #include "mozilla/RDDProcessHost.h"
51 #include "mozilla/Services.h"
52 #include "mozilla/SharedThreadPool.h"
53 #include "mozilla/StaticMutex.h"
54 #include "mozilla/TaskQueue.h"
55 #include "mozilla/glean/DomMetrics.h"
56 #include "mozilla/Telemetry.h"
57 #include "mozilla/UniquePtrExtensions.h"
58 #include "mozilla/ipc/IOThread.h"
59 #include "mozilla/ipc/EnvironmentMap.h"
60 #include "mozilla/ipc/NodeController.h"
61 #include "mozilla/net/SocketProcessHost.h"
62 #include "nsDirectoryService.h"
63 #include "nsDirectoryServiceDefs.h"
64 #include "nsExceptionHandler.h"
66 #include "nsIObserverService.h"
67 #include "nsPrintfCString.h"
72 # include "nsIWinTaskbar.h"
73 # define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
75 # if defined(MOZ_SANDBOX)
76 # include "WinUtils.h"
77 # include "mozilla/Preferences.h"
78 # include "mozilla/sandboxing/sandboxLogging.h"
81 # include "mozilla/NativeNt.h"
82 # include "mozilla/CacheNtDllThunk.h"
85 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
86 # include "mozilla/SandboxLaunch.h"
89 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
90 # include "GMPProcessParent.h"
91 # include "nsMacUtilsImpl.h"
94 #include "mozilla/ipc/UtilityProcessHost.h"
95 #include "mozilla/ipc/UtilityProcessSandboxing.h"
97 #include "nsClassHashtable.h"
98 #include "nsHashKeys.h"
99 #include "nsNativeCharsetUtils.h"
100 #include "nsTArray.h"
101 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
102 #include "nsIThread.h"
104 using mozilla::MonitorAutoLock
;
105 using mozilla::Preferences
;
106 using mozilla::StaticMutexAutoLock
;
108 #ifdef MOZ_WIDGET_ANDROID
109 # include "AndroidBridge.h"
110 # include "mozilla/java/GeckoProcessManagerWrappers.h"
111 # include "mozilla/java/GeckoProcessTypeWrappers.h"
112 # include "mozilla/java/GeckoResultWrappers.h"
113 # include "mozilla/jni/Refs.h"
114 # include "mozilla/jni/Utils.h"
117 #ifdef MOZ_ENABLE_FORKSERVER
118 # include "mozilla/ipc/ForkServiceChild.h"
121 static bool ShouldHaveDirectoryService() {
122 return GeckoProcessType_Default
== XRE_GetProcessType();
128 struct LaunchResults
{
129 base::ProcessHandle mHandle
= 0;
131 task_t mChildTask
= MACH_PORT_NULL
;
134 Maybe
<ExtensionKitProcess
> mExtensionKitProcess
;
135 DarwinObjectPtr
<xpc_connection_t
> mXPCConnection
;
136 UniqueBEProcessCapabilityGrant mForegroundCapabilityGrant
;
138 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
139 UniquePtr
<SandboxBroker
> mSandboxBroker
;
142 typedef mozilla::MozPromise
<LaunchResults
, LaunchError
, true>
143 ProcessLaunchPromise
;
145 // Monotonic counter used to generate a unique ChildID for each process as it is
146 // created. The parent process is given the ChildID of `0`, and each child
147 // process is given a non-zero ID.
148 static Atomic
<int32_t> gChildCounter
;
150 class BaseProcessLauncher
{
152 BaseProcessLauncher(GeckoChildProcessHost
* aHost
,
153 geckoargs::ChildProcessArgs
&& aExtraOpts
)
154 : mProcessType(aHost
->mProcessType
),
155 mLaunchOptions(std::move(aHost
->mLaunchOptions
)),
156 mChildArgs(std::move(aExtraOpts
))
159 mGroupId(aHost
->mGroupId
)
161 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
163 mAllowedFilesRead(aHost
->mAllowedFilesRead
),
164 mSandboxLevel(aHost
->mSandboxLevel
),
165 mSandbox(aHost
->mSandbox
),
166 mIsFileContent(aHost
->mIsFileContent
),
167 mEnableSandboxLogging(aHost
->mEnableSandboxLogging
)
169 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
171 mDisableOSActivityMode(aHost
->mDisableOSActivityMode
)
174 aHost
->mInitialChannelId
.ToProvidedString(mInitialChannelIdString
);
175 SprintfLiteral(mChildIDString
, "%d", aHost
->mChildID
);
177 // Compute the serial event target we'll use for launching.
178 nsCOMPtr
<nsIEventTarget
> threadOrPool
= GetIPCLauncher();
180 TaskQueue::Create(threadOrPool
.forget(), "BaseProcessLauncher");
182 if (ShouldHaveDirectoryService()) {
183 // "Current process directory" means the app dir, not the current
184 // working dir or similar.
186 << nsDirectoryService::gService
->GetCurrentProcessDirectory(
187 getter_AddRefs(mAppDir
));
191 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher
);
193 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
194 void SetLaunchArchitecture(uint32_t aLaunchArch
) {
195 mLaunchArch
= aLaunchArch
;
199 RefPtr
<ProcessLaunchPromise
> Launch(GeckoChildProcessHost
*);
202 virtual ~BaseProcessLauncher() = default;
204 RefPtr
<ProcessLaunchPromise
> PerformAsyncLaunch();
205 RefPtr
<ProcessLaunchPromise
> FinishLaunch();
207 // Overrideable hooks. If superclass behavior is invoked, it's always at the
208 // top of the override.
209 virtual Result
<Ok
, LaunchError
> DoSetup();
210 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() = 0;
211 virtual Result
<Ok
, LaunchError
> DoFinishLaunch();
213 void MapChildLogging();
215 static BinPathType
GetPathToBinary(FilePath
&, GeckoProcessType
);
217 void GetChildLogName(const char* origLogName
, nsACString
& buffer
);
219 const char* ChildProcessType() {
220 return XRE_GeckoProcessTypeToString(mProcessType
);
223 nsCOMPtr
<nsISerialEventTarget
> mLaunchThread
;
224 GeckoProcessType mProcessType
;
225 UniquePtr
<base::LaunchOptions
> mLaunchOptions
;
226 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
227 uint32_t mLaunchArch
= base::PROCESS_ARCH_INVALID
;
229 geckoargs::ChildProcessArgs mChildArgs
;
233 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
234 std::vector
<std::wstring
> mAllowedFilesRead
;
235 int32_t mSandboxLevel
;
236 SandboxingKind mSandbox
;
238 bool mEnableSandboxLogging
;
240 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
241 // Controls whether or not the process will be launched with
242 // environment variable OS_ACTIVITY_MODE set to "disabled".
243 bool mDisableOSActivityMode
;
245 LaunchResults mResults
= LaunchResults();
246 TimeStamp mStartTimeStamp
= TimeStamp::Now();
247 char mInitialChannelIdString
[NSID_LENGTH
];
248 char mChildIDString
[32];
250 // Set during launch.
251 nsCOMPtr
<nsIFile
> mAppDir
;
255 class WindowsProcessLauncher
: public BaseProcessLauncher
{
257 WindowsProcessLauncher(GeckoChildProcessHost
* aHost
,
258 geckoargs::ChildProcessArgs
&& aExtraOpts
)
259 : BaseProcessLauncher(aHost
, std::move(aExtraOpts
)),
260 mCachedNtdllThunk(GetCachedNtDllThunk()) {}
263 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
264 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
265 virtual Result
<Ok
, LaunchError
> DoFinishLaunch() override
;
267 mozilla::Maybe
<CommandLine
> mCmdLine
;
269 bool mUseSandbox
= false;
272 const Buffer
<IMAGE_THUNK_DATA
>* mCachedNtdllThunk
;
274 typedef WindowsProcessLauncher ProcessLauncher
;
278 class PosixProcessLauncher
: public BaseProcessLauncher
{
280 PosixProcessLauncher(GeckoChildProcessHost
* aHost
,
281 geckoargs::ChildProcessArgs
&& aExtraOpts
)
282 : BaseProcessLauncher(aHost
, std::move(aExtraOpts
)),
283 mProfileDir(aHost
->mProfileDir
) {}
286 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
287 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
289 nsCOMPtr
<nsIFile
> mProfileDir
;
292 # if defined(XP_MACOSX)
293 class MacProcessLauncher
: public PosixProcessLauncher
{
295 MacProcessLauncher(GeckoChildProcessHost
* aHost
,
296 geckoargs::ChildProcessArgs
&& aExtraOpts
)
297 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)),
298 // Put a random number into the channel name, so that
299 // a compromised renderer can't pretend being the child
300 // that's forked off.
302 StringPrintf("org.mozilla.machname.%d",
303 base::RandInt(0, std::numeric_limits
<int>::max()))) {
304 MOZ_ASSERT(mMachConnectionName
.size() < BOOTSTRAP_MAX_NAME_LEN
);
308 virtual Result
<Ok
, LaunchError
> DoFinishLaunch() override
;
310 std::string mMachConnectionName
;
311 // We add a mach port to the command line so the child can communicate its
312 // 'task_t' back to the parent.
313 mozilla::UniqueMachReceiveRight mParentRecvPort
;
315 friend class PosixProcessLauncher
;
317 typedef MacProcessLauncher ProcessLauncher
;
318 # elif defined(MOZ_WIDGET_ANDROID)
319 class AndroidProcessLauncher
: public PosixProcessLauncher
{
321 AndroidProcessLauncher(GeckoChildProcessHost
* aHost
,
322 geckoargs::ChildProcessArgs
&& aExtraOpts
)
323 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)) {}
326 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
327 RefPtr
<ProcessHandlePromise
> LaunchAndroidService(
328 const GeckoProcessType aType
, const geckoargs::ChildProcessArgs
& args
);
330 typedef AndroidProcessLauncher ProcessLauncher
;
331 // NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
332 // orthogonal IPC machinery there. Conversely, there are tier-3 non-Linux
333 // platforms (BSD and Solaris) where we want the "linux" IPC machinery. So
334 // we use MOZ_WIDGET_* to choose the platform backend.
335 # elif defined(MOZ_WIDGET_GTK)
336 class LinuxProcessLauncher
: public PosixProcessLauncher
{
338 LinuxProcessLauncher(GeckoChildProcessHost
* aHost
,
339 geckoargs::ChildProcessArgs
&& aExtraOpts
)
340 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)) {}
343 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
345 typedef LinuxProcessLauncher ProcessLauncher
;
346 # elif defined(MOZ_WIDGET_UIKIT)
347 class IosProcessLauncher
: public PosixProcessLauncher
{
349 IosProcessLauncher(GeckoChildProcessHost
* aHost
,
350 geckoargs::ChildProcessArgs
&& aExtraOpts
)
351 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)) {}
354 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
356 DarwinObjectPtr
<xpc_object_t
> mBootstrapMessage
;
358 typedef IosProcessLauncher ProcessLauncher
;
360 # error "Unknown platform"
364 using base::ProcessHandle
;
365 using mozilla::ipc::BaseProcessLauncher
;
366 using mozilla::ipc::ProcessLauncher
;
368 mozilla::StaticAutoPtr
<mozilla::LinkedList
<GeckoChildProcessHost
>>
369 GeckoChildProcessHost::sGeckoChildProcessHosts
;
371 mozilla::StaticMutex
GeckoChildProcessHost::sMutex
;
373 GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType
,
375 : mProcessType(aProcessType
),
376 mChildID(++gChildCounter
),
377 mIsFileContent(aIsFileContent
),
378 mMonitor("mozilla.ipc.GeckoChildProcessHost.mMonitor"),
379 mLaunchOptions(MakeUnique
<base::LaunchOptions
>()),
380 mInitialChannelId(nsID::GenerateUUID()),
381 mProcessState(CREATING_CHANNEL
),
385 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
386 mEnableSandboxLogging(false),
389 mHandleLock("mozilla.ipc.GeckoChildProcessHost.mHandleLock"),
390 mChildProcessHandle(0),
391 #if defined(XP_DARWIN)
392 mChildTask(MACH_PORT_NULL
),
394 #if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
395 mDisableOSActivityMode(false),
398 MOZ_COUNT_CTOR(GeckoChildProcessHost
);
399 MOZ_RELEASE_ASSERT(mChildID
> 0, "gChildCounter overflowed");
400 StaticMutexAutoLock
lock(sMutex
);
401 if (!sGeckoChildProcessHosts
) {
402 sGeckoChildProcessHosts
= new mozilla::LinkedList
<GeckoChildProcessHost
>();
404 sGeckoChildProcessHosts
->insertBack(this);
405 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
406 if (aProcessType
== GeckoProcessType_RDD
) {
407 // The RDD process makes limited use of EGL. If Mesa's shader
408 // cache is enabled and the directory isn't explicitly set, then
409 // it will try to getpwuid() the user which can cause problems
410 // with sandboxing. Because we shouldn't need shader caching in
411 // this process, we just disable the cache to prevent that.
412 mLaunchOptions
->env_map
["MESA_GLSL_CACHE_DISABLE"] = "true";
413 mLaunchOptions
->env_map
["MESA_SHADER_CACHE_DISABLE"] = "true";
414 // In case the nvidia driver is also loaded:
415 mLaunchOptions
->env_map
["__GL_SHADER_DISK_CACHE"] = "0";
420 GeckoChildProcessHost::~GeckoChildProcessHost() {
422 MOZ_RELEASE_ASSERT(mDestroying
);
424 MOZ_COUNT_DTOR(GeckoChildProcessHost
);
427 mozilla::AutoWriteLock
hLock(mHandleLock
);
428 #if defined(XP_DARWIN)
429 if (mChildTask
!= MACH_PORT_NULL
) {
430 mach_port_deallocate(mach_task_self(), mChildTask
);
434 if (mForegroundCapabilityGrant
) {
435 mForegroundCapabilityGrant
.reset();
437 if (mExtensionKitProcess
) {
438 mExtensionKitProcess
->Invalidate();
440 if (mXPCConnection
) {
441 xpc_connection_cancel(mXPCConnection
.get());
445 if (mChildProcessHandle
!= 0) {
446 ProcessWatcher::EnsureProcessTerminated(
448 #ifdef NS_FREE_PERMANENT_DATA
449 // If we're doing leak logging, shutdown can be slow.
451 false // don't "force"
454 mChildProcessHandle
= 0;
459 base::ProcessHandle
GeckoChildProcessHost::GetChildProcessHandle() {
460 mozilla::AutoReadLock
handleLock(mHandleLock
);
461 return mChildProcessHandle
;
464 base::ProcessId
GeckoChildProcessHost::GetChildProcessId() {
465 mozilla::AutoReadLock
handleLock(mHandleLock
);
466 if (!mChildProcessHandle
) {
469 return base::GetProcId(mChildProcessHandle
);
473 task_t
GeckoChildProcessHost::GetChildTask() {
474 mozilla::AutoReadLock
handleLock(mHandleLock
);
479 void GeckoChildProcessHost::RemoveFromProcessList() {
480 StaticMutexAutoLock
lock(sMutex
);
481 if (!sGeckoChildProcessHosts
) {
484 LinkedListElement
<GeckoChildProcessHost
>::removeFrom(
485 *sGeckoChildProcessHosts
);
488 void GeckoChildProcessHost::Destroy() {
489 MOZ_RELEASE_ASSERT(!mDestroying
);
490 // We can remove from the list before it's really destroyed
491 RemoveFromProcessList();
492 RefPtr
<ProcessHandlePromise
> whenReady
= mHandlePromise
;
495 // AsyncLaunch not called yet, so dispatch immediately.
496 whenReady
= ProcessHandlePromise::CreateAndReject(
497 LaunchError("DestroyEarly"), __func__
);
500 using Value
= ProcessHandlePromise::ResolveOrRejectValue
;
502 whenReady
->Then(XRE_GetAsyncIOEventTarget(), __func__
,
503 [this](const Value
&) { delete this; });
507 mozilla::BinPathType
BaseProcessLauncher::GetPathToBinary(
508 FilePath
& exePath
, GeckoProcessType processType
) {
510 BinPathType pathType
= XRE_GetChildProcBinPathType(processType
);
512 if (pathType
== BinPathType::Self
) {
514 wchar_t exePathBuf
[MAXPATHLEN
];
515 if (!::GetModuleFileNameW(nullptr, exePathBuf
, MAXPATHLEN
)) {
516 MOZ_CRASH("GetModuleFileNameW failed (FIXME)");
518 exePath
= FilePath::FromWStringHack(exePathBuf
);
520 exePath
= FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
525 #ifdef MOZ_WIDGET_COCOA
526 // The GMP child process runs via the Media Plugin Helper executable
527 // which is a clone of plugin-container allowing for GMP-specific
528 // codesigning entitlements.
529 nsCString bundleName
;
530 std::string executableLeafName
;
531 if (processType
== GeckoProcessType_GMPlugin
&&
532 mozilla::StaticPrefs::media_plugin_helper_process_enabled()) {
533 bundleName
= MOZ_EME_PROCESS_BUNDLENAME
;
534 executableLeafName
= MOZ_EME_PROCESS_NAME_BRANDED
;
536 bundleName
= MOZ_CHILD_PROCESS_BUNDLENAME
;
537 executableLeafName
= MOZ_CHILD_PROCESS_NAME
;
541 if (ShouldHaveDirectoryService()) {
542 MOZ_ASSERT(gGREBinPath
);
544 exePath
= FilePath(char16ptr_t(gGREBinPath
));
545 #elif MOZ_WIDGET_COCOA
546 nsCOMPtr
<nsIFile
> childProcPath
;
547 if (NS_SUCCEEDED(NS_NewLocalFile(nsDependentString(gGREBinPath
),
548 getter_AddRefs(childProcPath
)))) {
549 // We need to use an App Bundle on OS X so that we can hide
550 // the dock icon. See Bug 557225.
551 if (NS_SUCCEEDED(childProcPath
->AppendNative(bundleName
)) &&
552 NS_SUCCEEDED(childProcPath
->AppendNative("Contents"_ns
)) &&
553 NS_SUCCEEDED(childProcPath
->AppendNative("MacOS"_ns
))) {
555 if (NS_SUCCEEDED(childProcPath
->GetNativePath(tempCPath
))) {
556 exePath
= FilePath(tempCPath
.get());
563 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath
), path
))) {
564 exePath
= FilePath(path
.get());
569 if (exePath
.empty()) {
572 FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
574 exePath
= FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
576 exePath
= exePath
.DirName();
579 #ifdef MOZ_WIDGET_COCOA
580 exePath
= exePath
.Append(executableLeafName
);
582 exePath
= exePath
.AppendASCII(MOZ_CHILD_PROCESS_NAME
);
588 #ifdef MOZ_WIDGET_COCOA
589 class AutoCFTypeObject
{
591 explicit AutoCFTypeObject(CFTypeRef object
) { mObject
= object
; }
592 ~AutoCFTypeObject() { ::CFRelease(mObject
); }
599 // We start the unique IDs at 1 so that 0 can be used to mean that
600 // a component has no unique ID assigned to it.
601 uint32_t GeckoChildProcessHost::sNextUniqueID
= 1;
604 uint32_t GeckoChildProcessHost::GetUniqueID() { return sNextUniqueID
++; }
607 void GeckoChildProcessHost::SetEnv(const char* aKey
, const char* aValue
) {
608 MOZ_ASSERT(mLaunchOptions
);
609 mLaunchOptions
->env_map
[ENVIRONMENT_STRING(aKey
)] =
610 ENVIRONMENT_STRING(aValue
);
613 bool GeckoChildProcessHost::PrepareLaunch(
614 geckoargs::ChildProcessArgs
& aExtraOpts
) {
615 if (CrashReporter::GetEnabled()) {
616 CrashReporter::OOPInit();
619 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
620 if (!SandboxLaunch::Configure(mProcessType
, mSandbox
, aExtraOpts
,
621 mLaunchOptions
.get())) {
628 # if defined(MOZ_SANDBOX)
629 // We need to get the pref here as the process is launched off main thread.
630 if (mProcessType
== GeckoProcessType_Content
) {
631 // Win32k Lockdown state must be initialized on the main thread.
632 // This is our last chance to do it before it is read on the IPC Launch
634 GetWin32kLockdownState();
635 mSandboxLevel
= GetEffectiveContentSandboxLevel();
636 mEnableSandboxLogging
=
637 Preferences::GetBool("security.sandbox.logging.enabled");
639 // We currently have to whitelist certain paths for tests to work in some
640 // development configurations.
641 nsAutoString readPaths
;
642 nsresult rv
= Preferences::GetString(
643 "security.sandbox.content.read_path_whitelist", readPaths
);
644 if (NS_SUCCEEDED(rv
)) {
645 for (const nsAString
& readPath
: readPaths
.Split(',')) {
646 nsString
trimmedPath(readPath
);
647 trimmedPath
.Trim(" ", true, true);
648 std::wstring
resolvedPath(trimmedPath
.Data());
649 // Check if path ends with '\' as this indicates we want to give read
650 // access to a directory and so it needs a wildcard.
651 if (resolvedPath
.back() == L
'\\') {
652 resolvedPath
.append(L
"*");
654 mAllowedFilesRead
.push_back(resolvedPath
);
660 # if defined(MOZ_SANDBOX)
661 // For other process types we can't rely on them being launched on main
662 // thread and they may not have access to prefs in the child process, so allow
663 // them to turn on logging via an environment variable.
664 mEnableSandboxLogging
=
665 mEnableSandboxLogging
|| !!PR_GetEnv("MOZ_SANDBOX_LOGGING");
668 #elif defined(XP_MACOSX)
669 # if defined(MOZ_SANDBOX)
670 if (ShouldHaveDirectoryService() &&
671 mProcessType
!= GeckoProcessType_GMPlugin
) {
672 mozilla::Unused
<< NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
,
673 getter_AddRefs(mProfileDir
));
682 void GeckoChildProcessHost::InitWindowsGroupID() {
683 // On Win7+, pass the application user model to the child, so it can
684 // register with it. This insures windows created by the container
685 // properly group with the parent app on the Win7 taskbar.
686 nsCOMPtr
<nsIWinTaskbar
> taskbarInfo
= do_GetService(NS_TASKBAR_CONTRACTID
);
688 bool isSupported
= false;
689 taskbarInfo
->GetAvailable(&isSupported
);
691 if (isSupported
&& NS_SUCCEEDED(taskbarInfo
->GetDefaultGroupId(appId
))) {
692 MOZ_ASSERT(mGroupId
.EqualsLiteral("-"));
693 mGroupId
.Assign(appId
);
699 bool GeckoChildProcessHost::SyncLaunch(geckoargs::ChildProcessArgs aExtraOpts
,
701 if (!AsyncLaunch(std::move(aExtraOpts
))) {
704 return WaitUntilConnected(aTimeoutMs
);
707 // Note: for most process types, we currently call AsyncLaunch, and therefore
708 // the *ProcessLauncher constructor, on the main thread, while the
709 // ProcessLauncher methods to actually execute the launch are called on the IO
710 // or IPC launcher thread. GMP processes are an exception - the GMP code
711 // invokes GeckoChildProcessHost from non-main-threads, and therefore we cannot
712 // rely on having access to mainthread-only services (like the directory
713 // service) from this code if we're launching that type of process.
714 bool GeckoChildProcessHost::AsyncLaunch(
715 geckoargs::ChildProcessArgs aExtraOpts
) {
716 if (!PrepareLaunch(aExtraOpts
)) {
720 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
721 if (IsMacSandboxLaunchEnabled() &&
722 !AppendMacSandboxParams(aExtraOpts
.mArgs
)) {
727 RefPtr
<BaseProcessLauncher
> launcher
=
728 new ProcessLauncher(this, std::move(aExtraOpts
));
729 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
730 launcher
->SetLaunchArchitecture(mLaunchArch
);
733 // Note: Destroy() waits on mHandlePromise to delete |this|. As such, we want
734 // to be sure that all of our post-launch processing on |this| happens before
735 // mHandlePromise notifies.
736 MOZ_ASSERT(mHandlePromise
== nullptr);
738 mozilla::InvokeAsync
<GeckoChildProcessHost
*>(
739 XRE_GetAsyncIOEventTarget(), launcher
.get(), __func__
,
740 &BaseProcessLauncher::Launch
, this)
742 XRE_GetAsyncIOEventTarget(), __func__
,
743 [this](LaunchResults
&& aResults
) {
746 mozilla::AutoWriteLock
handleLock(mHandleLock
);
747 if (!OpenPrivilegedHandle(base::GetProcId(aResults
.mHandle
))
749 // If we failed in opening the process handle, try
750 // harder by duplicating one.
751 && !::DuplicateHandle(
752 ::GetCurrentProcess(), aResults
.mHandle
,
753 ::GetCurrentProcess(), &mChildProcessHandle
,
754 PROCESS_DUP_HANDLE
| PROCESS_TERMINATE
|
755 PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
|
760 MOZ_CRASH("cannot open handle to child process");
762 // The original handle is no longer needed; it must
763 // be closed to prevent a resource leak.
764 base::CloseProcessHandle(aResults
.mHandle
);
765 // FIXME (bug 1720523): define a cross-platform
766 // "safe" invalid value to use in places like this.
767 aResults
.mHandle
= 0;
770 this->mChildTask
= aResults
.mChildTask
;
773 this->mExtensionKitProcess
= aResults
.mExtensionKitProcess
;
774 this->mXPCConnection
= aResults
.mXPCConnection
;
775 this->mForegroundCapabilityGrant
=
776 std::move(aResults
.mForegroundCapabilityGrant
);
780 mNodeChannel
->SetOtherPid(
781 base::GetProcId(this->mChildProcessHandle
));
783 mNodeChannel
->SetMachTaskPort(this->mChildTask
);
787 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
788 this->mSandboxBroker
= std::move(aResults
.mSandboxBroker
);
791 MonitorAutoLock
lock(mMonitor
);
792 // The OnChannel{Connected,Error} may have already advanced
794 if (mProcessState
< PROCESS_CREATED
) {
795 mProcessState
= PROCESS_CREATED
;
799 return ProcessHandlePromise::CreateAndResolve(
800 GetChildProcessHandle(), __func__
);
802 [this](const LaunchError aError
) {
803 // WaitUntilConnected might be waiting for us to signal.
804 // If something failed let's set the error state and notify.
806 << "Failed to launch "
807 << XRE_GeckoProcessTypeToString(mProcessType
)
808 << " subprocess @" << aError
.FunctionName()
809 << " (Error:" << aError
.ErrorCode() << ")";
810 Telemetry::Accumulate(
811 Telemetry::SUBPROCESS_LAUNCH_FAILURE
,
813 XRE_GeckoProcessTypeToString(mProcessType
)));
814 nsCString telemetryKey
= nsPrintfCString(
820 aError
.FunctionName().get(), aError
.ErrorCode(),
821 XRE_GeckoProcessTypeToString(mProcessType
));
822 // Max telemetry key is 72 chars
823 // https://searchfox.org/mozilla-central/rev/c244b16815d1fc827d141472b9faac5610f250e7/toolkit/components/telemetry/core/TelemetryScalar.cpp#105
824 if (telemetryKey
.Length() > 72) {
825 NS_WARNING(nsPrintfCString("Truncating telemetry key: %s",
828 telemetryKey
.Truncate(72);
830 glean::dom_parentprocess::process_launch_errors
834 MonitorAutoLock
lock(mMonitor
);
835 mProcessState
= PROCESS_ERROR
;
838 return ProcessHandlePromise::CreateAndReject(aError
, __func__
);
843 bool GeckoChildProcessHost::WaitUntilConnected(int32_t aTimeoutMs
) {
844 AUTO_PROFILER_LABEL("GeckoChildProcessHost::WaitUntilConnected", OTHER
);
846 // NB: this uses a different mechanism than the chromium parent
848 TimeDuration timeout
= (aTimeoutMs
> 0)
849 ? TimeDuration::FromMilliseconds(aTimeoutMs
)
850 : TimeDuration::Forever();
852 MonitorAutoLock
lock(mMonitor
);
853 TimeStamp waitStart
= TimeStamp::Now();
856 // We'll receive several notifications, we need to exit when we
857 // have either successfully launched or have timed out.
858 while (mProcessState
!= PROCESS_CONNECTED
) {
859 // If there was an error then return it, don't wait out the timeout.
860 if (mProcessState
== PROCESS_ERROR
) {
864 CVStatus status
= lock
.Wait(timeout
);
865 if (status
== CVStatus::Timeout
) {
869 if (timeout
!= TimeDuration::Forever()) {
870 current
= TimeStamp::Now();
871 timeout
-= current
- waitStart
;
876 return mProcessState
== PROCESS_CONNECTED
;
879 bool GeckoChildProcessHost::WaitForProcessHandle() {
880 MonitorAutoLock
lock(mMonitor
);
881 while (mProcessState
< PROCESS_CREATED
) {
884 MOZ_ASSERT(mProcessState
== PROCESS_ERROR
|| GetChildProcessHandle());
886 return mProcessState
< PROCESS_ERROR
;
889 bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(
890 geckoargs::ChildProcessArgs aExtraOpts
) {
891 if (!AsyncLaunch(std::move(aExtraOpts
))) {
894 return WaitForProcessHandle();
897 void GeckoChildProcessHost::InitializeChannel(
898 IPC::Channel::ChannelHandle
&& aServerHandle
) {
899 // Create the IPC channel which will be used for communication with this
901 mozilla::UniquePtr
<IPC::Channel
> channel
= MakeUnique
<IPC::Channel
>(
902 std::move(aServerHandle
), IPC::Channel::MODE_SERVER
,
903 base::kInvalidProcessId
);
905 channel
->StartAcceptingHandles(IPC::Channel::MODE_SERVER
);
906 #elif defined(XP_DARWIN)
907 channel
->StartAcceptingMachPorts(IPC::Channel::MODE_SERVER
);
910 mNodeController
= NodeController::GetSingleton();
911 std::tie(mInitialPort
, mNodeChannel
) =
912 mNodeController
->InviteChildProcess(std::move(channel
), this);
914 MonitorAutoLock
lock(mMonitor
);
915 mProcessState
= CHANNEL_INITIALIZED
;
919 void GeckoChildProcessHost::SetAlreadyDead() {
920 mozilla::AutoWriteLock
handleLock(mHandleLock
);
921 if (mChildProcessHandle
&&
922 mChildProcessHandle
!= base::kInvalidProcessHandle
) {
923 base::CloseProcessHandle(mChildProcessHandle
);
926 mChildProcessHandle
= 0;
929 void BaseProcessLauncher::GetChildLogName(const char* origLogName
,
930 nsACString
& buffer
) {
932 // On Windows we must expand relative paths because sandboxing rules
933 // bound only to full paths. fopen fowards to NtCreateFile which checks
934 // the path against the sanboxing rules as passed to fopen (left relative).
935 char absPath
[MAX_PATH
+ 2];
936 if (_fullpath(absPath
, origLogName
, sizeof(absPath
))) {
937 buffer
.Append(absPath
);
941 buffer
.Append(origLogName
);
944 // Remove .moz_log extension to avoid its duplication, it will be added
945 // automatically by the logging backend
946 static constexpr auto kMozLogExt
= nsLiteralCString
{MOZ_LOG_FILE_EXTENSION
};
947 if (StringEndsWith(buffer
, kMozLogExt
)) {
948 buffer
.Truncate(buffer
.Length() - kMozLogExt
.Length());
951 // Append child-specific postfix to name
952 buffer
.AppendLiteral(".child-");
953 buffer
.AppendASCII(mChildIDString
);
956 // Windows needs a single dedicated thread for process launching,
957 // because of thread-safety restrictions/assertions in the sandbox
960 // Android also needs a single dedicated thread to simplify thread
963 // Fork server needs a dedicated thread for accessing
964 // |ForkServiceChild|.
965 #if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || \
966 defined(MOZ_ENABLE_FORKSERVER)
968 static mozilla::StaticMutex gIPCLaunchThreadMutex
;
969 static mozilla::StaticRefPtr
<nsIThread
> gIPCLaunchThread
970 MOZ_GUARDED_BY(gIPCLaunchThreadMutex
);
972 class IPCLaunchThreadObserver final
: public nsIObserver
{
977 virtual ~IPCLaunchThreadObserver() = default;
980 NS_IMPL_ISUPPORTS(IPCLaunchThreadObserver
, nsIObserver
, nsISupports
)
983 IPCLaunchThreadObserver::Observe(nsISupports
* aSubject
, const char* aTopic
,
984 const char16_t
* aData
) {
985 MOZ_RELEASE_ASSERT(strcmp(aTopic
, "xpcom-shutdown-threads") == 0);
987 nsCOMPtr
<nsIThread
> thread
;
989 StaticMutexAutoLock
lock(gIPCLaunchThreadMutex
);
990 thread
= gIPCLaunchThread
.forget();
993 nsresult rv
= thread
? thread
->Shutdown() : NS_OK
;
994 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
998 nsCOMPtr
<nsIEventTarget
> GetIPCLauncher() {
999 StaticMutexAutoLock
lock(gIPCLaunchThreadMutex
);
1000 if (!gIPCLaunchThread
) {
1001 nsCOMPtr
<nsIThread
> thread
;
1002 nsresult rv
= NS_NewNamedThread("IPC Launch"_ns
, getter_AddRefs(thread
));
1003 if (!NS_WARN_IF(NS_FAILED(rv
))) {
1004 NS_DispatchToMainThread(
1005 NS_NewRunnableFunction("GeckoChildProcessHost::GetIPCLauncher", [] {
1006 nsCOMPtr
<nsIObserverService
> obsService
=
1007 mozilla::services::GetObserverService();
1008 nsCOMPtr
<nsIObserver
> obs
= new IPCLaunchThreadObserver();
1009 obsService
->AddObserver(obs
, "xpcom-shutdown-threads", false);
1011 gIPCLaunchThread
= thread
.forget();
1015 nsCOMPtr
<nsIEventTarget
> thread
= gIPCLaunchThread
.get();
1016 MOZ_DIAGNOSTIC_ASSERT(thread
);
1020 #else // defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) ||
1021 // defined(MOZ_ENABLE_FORKSERVER)
1023 // Other platforms use an on-demand thread pool.
1025 nsCOMPtr
<nsIEventTarget
> GetIPCLauncher() {
1026 nsCOMPtr
<nsIEventTarget
> pool
=
1027 mozilla::SharedThreadPool::Get("IPC Launch"_ns
);
1028 MOZ_DIAGNOSTIC_ASSERT(pool
);
1032 #endif // XP_WIN || MOZ_WIDGET_ANDROID || MOZ_ENABLE_FORKSERVER
1036 AddAppDirToCommandLine(CommandLine
& aCmdLine
, nsIFile
* aAppDir
)
1038 AddAppDirToCommandLine(geckoargs::ChildProcessArgs
& aCmdLine
,
1039 nsIFile
* aAppDir
, nsIFile
* aProfileDir
)
1042 // Content processes need access to application resources, so pass
1043 // the full application directory path to the child process.
1047 MOZ_ALWAYS_SUCCEEDS(aAppDir
->GetPath(path
));
1048 aCmdLine
.AppendLooseValue(UTF8ToWide(geckoargs::sAppDir
.Name()));
1049 std::wstring
wpath(path
.get());
1050 aCmdLine
.AppendLooseValue(wpath
);
1053 MOZ_ALWAYS_SUCCEEDS(aAppDir
->GetNativePath(path
));
1054 geckoargs::sAppDir
.Put(path
.get(), aCmdLine
);
1057 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1058 // Full path to the profile dir
1060 // If the profile doesn't exist, normalization will
1061 // fail. But we don't return an error here because some
1062 // tests require startup with a missing profile dir.
1063 // For users, almost universally, the profile will be in
1064 // the home directory and normalization isn't required.
1065 mozilla::Unused
<< aProfileDir
->Normalize();
1067 MOZ_ALWAYS_SUCCEEDS(aProfileDir
->GetNativePath(path
));
1068 geckoargs::sProfile
.Put(path
.get(), aCmdLine
);
1074 #if defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1075 static bool Contains(const geckoargs::ChildProcessArgs
& aExtraOpts
,
1076 const char* aValue
) {
1077 return std::any_of(aExtraOpts
.mArgs
.begin(), aExtraOpts
.mArgs
.end(),
1078 [&](const std::string arg
) {
1079 return arg
.find(aValue
) != std::string::npos
;
1082 #endif // defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1084 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::PerformAsyncLaunch() {
1085 Result
<Ok
, LaunchError
> aError
= DoSetup();
1086 if (aError
.isErr()) {
1087 return ProcessLaunchPromise::CreateAndReject(aError
.unwrapErr(), __func__
);
1089 RefPtr
<BaseProcessLauncher
> self
= this;
1090 return DoLaunch()->Then(
1091 mLaunchThread
, __func__
,
1092 [self
](base::ProcessHandle aHandle
) {
1093 self
->mResults
.mHandle
= aHandle
;
1094 return self
->FinishLaunch();
1096 [](LaunchError aError
) {
1097 return ProcessLaunchPromise::CreateAndReject(aError
, __func__
);
1101 Result
<Ok
, LaunchError
> BaseProcessLauncher::DoSetup() {
1102 RefPtr
<BaseProcessLauncher
> self
= this;
1103 GetProfilerEnvVarsForChildProcess([self
](const char* key
, const char* value
) {
1104 self
->mLaunchOptions
->env_map
[ENVIRONMENT_STRING(key
)] =
1105 ENVIRONMENT_STRING(value
);
1108 if (mProcessType
== GeckoProcessType_Content
) {
1109 nsAutoCString
mallocOpts(PR_GetEnv("MALLOC_OPTIONS"));
1110 // Disable randomization of small arenas in content.
1111 mallocOpts
.Append("r");
1112 self
->mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("MALLOC_OPTIONS")] =
1113 ENVIRONMENT_STRING(mallocOpts
.get());
1119 geckoargs::sInitialChannelID
.Put(mInitialChannelIdString
, mChildArgs
);
1121 geckoargs::sParentPid
.Put(static_cast<uint64_t>(base::GetCurrentProcId()),
1124 if (!CrashReporter::IsDummy() && CrashReporter::GetEnabled()) {
1125 #if defined(MOZ_WIDGET_COCOA) || defined(XP_WIN)
1126 geckoargs::sCrashReporter
.Put(CrashReporter::GetChildNotificationPipe(),
1128 #elif defined(XP_UNIX)
1129 UniqueFileHandle childCrashFd
= CrashReporter::GetChildNotificationPipe();
1130 if (!childCrashFd
) {
1131 return Err(LaunchError("DuplicateFileHandle failed"));
1133 geckoargs::sCrashReporter
.Put(std::move(childCrashFd
), mChildArgs
);
1140 void BaseProcessLauncher::MapChildLogging() {
1141 const char* origNSPRLogName
= PR_GetEnv("NSPR_LOG_FILE");
1142 const char* origMozLogName
= PR_GetEnv("MOZ_LOG_FILE");
1144 if (origNSPRLogName
) {
1145 nsAutoCString nsprLogName
;
1146 GetChildLogName(origNSPRLogName
, nsprLogName
);
1147 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("NSPR_LOG_FILE")] =
1148 ENVIRONMENT_STRING(nsprLogName
.get());
1150 if (origMozLogName
) {
1151 nsAutoCString mozLogName
;
1152 GetChildLogName(origMozLogName
, mozLogName
);
1153 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("MOZ_LOG_FILE")] =
1154 ENVIRONMENT_STRING(mozLogName
.get());
1157 // `RUST_LOG_CHILD` is meant for logging child processes only.
1158 nsAutoCString
childRustLog(PR_GetEnv("RUST_LOG_CHILD"));
1159 if (!childRustLog
.IsEmpty()) {
1160 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("RUST_LOG")] =
1161 ENVIRONMENT_STRING(childRustLog
.get());
1165 Result
<Ok
, LaunchError
> BaseProcessLauncher::DoFinishLaunch() {
1166 // We're in the parent and the child was launched. Clean up any FDs which were
1167 // transferred to the child in the parent as soon as possible, which will
1168 // allow the parent to detect when the child closes its handle (either due to
1169 // normal exit or due to crash).
1170 mChildArgs
.mFiles
.clear();
1175 #if defined(MOZ_WIDGET_GTK)
1176 Result
<Ok
, LaunchError
> LinuxProcessLauncher::DoSetup() {
1177 Result
<Ok
, LaunchError
> aError
= PosixProcessLauncher::DoSetup();
1178 if (aError
.isErr()) {
1182 if (mProcessType
== GeckoProcessType_Content
) {
1183 // disable IM module to avoid sandbox violation
1184 mLaunchOptions
->env_map
["GTK_IM_MODULE"] = "gtk-im-context-simple";
1186 // Disable ATK accessibility code in content processes because it conflicts
1187 // with the sandbox, and we proxy that information through the main process
1189 mLaunchOptions
->env_map
["NO_AT_BRIDGE"] = "1";
1194 #endif // MOZ_WIDGET_GTK
1197 Result
<Ok
, LaunchError
> PosixProcessLauncher::DoSetup() {
1198 Result
<Ok
, LaunchError
> aError
= BaseProcessLauncher::DoSetup();
1199 if (aError
.isErr()) {
1203 // XPCOM may not be initialized in some subprocesses. We don't want
1204 // to initialize XPCOM just for the directory service, especially
1205 // since LD_LIBRARY_PATH is already set correctly in subprocesses
1206 // (meaning that we don't need to set that up in the environment).
1207 if (ShouldHaveDirectoryService()) {
1208 MOZ_ASSERT(gGREBinPath
);
1210 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath
), path
);
1211 # if defined(XP_LINUX) || defined(__DragonFly__) || defined(XP_FREEBSD) || \
1212 defined(XP_NETBSD) || defined(XP_OPENBSD)
1213 const char* ld_library_path
= PR_GetEnv("LD_LIBRARY_PATH");
1214 nsCString
new_ld_lib_path(path
.get());
1216 if (ld_library_path
&& *ld_library_path
) {
1217 new_ld_lib_path
.Append(':');
1218 new_ld_lib_path
.Append(ld_library_path
);
1220 mLaunchOptions
->env_map
["LD_LIBRARY_PATH"] = new_ld_lib_path
.get();
1223 // With signed production Mac builds, the dynamic linker (dyld) will
1224 // ignore dyld environment variables preventing the use of variables
1225 // such as DYLD_LIBRARY_PATH and DYLD_INSERT_LIBRARIES.
1227 // If we're running with gtests, add the gtest XUL ahead of normal XUL on
1228 // the DYLD_LIBRARY_PATH so that plugin-container.app loads it instead.
1229 nsCString
new_dyld_lib_path(path
.get());
1230 if (PR_GetEnv("MOZ_RUN_GTEST")) {
1231 new_dyld_lib_path
= path
+ "/gtest:"_ns
+ new_dyld_lib_path
;
1232 mLaunchOptions
->env_map
["DYLD_LIBRARY_PATH"] = new_dyld_lib_path
.get();
1235 // DYLD_INSERT_LIBRARIES is currently unused by default but we allow
1236 // it to be set by the external environment.
1237 const char* interpose
= PR_GetEnv("DYLD_INSERT_LIBRARIES");
1238 if (interpose
&& strlen(interpose
) > 0) {
1239 mLaunchOptions
->env_map
["DYLD_INSERT_LIBRARIES"] = interpose
;
1242 // Prevent connection attempts to diagnosticd(8) to save cycles. Log
1243 // messages can trigger these connection attempts, but access to
1244 // diagnosticd is blocked in sandboxed child processes.
1245 # if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
1246 if (mDisableOSActivityMode
) {
1247 mLaunchOptions
->env_map
["OS_ACTIVITY_MODE"] = "disable";
1249 # endif // defined(MOZ_SANDBOX)
1254 BinPathType pathType
= GetPathToBinary(exePath
, mProcessType
);
1256 // Make sure the executable path is present at the start of our argument list.
1257 // If we're using BinPathType::Self, also add the `-contentproc` argument.
1258 if (pathType
== BinPathType::Self
) {
1259 std::string args
[]{exePath
.value(), "-contentproc"};
1260 mChildArgs
.mArgs
.insert(mChildArgs
.mArgs
.begin(), std::begin(args
),
1263 mChildArgs
.mArgs
.insert(mChildArgs
.mArgs
.begin(), exePath
.value());
1266 if ((mProcessType
== GeckoProcessType_Content
||
1267 mProcessType
== GeckoProcessType_ForkServer
) &&
1268 Omnijar::IsInitialized()) {
1269 // Make sure that child processes can find the omnijar, if they
1270 // use full XPCOM. See Omnijar::ChildProcessInit and its callers.
1272 nsCOMPtr
<nsIFile
> greFile
= Omnijar::GetPath(Omnijar::GRE
);
1273 if (greFile
&& NS_SUCCEEDED(greFile
->GetNativePath(path
))) {
1274 geckoargs::sGREOmni
.Put(path
.get(), mChildArgs
);
1276 nsCOMPtr
<nsIFile
> appFile
= Omnijar::GetPath(Omnijar::APP
);
1277 if (appFile
&& NS_SUCCEEDED(appFile
->GetNativePath(path
))) {
1278 geckoargs::sAppOmni
.Put(path
.get(), mChildArgs
);
1282 if (mProcessType
!= GeckoProcessType_GMPlugin
) {
1283 // Add the application directory path (-appdir path)
1285 AddAppDirToCommandLine(mChildArgs
, mAppDir
, mProfileDir
);
1287 AddAppDirToCommandLine(mChildArgs
, mAppDir
, nullptr);
1291 // XXX Command line params past this point are expected to be at
1292 // the end of the command line string, and in a specific order.
1293 // See XRE_InitChildProcess in nsEmbedFunction.
1295 # ifdef MOZ_WIDGET_COCOA
1297 auto* thisMac
= static_cast<MacProcessLauncher
*>(this);
1299 bootstrap_check_in(bootstrap_port
, thisMac
->mMachConnectionName
.c_str(),
1300 getter_Transfers(thisMac
->mParentRecvPort
));
1301 if (kr
!= KERN_SUCCESS
) {
1302 CHROMIUM_LOG(ERROR
) << "parent bootstrap_check_in failed: "
1303 << mach_error_string(kr
);
1304 return Err(LaunchError("bootstrap_check_in", kr
));
1306 mChildArgs
.mArgs
.push_back(thisMac
->mMachConnectionName
.c_str());
1308 # endif // MOZ_WIDGET_COCOA
1310 mChildArgs
.mArgs
.push_back(mChildIDString
);
1312 mChildArgs
.mArgs
.push_back(ChildProcessType());
1314 # if !defined(MOZ_WIDGET_ANDROID)
1315 // Add any files which need to be transferred to fds_to_remap.
1316 // NOTE: This doesn't transfer ownership of the files out of `mChildArgs`.
1317 geckoargs::AddToFdsToRemap(mChildArgs
, mLaunchOptions
->fds_to_remap
);
1324 #if defined(MOZ_WIDGET_ANDROID)
1325 RefPtr
<ProcessHandlePromise
> AndroidProcessLauncher::DoLaunch() {
1326 return LaunchAndroidService(mProcessType
, mChildArgs
);
1328 #endif // MOZ_WIDGET_ANDROID
1331 RefPtr
<ProcessHandlePromise
> PosixProcessLauncher::DoLaunch() {
1332 ProcessHandle handle
= 0;
1333 Result
<Ok
, LaunchError
> result
= Err(LaunchError
{"Launch not attempted"});
1334 # ifdef MOZ_ENABLE_FORKSERVER
1335 if (mProcessType
!= GeckoProcessType_ForkServer
&& ForkServiceChild::Get()) {
1336 result
= ForkServiceChild::Get()->SendForkNewSubprocess(
1337 std::move(mChildArgs
), std::move(*mLaunchOptions
), &handle
);
1342 base::LaunchApp(mChildArgs
.mArgs
, std::move(*mLaunchOptions
), &handle
);
1345 if (result
.isErr()) {
1346 return ProcessHandlePromise::CreateAndReject(result
.unwrapErr(), __func__
);
1348 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1353 RefPtr
<ProcessHandlePromise
> IosProcessLauncher::DoLaunch() {
1354 ExtensionKitProcess::Kind kind
= ExtensionKitProcess::Kind::WebContent
;
1355 if (mProcessType
== GeckoProcessType_GPU
) {
1356 kind
= ExtensionKitProcess::Kind::Rendering
;
1357 } else if (mProcessType
== GeckoProcessType_Socket
) {
1358 kind
= ExtensionKitProcess::Kind::Networking
;
1361 DarwinObjectPtr
<xpc_object_t
> bootstrapMessage
=
1362 AdoptDarwinObject(xpc_dictionary_create_empty());
1363 xpc_dictionary_set_string(bootstrapMessage
.get(), "message-name",
1366 DarwinObjectPtr
<xpc_object_t
> environDict
=
1367 AdoptDarwinObject(xpc_dictionary_create_empty());
1368 for (auto& [envKey
, envValue
] : mLaunchOptions
->env_map
) {
1369 xpc_dictionary_set_string(environDict
.get(), envKey
.c_str(),
1372 xpc_dictionary_set_value(bootstrapMessage
.get(), "environ",
1375 // Setup stdout and stderr to inherit.
1376 xpc_dictionary_set_fd(bootstrapMessage
.get(), "stdout", STDOUT_FILENO
);
1377 xpc_dictionary_set_fd(bootstrapMessage
.get(), "stderr", STDERR_FILENO
);
1379 DarwinObjectPtr
<xpc_object_t
> argsArray
=
1380 AdoptDarwinObject(xpc_array_create_empty());
1381 for (auto& argv
: mChildArgs
.mArgs
) {
1382 xpc_array_set_string(argsArray
.get(), XPC_ARRAY_APPEND
, argv
.c_str());
1384 MOZ_ASSERT(xpc_array_get_count(argsArray
.get()) == mChildArgs
.mArgs
.size());
1385 xpc_dictionary_set_value(bootstrapMessage
.get(), "argv", argsArray
.get());
1387 DarwinObjectPtr
<xpc_object_t
> fdsArray
=
1388 AdoptDarwinObject(xpc_array_create_empty());
1389 for (auto& file
: mChildArgs
.mFiles
) {
1390 xpc_array_set_fd(fdsArray
.get(), XPC_ARRAY_APPEND
, file
.get());
1392 MOZ_ASSERT(xpc_array_get_count(fdsArray
.get()) == mChildArgs
.mFiles
.size());
1393 xpc_dictionary_set_value(bootstrapMessage
.get(), "fds", fdsArray
.get());
1395 DarwinObjectPtr
<xpc_object_t
> sendRightsArray
=
1396 AdoptDarwinObject(xpc_array_create_empty());
1397 for (auto& sendRight
: mChildArgs
.mSendRights
) {
1398 // NOTE: As iOS doesn't expose an xpc_array_set_mach_send function, send
1399 // rights are wrapped with single-key dictionaries.
1400 DarwinObjectPtr
<xpc_object_t
> sendRightWrapper
=
1401 AdoptDarwinObject(xpc_dictionary_create_empty());
1402 xpc_dictionary_set_mach_send(sendRightWrapper
.get(), "port",
1404 xpc_array_set_value(sendRightsArray
.get(), XPC_ARRAY_APPEND
,
1405 sendRightWrapper
.get());
1407 MOZ_ASSERT(xpc_array_get_count(sendRightsArray
.get()) ==
1408 mChildArgs
.mSendRights
.size());
1409 xpc_dictionary_set_value(bootstrapMessage
.get(), "sendRights",
1410 sendRightsArray
.get());
1412 auto promise
= MakeRefPtr
<ProcessHandlePromise::Private
>(__func__
);
1413 ExtensionKitProcess::StartProcess(kind
, [self
= RefPtr
{this}, promise
,
1415 std::move(bootstrapMessage
)](
1416 Result
<ExtensionKitProcess
,
1417 LaunchError
>&& result
) {
1418 if (result
.isErr()) {
1419 CHROMIUM_LOG(ERROR
) << "ExtensionKitProcess::StartProcess failed";
1420 promise
->Reject(result
.unwrapErr(), __func__
);
1424 auto process
= result
.unwrap();
1425 self
->mResults
.mForegroundCapabilityGrant
=
1426 process
.GrantForegroundCapability();
1427 self
->mResults
.mXPCConnection
= process
.MakeLibXPCConnection();
1428 self
->mResults
.mExtensionKitProcess
= Some(std::move(process
));
1430 // We don't actually use the event handler for anything other than
1431 // watching for errors. Once the promise is resolved, this becomes a
1433 xpc_connection_set_event_handler(self
->mResults
.mXPCConnection
.get(), ^(
1434 xpc_object_t event
) {
1435 if (!event
|| xpc_get_type(event
) == XPC_TYPE_ERROR
) {
1436 CHROMIUM_LOG(WARNING
) << "XPC connection received encountered an error";
1437 promise
->Reject(LaunchError("xpc_connection_event_handler"), __func__
);
1440 xpc_connection_resume(self
->mResults
.mXPCConnection
.get());
1442 // Send our bootstrap message to the content and wait for it to reply with
1443 // the task port before resolving.
1444 // FIXME: Should we have a time-out for if the child process doesn't respond
1445 // in time? The main thread may be blocked while we're starting this
1447 xpc_connection_send_message_with_reply(
1448 self
->mResults
.mXPCConnection
.get(), bootstrapMessage
.get(), nullptr,
1449 ^(xpc_object_t reply
) {
1450 if (xpc_get_type(reply
) == XPC_TYPE_ERROR
) {
1452 << "Got error sending XPC bootstrap message to child";
1454 LaunchError("xpc_connection_send_message_with_reply error"),
1459 if (xpc_get_type(reply
) != XPC_TYPE_DICTIONARY
) {
1461 << "Unexpected reply type for bootstrap message from child";
1464 "xpc_connection_send_message_with_reply non-dictionary"),
1469 // FIXME: We have to trust the child to tell us its pid & mach task.
1470 // WebKit uses `xpc_connection_get_pid` to get the pid, however this
1471 // is marked as unavailable on iOS.
1473 // Given how the process is started, however, validating this
1474 // information it sends us this early during startup may be
1476 self
->mResults
.mChildTask
=
1477 xpc_dictionary_copy_mach_send(reply
, "task");
1479 static_cast<pid_t
>(xpc_dictionary_get_int64(reply
, "pid"));
1480 CHROMIUM_LOG(INFO
) << "ExtensionKit process started, task: "
1481 << self
->mResults
.mChildTask
<< ", pid: " << pid
;
1484 kern_return_t kr
= pid_for_task(self
->mResults
.mChildTask
, &taskPid
);
1485 if (kr
!= KERN_SUCCESS
|| pid
!= taskPid
) {
1486 CHROMIUM_LOG(ERROR
) << "Could not validate child task matches pid";
1487 promise
->Reject(LaunchError("pid_for_task mismatch"), __func__
);
1491 promise
->Resolve(pid
, __func__
);
1500 Result
<Ok
, LaunchError
> MacProcessLauncher::DoFinishLaunch() {
1501 Result
<Ok
, LaunchError
> aError
= PosixProcessLauncher::DoFinishLaunch();
1502 if (aError
.isErr()) {
1506 MOZ_ASSERT(mParentRecvPort
, "should have been configured during DoSetup()");
1508 // Wait for the child process to send us its 'task_t' data, then send it the
1509 // mach send/receive rights which are being passed on the commandline.
1510 const int kTimeoutMs
= 10000;
1511 MOZ_TRY(MachHandleProcessCheckIn(
1512 mParentRecvPort
.get(), base::GetProcId(mResults
.mHandle
), kTimeoutMs
,
1513 mChildArgs
.mSendRights
, &mResults
.mChildTask
));
1520 Result
<Ok
, LaunchError
> WindowsProcessLauncher::DoSetup() {
1521 Result
<Ok
, LaunchError
> aError
= BaseProcessLauncher::DoSetup();
1522 if (aError
.isErr()) {
1527 BinPathType pathType
= GetPathToBinary(exePath
, mProcessType
);
1529 # if defined(MOZ_SANDBOX) || defined(_ARM64_)
1530 const bool isGMP
= mProcessType
== GeckoProcessType_GMPlugin
;
1531 const bool isWidevine
= isGMP
&& Contains(mChildArgs
, "gmp-widevinecdm");
1532 # endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
1534 mCmdLine
.emplace(exePath
.ToWStringHack());
1536 if (pathType
== BinPathType::Self
) {
1537 mCmdLine
->AppendLooseValue(UTF8ToWide("-contentproc"));
1540 # ifdef HAS_DLL_BLOCKLIST
1541 if (IsDynamicBlocklistDisabled(
1543 CommandLine::ForCurrentProcess()->HasSwitch(UTF8ToWide(
1544 mozilla::geckoargs::sDisableDynamicDllBlocklist
.sMatch
)))) {
1545 mCmdLine
->AppendLooseValue(
1546 UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist
.sMatch
));
1548 # endif // HAS_DLL_BLOCKLIST
1550 for (const std::string
& arg
: mChildArgs
.mArgs
) {
1551 mCmdLine
->AppendLooseValue(UTF8ToWide(arg
));
1554 # if defined(MOZ_SANDBOX)
1555 mResults
.mSandboxBroker
= MakeUnique
<SandboxBroker
>();
1557 // XXX: Bug 1124167: We should get rid of the process specific logic for
1558 // sandboxing in this class at some point. Unfortunately it will take a bit
1559 // of reorganizing so I don't think this patch is the right time.
1560 switch (mProcessType
) {
1561 case GeckoProcessType_Content
:
1562 if (mSandboxLevel
> 0) {
1563 // For now we treat every failure as fatal in
1564 // SetSecurityLevelForContentProcess and just crash there right away.
1565 // Should this change in the future then we should also handle the error
1567 mResults
.mSandboxBroker
->SetSecurityLevelForContentProcess(
1568 mSandboxLevel
, mIsFileContent
);
1572 case GeckoProcessType_IPDLUnitTest
:
1573 // XXX: We don't sandbox this process type yet
1575 case GeckoProcessType_GMPlugin
:
1576 if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
1577 // The Widevine CDM on Windows can only load at USER_RESTRICTED,
1578 // not at USER_LOCKDOWN. So look in the command line arguments
1579 // to see if we're loading the path to the Widevine CDM, and if
1580 // so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
1582 isWidevine
? SandboxBroker::Restricted
: SandboxBroker::LockDown
;
1584 !mResults
.mSandboxBroker
->SetSecurityLevelForGMPlugin(level
))) {
1585 return Err(LaunchError("SetSecurityLevelForGMPlugin"));
1590 case GeckoProcessType_GPU
:
1591 if (mSandboxLevel
> 0 && !PR_GetEnv("MOZ_DISABLE_GPU_SANDBOX")) {
1592 // For now we treat every failure as fatal in
1593 // SetSecurityLevelForGPUProcess and just crash there right away. Should
1594 // this change in the future then we should also handle the error here.
1595 mResults
.mSandboxBroker
->SetSecurityLevelForGPUProcess(mSandboxLevel
);
1599 case GeckoProcessType_VR
:
1600 if (mSandboxLevel
> 0 && !PR_GetEnv("MOZ_DISABLE_VR_SANDBOX")) {
1601 // TODO: Implement sandbox for VR process, Bug 1430043.
1604 case GeckoProcessType_RDD
:
1605 if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
1607 !mResults
.mSandboxBroker
->SetSecurityLevelForRDDProcess())) {
1608 return Err(LaunchError("SetSecurityLevelForRDDProcess"));
1613 case GeckoProcessType_Socket
:
1614 if (!PR_GetEnv("MOZ_DISABLE_SOCKET_PROCESS_SANDBOX")) {
1616 !mResults
.mSandboxBroker
->SetSecurityLevelForSocketProcess())) {
1617 return Err(LaunchError("SetSecurityLevelForSocketProcess"));
1622 case GeckoProcessType_Utility
:
1623 if (IsUtilitySandboxEnabled(mSandbox
)) {
1624 if (!mResults
.mSandboxBroker
->SetSecurityLevelForUtilityProcess(
1626 return Err(LaunchError("SetSecurityLevelForUtilityProcess"));
1631 case GeckoProcessType_Default
:
1633 MOZ_CRASH("Bad process type in GeckoChildProcessHost");
1638 for (auto it
= mAllowedFilesRead
.begin(); it
!= mAllowedFilesRead
.end();
1640 mResults
.mSandboxBroker
->AllowReadFile(it
->c_str());
1643 if (mResults
.mSandboxBroker
->IsWin32kLockedDown()) {
1644 mCmdLine
->AppendLooseValue(
1645 UTF8ToWide(geckoargs::sWin32kLockedDown
.Name()));
1648 # endif // defined(MOZ_SANDBOX)
1650 // Add the application directory path (-appdir path)
1651 AddAppDirToCommandLine(mCmdLine
.ref(), mAppDir
);
1653 // XXX Command line params past this point are expected to be at
1654 // the end of the command line string, and in a specific order.
1655 // See XRE_InitChildProcess in nsEmbedFunction.
1658 mCmdLine
->AppendLooseValue(mGroupId
.get());
1661 mCmdLine
->AppendLooseValue(UTF8ToWide(mChildIDString
));
1664 mCmdLine
->AppendLooseValue(UTF8ToWide(ChildProcessType()));
1666 // Add any files which need to be transferred to handles_to_inherit.
1667 for (auto& file
: mChildArgs
.mFiles
) {
1668 mLaunchOptions
->handles_to_inherit
.push_back(file
.get());
1673 // Mark the handles to inherit as inheritable.
1674 for (HANDLE h
: mLaunchOptions
->handles_to_inherit
) {
1675 mResults
.mSandboxBroker
->AddHandleToShare(h
);
1678 # endif // MOZ_SANDBOX
1683 RefPtr
<ProcessHandlePromise
> WindowsProcessLauncher::DoLaunch() {
1684 ProcessHandle handle
= 0;
1687 const IMAGE_THUNK_DATA
* cachedNtdllThunk
=
1688 mCachedNtdllThunk
? mCachedNtdllThunk
->begin() : nullptr;
1689 Result
<Ok
, LaunchError
> err
= mResults
.mSandboxBroker
->LaunchApp(
1690 mCmdLine
->program().c_str(), mCmdLine
->command_line_string().c_str(),
1691 mLaunchOptions
->env_map
, mProcessType
, mEnableSandboxLogging
,
1692 cachedNtdllThunk
, &handle
);
1694 EnvironmentLog("MOZ_PROCESS_LOG")
1695 .print("==> process %d launched child process %d (%S)\n",
1696 base::GetCurrentProcId(), base::GetProcId(handle
),
1697 mCmdLine
->command_line_string().c_str());
1698 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1700 return ProcessHandlePromise::CreateAndReject(err
.unwrapErr(), __func__
);
1702 # endif // defined(MOZ_SANDBOX)
1704 Result
<Ok
, LaunchError
> launchErr
=
1705 base::LaunchApp(mCmdLine
.ref(), *mLaunchOptions
, &handle
);
1706 if (launchErr
.isErr()) {
1707 return ProcessHandlePromise::CreateAndReject(launchErr
.unwrapErr(),
1710 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1713 Result
<Ok
, LaunchError
> WindowsProcessLauncher::DoFinishLaunch() {
1714 Result
<Ok
, LaunchError
> err
= BaseProcessLauncher::DoFinishLaunch();
1723 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::FinishLaunch() {
1724 Result
<Ok
, LaunchError
> aError
= DoFinishLaunch();
1725 if (aError
.isErr()) {
1726 return ProcessLaunchPromise::CreateAndReject(aError
.unwrapErr(), __func__
);
1729 MOZ_DIAGNOSTIC_ASSERT(mResults
.mHandle
);
1731 Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS
,
1734 return ProcessLaunchPromise::CreateAndResolve(std::move(mResults
), __func__
);
1737 bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid
) {
1738 if (mChildProcessHandle
) {
1739 MOZ_ASSERT(aPid
== base::GetProcId(mChildProcessHandle
));
1743 return base::OpenPrivilegedProcessHandle(aPid
, &mChildProcessHandle
);
1746 void GeckoChildProcessHost::OnChannelConnected(base::ProcessId peer_pid
) {
1748 mozilla::AutoWriteLock
hLock(mHandleLock
);
1749 if (!OpenPrivilegedHandle(peer_pid
)) {
1750 MOZ_CRASH("can't open handle to child process");
1753 MonitorAutoLock
lock(mMonitor
);
1754 mProcessState
= PROCESS_CONNECTED
;
1758 RefPtr
<ProcessHandlePromise
> GeckoChildProcessHost::WhenProcessHandleReady() {
1759 MOZ_ASSERT(mHandlePromise
!= nullptr);
1760 return mHandlePromise
;
1763 #ifdef MOZ_WIDGET_ANDROID
1764 RefPtr
<ProcessHandlePromise
> AndroidProcessLauncher::LaunchAndroidService(
1765 const GeckoProcessType aType
, const geckoargs::ChildProcessArgs
& args
) {
1766 JNIEnv
* const env
= mozilla::jni::GetEnvForThread();
1769 const size_t argvSize
= args
.mArgs
.size();
1770 jni::ObjectArray::LocalRef jargs
=
1771 jni::ObjectArray::New
<jni::String
>(argvSize
);
1772 for (size_t ix
= 0; ix
< argvSize
; ix
++) {
1773 jargs
->SetElement(ix
, jni::StringParam(args
.mArgs
[ix
].c_str(), env
));
1776 std::vector
<int> fds(args
.mFiles
.size());
1777 for (size_t ix
= 0; ix
< fds
.size(); ix
++) {
1778 fds
[ix
] = args
.mFiles
[ix
].get();
1780 jni::IntArray::LocalRef jfds
= jni::IntArray::New(fds
.data(), fds
.size());
1782 auto type
= java::GeckoProcessType::FromInt(aType
);
1783 auto genericResult
= java::GeckoProcessManager::Start(type
, jargs
, jfds
);
1784 auto typedResult
= java::GeckoResult::LocalRef(std::move(genericResult
));
1785 return ProcessHandlePromise::FromGeckoResult(typedResult
);
1789 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1790 bool GeckoChildProcessHost::AppendMacSandboxParams(StringVector
& aArgs
) {
1791 MacSandboxInfo info
;
1792 if (NS_WARN_IF(!FillMacSandboxInfo(info
))) {
1795 info
.AppendAsParams(aArgs
);
1799 // Fill |aInfo| with the flags needed to launch the utility sandbox
1800 bool GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo
& aInfo
) {
1801 aInfo
.type
= GetDefaultMacSandboxType();
1802 aInfo
.shouldLog
= Preferences::GetBool("security.sandbox.logging.enabled") ||
1803 PR_GetEnv("MOZ_SANDBOX_LOGGING");
1805 nsAutoCString appPath
;
1806 if (!nsMacUtilsImpl::GetAppPath(appPath
)) {
1807 MOZ_CRASH("Failed to get app path");
1809 aInfo
.appPath
.assign(appPath
.get());
1813 void GeckoChildProcessHost::DisableOSActivityMode() {
1814 mDisableOSActivityMode
= true;
1818 // If early sandbox startup is enabled for this process type, map the
1819 // process type to the sandbox type and enable the sandbox. Returns true
1820 // if no errors were encountered or if early sandbox startup is not
1821 // enabled for this process. Returns false if an error was encountered.
1824 bool GeckoChildProcessHost::StartMacSandbox(int aArgc
, char** aArgv
,
1825 std::string
& aErrorMessage
) {
1826 MacSandboxType sandboxType
= MacSandboxType_Invalid
;
1827 switch (XRE_GetProcessType()) {
1828 // For now, only support early sandbox startup for content,
1829 // RDD, and GMP processes. Add case statements for the additional
1830 // process types once early sandbox startup is implemented for them.
1831 case GeckoProcessType_Content
:
1832 // Content processes don't use GeckoChildProcessHost
1833 // to configure sandboxing so hard code the sandbox type.
1834 sandboxType
= MacSandboxType_Content
;
1836 case GeckoProcessType_RDD
:
1837 sandboxType
= RDDProcessHost::GetMacSandboxType();
1839 case GeckoProcessType_Socket
:
1840 sandboxType
= net::SocketProcessHost::GetMacSandboxType();
1842 case GeckoProcessType_GMPlugin
:
1843 sandboxType
= gmp::GMPProcessParent::GetMacSandboxType();
1845 case GeckoProcessType_Utility
:
1846 sandboxType
= ipc::UtilityProcessHost::GetMacSandboxType();
1852 return mozilla::StartMacSandboxIfEnabled(sandboxType
, aArgc
, aArgv
,
1856 #endif /* XP_MACOSX && MOZ_SANDBOX */
1859 void GeckoChildProcessHost::GetAll(const GeckoProcessCallback
& aCallback
) {
1860 StaticMutexAutoLock
lock(sMutex
);
1861 if (!sGeckoChildProcessHosts
) {
1864 for (GeckoChildProcessHost
* gp
= sGeckoChildProcessHosts
->getFirst(); gp
;
1865 gp
= static_cast<mozilla::LinkedListElement
<GeckoChildProcessHost
>*>(gp
)
1871 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::Launch(
1872 GeckoChildProcessHost
* aHost
) {
1875 // The ForkServer doesn't use IPC::Channel for communication, so we can skip
1877 if (mProcessType
!= GeckoProcessType_ForkServer
) {
1878 IPC::Channel::ChannelHandle serverHandle
;
1879 IPC::Channel::ChannelHandle clientHandle
;
1880 if (!IPC::Channel::CreateRawPipe(&serverHandle
, &clientHandle
)) {
1881 return ProcessLaunchPromise::CreateAndReject(LaunchError("CreateRawPipe"),
1884 aHost
->InitializeChannel(std::move(serverHandle
));
1885 geckoargs::sIPCHandle
.Put(std::move(clientHandle
), mChildArgs
);
1888 return InvokeAsync(mLaunchThread
, this, __func__
,
1889 &BaseProcessLauncher::PerformAsyncLaunch
);
1893 } // namespace mozilla