Backed out changeset 555c786396f8 (bug 1852046) as requested. CLOSED TREE
[gecko.git] / toolkit / xre / nsEmbedFunctions.cpp
blob1a6ae343d19cf8acb8281fefde0ab096ae62fa70
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/DebugOnly.h"
7 #include "nsXULAppAPI.h"
9 #include <stdlib.h>
10 #if defined(MOZ_WIDGET_GTK)
11 # include <glib.h>
12 #endif
14 #include "prenv.h"
16 #include "nsIAppShell.h"
17 #include "nsIToolkitProfile.h"
19 #ifdef XP_WIN
20 # include <process.h>
21 # include <shobjidl.h>
22 # include "mozilla/ipc/WindowsMessageLoop.h"
23 # ifdef MOZ_SANDBOX
24 # include "mozilla/RandomNum.h"
25 # endif
26 # include "mozilla/ScopeExit.h"
27 # include "mozilla/WinDllServices.h"
28 # include "mozilla/WindowsBCryptInitialization.h"
29 # include "WinUtils.h"
30 #endif
32 #include "nsAppRunner.h"
33 #include "nsExceptionHandler.h"
34 #include "mozilla/RuntimeExceptionModule.h"
35 #include "nsThreadUtils.h"
36 #include "nsJSUtils.h"
37 #include "nsWidgetsCID.h"
38 #include "nsXREDirProvider.h"
39 #ifdef MOZ_ASAN_REPORTER
40 # include "CmdLineAndEnvUtils.h"
41 # include "nsIFile.h"
42 #endif
44 #include "mozilla/Omnijar.h"
45 #if defined(XP_MACOSX)
46 # include <mach/mach.h>
47 # include <servers/bootstrap.h>
48 # include "nsVersionComparator.h"
49 # include "chrome/common/mach_ipc_mac.h"
50 # include "gfxPlatformMac.h"
51 #endif
52 #include "nsX11ErrorHandler.h"
53 #include "nsGDKErrorHandler.h"
54 #include "base/at_exit.h"
55 #include "base/message_loop.h"
56 #include "base/process_util.h"
57 #if defined(MOZ_WIDGET_ANDROID)
58 # include "chrome/common/ipc_channel.h"
59 # include "mozilla/jni/Utils.h"
60 # include "mozilla/ipc/ProcessUtils.h"
61 #endif // defined(MOZ_WIDGET_ANDROID)
63 #include "mozilla/AbstractThread.h"
64 #include "mozilla/FilePreferences.h"
65 #include "mozilla/IOInterposer.h"
66 #include "mozilla/ProcessType.h"
67 #include "mozilla/RDDProcessImpl.h"
68 #include "mozilla/ipc/UtilityProcessImpl.h"
69 #include "mozilla/UniquePtr.h"
71 #include "mozilla/ipc/BrowserProcessSubThread.h"
72 #include "mozilla/ipc/IOThreadChild.h"
73 #include "mozilla/ipc/ProcessChild.h"
75 #include "mozilla/dom/ContentProcess.h"
76 #include "mozilla/dom/ContentParent.h"
78 #include "mozilla/ipc/TestShellParent.h"
79 #if defined(XP_WIN)
80 # include "mozilla/WindowsConsole.h"
81 # include "mozilla/WindowsDllBlocklist.h"
82 #endif
84 #include "GMPProcessChild.h"
85 #include "mozilla/gfx/GPUProcessImpl.h"
86 #include "mozilla/net/SocketProcessImpl.h"
88 #include "ProfilerControl.h"
90 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
91 # include "mozilla/sandboxTarget.h"
92 # include "mozilla/sandboxing/loggingCallbacks.h"
93 # include "mozilla/RemoteSandboxBrokerProcessChild.h"
94 #endif
96 #if defined(MOZ_SANDBOX)
97 # include "XREChildData.h"
98 # include "mozilla/SandboxSettings.h"
99 #endif
101 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
102 # include "mozilla/Sandbox.h"
103 #endif
105 #if defined(XP_LINUX)
106 # include <sys/prctl.h>
107 # ifndef PR_SET_PTRACER
108 # define PR_SET_PTRACER 0x59616d61
109 # endif
110 # ifndef PR_SET_PTRACER_ANY
111 # define PR_SET_PTRACER_ANY ((unsigned long)-1)
112 # endif
113 #endif
115 #ifdef MOZ_JPROF
116 # include "jprof.h"
117 #endif
119 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
120 # include "mozilla/sandboxing/SandboxInitialization.h"
121 # include "mozilla/sandboxing/sandboxLogging.h"
122 #endif
124 #if defined(MOZ_ENABLE_FORKSERVER)
125 # include "mozilla/ipc/ForkServer.h"
126 #endif
128 #if defined(MOZ_X11)
129 # include <X11/Xlib.h>
130 #endif
132 #include "VRProcessChild.h"
134 using namespace mozilla;
136 using mozilla::ipc::BrowserProcessSubThread;
137 using mozilla::ipc::GeckoChildProcessHost;
138 using mozilla::ipc::IOThreadChild;
139 using mozilla::ipc::ProcessChild;
141 using mozilla::dom::ContentParent;
142 using mozilla::dom::ContentProcess;
144 using mozilla::gmp::GMPProcessChild;
146 using mozilla::ipc::TestShellCommandParent;
147 using mozilla::ipc::TestShellParent;
149 namespace mozilla::_ipdltest {
150 // Set in IPDLUnitTest.cpp when running gtests.
151 UniquePtr<mozilla::ipc::ProcessChild> (*gMakeIPDLUnitTestProcessChild)(
152 base::ProcessId, const nsID&) = nullptr;
153 } // namespace mozilla::_ipdltest
155 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
157 const char* XRE_GeckoProcessTypeToString(GeckoProcessType aProcessType) {
158 switch (aProcessType) {
159 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
160 process_bin_type, procinfo_typename, \
161 webidl_typename, allcaps_name) \
162 case GeckoProcessType::GeckoProcessType_##enum_name: \
163 return string_name;
164 #include "mozilla/GeckoProcessTypes.h"
165 #undef GECKO_PROCESS_TYPE
166 default:
167 return "invalid";
171 const char* XRE_ChildProcessTypeToAnnotation(GeckoProcessType aProcessType) {
172 switch (aProcessType) {
173 case GeckoProcessType_GMPlugin:
174 return "plugin";
175 case GeckoProcessType_Default:
176 return "";
177 case GeckoProcessType_Content:
178 return "content";
179 default:
180 return XRE_GeckoProcessTypeToString(aProcessType);
184 #if defined(MOZ_WIDGET_ANDROID)
185 void XRE_SetAndroidChildFds(JNIEnv* env, const XRE_AndroidChildFds& fds) {
186 mozilla::jni::SetGeckoThreadEnv(env);
187 mozilla::ipc::SetPrefsFd(fds.mPrefsFd);
188 mozilla::ipc::SetPrefMapFd(fds.mPrefMapFd);
189 IPC::Channel::SetClientChannelFd(fds.mIpcFd);
190 CrashReporter::SetNotificationPipeForChild(fds.mCrashFd);
192 #endif // defined(MOZ_WIDGET_ANDROID)
194 void XRE_SetProcessType(const char* aProcessTypeString) {
195 SetGeckoProcessType(aProcessTypeString);
198 #if defined(XP_WIN)
199 void SetTaskbarGroupId(const nsString& aId) {
200 if (FAILED(SetCurrentProcessExplicitAppUserModelID(aId.get()))) {
201 NS_WARNING(
202 "SetCurrentProcessExplicitAppUserModelID failed for child process.");
205 #endif
207 #if defined(MOZ_SANDBOX)
208 void AddContentSandboxLevelAnnotation() {
209 if (XRE_GetProcessType() == GeckoProcessType_Content) {
210 int level = GetEffectiveContentSandboxLevel();
211 CrashReporter::AnnotateCrashReport(
212 CrashReporter::Annotation::ContentSandboxLevel, level);
213 } else if (XRE_GetProcessType() == GeckoProcessType_GPU) {
214 int level = GetEffectiveGpuSandboxLevel();
215 CrashReporter::AnnotateCrashReport(
216 CrashReporter::Annotation::GpuSandboxLevel, level);
219 #endif /* MOZ_SANDBOX */
221 namespace {
223 int GetDebugChildPauseTime() {
224 auto pauseStr = PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE");
225 if (pauseStr && *pauseStr) {
226 int pause = atoi(pauseStr);
227 if (pause != 1) { // must be !=1 since =1 enables the default pause time
228 #if defined(XP_WIN)
229 pause *= 1000; // convert to ms
230 #endif
231 return pause;
234 #ifdef XP_UNIX
235 return 30; // seconds
236 #elif defined(XP_WIN)
237 return 10000; // milliseconds
238 #else
239 return 0;
240 #endif
243 static bool IsCrashReporterEnabled(const char* aArg) {
244 // on windows and mac, |aArg| is the named pipe on which the server is
245 // listening for requests, or "-" if crash reporting is disabled.
246 #if defined(XP_MACOSX) || defined(XP_WIN)
247 return 0 != strcmp("-", aArg);
248 #else
249 // on POSIX, |aArg| is "true" if crash reporting is enabled, false otherwise
250 return 0 != strcmp("false", aArg);
251 #endif
254 } // namespace
256 nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
257 const XREChildData* aChildData) {
258 NS_ENSURE_ARG_MIN(aArgc, 2);
259 NS_ENSURE_ARG_POINTER(aArgv);
260 NS_ENSURE_ARG_POINTER(aArgv[0]);
261 MOZ_ASSERT(aChildData);
263 NS_SetCurrentThreadName("MainThread");
265 #ifdef MOZ_ASAN_REPORTER
266 // In ASan reporter builds, we need to set ASan's log_path as early as
267 // possible, so it dumps its errors into files there instead of using
268 // the default stderr location. Since this is crucial for ASan reporter
269 // to work at all (and we don't want people to use a non-functional
270 // ASan reporter build), all failures while setting log_path are fatal.
272 // We receive this log_path via the ASAN_REPORTER_PATH environment variable
273 // because there is no other way to generically get the necessary profile
274 // directory in all child types without adding support for that in each
275 // child process type class (at the risk of missing this in a child).
277 // In certain cases (e.g. child startup through xpcshell or gtests), this
278 // code needs to remain disabled, as no ASAN_REPORTER_PATH would be available.
279 if (!PR_GetEnv("MOZ_DISABLE_ASAN_REPORTER") && !PR_GetEnv("MOZ_RUN_GTEST")) {
280 nsCOMPtr<nsIFile> asanReporterPath = GetFileFromEnv("ASAN_REPORTER_PATH");
281 if (!asanReporterPath) {
282 MOZ_CRASH("Child did not receive ASAN_REPORTER_PATH!");
284 setASanReporterPath(asanReporterPath);
286 #endif
288 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
289 // This has to happen before glib thread pools are started.
290 mozilla::SandboxEarlyInit();
291 // This just needs to happen before sandboxing, to initialize the
292 // cached value, but libmozsandbox can't see this symbol.
293 mozilla::GetNumberOfProcessors();
294 #endif
296 #ifdef MOZ_JPROF
297 // Call the code to install our handler
298 setupProfilingStuff();
299 #endif
301 #if defined(XP_WIN)
302 // From the --attach-console support in nsNativeAppSupportWin.cpp, but
303 // here we are a content child process, so we always attempt to attach
304 // to the parent's (ie, the browser's) console.
305 // Try to attach console to the parent process.
306 // It will succeed when the parent process is a command line,
307 // so that stdio will be displayed in it.
308 UseParentConsole();
310 # if defined(MOZ_SANDBOX)
311 if (aChildData->sandboxTargetServices) {
312 SandboxTarget::Instance()->SetTargetServices(
313 aChildData->sandboxTargetServices);
315 # endif
316 #endif
318 // NB: This must be called before profiler_init
319 ScopedLogging logger;
321 mozilla::LogModule::Init(aArgc, aArgv);
323 AUTO_BASE_PROFILER_LABEL("XRE_InitChildProcess (around Gecko Profiler)",
324 OTHER);
325 AUTO_PROFILER_INIT;
326 AUTO_PROFILER_LABEL("XRE_InitChildProcess", OTHER);
328 #ifdef XP_MACOSX
329 gfxPlatformMac::RegisterSupplementalFonts();
330 #endif
332 // Ensure AbstractThread is minimally setup, so async IPC messages
333 // work properly.
334 AbstractThread::InitTLS();
336 // Complete 'task_t' exchange for Mac OS X. This structure has the same size
337 // regardless of architecture so we don't have any cross-arch issues here.
338 #ifdef XP_MACOSX
339 if (aArgc < 1) return NS_ERROR_FAILURE;
341 # if defined(MOZ_SANDBOX)
342 // Save the original number of arguments to pass to the sandbox
343 // setup routine which also uses the crash server argument.
344 int allArgc = aArgc;
345 # endif /* MOZ_SANDBOX */
347 // Acquire the mach bootstrap port name from our command line, and send our
348 // task_t to the parent process.
349 const char* const mach_port_name = aArgv[--aArgc];
351 const int kTimeoutMs = 1000;
353 UniqueMachSendRight task_sender;
354 kern_return_t kr = bootstrap_look_up(bootstrap_port, mach_port_name,
355 getter_Transfers(task_sender));
356 if (kr != KERN_SUCCESS) {
357 NS_WARNING(nsPrintfCString("child bootstrap_look_up failed: %s",
358 mach_error_string(kr))
359 .get());
360 return NS_ERROR_FAILURE;
363 kr = MachSendPortSendRight(task_sender.get(), mach_task_self(),
364 Some(kTimeoutMs));
365 if (kr != KERN_SUCCESS) {
366 NS_WARNING(nsPrintfCString("child MachSendPortSendRight failed: %s",
367 mach_error_string(kr))
368 .get());
369 return NS_ERROR_FAILURE;
372 # if defined(MOZ_SANDBOX)
373 std::string sandboxError;
374 if (!GeckoChildProcessHost::StartMacSandbox(allArgc, aArgv, sandboxError)) {
375 printf_stderr("Sandbox error: %s\n", sandboxError.c_str());
376 MOZ_CRASH("Sandbox initialization failed");
378 # endif /* MOZ_SANDBOX */
380 #endif /* XP_MACOSX */
382 SetupErrorHandling(aArgv[0]);
384 bool exceptionHandlerIsSet = false;
385 if (!CrashReporter::IsDummy()) {
386 #if defined(XP_WIN)
387 if (aArgc < 1) {
388 return NS_ERROR_FAILURE;
390 // Pop the first argument, this is used by the WER runtime exception module
391 // which reads it from the command-line so we can just discard it here.
392 --aArgc;
393 #endif
395 if (aArgc < 1) return NS_ERROR_FAILURE;
396 const char* const crashReporterArg = aArgv[--aArgc];
398 if (IsCrashReporterEnabled(crashReporterArg)) {
399 exceptionHandlerIsSet =
400 CrashReporter::SetRemoteExceptionHandler(crashReporterArg);
401 MOZ_ASSERT(exceptionHandlerIsSet,
402 "Should have been able to set remote exception handler");
404 if (!exceptionHandlerIsSet) {
405 // Bug 684322 will add better visibility into this condition
406 NS_WARNING("Could not setup crash reporting\n");
408 } else {
409 // We might have registered a runtime exception module very early in
410 // process startup to catch early crashes. This is before we process the
411 // crash reporter arg, so unregister here if it turns out the crash
412 // reporter is disabled.
413 CrashReporter::UnregisterRuntimeExceptionModule();
417 gArgv = aArgv;
418 gArgc = aArgc;
420 #ifdef MOZ_X11
421 XInitThreads();
422 #endif
423 #ifdef MOZ_WIDGET_GTK
424 // Setting the name here avoids the need to pass this through to gtk_init().
425 g_set_prgname(aArgv[0]);
426 #endif
428 #ifdef XP_UNIX
429 if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
430 PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
431 # if defined(XP_LINUX) && defined(DEBUG)
432 if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) != 0) {
433 printf_stderr("Could not allow ptrace from any process.\n");
435 # endif
436 printf_stderr(
437 "\n\nCHILDCHILDCHILDCHILD (process type %s)\n debug me @ %d\n\n",
438 XRE_GetProcessTypeString(), base::GetCurrentProcId());
439 sleep(GetDebugChildPauseTime());
441 #elif defined(XP_WIN)
442 if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) {
443 NS_DebugBreak(NS_DEBUG_BREAK,
444 "Invoking NS_DebugBreak() to debug child process", nullptr,
445 __FILE__, __LINE__);
446 } else if (PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
447 printf_stderr(
448 "\n\nCHILDCHILDCHILDCHILD (process type %s)\n debug me @ %lu\n\n",
449 XRE_GetProcessTypeString(), base::GetCurrentProcId());
450 ::Sleep(GetDebugChildPauseTime());
452 #endif
454 #ifdef MOZ_WIDGET_ANDROID
455 // The parent process already did this, but Gecko child processes on
456 // Android aren't descendants of the parent process, so they don't
457 // inherit its rlimits.
458 mozilla::startup::IncreaseDescriptorLimits();
459 #endif
461 // child processes launched by GeckoChildProcessHost get this magic
462 // argument appended to their command lines
463 const char* const parentPIDString = aArgv[aArgc - 1];
464 MOZ_ASSERT(parentPIDString, "NULL parent PID");
465 --aArgc;
467 char* end = 0;
468 base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
469 MOZ_ASSERT(!*end, "invalid parent PID");
471 // They also get the initial message channel ID passed in the same manner.
472 const char* const messageChannelIdString = aArgv[aArgc - 1];
473 MOZ_ASSERT(messageChannelIdString, "NULL MessageChannel Id");
474 --aArgc;
476 nsID messageChannelId{};
477 if (!messageChannelId.Parse(messageChannelIdString)) {
478 return NS_ERROR_FAILURE;
481 #if defined(XP_WIN)
482 // On Win7+, when not running as an MSIX package, register the application
483 // user model id passed in by parent. This ensures windows created by the
484 // container properly group with the parent app on the Win7 taskbar.
485 // MSIX packages explicitly do not support setting the appid from within
486 // the app, as it is set in the package manifest instead.
487 const char* const appModelUserId = aArgv[--aArgc];
488 if (appModelUserId && !mozilla::widget::WinUtils::HasPackageIdentity()) {
489 // '-' implies no support
490 if (*appModelUserId != '-') {
491 nsString appId;
492 CopyASCIItoUTF16(nsDependentCString(appModelUserId), appId);
493 // The version string is encased in quotes
494 appId.Trim("\"");
495 // Set the id
496 SetTaskbarGroupId(appId);
499 #endif
501 base::AtExitManager exitManager;
503 nsresult rv = XRE_InitCommandLine(aArgc, aArgv);
504 if (NS_FAILED(rv)) {
505 return NS_ERROR_FAILURE;
508 MessageLoop::Type uiLoopType;
509 switch (XRE_GetProcessType()) {
510 case GeckoProcessType_Content:
511 case GeckoProcessType_GPU:
512 case GeckoProcessType_IPDLUnitTest:
513 case GeckoProcessType_VR:
514 case GeckoProcessType_RDD:
515 case GeckoProcessType_Socket:
516 case GeckoProcessType_Utility:
517 // Content processes need the XPCOM/chromium frankenventloop
518 uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
519 break;
520 case GeckoProcessType_GMPlugin:
521 gmp::GMPProcessChild::InitStatics(aArgc, aArgv);
522 uiLoopType = gmp::GMPProcessChild::UseXPCOM()
523 ? MessageLoop::TYPE_MOZILLA_CHILD
524 : MessageLoop::TYPE_DEFAULT;
525 break;
526 case GeckoProcessType_RemoteSandboxBroker:
527 uiLoopType = MessageLoop::TYPE_DEFAULT;
528 break;
529 default:
530 uiLoopType = MessageLoop::TYPE_UI;
531 break;
534 #if defined(XP_WIN)
535 # if defined(MOZ_SANDBOX)
536 if (aChildData->sandboxBrokerServices) {
537 SandboxBroker::Initialize(aChildData->sandboxBrokerServices);
538 SandboxBroker::GeckoDependentInitialize();
540 # endif // defined(MOZ_SANDBOX)
543 DebugOnly<bool> result = mozilla::WindowsBCryptInitialization();
544 MOZ_ASSERT(result);
546 #endif // defined(XP_WIN)
549 // This is a lexical scope for the MessageLoop below. We want it
550 // to go out of scope before NS_LogTerm() so that we don't get
551 // spurious warnings about XPCOM objects being destroyed from a
552 // static context.
554 AutoIOInterposer ioInterposerGuard;
556 // Associate this thread with a UI MessageLoop
557 MessageLoop uiMessageLoop(uiLoopType);
559 UniquePtr<ProcessChild> process;
560 switch (XRE_GetProcessType()) {
561 case GeckoProcessType_Default:
562 MOZ_CRASH("This makes no sense");
563 break;
565 case GeckoProcessType_Content:
566 ioInterposerGuard.Init();
567 process = MakeUnique<ContentProcess>(parentPID, messageChannelId);
568 break;
570 case GeckoProcessType_IPDLUnitTest:
571 MOZ_RELEASE_ASSERT(mozilla::_ipdltest::gMakeIPDLUnitTestProcessChild,
572 "xul-gtest not loaded!");
573 process = mozilla::_ipdltest::gMakeIPDLUnitTestProcessChild(
574 parentPID, messageChannelId);
575 break;
577 case GeckoProcessType_GMPlugin:
578 process =
579 MakeUnique<gmp::GMPProcessChild>(parentPID, messageChannelId);
580 break;
582 case GeckoProcessType_GPU:
583 process =
584 MakeUnique<gfx::GPUProcessImpl>(parentPID, messageChannelId);
585 break;
587 case GeckoProcessType_VR:
588 process =
589 MakeUnique<gfx::VRProcessChild>(parentPID, messageChannelId);
590 break;
592 case GeckoProcessType_RDD:
593 process = MakeUnique<RDDProcessImpl>(parentPID, messageChannelId);
594 break;
596 case GeckoProcessType_Socket:
597 ioInterposerGuard.Init();
598 process =
599 MakeUnique<net::SocketProcessImpl>(parentPID, messageChannelId);
600 break;
602 case GeckoProcessType_Utility:
603 process =
604 MakeUnique<ipc::UtilityProcessImpl>(parentPID, messageChannelId);
605 break;
607 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
608 case GeckoProcessType_RemoteSandboxBroker:
609 process = MakeUnique<RemoteSandboxBrokerProcessChild>(
610 parentPID, messageChannelId);
611 break;
612 #endif
614 #if defined(MOZ_ENABLE_FORKSERVER)
615 case GeckoProcessType_ForkServer:
616 MOZ_CRASH("Fork server should not go here");
617 break;
618 #endif
619 default:
620 MOZ_CRASH("Unknown main thread class");
623 if (!process->Init(aArgc, aArgv)) {
624 return NS_ERROR_FAILURE;
627 #if defined(XP_WIN)
628 // Set child processes up such that they will get killed after the
629 // chrome process is killed in cases where the user shuts the system
630 // down or logs off.
631 ::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY);
633 RefPtr<DllServices> dllSvc(DllServices::Get());
634 auto dllSvcDisable =
635 MakeScopeExit([&dllSvc]() { dllSvc->DisableFull(); });
636 #endif
638 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
639 // We need to do this after the process has been initialised, as
640 // InitLoggingIfRequired may need access to prefs.
641 mozilla::sandboxing::InitLoggingIfRequired(
642 aChildData->ProvideLogFunction);
643 #endif
644 if (XRE_GetProcessType() != GeckoProcessType_RemoteSandboxBroker) {
645 // Remote sandbox launcher process doesn't have prerequisites for
646 // these...
647 mozilla::FilePreferences::InitDirectoriesAllowlist();
648 mozilla::FilePreferences::InitPrefs();
651 #if defined(MOZ_SANDBOX)
652 AddContentSandboxLevelAnnotation();
653 #endif
655 // Run the UI event loop on the main thread.
656 uiMessageLoop.MessageLoop::Run();
658 // Allow ProcessChild to clean up after itself before going out of
659 // scope and being deleted
660 process->CleanUp();
661 mozilla::Omnijar::CleanUp();
665 CrashReporter::UnsetRemoteExceptionHandler(exceptionHandlerIsSet);
667 return XRE_DeinitCommandLine();
670 MessageLoop* XRE_GetIOMessageLoop() {
671 if (GetGeckoProcessType() == GeckoProcessType_Default) {
672 return BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
674 return IOThreadChild::message_loop();
677 nsresult XRE_RunAppShell() {
678 nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
679 NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
680 #if defined(XP_MACOSX)
681 if (XRE_UseNativeEventProcessing()) {
682 // In content processes that want XPCOM (and hence want
683 // AppShell), we usually run our hybrid event loop through
684 // MessagePump::Run(), by way of nsBaseAppShell::Run(). The
685 // Cocoa nsAppShell impl, however, implements its own Run()
686 // that's unaware of MessagePump. That's all rather suboptimal,
687 // but oddly enough not a problem... usually.
689 // The problem with this setup comes during startup.
690 // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
691 // service, so we have to init IPC first. But, IPC also
692 // indirectly kinda-depends on XPCOM, because MessagePump
693 // schedules work from off-main threads (e.g. IO thread) by
694 // using NS_DispatchToMainThread(). If the IO thread receives a
695 // Message from the parent before nsThreadManager is
696 // initialized, then DispatchToMainThread() will fail, although
697 // MessagePump will remember the task. This race condition
698 // isn't a problem when appShell->Run() ends up in
699 // MessagePump::Run(), because MessagePump will immediate see it
700 // has work to do. It *is* a problem when we end up in [NSApp
701 // run], because it's not aware that MessagePump has work that
702 // needs to be processed; that was supposed to be signaled by
703 // nsIRunnable(s).
705 // So instead of hacking Cocoa nsAppShell or rewriting the
706 // event-loop system, we compromise here by processing any tasks
707 // that might have been enqueued on MessagePump, *before*
708 // MessagePump::ScheduleWork was able to successfully
709 // DispatchToMainThread().
710 MessageLoop* loop = MessageLoop::current();
711 bool couldNest = loop->NestableTasksAllowed();
713 loop->SetNestableTasksAllowed(true);
714 RefPtr<Runnable> task = new MessageLoop::QuitTask();
715 loop->PostTask(task.forget());
716 loop->Run();
718 loop->SetNestableTasksAllowed(couldNest);
720 #endif // XP_MACOSX
721 return appShell->Run();
724 void XRE_ShutdownChildProcess() {
725 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
727 mozilla::DebugOnly<MessageLoop*> ioLoop = XRE_GetIOMessageLoop();
728 MOZ_ASSERT(!!ioLoop, "Bad shutdown order");
730 // Quit() sets off the following chain of events
731 // (1) UI loop starts quitting
732 // (2) UI loop returns from Run() in XRE_InitChildProcess()
733 // (3) ProcessChild goes out of scope and terminates the IO thread
734 // (4) ProcessChild joins the IO thread
735 // (5) exit()
736 MessageLoop::current()->Quit();
738 #if defined(XP_MACOSX)
739 nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
740 if (appShell) {
741 // On Mac, we might be only above nsAppShell::Run(), not
742 // MessagePump::Run(). See XRE_RunAppShell(). To account for
743 // that case, we fire off an Exit() here. If we were indeed
744 // above MessagePump::Run(), this Exit() is just superfluous.
745 appShell->Exit();
747 #endif // XP_MACOSX
750 namespace {
751 ContentParent* gContentParent; // long-lived, manually refcounted
752 TestShellParent* GetOrCreateTestShellParent() {
753 if (!gContentParent) {
754 // Use a "web" child process by default. File a bug if you don't like
755 // this and you're sure you wouldn't be better off writing a "browser"
756 // chrome mochitest where you can have multiple types of content
757 // processes.
758 RefPtr<ContentParent> parent =
759 ContentParent::GetNewOrUsedBrowserProcess(DEFAULT_REMOTE_TYPE);
760 parent.forget(&gContentParent);
761 } else if (gContentParent->IsShuttingDown()) {
762 return nullptr;
764 TestShellParent* tsp = gContentParent->GetTestShellSingleton();
765 if (!tsp) {
766 tsp = gContentParent->CreateTestShell();
768 return tsp;
771 } // namespace
773 bool XRE_SendTestShellCommand(JSContext* aCx, JSString* aCommand,
774 JS::Value* aCallback) {
775 JS::Rooted<JSString*> cmd(aCx, aCommand);
776 TestShellParent* tsp = GetOrCreateTestShellParent();
777 NS_ENSURE_TRUE(tsp, false);
779 nsAutoJSString command;
780 NS_ENSURE_TRUE(command.init(aCx, cmd), false);
782 if (!aCallback) {
783 return tsp->SendExecuteCommand(command);
786 TestShellCommandParent* callback = static_cast<TestShellCommandParent*>(
787 tsp->SendPTestShellCommandConstructor(command));
788 NS_ENSURE_TRUE(callback, false);
790 NS_ENSURE_TRUE(callback->SetCallback(aCx, *aCallback), false);
792 return true;
795 bool XRE_ShutdownTestShell() {
796 if (!gContentParent) {
797 return true;
799 bool ret = true;
800 if (gContentParent->IsAlive()) {
801 ret = gContentParent->DestroyTestShell(
802 gContentParent->GetTestShellSingleton());
804 NS_RELEASE(gContentParent);
805 return ret;
808 #ifdef MOZ_X11
809 void XRE_InstallX11ErrorHandler() {
810 # ifdef MOZ_WIDGET_GTK
811 InstallGdkErrorHandler();
812 # endif
814 // Ensure our X11 error handler overrides the default GDK error handler such
815 // that errors are ignored by default. GDK will install its own error handler
816 // temporarily when pushing error traps internally as needed. This avoids us
817 // otherwise having to frequently override the error handler merely to trap
818 // errors in multiple places that would otherwise contend with GDK or other
819 // libraries that might also override the handler.
820 InstallX11ErrorHandler();
823 void XRE_CleanupX11ErrorHandler() { CleanupX11ErrorHandler(); }
824 #endif
826 #ifdef MOZ_ENABLE_FORKSERVER
827 int XRE_ForkServer(int* aArgc, char*** aArgv) {
828 return mozilla::ipc::ForkServer::RunForkServer(aArgc, aArgv) ? 1 : 0;
830 #endif