Bug 1799470 - Merge old embedding logic into ContentChild r=nika

Differential Revision: https://phabricator.services.mozilla.com/D164596
This commit is contained in:
Chris Martin 2022-12-15 03:06:22 +00:00
parent 9f2950c821
commit cfcb9fcb81
7 changed files with 76 additions and 219 deletions

View File

@ -30,6 +30,7 @@
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/ProcessUtils.h"
#include "mozilla/GeckoArgs.h"
#include "nsAppStartupNotifier.h"
using mozilla::ipc::IOThreadChild;
@ -85,6 +86,45 @@ static void SetUpSandboxEnvironment() {
}
#endif
static nsresult GetGREDir(nsIFile** aResult) {
nsCOMPtr<nsIFile> current;
nsresult rv = XRE_GetBinaryPath(getter_AddRefs(current));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef OS_MACOSX
// Walk out of [subprocess].app/Contents/MacOS to the real GRE dir
const int depth = 4;
#else
const int depth = 1;
#endif
for (int i = 0; i < depth; ++i) {
nsCOMPtr<nsIFile> parent;
rv = current->GetParent(getter_AddRefs(parent));
NS_ENSURE_SUCCESS(rv, rv);
current = parent;
NS_ENSURE_TRUE(current, NS_ERROR_UNEXPECTED);
}
#ifdef OS_MACOSX
rv = current->SetNativeLeafName("Resources"_ns);
NS_ENSURE_SUCCESS(rv, rv);
#endif
current.forget(aResult);
return NS_OK;
}
ContentProcess::ContentProcess(ProcessId aParentPid,
const nsID& aMessageChannelId)
: ProcessChild(aParentPid, aMessageChannelId) {
NS_LogInit();
}
ContentProcess::~ContentProcess() { NS_LogTerm(); }
bool ContentProcess::Init(int aArgc, char* aArgv[]) {
Maybe<uint64_t> childID = geckoargs::sChildID.Get(aArgc, aArgv);
Maybe<bool> isForBrowser = Nothing();
@ -92,13 +132,16 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
geckoargs::sParentBuildID.Get(aArgc, aArgv);
Maybe<uint64_t> jsInitHandle;
Maybe<uint64_t> jsInitLen = geckoargs::sJsInitLen.Get(aArgc, aArgv);
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
nsCOMPtr<nsIFile> profileDir;
#endif
nsCOMPtr<nsIFile> appDirArg;
Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv);
if (appDir.isSome()) {
mXREEmbed.SetAppDir(nsDependentCString(*appDir));
bool flag;
nsresult rv = XRE_GetFileFromPath(*appDir, getter_AddRefs(appDirArg));
if (NS_FAILED(rv) || NS_FAILED(appDirArg->Exists(&flag)) || !flag) {
NS_WARNING("Invalid application directory passed to content process.");
appDirArg = nullptr;
}
}
Maybe<bool> safeMode = geckoargs::sSafeMode.Get(aArgc, aArgv);
@ -121,6 +164,7 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
#endif
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
nsCOMPtr<nsIFile> profileDir;
bool flag;
Maybe<const char*> profile = geckoargs::sProfile.Get(aArgc, aArgv);
// xpcshell self-test on macOS will hit this, so check isSome() otherwise
@ -153,7 +197,26 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
mContent.Init(TakeInitialEndpoint(), *parentBuildID, *childID, *isForBrowser);
mXREEmbed.Start();
nsCOMPtr<nsIFile> greDir;
nsresult rv = GetGREDir(getter_AddRefs(greDir));
if (NS_FAILED(rv)) {
return false;
}
nsCOMPtr<nsIFile> xpcomAppDir = appDirArg ? appDirArg : greDir;
rv = mDirProvider.Initialize(xpcomAppDir, greDir, nullptr);
if (NS_FAILED(rv)) {
return false;
}
rv = NS_InitXPCOM(nullptr, xpcomAppDir, &mDirProvider);
if (NS_FAILED(rv)) {
return false;
}
nsAppStartupNotifier::NotifyObservers(APPSTARTUP_CATEGORY);
#if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
mContent.SetProfileDir(profileDir);
# if defined(DEBUG)
@ -177,6 +240,9 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
// Note: CleanUp() never gets called in non-debug builds because we exit early
// in ContentChild::ActorDestroy().
void ContentProcess::CleanUp() { mXREEmbed.Stop(); }
void ContentProcess::CleanUp() {
mDirProvider.DoShutdown();
NS_ShutdownXPCOM(nullptr);
}
} // namespace mozilla::dom

View File

@ -8,8 +8,8 @@
#define dom_tabs_ContentThread_h 1
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/ipc/ScopedXREEmbed.h"
#include "ContentChild.h"
#include "nsXREDirProvider.h"
#if defined(XP_WIN)
# include "mozilla/mscom/ProcessRuntime.h"
@ -25,9 +25,8 @@ class ContentProcess : public mozilla::ipc::ProcessChild {
using ProcessChild = mozilla::ipc::ProcessChild;
public:
using ProcessChild::ProcessChild;
~ContentProcess() = default;
ContentProcess(ProcessId aParentPid, const nsID& aMessageChannelId);
~ContentProcess();
virtual bool Init(int aArgc, char* aArgv[]) override;
virtual void CleanUp() override;
@ -39,7 +38,7 @@ class ContentProcess : public mozilla::ipc::ProcessChild {
// constructing mXREEmbed.
mozilla::mscom::ProcessRuntime mCOMRuntime;
#endif
mozilla::ipc::ScopedXREEmbed mXREEmbed;
nsXREDirProvider mDirProvider;
};
} // namespace mozilla::dom

View File

@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScopedXREEmbed.h"
#include "base/command_line.h"
#include "base/string_util.h"
#include "nsIFile.h"
#include "nsCOMPtr.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
using mozilla::ipc::ScopedXREEmbed;
ScopedXREEmbed::ScopedXREEmbed() : mShouldKillEmbedding(false) { NS_LogInit(); }
ScopedXREEmbed::~ScopedXREEmbed() {
Stop();
NS_LogTerm();
}
void ScopedXREEmbed::SetAppDir(const nsACString& aPath) {
bool flag;
nsresult rv =
XRE_GetFileFromPath(aPath.BeginReading(), getter_AddRefs(mAppDir));
if (NS_FAILED(rv) || NS_FAILED(mAppDir->Exists(&flag)) || !flag) {
NS_WARNING("Invalid application directory passed to content process.");
mAppDir = nullptr;
}
}
void ScopedXREEmbed::Start() {
nsCOMPtr<nsIFile> localFile;
nsresult rv = XRE_GetBinaryPath(getter_AddRefs(localFile));
if (NS_FAILED(rv)) return;
nsCOMPtr<nsIFile> parent;
rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return;
localFile = parent;
NS_ENSURE_TRUE_VOID(localFile);
#ifdef OS_MACOSX
if (XRE_IsContentProcess()) {
// We're an XPCOM-using subprocess. Walk out of
// [subprocess].app/Contents/MacOS to the real GRE dir.
rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return;
localFile = parent;
NS_ENSURE_TRUE_VOID(localFile);
rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return;
localFile = parent;
NS_ENSURE_TRUE_VOID(localFile);
rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return;
localFile = parent;
NS_ENSURE_TRUE_VOID(localFile);
rv = localFile->SetNativeLeafName("Resources"_ns);
if (NS_FAILED(rv)) {
return;
}
}
#endif
if (mAppDir)
rv = XRE_InitEmbedding2(localFile, mAppDir, nullptr);
else
rv = XRE_InitEmbedding2(localFile, localFile, nullptr);
if (NS_FAILED(rv)) return;
mShouldKillEmbedding = true;
}
void ScopedXREEmbed::Stop() {
if (mShouldKillEmbedding) {
XRE_TermEmbedding();
mShouldKillEmbedding = false;
}
}

View File

@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __IPC_GLUE_SCOPEDXREEMBED_H__
#define __IPC_GLUE_SCOPEDXREEMBED_H__
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIFile.h"
namespace mozilla {
namespace ipc {
class ScopedXREEmbed {
public:
ScopedXREEmbed();
~ScopedXREEmbed();
void Start();
void Stop();
void SetAppDir(const nsACString& aPath);
private:
bool mShouldKillEmbedding;
nsCOMPtr<nsIFile> mAppDir;
};
} /* namespace ipc */
} /* namespace mozilla */
#endif /* __IPC_GLUE_SCOPEDXREEMBED_H__ */

View File

@ -54,7 +54,6 @@ EXPORTS.mozilla.ipc += [
"RandomAccessStreamUtils.h",
"RawShmem.h",
"ScopedPort.h",
"ScopedXREEmbed.h",
"SerializedStructuredCloneBuffer.h",
"SharedMemory.h",
"SharedMemoryBasic.h",
@ -183,7 +182,6 @@ UNIFIED_SOURCES += [
"RandomAccessStreamUtils.cpp",
"RawShmem.cpp",
"ScopedPort.cpp",
"ScopedXREEmbed.cpp",
"SerializedStructuredCloneBuffer.cpp",
"SharedMemory.cpp",
"Shmem.cpp",

View File

@ -141,7 +141,6 @@ using mozilla::ipc::BrowserProcessSubThread;
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::ipc::IOThreadChild;
using mozilla::ipc::ProcessChild;
using mozilla::ipc::ScopedXREEmbed;
using mozilla::dom::ContentParent;
using mozilla::dom::ContentProcess;
@ -159,56 +158,6 @@ UniquePtr<mozilla::ipc::ProcessChild> (*gMakeIPDLUnitTestProcessChild)(
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static int32_t sInitCounter;
nsresult XRE_InitEmbedding2(nsIFile* aLibXULDirectory, nsIFile* aAppDirectory,
nsIDirectoryServiceProvider* aAppDirProvider) {
// Initialize some globals to make nsXREDirProvider happy
static char* kNullCommandLine[] = {nullptr};
gArgv = kNullCommandLine;
gArgc = 0;
NS_ENSURE_ARG(aLibXULDirectory);
if (++sInitCounter > 1) // XXXbsmedberg is this really the right solution?
return NS_OK;
if (!aAppDirectory) aAppDirectory = aLibXULDirectory;
nsresult rv;
new nsXREDirProvider; // This sets gDirServiceProvider
if (!gDirServiceProvider) return NS_ERROR_OUT_OF_MEMORY;
rv = gDirServiceProvider->Initialize(aAppDirectory, aLibXULDirectory,
aAppDirProvider);
if (NS_FAILED(rv)) return rv;
rv = NS_InitXPCOM(nullptr, aAppDirectory, gDirServiceProvider);
if (NS_FAILED(rv)) return rv;
// We do not need to autoregister components here. The CheckCompatibility()
// bits in nsAppRunner.cpp check for an invalidation flag in
// compatibility.ini.
// If the app wants to autoregister every time (for instance, if it's debug),
// it can do so after we return from this function.
nsAppStartupNotifier::NotifyObservers(APPSTARTUP_CATEGORY);
return NS_OK;
}
void XRE_TermEmbedding() {
if (--sInitCounter != 0) return;
NS_ASSERTION(gDirServiceProvider,
"XRE_TermEmbedding without XRE_InitEmbedding");
gDirServiceProvider->DoShutdown();
NS_ShutdownXPCOM(nullptr);
delete gDirServiceProvider;
}
const char* XRE_GeckoProcessTypeToString(GeckoProcessType aProcessType) {
switch (aProcessType) {
#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \

View File

@ -219,29 +219,6 @@ nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult);
*/
nsresult XRE_GetBinaryPath(nsIFile** aResult);
/**
* Initialize libXUL for embedding purposes.
*
* @param aLibXULDirectory The directory in which the libXUL shared library
* was found.
* @param aAppDirectory The directory in which the application components
* and resources can be found. This will map to
* the NS_OS_CURRENT_PROCESS_DIR directory service
* key.
* @param aAppDirProvider A directory provider for the application. This
* provider will be aggregated by a libxul provider
* which will provide the base required GRE keys.
*
* @note This function must be called from the "main" thread.
*
* @note At the present time, this function may only be called once in
* a given process. Use XRE_TermEmbedding to clean up and free
* resources allocated by XRE_InitEmbedding.
*/
nsresult XRE_InitEmbedding2(nsIFile* aLibXULDirectory, nsIFile* aAppDirectory,
nsIDirectoryServiceProvider* aAppDirProvider);
/**
* Register XPCOM components found in an array of files/directories.
* This method may be called at any time before or after XRE_main or
@ -288,11 +265,6 @@ nsresult XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation);
*/
nsresult XRE_AddJarManifestLocation(NSLocationType aType, nsIFile* aLocation);
/**
* Terminate embedding started with XRE_InitEmbedding or XRE_InitEmbedding2
*/
void XRE_TermEmbedding();
/**
* Parse an INI file (application.ini or override.ini) into an existing
* nsXREAppData structure.