ContentProcess.cpp (6467B)
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/. */ 6 7 #include "ContentProcess.h" 8 9 #include "mozilla/Preferences.h" 10 11 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 12 # include <stdlib.h> 13 14 # include "mozilla/Sandbox.h" 15 # include "mozilla/SandboxSettings.h" 16 #endif 17 18 #include "mozilla/GeckoArgs.h" 19 #include "mozilla/Omnijar.h" 20 #include "mozilla/ipc/BackgroundChild.h" 21 #include "mozilla/ipc/ProcessUtils.h" 22 #include "nsAppRunner.h" 23 #include "nsCategoryManagerUtils.h" 24 25 namespace mozilla::dom { 26 27 static nsresult GetGREDir(nsIFile** aResult) { 28 nsCOMPtr<nsIFile> current; 29 nsresult rv = XRE_GetBinaryPath(getter_AddRefs(current)); 30 NS_ENSURE_SUCCESS(rv, rv); 31 32 #if defined(XP_MACOSX) 33 // Walk out of [subprocess].app/Contents/MacOS to the real GRE dir 34 const int depth = 4; 35 #elif defined(XP_IOS) 36 // Walk out of Extensions/[subprocess].appex to the real GRE dir 37 const int depth = 3; 38 #else 39 const int depth = 1; 40 #endif 41 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); 46 47 current = parent; 48 NS_ENSURE_TRUE(current, NS_ERROR_UNEXPECTED); 49 } 50 51 #if defined(XP_MACOSX) 52 rv = current->SetNativeLeafName("Resources"_ns); 53 NS_ENSURE_SUCCESS(rv, rv); 54 #elif defined(XP_IOS) 55 // FIXME: Consider looking up the GeckoView.framework bundle directly, rather 56 // than deriving it from XRE_GetBinaryPath on iOS. This may be more resilient 57 // especially once we properly bundle XUL into a separate framework or support 58 // multiple embedders. 59 rv = current->AppendNative("Frameworks"_ns); 60 NS_ENSURE_SUCCESS(rv, rv); 61 rv = current->AppendNative("GeckoView.framework"_ns); 62 NS_ENSURE_SUCCESS(rv, rv); 63 rv = current->AppendNative("Frameworks"_ns); 64 NS_ENSURE_SUCCESS(rv, rv); 65 #endif 66 67 current.forget(aResult); 68 69 return NS_OK; 70 } 71 72 ContentProcess::ContentProcess(IPC::Channel::ChannelHandle aClientChannel, 73 ProcessId aParentPid, 74 const nsID& aMessageChannelId) 75 : ProcessChild(std::move(aClientChannel), aParentPid, aMessageChannelId) { 76 NS_LogInit(); 77 } 78 79 ContentProcess::~ContentProcess() { NS_LogTerm(); } 80 81 bool ContentProcess::Init(int aArgc, char* aArgv[]) { 82 InfallibleInit(aArgc, aArgv); 83 return true; 84 } 85 86 void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) { 87 Maybe<bool> isForBrowser = Nothing(); 88 Maybe<const char*> parentBuildID = 89 geckoargs::sParentBuildID.Get(aArgc, aArgv); 90 91 // command line: -jsInitHandle handle 92 Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> jsInitHandle = 93 geckoargs::sJsInitHandle.Get(aArgc, aArgv); 94 95 nsCOMPtr<nsIFile> appDirArg; 96 Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv); 97 if (appDir.isSome()) { 98 bool flag; 99 nsresult rv = XRE_GetFileFromPath(*appDir, getter_AddRefs(appDirArg)); 100 if (NS_FAILED(rv) || NS_FAILED(appDirArg->Exists(&flag)) || !flag) { 101 NS_WARNING("Invalid application directory passed to content process."); 102 appDirArg = nullptr; 103 } 104 } 105 106 Maybe<bool> safeMode = geckoargs::sSafeMode.Get(aArgc, aArgv); 107 if (safeMode.isSome()) { 108 gSafeMode = *safeMode; 109 } 110 111 Maybe<bool> isForBrowerParam = geckoargs::sIsForBrowser.Get(aArgc, aArgv); 112 Maybe<bool> notForBrowserParam = geckoargs::sNotForBrowser.Get(aArgc, aArgv); 113 if (isForBrowerParam.isSome()) { 114 isForBrowser = Some(true); 115 } 116 if (notForBrowserParam.isSome()) { 117 isForBrowser = Some(false); 118 } 119 120 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 121 nsCOMPtr<nsIFile> profileDir; 122 bool flag; 123 Maybe<const char*> profile = geckoargs::sProfile.Get(aArgc, aArgv); 124 // xpcshell self-test on macOS will hit this, so check isSome() otherwise 125 // Maybe<> assertions will MOZ_CRASH() us. 126 if (profile.isSome()) { 127 nsresult rv = XRE_GetFileFromPath(*profile, getter_AddRefs(profileDir)); 128 if (NS_FAILED(rv) || NS_FAILED(profileDir->Exists(&flag)) || !flag) { 129 NS_WARNING("Invalid profile directory passed to content process."); 130 profileDir = nullptr; 131 } 132 } else { 133 NS_WARNING("No profile directory passed to content process."); 134 } 135 #endif /* XP_MACOSX && MOZ_SANDBOX */ 136 137 // Did we find all the mandatory flags? 138 if (isForBrowser.isNothing()) { 139 MOZ_CRASH("isForBrowser flag missing"); 140 } 141 if (parentBuildID.isNothing()) { 142 MOZ_CRASH("parentBuildID flag missing"); 143 } 144 145 if (!ProcessChild::InitPrefs(aArgc, aArgv)) { 146 MOZ_CRASH("InitPrefs failed"); 147 } 148 149 if (jsInitHandle && 150 !::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract())) { 151 MOZ_CRASH("ImportSharedJSInit failed"); 152 } 153 154 mContent.Init(TakeInitialEndpoint(), *parentBuildID, *isForBrowser); 155 156 nsCOMPtr<nsIFile> greDir; 157 nsresult rv = GetGREDir(getter_AddRefs(greDir)); 158 if (NS_FAILED(rv)) { 159 MOZ_CRASH("GetGREDir failed"); 160 } 161 162 nsCOMPtr<nsIFile> xpcomAppDir = appDirArg ? appDirArg : greDir; 163 164 rv = mDirProvider.Initialize(xpcomAppDir, greDir); 165 if (NS_FAILED(rv)) { 166 MOZ_CRASH("mDirProvider.Initialize failed"); 167 } 168 169 // Handle the -greomni/-appomni flags (unless the forkserver already 170 // preloaded the jar(s)). 171 if (!Omnijar::IsInitialized()) { 172 Omnijar::ChildProcessInit(aArgc, aArgv); 173 } 174 175 rv = NS_InitXPCOM(nullptr, xpcomAppDir, &mDirProvider); 176 if (NS_FAILED(rv)) { 177 MOZ_CRASH("NS_InitXPCOM failed"); 178 } 179 180 // "app-startup" is the name of both the category and the event 181 NS_CreateServicesFromCategory("app-startup", nullptr, "app-startup", nullptr); 182 183 #if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX) 184 mContent.SetProfileDir(profileDir); 185 # if defined(DEBUG) 186 if (IsContentSandboxEnabled()) { 187 AssertMacSandboxEnabled(); 188 } 189 # endif /* DEBUG */ 190 #endif /* XP_MACOSX && MOZ_SANDBOX */ 191 192 // Do this as early as possible to get the parent process to initialize the 193 // background thread since we'll likely need database information very soon. 194 mozilla::ipc::BackgroundChild::Startup(); 195 mozilla::ipc::BackgroundChild::InitContentStarter(&mContent); 196 } 197 198 // Note: CleanUp() never gets called in non-debug builds because we exit early 199 // in ContentChild::ActorDestroy(). 200 void ContentProcess::CleanUp() { 201 mDirProvider.DoShutdown(); 202 NS_ShutdownXPCOM(nullptr); 203 } 204 205 } // namespace mozilla::dom