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 "mozilla/ipc/IOThreadChild.h"
9 #include "ContentProcess.h"
10 #include "base/shared_memory.h"
11 #include "mozilla/Preferences.h"
13 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
15 # include "mozilla/Sandbox.h"
16 # include "mozilla/SandboxSettings.h"
19 #include "nsAppRunner.h"
20 #include "mozilla/ipc/BackgroundChild.h"
21 #include "mozilla/ipc/ProcessUtils.h"
22 #include "mozilla/GeckoArgs.h"
23 #include "mozilla/Omnijar.h"
24 #include "nsCategoryManagerUtils.h"
26 using mozilla::ipc::IOThreadChild
;
28 namespace mozilla::dom
{
30 static nsresult
GetGREDir(nsIFile
** aResult
) {
31 nsCOMPtr
<nsIFile
> current
;
32 nsresult rv
= XRE_GetBinaryPath(getter_AddRefs(current
));
33 NS_ENSURE_SUCCESS(rv
, rv
);
36 // Walk out of [subprocess].app/Contents/MacOS to the real GRE dir
42 for (int i
= 0; i
< depth
; ++i
) {
43 nsCOMPtr
<nsIFile
> parent
;
44 rv
= current
->GetParent(getter_AddRefs(parent
));
45 NS_ENSURE_SUCCESS(rv
, rv
);
48 NS_ENSURE_TRUE(current
, NS_ERROR_UNEXPECTED
);
52 rv
= current
->SetNativeLeafName("Resources"_ns
);
53 NS_ENSURE_SUCCESS(rv
, rv
);
56 current
.forget(aResult
);
61 ContentProcess::ContentProcess(ProcessId aParentPid
,
62 const nsID
& aMessageChannelId
)
63 : ProcessChild(aParentPid
, aMessageChannelId
) {
67 ContentProcess::~ContentProcess() { NS_LogTerm(); }
69 bool ContentProcess::Init(int aArgc
, char* aArgv
[]) {
70 Maybe
<uint64_t> childID
= geckoargs::sChildID
.Get(aArgc
, aArgv
);
71 Maybe
<bool> isForBrowser
= Nothing();
72 Maybe
<const char*> parentBuildID
=
73 geckoargs::sParentBuildID
.Get(aArgc
, aArgv
);
74 Maybe
<uint64_t> jsInitHandle
;
75 Maybe
<uint64_t> jsInitLen
= geckoargs::sJsInitLen
.Get(aArgc
, aArgv
);
77 nsCOMPtr
<nsIFile
> appDirArg
;
78 Maybe
<const char*> appDir
= geckoargs::sAppDir
.Get(aArgc
, aArgv
);
79 if (appDir
.isSome()) {
81 nsresult rv
= XRE_GetFileFromPath(*appDir
, getter_AddRefs(appDirArg
));
82 if (NS_FAILED(rv
) || NS_FAILED(appDirArg
->Exists(&flag
)) || !flag
) {
83 NS_WARNING("Invalid application directory passed to content process.");
88 Maybe
<bool> safeMode
= geckoargs::sSafeMode
.Get(aArgc
, aArgv
);
89 if (safeMode
.isSome()) {
90 gSafeMode
= *safeMode
;
93 Maybe
<bool> isForBrowerParam
= geckoargs::sIsForBrowser
.Get(aArgc
, aArgv
);
94 Maybe
<bool> notForBrowserParam
= geckoargs::sNotForBrowser
.Get(aArgc
, aArgv
);
95 if (isForBrowerParam
.isSome()) {
96 isForBrowser
= Some(true);
98 if (notForBrowserParam
.isSome()) {
99 isForBrowser
= Some(false);
102 // command line: [-jsInitHandle handle] -jsInitLen length
104 jsInitHandle
= geckoargs::sJsInitHandle
.Get(aArgc
, aArgv
);
107 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
108 nsCOMPtr
<nsIFile
> profileDir
;
110 Maybe
<const char*> profile
= geckoargs::sProfile
.Get(aArgc
, aArgv
);
111 // xpcshell self-test on macOS will hit this, so check isSome() otherwise
112 // Maybe<> assertions will MOZ_CRASH() us.
113 if (profile
.isSome()) {
114 nsresult rv
= XRE_GetFileFromPath(*profile
, getter_AddRefs(profileDir
));
115 if (NS_FAILED(rv
) || NS_FAILED(profileDir
->Exists(&flag
)) || !flag
) {
116 NS_WARNING("Invalid profile directory passed to content process.");
117 profileDir
= nullptr;
120 NS_WARNING("No profile directory passed to content process.");
122 #endif /* XP_MACOSX && MOZ_SANDBOX */
124 // Did we find all the mandatory flags?
125 if (childID
.isNothing() || isForBrowser
.isNothing() ||
126 parentBuildID
.isNothing()) {
130 if (!ProcessChild::InitPrefs(aArgc
, aArgv
)) {
134 if (!::mozilla::ipc::ImportSharedJSInit(jsInitHandle
.valueOr(0),
135 jsInitLen
.valueOr(0))) {
139 mContent
.Init(TakeInitialEndpoint(), *parentBuildID
, *childID
, *isForBrowser
);
141 nsCOMPtr
<nsIFile
> greDir
;
142 nsresult rv
= GetGREDir(getter_AddRefs(greDir
));
147 nsCOMPtr
<nsIFile
> xpcomAppDir
= appDirArg
? appDirArg
: greDir
;
149 rv
= mDirProvider
.Initialize(xpcomAppDir
, greDir
);
154 // Handle the -greomni/-appomni flags (unless the forkserver already
155 // preloaded the jar(s)).
156 if (!Omnijar::IsInitialized()) {
157 Omnijar::ChildProcessInit(aArgc
, aArgv
);
160 rv
= NS_InitXPCOM(nullptr, xpcomAppDir
, &mDirProvider
);
165 // "app-startup" is the name of both the category and the event
166 NS_CreateServicesFromCategory("app-startup", nullptr, "app-startup", nullptr);
168 #if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
169 mContent
.SetProfileDir(profileDir
);
171 if (IsContentSandboxEnabled()) {
172 AssertMacSandboxEnabled();
175 #endif /* XP_MACOSX && MOZ_SANDBOX */
177 // Do this as early as possible to get the parent process to initialize the
178 // background thread since we'll likely need database information very soon.
179 mozilla::ipc::BackgroundChild::Startup();
180 mozilla::ipc::BackgroundChild::InitContentStarter(&mContent
);
185 // Note: CleanUp() never gets called in non-debug builds because we exit early
186 // in ContentChild::ActorDestroy().
187 void ContentProcess::CleanUp() {
188 mDirProvider
.DoShutdown();
189 NS_ShutdownXPCOM(nullptr);
192 } // namespace mozilla::dom