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"
16 #include "mozilla/ProcessType.h"
17 #ifdef MOZ_WIDGET_COCOA
18 # include <bsm/libbsm.h>
19 # include <mach/mach_traps.h>
20 # include <servers/bootstrap.h>
21 # include "SharedMemoryBasic.h"
22 # include "base/rand_util.h"
23 # include "chrome/common/mach_ipc_mac.h"
24 # include "mozilla/StaticPrefs_media.h"
25 # include "nsILocalFileMac.h"
28 #include "GeckoProfiler.h"
29 #include "MainThreadUtils.h"
30 #include "mozilla/Preferences.h"
31 #include "mozilla/Sprintf.h"
32 #include "nsXPCOMPrivate.h"
36 #if defined(MOZ_SANDBOX)
37 # include "mozilla/SandboxSettings.h"
38 # include "nsAppDirectoryServiceDefs.h"
43 #include "ProtocolUtils.h"
44 #include "mozilla/LinkedList.h"
45 #include "mozilla/Logging.h"
46 #include "mozilla/Maybe.h"
47 #include "mozilla/GeckoArgs.h"
48 #include "mozilla/Omnijar.h"
49 #include "mozilla/RDDProcessHost.h"
50 #include "mozilla/Services.h"
51 #include "mozilla/SharedThreadPool.h"
52 #include "mozilla/StaticMutex.h"
53 #include "mozilla/TaskQueue.h"
54 #include "mozilla/Telemetry.h"
55 #include "mozilla/UniquePtrExtensions.h"
56 #include "mozilla/ipc/BrowserProcessSubThread.h"
57 #include "mozilla/ipc/EnvironmentMap.h"
58 #include "mozilla/ipc/NodeController.h"
59 #include "mozilla/net/SocketProcessHost.h"
60 #include "nsDirectoryService.h"
61 #include "nsDirectoryServiceDefs.h"
62 #include "nsExceptionHandler.h"
64 #include "nsIObserverService.h"
65 #include "nsPrintfCString.h"
70 # include "mozilla/WindowsVersion.h"
71 # include "nsIWinTaskbar.h"
72 # define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
74 # if defined(MOZ_SANDBOX)
75 # include "WinUtils.h"
76 # include "mozilla/Preferences.h"
77 # include "mozilla/sandboxing/sandboxLogging.h"
79 # include "mozilla/remoteSandboxBroker.h"
83 # include "mozilla/NativeNt.h"
84 # include "mozilla/CacheNtDllThunk.h"
87 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
88 # include "mozilla/SandboxLaunch.h"
91 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
92 # include "GMPProcessParent.h"
93 # include "nsMacUtilsImpl.h"
96 #include "mozilla/ipc/UtilityProcessHost.h"
97 #include "mozilla/ipc/UtilityProcessSandboxing.h"
99 #include "nsClassHashtable.h"
100 #include "nsHashKeys.h"
101 #include "nsNativeCharsetUtils.h"
102 #include "nsTArray.h"
103 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
104 #include "nsIThread.h"
106 using mozilla::MonitorAutoLock
;
107 using mozilla::Preferences
;
108 using mozilla::StaticMutexAutoLock
;
110 #ifdef MOZ_WIDGET_ANDROID
111 # include "AndroidBridge.h"
112 # include "mozilla/java/GeckoProcessManagerWrappers.h"
113 # include "mozilla/java/GeckoProcessTypeWrappers.h"
114 # include "mozilla/java/GeckoResultWrappers.h"
115 # include "mozilla/jni/Refs.h"
116 # include "mozilla/jni/Utils.h"
119 #ifdef MOZ_ENABLE_FORKSERVER
120 # include "mozilla/ipc/ForkServiceChild.h"
123 static bool ShouldHaveDirectoryService() {
124 return GeckoProcessType_Default
== XRE_GetProcessType();
130 struct LaunchResults
{
131 base::ProcessHandle mHandle
= 0;
133 task_t mChildTask
= MACH_PORT_NULL
;
135 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
136 RefPtr
<AbstractSandboxBroker
> mSandboxBroker
;
139 typedef mozilla::MozPromise
<LaunchResults
, LaunchError
, true>
140 ProcessLaunchPromise
;
142 static Atomic
<int32_t> gChildCounter
;
144 static inline nsISerialEventTarget
* IOThread() {
145 return XRE_GetIOMessageLoop()->SerialEventTarget();
148 class BaseProcessLauncher
{
150 BaseProcessLauncher(GeckoChildProcessHost
* aHost
,
151 std::vector
<std::string
>&& aExtraOpts
)
152 : mProcessType(aHost
->mProcessType
),
153 mLaunchOptions(std::move(aHost
->mLaunchOptions
)),
154 mExtraOpts(std::move(aExtraOpts
)),
156 mGroupId(aHost
->mGroupId
),
158 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
159 mAllowedFilesRead(aHost
->mAllowedFilesRead
),
160 mSandboxLevel(aHost
->mSandboxLevel
),
161 mSandbox(aHost
->mSandbox
),
162 mIsFileContent(aHost
->mIsFileContent
),
163 mEnableSandboxLogging(aHost
->mEnableSandboxLogging
),
165 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
166 mDisableOSActivityMode(aHost
->mDisableOSActivityMode
),
168 mTmpDirName(aHost
->mTmpDirName
),
169 mChildId(++gChildCounter
) {
170 SprintfLiteral(mPidString
, "%" PRIPID
, base::GetCurrentProcId());
171 aHost
->mInitialChannelId
.ToProvidedString(mInitialChannelIdString
);
173 // Compute the serial event target we'll use for launching.
174 nsCOMPtr
<nsIEventTarget
> threadOrPool
= GetIPCLauncher();
176 TaskQueue::Create(threadOrPool
.forget(), "BaseProcessLauncher");
178 if (ShouldHaveDirectoryService()) {
179 // "Current process directory" means the app dir, not the current
180 // working dir or similar.
182 << nsDirectoryService::gService
->GetCurrentProcessDirectory(
183 getter_AddRefs(mAppDir
));
187 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher
);
189 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
190 void SetLaunchArchitecture(uint32_t aLaunchArch
) {
191 mLaunchArch
= aLaunchArch
;
195 RefPtr
<ProcessLaunchPromise
> Launch(GeckoChildProcessHost
*);
198 virtual ~BaseProcessLauncher() = default;
200 RefPtr
<ProcessLaunchPromise
> PerformAsyncLaunch();
201 RefPtr
<ProcessLaunchPromise
> FinishLaunch();
203 // Overrideable hooks. If superclass behavior is invoked, it's always at the
204 // top of the override.
205 virtual Result
<Ok
, LaunchError
> DoSetup();
206 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() = 0;
207 virtual Result
<Ok
, LaunchError
> DoFinishLaunch();
209 void MapChildLogging();
211 static BinPathType
GetPathToBinary(FilePath
&, GeckoProcessType
);
213 void GetChildLogName(const char* origLogName
, nsACString
& buffer
);
215 const char* ChildProcessType() {
216 return XRE_GeckoProcessTypeToString(mProcessType
);
219 nsCOMPtr
<nsISerialEventTarget
> mLaunchThread
;
220 GeckoProcessType mProcessType
;
221 UniquePtr
<base::LaunchOptions
> mLaunchOptions
;
222 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
223 uint32_t mLaunchArch
= base::PROCESS_ARCH_INVALID
;
225 std::vector
<std::string
> mExtraOpts
;
229 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
230 std::vector
<std::wstring
> mAllowedFilesRead
;
231 int32_t mSandboxLevel
;
232 SandboxingKind mSandbox
;
234 bool mEnableSandboxLogging
;
236 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
237 // Controls whether or not the process will be launched with
238 // environment variable OS_ACTIVITY_MODE set to "disabled".
239 bool mDisableOSActivityMode
;
241 nsCString mTmpDirName
;
242 LaunchResults mResults
= LaunchResults();
244 TimeStamp mStartTimeStamp
= TimeStamp::Now();
246 char mInitialChannelIdString
[NSID_LENGTH
];
248 // Set during launch.
249 IPC::Channel::ChannelHandle mClientChannelHandle
;
250 nsCOMPtr
<nsIFile
> mAppDir
;
254 class WindowsProcessLauncher final
: public BaseProcessLauncher
{
256 WindowsProcessLauncher(GeckoChildProcessHost
* aHost
,
257 std::vector
<std::string
>&& aExtraOpts
)
258 : BaseProcessLauncher(aHost
, std::move(aExtraOpts
)),
259 mCachedNtdllThunk(GetCachedNtDllThunk()) {}
262 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
263 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
264 virtual Result
<Ok
, LaunchError
> DoFinishLaunch() override
;
267 void AddApplicationPrefetchArgument();
269 mozilla::Maybe
<CommandLine
> mCmdLine
;
270 bool mUseSandbox
= false;
272 const Buffer
<IMAGE_THUNK_DATA
>* mCachedNtdllThunk
;
274 typedef WindowsProcessLauncher ProcessLauncher
;
278 class PosixProcessLauncher
: public BaseProcessLauncher
{
280 PosixProcessLauncher(GeckoChildProcessHost
* aHost
,
281 std::vector
<std::string
>&& aExtraOpts
)
282 : BaseProcessLauncher(aHost
, std::move(aExtraOpts
)),
283 mProfileDir(aHost
->mProfileDir
),
284 mChannelDstFd(IPC::Channel::GetClientChannelHandle()) {}
287 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
288 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
290 nsCOMPtr
<nsIFile
> mProfileDir
;
292 std::vector
<std::string
> mChildArgv
;
296 # if defined(XP_MACOSX)
297 class MacProcessLauncher
: public PosixProcessLauncher
{
299 MacProcessLauncher(GeckoChildProcessHost
* aHost
,
300 std::vector
<std::string
>&& aExtraOpts
)
301 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)),
302 // Put a random number into the channel name, so that
303 // a compromised renderer can't pretend being the child
304 // that's forked off.
306 StringPrintf("org.mozilla.machname.%d",
307 base::RandInt(0, std::numeric_limits
<int>::max()))) {
308 MOZ_ASSERT(mMachConnectionName
.size() < BOOTSTRAP_MAX_NAME_LEN
);
312 virtual Result
<Ok
, LaunchError
> DoFinishLaunch() override
;
314 std::string mMachConnectionName
;
315 // We add a mach port to the command line so the child can communicate its
316 // 'task_t' back to the parent.
317 mozilla::UniqueMachReceiveRight mParentRecvPort
;
319 friend class PosixProcessLauncher
;
321 typedef MacProcessLauncher ProcessLauncher
;
322 # elif defined(MOZ_WIDGET_ANDROID)
323 class AndroidProcessLauncher
: public PosixProcessLauncher
{
325 AndroidProcessLauncher(GeckoChildProcessHost
* aHost
,
326 std::vector
<std::string
>&& aExtraOpts
)
327 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)) {}
330 virtual RefPtr
<ProcessHandlePromise
> DoLaunch() override
;
331 RefPtr
<ProcessHandlePromise
> LaunchAndroidService(
332 const GeckoProcessType aType
, const std::vector
<std::string
>& argv
,
333 const base::file_handle_mapping_vector
& fds_to_remap
);
335 typedef AndroidProcessLauncher ProcessLauncher
;
336 // NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
337 // orthogonal IPC machinery there. Conversely, there are tier-3 non-Linux
338 // platforms (BSD and Solaris) where we want the "linux" IPC machinery. So
339 // we use MOZ_WIDGET_* to choose the platform backend.
340 # elif defined(MOZ_WIDGET_GTK)
341 class LinuxProcessLauncher
: public PosixProcessLauncher
{
343 LinuxProcessLauncher(GeckoChildProcessHost
* aHost
,
344 std::vector
<std::string
>&& aExtraOpts
)
345 : PosixProcessLauncher(aHost
, std::move(aExtraOpts
)) {}
348 virtual Result
<Ok
, LaunchError
> DoSetup() override
;
350 typedef LinuxProcessLauncher ProcessLauncher
;
352 # error "Unknown platform"
356 using base::ProcessHandle
;
357 using mozilla::ipc::BaseProcessLauncher
;
358 using mozilla::ipc::ProcessLauncher
;
360 mozilla::StaticAutoPtr
<mozilla::LinkedList
<GeckoChildProcessHost
>>
361 GeckoChildProcessHost::sGeckoChildProcessHosts
;
363 mozilla::StaticMutex
GeckoChildProcessHost::sMutex
;
365 GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType
,
367 : mProcessType(aProcessType
),
368 mIsFileContent(aIsFileContent
),
369 mMonitor("mozilla.ipc.GeckoChildProcessHost.mMonitor"),
370 mLaunchOptions(MakeUnique
<base::LaunchOptions
>()),
371 mInitialChannelId(nsID::GenerateUUID()),
372 mProcessState(CREATING_CHANNEL
),
376 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
377 mEnableSandboxLogging(false),
380 mHandleLock("mozilla.ipc.GeckoChildProcessHost.mHandleLock"),
381 mChildProcessHandle(0),
382 #if defined(MOZ_WIDGET_COCOA)
383 mChildTask(MACH_PORT_NULL
),
385 #if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
386 mDisableOSActivityMode(false),
389 MOZ_COUNT_CTOR(GeckoChildProcessHost
);
390 StaticMutexAutoLock
lock(sMutex
);
391 if (!sGeckoChildProcessHosts
) {
392 sGeckoChildProcessHosts
= new mozilla::LinkedList
<GeckoChildProcessHost
>();
394 sGeckoChildProcessHosts
->insertBack(this);
395 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
396 if (aProcessType
== GeckoProcessType_Content
) {
397 # if defined(MOZ_CONTENT_TEMP_DIR)
398 // The content process needs the content temp dir:
399 nsCOMPtr
<nsIFile
> contentTempDir
;
400 nsresult rv
= NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR
,
401 getter_AddRefs(contentTempDir
));
402 if (NS_SUCCEEDED(rv
)) {
403 contentTempDir
->GetNativePath(mTmpDirName
);
406 } else 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";
418 #if defined(MOZ_ENABLE_FORKSERVER)
419 if (aProcessType
!= GeckoProcessType_ForkServer
&& ForkServiceChild::Get()) {
420 mLaunchOptions
->use_forkserver
= true;
425 GeckoChildProcessHost::~GeckoChildProcessHost()
429 MOZ_RELEASE_ASSERT(mDestroying
);
431 MOZ_COUNT_DTOR(GeckoChildProcessHost
);
434 mozilla::AutoWriteLock
hLock(mHandleLock
);
435 #if defined(MOZ_WIDGET_COCOA)
436 if (mChildTask
!= MACH_PORT_NULL
) {
437 mach_port_deallocate(mach_task_self(), mChildTask
);
441 if (mChildProcessHandle
!= 0) {
442 ProcessWatcher::EnsureProcessTerminated(
444 #ifdef NS_FREE_PERMANENT_DATA
445 // If we're doing leak logging, shutdown can be slow.
447 false // don't "force"
450 mChildProcessHandle
= 0;
454 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
455 if (mSandboxBroker
) {
456 mSandboxBroker
->Shutdown();
457 mSandboxBroker
= nullptr;
462 base::ProcessHandle
GeckoChildProcessHost::GetChildProcessHandle() {
463 mozilla::AutoReadLock
handleLock(mHandleLock
);
464 return mChildProcessHandle
;
467 base::ProcessId
GeckoChildProcessHost::GetChildProcessId() {
468 mozilla::AutoReadLock
handleLock(mHandleLock
);
469 if (!mChildProcessHandle
) {
472 return base::GetProcId(mChildProcessHandle
);
476 task_t
GeckoChildProcessHost::GetChildTask() {
477 mozilla::AutoReadLock
handleLock(mHandleLock
);
482 void GeckoChildProcessHost::RemoveFromProcessList() {
483 StaticMutexAutoLock
lock(sMutex
);
484 if (!sGeckoChildProcessHosts
) {
487 LinkedListElement
<GeckoChildProcessHost
>::removeFrom(
488 *sGeckoChildProcessHosts
);
491 void GeckoChildProcessHost::Destroy() {
492 MOZ_RELEASE_ASSERT(!mDestroying
);
493 // We can remove from the list before it's really destroyed
494 RemoveFromProcessList();
495 RefPtr
<ProcessHandlePromise
> whenReady
= mHandlePromise
;
498 // AsyncLaunch not called yet, so dispatch immediately.
499 whenReady
= ProcessHandlePromise::CreateAndReject(
500 LaunchError("DestroyEarly"), __func__
);
503 using Value
= ProcessHandlePromise::ResolveOrRejectValue
;
505 whenReady
->Then(XRE_GetIOMessageLoop()->SerialEventTarget(), __func__
,
506 [this](const Value
&) { delete this; });
510 mozilla::BinPathType
BaseProcessLauncher::GetPathToBinary(
511 FilePath
& exePath
, GeckoProcessType processType
) {
512 BinPathType pathType
= XRE_GetChildProcBinPathType(processType
);
514 if (pathType
== BinPathType::Self
) {
516 wchar_t exePathBuf
[MAXPATHLEN
];
517 if (!::GetModuleFileNameW(nullptr, exePathBuf
, MAXPATHLEN
)) {
518 MOZ_CRASH("GetModuleFileNameW failed (FIXME)");
520 exePath
= FilePath::FromWStringHack(exePathBuf
);
522 exePath
= FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
527 #ifdef MOZ_WIDGET_COCOA
528 // The GMP child process runs via the Media Plugin Helper executable
529 // which is a clone of plugin-container allowing for GMP-specific
530 // codesigning entitlements.
531 nsCString bundleName
;
532 std::string executableLeafName
;
533 if (processType
== GeckoProcessType_GMPlugin
&&
534 mozilla::StaticPrefs::media_plugin_helper_process_enabled()) {
535 bundleName
= MOZ_EME_PROCESS_BUNDLENAME
;
536 executableLeafName
= MOZ_EME_PROCESS_NAME_BRANDED
;
538 bundleName
= MOZ_CHILD_PROCESS_BUNDLENAME
;
539 executableLeafName
= MOZ_CHILD_PROCESS_NAME
;
543 if (ShouldHaveDirectoryService()) {
544 MOZ_ASSERT(gGREBinPath
);
546 exePath
= FilePath(char16ptr_t(gGREBinPath
));
547 #elif MOZ_WIDGET_COCOA
548 nsCOMPtr
<nsIFile
> childProcPath
;
549 NS_NewLocalFile(nsDependentString(gGREBinPath
), false,
550 getter_AddRefs(childProcPath
));
552 // We need to use an App Bundle on OS X so that we can hide
553 // the dock icon. See Bug 557225.
554 childProcPath
->AppendNative(bundleName
);
555 childProcPath
->AppendNative("Contents"_ns
);
556 childProcPath
->AppendNative("MacOS"_ns
);
558 childProcPath
->GetNativePath(tempCPath
);
559 exePath
= FilePath(tempCPath
.get());
562 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath
), path
);
563 exePath
= FilePath(path
.get());
567 if (exePath
.empty()) {
570 FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
572 exePath
= FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
574 exePath
= exePath
.DirName();
577 #ifdef MOZ_WIDGET_COCOA
578 exePath
= exePath
.Append(executableLeafName
);
580 exePath
= exePath
.AppendASCII(MOZ_CHILD_PROCESS_NAME
);
586 #ifdef MOZ_WIDGET_COCOA
587 class AutoCFTypeObject
{
589 explicit AutoCFTypeObject(CFTypeRef object
) { mObject
= object
; }
590 ~AutoCFTypeObject() { ::CFRelease(mObject
); }
597 // We start the unique IDs at 1 so that 0 can be used to mean that
598 // a component has no unique ID assigned to it.
599 uint32_t GeckoChildProcessHost::sNextUniqueID
= 1;
602 uint32_t GeckoChildProcessHost::GetUniqueID() { return sNextUniqueID
++; }
605 void GeckoChildProcessHost::SetEnv(const char* aKey
, const char* aValue
) {
606 MOZ_ASSERT(mLaunchOptions
);
607 mLaunchOptions
->env_map
[ENVIRONMENT_STRING(aKey
)] =
608 ENVIRONMENT_STRING(aValue
);
611 void GeckoChildProcessHost::PrepareLaunch() {
612 if (CrashReporter::GetEnabled()) {
613 CrashReporter::OOPInit();
616 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
617 SandboxLaunch::Configure(mProcessType
, mSandbox
, mLaunchOptions
.get());
622 # if defined(MOZ_SANDBOX)
623 // We need to get the pref here as the process is launched off main thread.
624 if (mProcessType
== GeckoProcessType_Content
) {
625 // Win32k Lockdown state must be initialized on the main thread.
626 // This is our last chance to do it before it is read on the IPC Launch
628 GetWin32kLockdownState();
629 mSandboxLevel
= GetEffectiveContentSandboxLevel();
630 mEnableSandboxLogging
=
631 Preferences::GetBool("security.sandbox.logging.enabled");
633 // We currently have to whitelist certain paths for tests to work in some
634 // development configurations.
635 nsAutoString readPaths
;
636 nsresult rv
= Preferences::GetString(
637 "security.sandbox.content.read_path_whitelist", readPaths
);
638 if (NS_SUCCEEDED(rv
)) {
639 for (const nsAString
& readPath
: readPaths
.Split(',')) {
640 nsString
trimmedPath(readPath
);
641 trimmedPath
.Trim(" ", true, true);
642 std::wstring
resolvedPath(trimmedPath
.Data());
643 // Check if path ends with '\' as this indicates we want to give read
644 // access to a directory and so it needs a wildcard.
645 if (resolvedPath
.back() == L
'\\') {
646 resolvedPath
.append(L
"*");
648 mAllowedFilesRead
.push_back(resolvedPath
);
654 # if defined(MOZ_SANDBOX)
655 // For other process types we can't rely on them being launched on main
656 // thread and they may not have access to prefs in the child process, so allow
657 // them to turn on logging via an environment variable.
658 mEnableSandboxLogging
=
659 mEnableSandboxLogging
|| !!PR_GetEnv("MOZ_SANDBOX_LOGGING");
662 #elif defined(XP_MACOSX)
663 # if defined(MOZ_SANDBOX)
664 if (ShouldHaveDirectoryService() &&
665 mProcessType
!= GeckoProcessType_GMPlugin
) {
666 mozilla::Unused
<< NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
,
667 getter_AddRefs(mProfileDir
));
674 void GeckoChildProcessHost::InitWindowsGroupID() {
675 // On Win7+, pass the application user model to the child, so it can
676 // register with it. This insures windows created by the container
677 // properly group with the parent app on the Win7 taskbar.
678 nsCOMPtr
<nsIWinTaskbar
> taskbarInfo
= do_GetService(NS_TASKBAR_CONTRACTID
);
680 bool isSupported
= false;
681 taskbarInfo
->GetAvailable(&isSupported
);
683 if (isSupported
&& NS_SUCCEEDED(taskbarInfo
->GetDefaultGroupId(appId
))) {
684 MOZ_ASSERT(mGroupId
.EqualsLiteral("-"));
685 mGroupId
.Assign(appId
);
691 bool GeckoChildProcessHost::SyncLaunch(std::vector
<std::string
> aExtraOpts
,
693 if (!AsyncLaunch(std::move(aExtraOpts
))) {
696 return WaitUntilConnected(aTimeoutMs
);
699 // Note: for most process types, we currently call AsyncLaunch, and therefore
700 // the *ProcessLauncher constructor, on the main thread, while the
701 // ProcessLauncher methods to actually execute the launch are called on the IO
702 // or IPC launcher thread. GMP processes are an exception - the GMP code
703 // invokes GeckoChildProcessHost from non-main-threads, and therefore we cannot
704 // rely on having access to mainthread-only services (like the directory
705 // service) from this code if we're launching that type of process.
706 bool GeckoChildProcessHost::AsyncLaunch(std::vector
<std::string
> aExtraOpts
) {
709 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
710 if (IsMacSandboxLaunchEnabled() && !AppendMacSandboxParams(aExtraOpts
)) {
715 RefPtr
<BaseProcessLauncher
> launcher
=
716 new ProcessLauncher(this, std::move(aExtraOpts
));
717 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
718 launcher
->SetLaunchArchitecture(mLaunchArch
);
721 // Note: Destroy() waits on mHandlePromise to delete |this|. As such, we want
722 // to be sure that all of our post-launch processing on |this| happens before
723 // mHandlePromise notifies.
724 MOZ_ASSERT(mHandlePromise
== nullptr);
726 mozilla::InvokeAsync
<GeckoChildProcessHost
*>(
727 IOThread(), launcher
.get(), __func__
, &BaseProcessLauncher::Launch
,
730 IOThread(), __func__
,
731 [this](LaunchResults
&& aResults
) {
734 mozilla::AutoWriteLock
handleLock(mHandleLock
);
735 if (!OpenPrivilegedHandle(base::GetProcId(aResults
.mHandle
))
737 // If we failed in opening the process handle, try
738 // harder by duplicating one.
739 && !::DuplicateHandle(
740 ::GetCurrentProcess(), aResults
.mHandle
,
741 ::GetCurrentProcess(), &mChildProcessHandle
,
742 PROCESS_DUP_HANDLE
| PROCESS_TERMINATE
|
743 PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
|
748 MOZ_CRASH("cannot open handle to child process");
750 // The original handle is no longer needed; it must
751 // be closed to prevent a resource leak.
752 base::CloseProcessHandle(aResults
.mHandle
);
753 // FIXME (bug 1720523): define a cross-platform
754 // "safe" invalid value to use in places like this.
755 aResults
.mHandle
= 0;
758 this->mChildTask
= aResults
.mChildTask
;
762 mNodeChannel
->SetOtherPid(
763 base::GetProcId(this->mChildProcessHandle
));
765 mNodeChannel
->SetMachTaskPort(this->mChildTask
);
769 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
770 this->mSandboxBroker
= std::move(aResults
.mSandboxBroker
);
773 MonitorAutoLock
lock(mMonitor
);
774 // The OnChannel{Connected,Error} may have already advanced
776 if (mProcessState
< PROCESS_CREATED
) {
777 mProcessState
= PROCESS_CREATED
;
781 return ProcessHandlePromise::CreateAndResolve(
782 GetChildProcessHandle(), __func__
);
784 [this](const LaunchError aError
) {
785 // WaitUntilConnected might be waiting for us to signal.
786 // If something failed let's set the error state and notify.
788 << "Failed to launch "
789 << XRE_GeckoProcessTypeToString(mProcessType
)
791 Telemetry::Accumulate(
792 Telemetry::SUBPROCESS_LAUNCH_FAILURE
,
794 XRE_GeckoProcessTypeToString(mProcessType
)));
795 nsCString telemetryKey
= nsPrintfCString(
801 aError
.FunctionName(), aError
.ErrorCode(),
802 XRE_GeckoProcessTypeToString(mProcessType
));
803 // Max telemetry key is 72 chars
804 // https://searchfox.org/mozilla-central/rev/c244b16815d1fc827d141472b9faac5610f250e7/toolkit/components/telemetry/core/TelemetryScalar.cpp#105
805 if (telemetryKey
.Length() > 72) {
806 NS_WARNING(nsPrintfCString("Truncating telemetry key: %s",
809 telemetryKey
.Truncate(72);
811 Telemetry::ScalarAdd(
812 Telemetry::ScalarID::
813 DOM_PARENTPROCESS_PROCESS_LAUNCH_ERRORS
,
814 NS_ConvertUTF8toUTF16(telemetryKey
), 1);
816 MonitorAutoLock
lock(mMonitor
);
817 mProcessState
= PROCESS_ERROR
;
820 return ProcessHandlePromise::CreateAndReject(aError
, __func__
);
825 bool GeckoChildProcessHost::WaitUntilConnected(int32_t aTimeoutMs
) {
826 AUTO_PROFILER_LABEL("GeckoChildProcessHost::WaitUntilConnected", OTHER
);
828 // NB: this uses a different mechanism than the chromium parent
830 TimeDuration timeout
= (aTimeoutMs
> 0)
831 ? TimeDuration::FromMilliseconds(aTimeoutMs
)
832 : TimeDuration::Forever();
834 MonitorAutoLock
lock(mMonitor
);
835 TimeStamp waitStart
= TimeStamp::Now();
838 // We'll receive several notifications, we need to exit when we
839 // have either successfully launched or have timed out.
840 while (mProcessState
!= PROCESS_CONNECTED
) {
841 // If there was an error then return it, don't wait out the timeout.
842 if (mProcessState
== PROCESS_ERROR
) {
846 CVStatus status
= lock
.Wait(timeout
);
847 if (status
== CVStatus::Timeout
) {
851 if (timeout
!= TimeDuration::Forever()) {
852 current
= TimeStamp::Now();
853 timeout
-= current
- waitStart
;
858 return mProcessState
== PROCESS_CONNECTED
;
861 bool GeckoChildProcessHost::WaitForProcessHandle() {
862 MonitorAutoLock
lock(mMonitor
);
863 while (mProcessState
< PROCESS_CREATED
) {
866 MOZ_ASSERT(mProcessState
== PROCESS_ERROR
|| GetChildProcessHandle());
868 return mProcessState
< PROCESS_ERROR
;
871 bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(
872 StringVector aExtraOpts
) {
873 if (!AsyncLaunch(std::move(aExtraOpts
))) {
876 return WaitForProcessHandle();
879 void GeckoChildProcessHost::InitializeChannel(
880 IPC::Channel::ChannelHandle
&& aServerHandle
) {
881 // Create the IPC channel which will be used for communication with this
883 mozilla::UniquePtr
<IPC::Channel
> channel
= MakeUnique
<IPC::Channel
>(
884 std::move(aServerHandle
), IPC::Channel::MODE_SERVER
,
885 base::kInvalidProcessId
);
887 channel
->StartAcceptingHandles(IPC::Channel::MODE_SERVER
);
888 #elif defined(XP_DARWIN)
889 channel
->StartAcceptingMachPorts(IPC::Channel::MODE_SERVER
);
892 mNodeController
= NodeController::GetSingleton();
893 std::tie(mInitialPort
, mNodeChannel
) =
894 mNodeController
->InviteChildProcess(std::move(channel
), this);
896 MonitorAutoLock
lock(mMonitor
);
897 mProcessState
= CHANNEL_INITIALIZED
;
901 void GeckoChildProcessHost::SetAlreadyDead() {
902 mozilla::AutoWriteLock
handleLock(mHandleLock
);
903 if (mChildProcessHandle
&&
904 mChildProcessHandle
!= base::kInvalidProcessHandle
) {
905 base::CloseProcessHandle(mChildProcessHandle
);
908 mChildProcessHandle
= 0;
911 void BaseProcessLauncher::GetChildLogName(const char* origLogName
,
912 nsACString
& buffer
) {
914 // On Windows we must expand relative paths because sandboxing rules
915 // bound only to full paths. fopen fowards to NtCreateFile which checks
916 // the path against the sanboxing rules as passed to fopen (left relative).
917 char absPath
[MAX_PATH
+ 2];
918 if (_fullpath(absPath
, origLogName
, sizeof(absPath
))) {
919 buffer
.Append(absPath
);
923 buffer
.Append(origLogName
);
926 // Remove .moz_log extension to avoid its duplication, it will be added
927 // automatically by the logging backend
928 static constexpr auto kMozLogExt
= nsLiteralCString
{MOZ_LOG_FILE_EXTENSION
};
929 if (StringEndsWith(buffer
, kMozLogExt
)) {
930 buffer
.Truncate(buffer
.Length() - kMozLogExt
.Length());
933 // Append child-specific postfix to name
934 buffer
.AppendLiteral(".child-");
935 buffer
.AppendInt(mChildId
);
938 // Windows needs a single dedicated thread for process launching,
939 // because of thread-safety restrictions/assertions in the sandbox
942 // Android also needs a single dedicated thread to simplify thread
945 // Fork server needs a dedicated thread for accessing
946 // |ForkServiceChild|.
947 #if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || \
948 defined(MOZ_ENABLE_FORKSERVER)
950 static mozilla::StaticMutex gIPCLaunchThreadMutex
;
951 static mozilla::StaticRefPtr
<nsIThread
> gIPCLaunchThread
952 MOZ_GUARDED_BY(gIPCLaunchThreadMutex
);
954 class IPCLaunchThreadObserver final
: public nsIObserver
{
959 virtual ~IPCLaunchThreadObserver() = default;
962 NS_IMPL_ISUPPORTS(IPCLaunchThreadObserver
, nsIObserver
, nsISupports
)
965 IPCLaunchThreadObserver::Observe(nsISupports
* aSubject
, const char* aTopic
,
966 const char16_t
* aData
) {
967 MOZ_RELEASE_ASSERT(strcmp(aTopic
, "xpcom-shutdown-threads") == 0);
968 StaticMutexAutoLock
lock(gIPCLaunchThreadMutex
);
971 if (gIPCLaunchThread
) {
972 rv
= gIPCLaunchThread
->Shutdown();
973 gIPCLaunchThread
= nullptr;
975 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
979 nsCOMPtr
<nsIEventTarget
> GetIPCLauncher() {
980 StaticMutexAutoLock
lock(gIPCLaunchThreadMutex
);
981 if (!gIPCLaunchThread
) {
982 nsCOMPtr
<nsIThread
> thread
;
983 nsresult rv
= NS_NewNamedThread("IPC Launch"_ns
, getter_AddRefs(thread
));
984 if (!NS_WARN_IF(NS_FAILED(rv
))) {
985 NS_DispatchToMainThread(
986 NS_NewRunnableFunction("GeckoChildProcessHost::GetIPCLauncher", [] {
987 nsCOMPtr
<nsIObserverService
> obsService
=
988 mozilla::services::GetObserverService();
989 nsCOMPtr
<nsIObserver
> obs
= new IPCLaunchThreadObserver();
990 obsService
->AddObserver(obs
, "xpcom-shutdown-threads", false);
992 gIPCLaunchThread
= thread
.forget();
996 nsCOMPtr
<nsIEventTarget
> thread
= gIPCLaunchThread
.get();
997 MOZ_DIAGNOSTIC_ASSERT(thread
);
1001 #else // defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) ||
1002 // defined(MOZ_ENABLE_FORKSERVER)
1004 // Other platforms use an on-demand thread pool.
1006 nsCOMPtr
<nsIEventTarget
> GetIPCLauncher() {
1007 nsCOMPtr
<nsIEventTarget
> pool
=
1008 mozilla::SharedThreadPool::Get("IPC Launch"_ns
);
1009 MOZ_DIAGNOSTIC_ASSERT(pool
);
1013 #endif // XP_WIN || MOZ_WIDGET_ANDROID || MOZ_ENABLE_FORKSERVER
1017 AddAppDirToCommandLine(CommandLine
& aCmdLine
, nsIFile
* aAppDir
)
1019 AddAppDirToCommandLine(std::vector
<std::string
>& aCmdLine
, nsIFile
* aAppDir
,
1020 nsIFile
* aProfileDir
)
1023 // Content processes need access to application resources, so pass
1024 // the full application directory path to the child process.
1028 MOZ_ALWAYS_SUCCEEDS(aAppDir
->GetPath(path
));
1029 aCmdLine
.AppendLooseValue(UTF8ToWide(geckoargs::sAppDir
.Name()));
1030 std::wstring
wpath(path
.get());
1031 aCmdLine
.AppendLooseValue(wpath
);
1034 MOZ_ALWAYS_SUCCEEDS(aAppDir
->GetNativePath(path
));
1035 geckoargs::sAppDir
.Put(path
.get(), aCmdLine
);
1038 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1039 // Full path to the profile dir
1041 // If the profile doesn't exist, normalization will
1042 // fail. But we don't return an error here because some
1043 // tests require startup with a missing profile dir.
1044 // For users, almost universally, the profile will be in
1045 // the home directory and normalization isn't required.
1046 mozilla::Unused
<< aProfileDir
->Normalize();
1048 MOZ_ALWAYS_SUCCEEDS(aProfileDir
->GetNativePath(path
));
1049 geckoargs::sProfile
.Put(path
.get(), aCmdLine
);
1055 #if defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1056 static bool Contains(const std::vector
<std::string
>& aExtraOpts
,
1057 const char* aValue
) {
1058 return std::any_of(aExtraOpts
.begin(), aExtraOpts
.end(),
1059 [&](const std::string arg
) {
1060 return arg
.find(aValue
) != std::string::npos
;
1063 #endif // defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1065 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::PerformAsyncLaunch() {
1066 Result
<Ok
, LaunchError
> aError
= DoSetup();
1067 if (aError
.isErr()) {
1068 return ProcessLaunchPromise::CreateAndReject(aError
.unwrapErr(), __func__
);
1070 RefPtr
<BaseProcessLauncher
> self
= this;
1071 return DoLaunch()->Then(
1072 mLaunchThread
, __func__
,
1073 [self
](base::ProcessHandle aHandle
) {
1074 self
->mResults
.mHandle
= aHandle
;
1075 return self
->FinishLaunch();
1077 [](LaunchError aError
) {
1078 return ProcessLaunchPromise::CreateAndReject(aError
, __func__
);
1082 Result
<Ok
, LaunchError
> BaseProcessLauncher::DoSetup() {
1083 RefPtr
<BaseProcessLauncher
> self
= this;
1084 GetProfilerEnvVarsForChildProcess([self
](const char* key
, const char* value
) {
1085 self
->mLaunchOptions
->env_map
[ENVIRONMENT_STRING(key
)] =
1086 ENVIRONMENT_STRING(value
);
1089 if (mProcessType
== GeckoProcessType_Content
) {
1090 nsAutoCString
mallocOpts(PR_GetEnv("MALLOC_OPTIONS"));
1091 // Disable randomization of small arenas in content.
1092 mallocOpts
.Append("r");
1093 self
->mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("MALLOC_OPTIONS")] =
1094 ENVIRONMENT_STRING(mallocOpts
.get());
1103 void BaseProcessLauncher::MapChildLogging() {
1104 const char* origNSPRLogName
= PR_GetEnv("NSPR_LOG_FILE");
1105 const char* origMozLogName
= PR_GetEnv("MOZ_LOG_FILE");
1107 if (origNSPRLogName
) {
1108 nsAutoCString nsprLogName
;
1109 GetChildLogName(origNSPRLogName
, nsprLogName
);
1110 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("NSPR_LOG_FILE")] =
1111 ENVIRONMENT_STRING(nsprLogName
.get());
1113 if (origMozLogName
) {
1114 nsAutoCString mozLogName
;
1115 GetChildLogName(origMozLogName
, mozLogName
);
1116 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("MOZ_LOG_FILE")] =
1117 ENVIRONMENT_STRING(mozLogName
.get());
1120 // `RUST_LOG_CHILD` is meant for logging child processes only.
1121 nsAutoCString
childRustLog(PR_GetEnv("RUST_LOG_CHILD"));
1122 if (!childRustLog
.IsEmpty()) {
1123 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("RUST_LOG")] =
1124 ENVIRONMENT_STRING(childRustLog
.get());
1128 Result
<Ok
, LaunchError
> BaseProcessLauncher::DoFinishLaunch() {
1129 // We're in the parent and the child was launched. Close the child channel
1130 // handle in the parent as soon as possible, which will allow the parent to
1131 // detect when the child closes its handle (either due to normal exit or due
1133 mClientChannelHandle
= nullptr;
1138 #if defined(MOZ_WIDGET_GTK)
1139 Result
<Ok
, LaunchError
> LinuxProcessLauncher::DoSetup() {
1140 Result
<Ok
, LaunchError
> aError
= PosixProcessLauncher::DoSetup();
1141 if (aError
.isErr()) {
1145 if (mProcessType
== GeckoProcessType_Content
) {
1146 // disable IM module to avoid sandbox violation
1147 mLaunchOptions
->env_map
["GTK_IM_MODULE"] = "gtk-im-context-simple";
1149 // Disable ATK accessibility code in content processes because it conflicts
1150 // with the sandbox, and we proxy that information through the main process
1152 mLaunchOptions
->env_map
["NO_AT_BRIDGE"] = "1";
1156 if (!mTmpDirName
.IsEmpty()) {
1157 // Point a bunch of things that might want to write from content to our
1158 // shiny new content-process specific tmpdir
1159 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("TMPDIR")] =
1160 ENVIRONMENT_STRING(mTmpDirName
.get());
1161 // Partial fix for bug 1380051 (not persistent - should be)
1162 mLaunchOptions
->env_map
[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
1163 ENVIRONMENT_STRING(mTmpDirName
.get());
1165 # endif // MOZ_SANDBOX
1169 #endif // MOZ_WIDGET_GTK
1172 Result
<Ok
, LaunchError
> PosixProcessLauncher::DoSetup() {
1173 Result
<Ok
, LaunchError
> aError
= BaseProcessLauncher::DoSetup();
1174 if (aError
.isErr()) {
1178 // XPCOM may not be initialized in some subprocesses. We don't want
1179 // to initialize XPCOM just for the directory service, especially
1180 // since LD_LIBRARY_PATH is already set correctly in subprocesses
1181 // (meaning that we don't need to set that up in the environment).
1182 if (ShouldHaveDirectoryService()) {
1183 MOZ_ASSERT(gGREBinPath
);
1185 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath
), path
);
1186 # if defined(XP_LINUX) || defined(__DragonFly__) || defined(XP_FREEBSD) || \
1187 defined(XP_NETBSD) || defined(XP_OPENBSD)
1188 const char* ld_library_path
= PR_GetEnv("LD_LIBRARY_PATH");
1189 nsCString
new_ld_lib_path(path
.get());
1191 if (ld_library_path
&& *ld_library_path
) {
1192 new_ld_lib_path
.Append(':');
1193 new_ld_lib_path
.Append(ld_library_path
);
1195 mLaunchOptions
->env_map
["LD_LIBRARY_PATH"] = new_ld_lib_path
.get();
1198 // With signed production Mac builds, the dynamic linker (dyld) will
1199 // ignore dyld environment variables preventing the use of variables
1200 // such as DYLD_LIBRARY_PATH and DYLD_INSERT_LIBRARIES.
1202 // If we're running with gtests, add the gtest XUL ahead of normal XUL on
1203 // the DYLD_LIBRARY_PATH so that plugin-container.app loads it instead.
1204 nsCString
new_dyld_lib_path(path
.get());
1205 if (PR_GetEnv("MOZ_RUN_GTEST")) {
1206 new_dyld_lib_path
= path
+ "/gtest:"_ns
+ new_dyld_lib_path
;
1207 mLaunchOptions
->env_map
["DYLD_LIBRARY_PATH"] = new_dyld_lib_path
.get();
1210 // DYLD_INSERT_LIBRARIES is currently unused by default but we allow
1211 // it to be set by the external environment.
1212 const char* interpose
= PR_GetEnv("DYLD_INSERT_LIBRARIES");
1213 if (interpose
&& strlen(interpose
) > 0) {
1214 mLaunchOptions
->env_map
["DYLD_INSERT_LIBRARIES"] = interpose
;
1217 // Prevent connection attempts to diagnosticd(8) to save cycles. Log
1218 // messages can trigger these connection attempts, but access to
1219 // diagnosticd is blocked in sandboxed child processes.
1221 if (mDisableOSActivityMode
) {
1222 mLaunchOptions
->env_map
["OS_ACTIVITY_MODE"] = "disable";
1224 # endif // defined(MOZ_SANDBOX)
1229 BinPathType pathType
= GetPathToBinary(exePath
, mProcessType
);
1231 // remap the IPC socket fd to a well-known int, as the OS does for
1232 // STDOUT_FILENO, for example
1233 // The fork server doesn't use IPC::Channel, so can skip this step.
1234 if (mProcessType
!= GeckoProcessType_ForkServer
) {
1235 # ifdef MOZ_WIDGET_ANDROID
1236 // On Android mChannelDstFd is uninitialised and the launching code uses
1237 // only the first of each pair.
1238 mLaunchOptions
->fds_to_remap
.push_back(
1239 std::pair
<int, int>(mClientChannelHandle
.get(), -1));
1241 MOZ_ASSERT(mChannelDstFd
>= 0);
1242 mLaunchOptions
->fds_to_remap
.push_back(
1243 std::pair
<int, int>(mClientChannelHandle
.get(), mChannelDstFd
));
1247 // no need for kProcessChannelID, the child process inherits the
1248 // other end of the socketpair() from us
1250 mChildArgv
.push_back(exePath
.value());
1252 if (pathType
== BinPathType::Self
) {
1253 mChildArgv
.push_back("-contentproc");
1256 mChildArgv
.insert(mChildArgv
.end(), mExtraOpts
.begin(), mExtraOpts
.end());
1258 if ((mProcessType
== GeckoProcessType_Content
||
1259 mProcessType
== GeckoProcessType_ForkServer
) &&
1260 Omnijar::IsInitialized()) {
1261 // Make sure that child processes can find the omnijar, if they
1262 // use full XPCOM. See Omnijar::ChildProcessInit and its callers.
1264 nsCOMPtr
<nsIFile
> greFile
= Omnijar::GetPath(Omnijar::GRE
);
1265 if (greFile
&& NS_SUCCEEDED(greFile
->GetNativePath(path
))) {
1266 geckoargs::sGREOmni
.Put(path
.get(), mChildArgv
);
1268 nsCOMPtr
<nsIFile
> appFile
= Omnijar::GetPath(Omnijar::APP
);
1269 if (appFile
&& NS_SUCCEEDED(appFile
->GetNativePath(path
))) {
1270 geckoargs::sAppOmni
.Put(path
.get(), mChildArgv
);
1274 if (mProcessType
!= GeckoProcessType_GMPlugin
) {
1275 // Add the application directory path (-appdir path)
1277 AddAppDirToCommandLine(mChildArgv
, mAppDir
, mProfileDir
);
1279 AddAppDirToCommandLine(mChildArgv
, mAppDir
, nullptr);
1283 mChildArgv
.push_back(mInitialChannelIdString
);
1285 mChildArgv
.push_back(mPidString
);
1287 if (!CrashReporter::IsDummy()) {
1288 # if defined(MOZ_WIDGET_COCOA)
1289 mChildArgv
.push_back(CrashReporter::GetChildNotificationPipe());
1290 # elif defined(XP_UNIX)
1291 int childCrashFd
, childCrashRemapFd
;
1292 if (NS_WARN_IF(!CrashReporter::CreateNotificationPipeForChild(
1293 &childCrashFd
, &childCrashRemapFd
))) {
1294 return Err(LaunchError("CR::CreateNotificationPipeForChild"));
1297 if (0 <= childCrashFd
) {
1298 mLaunchOptions
->fds_to_remap
.push_back(
1299 std::pair
<int, int>(childCrashFd
, childCrashRemapFd
));
1300 // "true" == crash reporting enabled
1301 mChildArgv
.push_back("true");
1303 // "false" == crash reporting disabled
1304 mChildArgv
.push_back("false");
1309 # ifdef MOZ_WIDGET_COCOA
1311 auto* thisMac
= static_cast<MacProcessLauncher
*>(this);
1313 bootstrap_check_in(bootstrap_port
, thisMac
->mMachConnectionName
.c_str(),
1314 getter_Transfers(thisMac
->mParentRecvPort
));
1315 if (kr
!= KERN_SUCCESS
) {
1316 CHROMIUM_LOG(ERROR
) << "parent bootstrap_check_in failed: "
1317 << mach_error_string(kr
);
1318 return Err(LaunchError("bootstrap_check_in", kr
));
1320 mChildArgv
.push_back(thisMac
->mMachConnectionName
.c_str());
1322 # endif // MOZ_WIDGET_COCOA
1324 mChildArgv
.push_back(ChildProcessType());
1329 #if defined(MOZ_WIDGET_ANDROID)
1330 RefPtr
<ProcessHandlePromise
> AndroidProcessLauncher::DoLaunch() {
1331 return LaunchAndroidService(mProcessType
, mChildArgv
,
1332 mLaunchOptions
->fds_to_remap
);
1334 #endif // MOZ_WIDGET_ANDROID
1337 RefPtr
<ProcessHandlePromise
> PosixProcessLauncher::DoLaunch() {
1338 ProcessHandle handle
= 0;
1339 Result
<Ok
, LaunchError
> aError
=
1340 base::LaunchApp(mChildArgv
, std::move(*mLaunchOptions
), &handle
);
1341 if (aError
.isErr()) {
1342 return ProcessHandlePromise::CreateAndReject(aError
.unwrapErr(), __func__
);
1344 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1349 Result
<Ok
, LaunchError
> MacProcessLauncher::DoFinishLaunch() {
1350 Result
<Ok
, LaunchError
> aError
= PosixProcessLauncher::DoFinishLaunch();
1351 if (aError
.isErr()) {
1355 MOZ_ASSERT(mParentRecvPort
, "should have been configured during DoSetup()");
1357 // Wait for the child process to send us its 'task_t' data.
1358 const int kTimeoutMs
= 10000;
1360 mozilla::UniqueMachSendRight child_task
;
1361 audit_token_t audit_token
{};
1362 kern_return_t kr
= MachReceivePortSendRight(
1363 mParentRecvPort
, mozilla::Some(kTimeoutMs
), &child_task
, &audit_token
);
1364 if (kr
!= KERN_SUCCESS
) {
1365 std::string errString
= StringPrintf("0x%x %s", kr
, mach_error_string(kr
));
1366 CHROMIUM_LOG(ERROR
) << "parent MachReceivePortSendRight failed: "
1368 return Err(LaunchError("MachReceivePortSendRight", kr
));
1371 // Ensure the message was sent by the newly spawned child process.
1372 if (audit_token_to_pid(audit_token
) != base::GetProcId(mResults
.mHandle
)) {
1373 CHROMIUM_LOG(ERROR
) << "task_t was not sent by child process";
1374 return Err(LaunchError("audit_token_to_pid"));
1377 // Ensure the task_t corresponds to the newly spawned child process.
1378 pid_t task_pid
= -1;
1379 kr
= pid_for_task(child_task
.get(), &task_pid
);
1380 if (kr
!= KERN_SUCCESS
) {
1381 CHROMIUM_LOG(ERROR
) << "pid_for_task failed: " << mach_error_string(kr
);
1382 return Err(LaunchError("pid_for_task", kr
));
1384 if (task_pid
!= base::GetProcId(mResults
.mHandle
)) {
1385 CHROMIUM_LOG(ERROR
) << "task_t is not for child process";
1386 return Err(LaunchError("task_pid"));
1389 mResults
.mChildTask
= child_task
.release();
1396 void WindowsProcessLauncher::AddApplicationPrefetchArgument() {
1397 // The Application Launch Prefetcher (ALPF) is an ill-documented Windows
1398 // subsystem that's intended to speed up process launching, apparently mostly
1399 // by assuming that a binary is going to want to load the same DLLs as it did
1400 // the last time it launched, and getting those prepped for loading as well.
1402 // For most applications, that's a good bet. For Firefox, it's less so, since
1403 // we use the same binary with different arguments to do completely different
1404 // things. Windows does allow applications to take up multiple slots in this
1405 // cache, but the "which bucket does this invocation go in?" mechanism is
1406 // highly unusual: the OS scans the command line and looks for a command-line
1407 // switch of a particular form.
1409 // (There is allegedly a way to do this without involving the command line,
1410 // OVERRIDE_PREFETCH_PARAMETER, but it's even more poorly documented.)
1412 // Applications' different prefetch-cache buckets are named with numbers from
1413 // "1" to some OS-version-determined limit, with an additional implicit "0"
1414 // cache bucket which is used when no valid prefetch cache slot is named.
1416 // (The "0" bucket's existence and behavior is not documented, but has been
1417 // confirmed by observing the creation and enumeration of cache files in the
1418 // C:\Windows\Prefetch folder.)
1419 static size_t const kMaxSlotNo
= IsWin1122H2OrLater() ? 16 : 8;
1421 // Determine the prefetch-slot number to be used for the process we're about
1424 // This may be changed freely between Firefox versions, as a Firefox update
1425 // will completely invalidate the prefetch cache anyway.
1426 size_t const prefetchSlot
= [&]() -> size_t {
1427 switch (mProcessType
) {
1428 // This code path is not used when starting the main process...
1429 case GeckoProcessType_Default
:
1430 // ...ForkServer is not used on Windows...
1431 case GeckoProcessType_ForkServer
:
1432 // ..."End" isn't a process-type, just a limit...
1433 case GeckoProcessType_End
:
1434 // ...and any new process-types should be considered explicitly here.
1436 MOZ_ASSERT_UNREACHABLE("Invalid process type");
1439 // These are started so rarely that we're not concerned about their
1440 // interaction with the prefetch cache.
1441 case GeckoProcessType_IPDLUnitTest
:
1442 case GeckoProcessType_VR
:
1445 // We reserve 1 for the main process as started by the launcher process.
1446 // (See LauncherProcessWin.cpp.) Otherwise, we mostly match the process-
1447 // type enumeration.
1448 case GeckoProcessType_Content
:
1450 case GeckoProcessType_Socket
:
1451 return 3; // usurps IPDLUnitTest
1452 case GeckoProcessType_GMPlugin
:
1454 case GeckoProcessType_GPU
:
1456 case GeckoProcessType_RemoteSandboxBroker
:
1457 return 6; // usurps VR
1458 case GeckoProcessType_RDD
:
1461 case GeckoProcessType_Utility
:
1462 // Continue the enumeration, using the SandboxingKind as a
1463 // probably-passably-precise proxy for the process's purpose.
1465 // (On Win10 and earlier this will lump all utility processes
1467 return std::min(kMaxSlotNo
, 8 + static_cast<size_t>(mSandbox
));
1470 MOZ_ASSERT(prefetchSlot
<= kMaxSlotNo
);
1472 if (prefetchSlot
== 0) {
1473 // default; no explicit argument needed
1477 std::wstring
arg(L
"/prefetch:");
1480 if (0 != _ultow_s(prefetchSlot
, buf
, 10)) {
1486 mCmdLine
->AppendLooseValue(arg
);
1489 Result
<Ok
, LaunchError
> WindowsProcessLauncher::DoSetup() {
1490 Result
<Ok
, LaunchError
> aError
= BaseProcessLauncher::DoSetup();
1491 if (aError
.isErr()) {
1496 BinPathType pathType
= GetPathToBinary(exePath
, mProcessType
);
1498 # if defined(MOZ_SANDBOX) || defined(_ARM64_)
1499 const bool isGMP
= mProcessType
== GeckoProcessType_GMPlugin
;
1500 const bool isWidevine
= isGMP
&& Contains(mExtraOpts
, "gmp-widevinecdm");
1501 # if defined(_ARM64_)
1502 bool useRemoteSandboxBroker
= false;
1503 if (mLaunchArch
& (base::PROCESS_ARCH_I386
| base::PROCESS_ARCH_X86_64
)) {
1504 // On Windows on ARM64 for ClearKey and Widevine, and for the sandbox
1505 // launcher process, we want to run the x86 plugin-container.exe in
1506 // the "i686" subdirectory, instead of the aarch64 plugin-container.exe.
1507 // So insert "i686" into the exePath.
1508 exePath
= exePath
.DirName().AppendASCII("i686").Append(exePath
.BaseName());
1509 useRemoteSandboxBroker
=
1510 mProcessType
!= GeckoProcessType_RemoteSandboxBroker
;
1512 # endif // if defined(_ARM64_)
1513 # endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
1515 mCmdLine
.emplace(exePath
.ToWStringHack());
1517 if (pathType
== BinPathType::Self
) {
1518 mCmdLine
->AppendLooseValue(UTF8ToWide("-contentproc"));
1521 # ifdef HAS_DLL_BLOCKLIST
1522 if (IsDynamicBlocklistDisabled(
1524 CommandLine::ForCurrentProcess()->HasSwitch(UTF8ToWide(
1525 mozilla::geckoargs::sDisableDynamicDllBlocklist
.sMatch
)))) {
1526 mCmdLine
->AppendLooseValue(
1527 UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist
.sMatch
));
1529 # endif // HAS_DLL_BLOCKLIST
1531 // Inherit the initial client channel handle into the child process.
1532 std::wstring processChannelID
=
1533 std::to_wstring(uint32_t(uintptr_t(mClientChannelHandle
.get())));
1534 mLaunchOptions
->handles_to_inherit
.push_back(mClientChannelHandle
.get());
1535 mCmdLine
->AppendSwitchWithValue(switches::kProcessChannelID
,
1538 for (std::vector
<std::string
>::iterator it
= mExtraOpts
.begin();
1539 it
!= mExtraOpts
.end(); ++it
) {
1540 mCmdLine
->AppendLooseValue(UTF8ToWide(*it
));
1543 # if defined(MOZ_SANDBOX)
1544 # if defined(_ARM64_)
1545 if (useRemoteSandboxBroker
)
1546 mResults
.mSandboxBroker
= new RemoteSandboxBroker(mLaunchArch
);
1548 # endif // if defined(_ARM64_)
1549 mResults
.mSandboxBroker
= new SandboxBroker();
1551 // XXX: Bug 1124167: We should get rid of the process specific logic for
1552 // sandboxing in this class at some point. Unfortunately it will take a bit
1553 // of reorganizing so I don't think this patch is the right time.
1554 switch (mProcessType
) {
1555 case GeckoProcessType_Content
:
1556 if (mSandboxLevel
> 0) {
1557 // For now we treat every failure as fatal in
1558 // SetSecurityLevelForContentProcess and just crash there right away.
1559 // Should this change in the future then we should also handle the error
1561 mResults
.mSandboxBroker
->SetSecurityLevelForContentProcess(
1562 mSandboxLevel
, mIsFileContent
);
1566 case GeckoProcessType_IPDLUnitTest
:
1567 // XXX: We don't sandbox this process type yet
1569 case GeckoProcessType_GMPlugin
:
1570 if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
1571 // The Widevine CDM on Windows can only load at USER_RESTRICTED,
1572 // not at USER_LOCKDOWN. So look in the command line arguments
1573 // to see if we're loading the path to the Widevine CDM, and if
1574 // so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
1576 isWidevine
? SandboxBroker::Restricted
: SandboxBroker::LockDown
;
1578 !mResults
.mSandboxBroker
->SetSecurityLevelForGMPlugin(level
))) {
1579 return Err(LaunchError("SetSecurityLevelForGMPlugin"));
1584 case GeckoProcessType_GPU
:
1585 if (mSandboxLevel
> 0 && !PR_GetEnv("MOZ_DISABLE_GPU_SANDBOX")) {
1586 // For now we treat every failure as fatal in
1587 // SetSecurityLevelForGPUProcess and just crash there right away. Should
1588 // this change in the future then we should also handle the error here.
1589 mResults
.mSandboxBroker
->SetSecurityLevelForGPUProcess(mSandboxLevel
);
1593 case GeckoProcessType_VR
:
1594 if (mSandboxLevel
> 0 && !PR_GetEnv("MOZ_DISABLE_VR_SANDBOX")) {
1595 // TODO: Implement sandbox for VR process, Bug 1430043.
1598 case GeckoProcessType_RDD
:
1599 if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
1601 !mResults
.mSandboxBroker
->SetSecurityLevelForRDDProcess())) {
1602 return Err(LaunchError("SetSecurityLevelForRDDProcess"));
1607 case GeckoProcessType_Socket
:
1608 if (!PR_GetEnv("MOZ_DISABLE_SOCKET_PROCESS_SANDBOX")) {
1610 !mResults
.mSandboxBroker
->SetSecurityLevelForSocketProcess())) {
1611 return Err(LaunchError("SetSecurityLevelForSocketProcess"));
1616 case GeckoProcessType_Utility
:
1617 if (IsUtilitySandboxEnabled(mSandbox
)) {
1618 if (!mResults
.mSandboxBroker
->SetSecurityLevelForUtilityProcess(
1620 return Err(LaunchError("SetSecurityLevelForUtilityProcess"));
1625 case GeckoProcessType_RemoteSandboxBroker
:
1626 // We don't sandbox the sandbox launcher...
1628 case GeckoProcessType_Default
:
1630 MOZ_CRASH("Bad process type in GeckoChildProcessHost");
1635 for (auto it
= mAllowedFilesRead
.begin(); it
!= mAllowedFilesRead
.end();
1637 mResults
.mSandboxBroker
->AllowReadFile(it
->c_str());
1640 if (mResults
.mSandboxBroker
->IsWin32kLockedDown()) {
1641 mCmdLine
->AppendLooseValue(
1642 UTF8ToWide(geckoargs::sWin32kLockedDown
.Name()));
1645 # endif // defined(MOZ_SANDBOX)
1647 // Add the application directory path (-appdir path)
1648 AddAppDirToCommandLine(mCmdLine
.ref(), mAppDir
);
1650 // XXX Command line params past this point are expected to be at
1651 // the end of the command line string, and in a specific order.
1652 // See XRE_InitChildProcess in nsEmbedFunction.
1655 mCmdLine
->AppendLooseValue(mGroupId
.get());
1657 // Initial MessageChannel id
1658 mCmdLine
->AppendLooseValue(UTF8ToWide(mInitialChannelIdString
));
1661 mCmdLine
->AppendLooseValue(UTF8ToWide(mPidString
));
1663 mCmdLine
->AppendLooseValue(
1664 UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
1667 mCmdLine
->AppendLooseValue(UTF8ToWide(ChildProcessType()));
1669 // Prefetch cache hint
1670 AddApplicationPrefetchArgument();
1674 // Mark the handles to inherit as inheritable.
1675 for (HANDLE h
: mLaunchOptions
->handles_to_inherit
) {
1676 mResults
.mSandboxBroker
->AddHandleToShare(h
);
1679 # endif // MOZ_SANDBOX
1684 RefPtr
<ProcessHandlePromise
> WindowsProcessLauncher::DoLaunch() {
1685 ProcessHandle handle
= 0;
1688 const IMAGE_THUNK_DATA
* cachedNtdllThunk
=
1689 mCachedNtdllThunk
? mCachedNtdllThunk
->begin() : nullptr;
1690 Result
<Ok
, LaunchError
> err
= mResults
.mSandboxBroker
->LaunchApp(
1691 mCmdLine
->program().c_str(), mCmdLine
->command_line_string().c_str(),
1692 mLaunchOptions
->env_map
, mProcessType
, mEnableSandboxLogging
,
1693 cachedNtdllThunk
, &handle
);
1695 EnvironmentLog("MOZ_PROCESS_LOG")
1696 .print("==> process %d launched child process %d (%S)\n",
1697 base::GetCurrentProcId(), base::GetProcId(handle
),
1698 mCmdLine
->command_line_string().c_str());
1699 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1701 return ProcessHandlePromise::CreateAndReject(err
.unwrapErr(), __func__
);
1703 # endif // defined(MOZ_SANDBOX)
1705 Result
<Ok
, LaunchError
> launchErr
=
1706 base::LaunchApp(mCmdLine
.ref(), *mLaunchOptions
, &handle
);
1707 if (launchErr
.isErr()) {
1708 return ProcessHandlePromise::CreateAndReject(launchErr
.unwrapErr(),
1711 return ProcessHandlePromise::CreateAndResolve(handle
, __func__
);
1714 Result
<Ok
, LaunchError
> WindowsProcessLauncher::DoFinishLaunch() {
1715 Result
<Ok
, LaunchError
> err
= BaseProcessLauncher::DoFinishLaunch();
1724 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::FinishLaunch() {
1725 Result
<Ok
, LaunchError
> aError
= DoFinishLaunch();
1726 if (aError
.isErr()) {
1727 return ProcessLaunchPromise::CreateAndReject(aError
.unwrapErr(), __func__
);
1730 MOZ_DIAGNOSTIC_ASSERT(mResults
.mHandle
);
1732 Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS
,
1735 return ProcessLaunchPromise::CreateAndResolve(mResults
, __func__
);
1738 bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid
) {
1739 if (mChildProcessHandle
) {
1740 MOZ_ASSERT(aPid
== base::GetProcId(mChildProcessHandle
));
1744 return base::OpenPrivilegedProcessHandle(aPid
, &mChildProcessHandle
);
1747 void GeckoChildProcessHost::OnChannelConnected(base::ProcessId peer_pid
) {
1749 mozilla::AutoWriteLock
hLock(mHandleLock
);
1750 if (!OpenPrivilegedHandle(peer_pid
)) {
1751 MOZ_CRASH("can't open handle to child process");
1754 MonitorAutoLock
lock(mMonitor
);
1755 mProcessState
= PROCESS_CONNECTED
;
1759 RefPtr
<ProcessHandlePromise
> GeckoChildProcessHost::WhenProcessHandleReady() {
1760 MOZ_ASSERT(mHandlePromise
!= nullptr);
1761 return mHandlePromise
;
1764 #ifdef MOZ_WIDGET_ANDROID
1765 RefPtr
<ProcessHandlePromise
> AndroidProcessLauncher::LaunchAndroidService(
1766 const GeckoProcessType aType
, const std::vector
<std::string
>& argv
,
1767 const base::file_handle_mapping_vector
& fds_to_remap
) {
1768 MOZ_RELEASE_ASSERT((2 <= fds_to_remap
.size()) && (fds_to_remap
.size() <= 5));
1769 JNIEnv
* const env
= mozilla::jni::GetEnvForThread();
1772 const int argvSize
= argv
.size();
1773 jni::ObjectArray::LocalRef jargs
=
1774 jni::ObjectArray::New
<jni::String
>(argvSize
);
1775 for (int ix
= 0; ix
< argvSize
; ix
++) {
1776 jargs
->SetElement(ix
, jni::StringParam(argv
[ix
].c_str(), env
));
1779 // XXX: this processing depends entirely on the internals of
1780 // ContentParent::LaunchSubprocess()
1781 // GeckoChildProcessHost::PerformAsyncLaunch(), and the order in
1782 // which they append to fds_to_remap. There must be a better way to do it.
1784 int32_t prefsFd
= fds_to_remap
[0].first
;
1785 int32_t prefMapFd
= fds_to_remap
[1].first
;
1786 int32_t ipcFd
= fds_to_remap
[2].first
;
1787 int32_t crashFd
= -1;
1788 if (fds_to_remap
.size() == 4) {
1789 crashFd
= fds_to_remap
[3].first
;
1792 auto type
= java::GeckoProcessType::FromInt(aType
);
1793 auto genericResult
= java::GeckoProcessManager::Start(
1794 type
, jargs
, prefsFd
, prefMapFd
, ipcFd
, crashFd
);
1795 auto typedResult
= java::GeckoResult::LocalRef(std::move(genericResult
));
1796 return ProcessHandlePromise::FromGeckoResult(typedResult
);
1800 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1801 bool GeckoChildProcessHost::AppendMacSandboxParams(StringVector
& aArgs
) {
1802 MacSandboxInfo info
;
1803 if (NS_WARN_IF(!FillMacSandboxInfo(info
))) {
1806 info
.AppendAsParams(aArgs
);
1810 // Fill |aInfo| with the flags needed to launch the utility sandbox
1811 bool GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo
& aInfo
) {
1812 aInfo
.type
= GetDefaultMacSandboxType();
1813 aInfo
.shouldLog
= Preferences::GetBool("security.sandbox.logging.enabled") ||
1814 PR_GetEnv("MOZ_SANDBOX_LOGGING");
1816 nsAutoCString appPath
;
1817 if (!nsMacUtilsImpl::GetAppPath(appPath
)) {
1818 MOZ_CRASH("Failed to get app path");
1820 aInfo
.appPath
.assign(appPath
.get());
1824 void GeckoChildProcessHost::DisableOSActivityMode() {
1825 mDisableOSActivityMode
= true;
1829 // If early sandbox startup is enabled for this process type, map the
1830 // process type to the sandbox type and enable the sandbox. Returns true
1831 // if no errors were encountered or if early sandbox startup is not
1832 // enabled for this process. Returns false if an error was encountered.
1835 bool GeckoChildProcessHost::StartMacSandbox(int aArgc
, char** aArgv
,
1836 std::string
& aErrorMessage
) {
1837 MacSandboxType sandboxType
= MacSandboxType_Invalid
;
1838 switch (XRE_GetProcessType()) {
1839 // For now, only support early sandbox startup for content,
1840 // RDD, and GMP processes. Add case statements for the additional
1841 // process types once early sandbox startup is implemented for them.
1842 case GeckoProcessType_Content
:
1843 // Content processes don't use GeckoChildProcessHost
1844 // to configure sandboxing so hard code the sandbox type.
1845 sandboxType
= MacSandboxType_Content
;
1847 case GeckoProcessType_RDD
:
1848 sandboxType
= RDDProcessHost::GetMacSandboxType();
1850 case GeckoProcessType_Socket
:
1851 sandboxType
= net::SocketProcessHost::GetMacSandboxType();
1853 case GeckoProcessType_GMPlugin
:
1854 sandboxType
= gmp::GMPProcessParent::GetMacSandboxType();
1856 case GeckoProcessType_Utility
:
1857 sandboxType
= ipc::UtilityProcessHost::GetMacSandboxType();
1863 return mozilla::StartMacSandboxIfEnabled(sandboxType
, aArgc
, aArgv
,
1867 #endif /* XP_MACOSX && MOZ_SANDBOX */
1870 void GeckoChildProcessHost::GetAll(const GeckoProcessCallback
& aCallback
) {
1871 StaticMutexAutoLock
lock(sMutex
);
1872 if (!sGeckoChildProcessHosts
) {
1875 for (GeckoChildProcessHost
* gp
= sGeckoChildProcessHosts
->getFirst(); gp
;
1876 gp
= static_cast<mozilla::LinkedListElement
<GeckoChildProcessHost
>*>(gp
)
1882 RefPtr
<ProcessLaunchPromise
> BaseProcessLauncher::Launch(
1883 GeckoChildProcessHost
* aHost
) {
1886 // The ForkServer doesn't use IPC::Channel for communication, so we can skip
1888 if (mProcessType
!= GeckoProcessType_ForkServer
) {
1889 IPC::Channel::ChannelHandle serverHandle
;
1890 if (!IPC::Channel::CreateRawPipe(&serverHandle
, &mClientChannelHandle
)) {
1891 return ProcessLaunchPromise::CreateAndReject(LaunchError("CreateRawPipe"),
1894 aHost
->InitializeChannel(std::move(serverHandle
));
1897 return InvokeAsync(mLaunchThread
, this, __func__
,
1898 &BaseProcessLauncher::PerformAsyncLaunch
);
1902 } // namespace mozilla