Bug 1306327 - Move reading application.ini to XRE_main. r=bsmedberg
Reading application.ini involves using nsCOMPtr<nsIFile>, and that can
only happen through the XPCOM glue, which we eventually want to get rid
of.
So, while keeping the command line argument/environment variable
handling in nsBrowserApp, we move the actually parsing of the file to
XRE_main, where things can be handled without the XPCOM glue.
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -171,40 +171,26 @@ int libfuzzer_main(int argc, char **argv
void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc,
LibFuzzerTestingFunc* testingFunc) {
return gBootstrap->XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
}
#endif
static int do_main(int argc, char* argv[], char* envp[])
{
- nsCOMPtr<nsIFile> appini;
- nsresult rv;
-
// Allow firefox.exe to launch XULRunner apps via -app <application.ini>
// Note that -app must be the *first* argument.
const char *appDataFile = getenv("XUL_APP_FILE");
- if (appDataFile && *appDataFile) {
- rv = gBootstrap->XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
- if (NS_FAILED(rv)) {
- Output("Invalid path found: '%s'", appDataFile);
- return 255;
- }
- }
- else if (argc > 1 && IsArg(argv[1], "app")) {
+ if ((!appDataFile || !*appDataFile) &&
+ (argc > 1 && IsArg(argv[1], "app"))) {
if (argc == 2) {
Output("Incorrect number of arguments passed to -app");
return 255;
}
-
- rv = gBootstrap->XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
- if (NS_FAILED(rv)) {
- Output("application.ini path not recognized: '%s'", argv[2]);
- return 255;
- }
+ appDataFile = argv[2];
char appEnv[MAXPATHLEN];
SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
if (putenv(strdup(appEnv))) {
Output("Couldn't set %s.\n", appEnv);
return 255;
}
argv[2] = argv[0];
@@ -219,66 +205,45 @@ static int do_main(int argc, char* argv[
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
shellData.sandboxBrokerServices =
sandboxing::GetInitializedBrokerServices();
#endif
return gBootstrap->XRE_XPCShellMain(--argc, argv, envp, &shellData);
}
- XREAppData appData;
+ BootstrapConfig config;
- if (appini) {
- rv = gBootstrap->XRE_ParseAppData(appini, appData);
- if (NS_FAILED(rv)) {
- Output("Couldn't read application.ini");
- return 255;
- }
-
- appini->GetParent(getter_AddRefs(appData.directory));
+ if (appDataFile && *appDataFile) {
+ config.appData = nullptr;
+ config.appDataPath = appDataFile;
} else {
// no -app flag so we use the compiled-in app data
- appData = sAppData;
-
- nsCOMPtr<nsIFile> exeFile;
- rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
- if (NS_FAILED(rv)) {
- Output("Couldn't find the application directory.\n");
- return 255;
- }
-
- nsCOMPtr<nsIFile> greDir;
- exeFile->GetParent(getter_AddRefs(greDir));
-#ifdef XP_MACOSX
- greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder));
-#endif
- nsCOMPtr<nsIFile> appSubdir;
- greDir->Clone(getter_AddRefs(appSubdir));
- appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
- appData.directory = appSubdir;
+ config.appData = &sAppData;
+ config.appDataPath = kDesktopFolder;
}
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
sandbox::BrokerServices* brokerServices =
sandboxing::GetInitializedBrokerServices();
#if defined(MOZ_CONTENT_SANDBOX)
if (!brokerServices) {
Output("Couldn't initialize the broker services.\n");
return 255;
}
#endif
- appData.sandboxBrokerServices = brokerServices;
+ config.sandboxBrokerServices = brokerServices;
#endif
#ifdef LIBFUZZER
if (getenv("LIBFUZZER"))
gBootstrap->XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
#endif
- return gBootstrap->XRE_main(argc, argv, appData);
+ return gBootstrap->XRE_main(argc, argv, config);
}
static bool
FileExists(const char *path)
{
#ifdef XP_WIN
wchar_t wideDir[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
--- a/toolkit/xre/Bootstrap.cpp
+++ b/toolkit/xre/Bootstrap.cpp
@@ -28,34 +28,26 @@ public:
virtual void NS_LogInit() override {
::NS_LogInit();
}
virtual void NS_LogTerm() override {
::NS_LogTerm();
}
- virtual nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) override {
- return ::XRE_GetFileFromPath(aPath, aResult);
- }
-
- virtual nsresult XRE_ParseAppData(nsIFile* aINIFile, mozilla::XREAppData& aAppData) override {
- return ::XRE_ParseAppData(aINIFile, aAppData);
- }
-
virtual void XRE_TelemetryAccumulate(int aID, uint32_t aSample) override {
::XRE_TelemetryAccumulate(aID, aSample);
}
virtual void XRE_StartupTimelineRecord(int aEvent, mozilla::TimeStamp aWhen) override {
::XRE_StartupTimelineRecord(aEvent, aWhen);
}
- virtual int XRE_main(int argc, char* argv[], const mozilla::XREAppData& aAppData) override {
- return ::XRE_main(argc, argv, aAppData);
+ virtual int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) override {
+ return ::XRE_main(argc, argv, aConfig);
}
virtual void XRE_StopLateWriteChecks() override {
::XRE_StopLateWriteChecks();
}
virtual int XRE_XPCShellMain(int argc, char** argv, char** envp, const XREShellData* aShellData) override {
return ::XRE_XPCShellMain(argc, argv, envp, aShellData);
--- a/toolkit/xre/Bootstrap.h
+++ b/toolkit/xre/Bootstrap.h
@@ -18,18 +18,39 @@
#ifdef MOZ_WIDGET_ANDROID
#include "jni.h"
extern "C" NS_EXPORT
void GeckoStart(JNIEnv* aEnv, char** argv, int argc, const mozilla::StaticXREAppData& aAppData);
#endif
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+namespace sandbox {
+class BrokerServices;
+}
+#endif
+
namespace mozilla {
+struct BootstrapConfig
+{
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+ /* Chromium sandbox BrokerServices. */
+ sandbox::BrokerServices* sandboxBrokerServices;
+#endif
+ /* Pointer to static XRE AppData from application.ini.h */
+ const StaticXREAppData* appData;
+ /* When the pointer above is null, points to the (string) path of an
+ * application.ini file to open and parse.
+ * When the pointer above is non-null, may indicate the directory where
+ * application files are, relative to the XRE. */
+ const char* appDataPath;
+};
+
/**
* This class is virtual abstract so that using it does not require linking
* any symbols. The singleton instance of this class is obtained from the
* exported method XRE_GetBootstrap.
*/
class Bootstrap
{
protected:
@@ -59,25 +80,21 @@ protected:
public:
typedef mozilla::UniquePtr<Bootstrap, BootstrapDelete> UniquePtr;
virtual void NS_LogInit() = 0;
virtual void NS_LogTerm() = 0;
- virtual nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) = 0;
-
- virtual nsresult XRE_ParseAppData(nsIFile* aINIFile, mozilla::XREAppData& aAppData) = 0;
-
virtual void XRE_TelemetryAccumulate(int aID, uint32_t aSample) = 0;
virtual void XRE_StartupTimelineRecord(int aEvent, mozilla::TimeStamp aWhen) = 0;
- virtual int XRE_main(int argc, char* argv[], const mozilla::XREAppData& aAppData) = 0;
+ virtual int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) = 0;
virtual void XRE_StopLateWriteChecks() = 0;
virtual int XRE_XPCShellMain(int argc, char** argv, char** envp, const XREShellData* aShellData) = 0;
virtual GeckoProcessType XRE_GetProcessType() = 0;
virtual void XRE_SetProcessType(const char* aProcessTypeString) = 0;
--- a/toolkit/xre/nsAndroidStartup.cpp
+++ b/toolkit/xre/nsAndroidStartup.cpp
@@ -13,16 +13,17 @@
#include "mozilla/jni/Utils.h"
#include "nsTArray.h"
#include "nsString.h"
#include "nsIFile.h"
#include "nsAppRunner.h"
#include "APKOpen.h"
#include "nsExceptionHandler.h"
+#include "mozilla/Bootstrap.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, MOZ_APP_NAME, args)
using namespace mozilla;
extern "C" NS_EXPORT void
GeckoStart(JNIEnv* env, char** argv, int argc, const StaticXREAppData& aAppData)
{
@@ -37,16 +38,17 @@ GeckoStart(JNIEnv* env, char** argv, int
}
#endif
if (!argv) {
LOG("Failed to get arguments for GeckoStart\n");
return;
}
- XREAppData appData;
- appData = aAppData;
+ BootstrapConfig config;
+ config.appData = &aAppData;
+ config.appDataPath = nullptr;
- int result = XRE_main(argc, argv, appData);
+ int result = XRE_main(argc, argv, config);
if (result)
LOG("XRE_main returned %d", result);
}
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -16,16 +16,17 @@
#include "mozilla/Poison.h"
#include "mozilla/Preferences.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "nsAppRunner.h"
#include "mozilla/XREAppData.h"
+#include "mozilla/Bootstrap.h"
#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
#include "nsUpdateDriver.h"
#endif
#include "ProfileReset.h"
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
#include "EventTracer.h"
#endif
@@ -3019,17 +3020,17 @@ public:
#endif
{};
~XREMain() {
mScopedXPCOM = nullptr;
mAppData = nullptr;
}
- int XRE_main(int argc, char* argv[], const XREAppData& aAppData);
+ int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig);
int XRE_mainInit(bool* aExitFlag);
int XRE_mainStartup(bool* aExitFlag);
nsresult XRE_mainRun();
nsCOMPtr<nsINativeAppSupport> mNativeApp;
nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
nsCOMPtr<nsIFile> mProfD;
nsCOMPtr<nsIFile> mProfLD;
@@ -3179,41 +3180,16 @@ XREMain::XRE_mainInit(bool* aExitFlag)
if (!mAppData->buildID) {
Output(true, "Error: App:BuildID not specified in application.ini\n");
return 1;
}
// XXX Originally ScopedLogging was here? Now it's in XRE_main above
// XRE_mainInit.
- if (!mAppData->xreDirectory) {
- nsCOMPtr<nsIFile> lf;
- rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
- if (NS_FAILED(rv))
- return 2;
-
- nsCOMPtr<nsIFile> greDir;
- rv = lf->GetParent(getter_AddRefs(greDir));
- if (NS_FAILED(rv))
- return 2;
-
-#ifdef XP_MACOSX
- nsCOMPtr<nsIFile> parent;
- greDir->GetParent(getter_AddRefs(parent));
- greDir = parent.forget();
- greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
-#endif
-
- mAppData->xreDirectory = greDir;
- }
-
- if (!mAppData->directory) {
- mAppData->directory = mAppData->xreDirectory;
- }
-
if (!mAppData->minVersion) {
Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
return 1;
}
if (!mAppData->maxVersion) {
// If no maxVersion is specified, we assume the app is only compatible
// with the initial preview release. Do not increment this number ever!
@@ -4521,17 +4497,17 @@ XRE_CreateStatsObject()
}
/*
* XRE_main - A class based main entry point used by most platforms.
* Note that on OSX, aAppData->xreDirectory will point to
* .app/Contents/Resources.
*/
int
-XREMain::XRE_main(int argc, char* argv[], const XREAppData& aAppData)
+XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig)
{
ScopedLogging log;
// NB: this must happen after the creation of |ScopedLogging log| since
// ScopedLogging::ScopedLogging calls NS_LogInit, and
// XRE_CreateStatsObject calls Telemetry::CreateStatisticsRecorder,
// and NS_LogInit must be called before Telemetry::CreateStatisticsRecorder.
// NS_LogInit must be called before Telemetry::CreateStatisticsRecorder
@@ -4550,30 +4526,84 @@ XREMain::XRE_main(int argc, char* argv[]
PROFILER_LABEL("Startup", "XRE_Main",
js::ProfileEntry::Category::OTHER);
nsresult rv = NS_OK;
gArgc = argc;
gArgv = argv;
- mAppData = MakeUnique<XREAppData>(aAppData);
+ if (aConfig.appData) {
+ mAppData = MakeUnique<XREAppData>(*aConfig.appData);
+ } else {
+ MOZ_RELEASE_ASSERT(aConfig.appDataPath);
+ nsCOMPtr<nsIFile> appini;
+ rv = XRE_GetFileFromPath(aConfig.appDataPath, getter_AddRefs(appini));
+ if (NS_FAILED(rv)) {
+ Output(true, "Error: unrecognized path: %s\n", aConfig.appDataPath);
+ return 1;
+ }
+
+ mAppData = MakeUnique<XREAppData>();
+ rv = XRE_ParseAppData(appini, *mAppData);
+ if (NS_FAILED(rv)) {
+ Output(true, "Couldn't read application.ini");
+ return 1;
+ }
+
+ appini->GetParent(getter_AddRefs(mAppData->directory));
+ }
+
if (!mAppData->remotingName) {
mAppData->remotingName = mAppData->name;
}
// used throughout this file
gAppData = mAppData.get();
nsCOMPtr<nsIFile> binFile;
rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile));
NS_ENSURE_SUCCESS(rv, 1);
rv = binFile->GetPath(gAbsoluteArgv0Path);
NS_ENSURE_SUCCESS(rv, 1);
+ if (!mAppData->xreDirectory) {
+ nsCOMPtr<nsIFile> lf;
+ rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
+ if (NS_FAILED(rv))
+ return 2;
+
+ nsCOMPtr<nsIFile> greDir;
+ rv = lf->GetParent(getter_AddRefs(greDir));
+ if (NS_FAILED(rv))
+ return 2;
+
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIFile> parent;
+ greDir->GetParent(getter_AddRefs(parent));
+ greDir = parent.forget();
+ greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
+#endif
+
+ mAppData->xreDirectory = greDir;
+ }
+
+ if (aConfig.appData && aConfig.appDataPath) {
+ mAppData->xreDirectory->Clone(getter_AddRefs(mAppData->directory));
+ mAppData->directory->AppendNative(nsDependentCString(aConfig.appDataPath));
+ }
+
+ if (!mAppData->directory) {
+ mAppData->directory = mAppData->xreDirectory;
+ }
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+ mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
+#endif
+
mozilla::IOInterposerInit ioInterposerGuard;
#if defined(XP_WIN)
// Some COM settings are global to the process and must be set before any non-
// trivial COM is run in the application. Since these settings may affect
// stability, we should instantiate COM ASAP so that we can ensure that these
// global settings are configured before anything can interfere.
mozilla::mscom::MainThreadRuntime msCOMRuntime;
@@ -4687,21 +4717,21 @@ XREMain::XRE_main(int argc, char* argv[]
}
void
XRE_StopLateWriteChecks(void) {
mozilla::StopLateWriteChecks();
}
int
-XRE_main(int argc, char* argv[], const XREAppData& aAppData)
+XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig)
{
XREMain main;
- int result = main.XRE_main(argc, argv, aAppData);
+ int result = main.XRE_main(argc, argv, aConfig);
mozilla::RecordShutdownEndTimeStamp();
return result;
}
nsresult
XRE_InitCommandLine(int aArgc, char* aArgv[])
{
nsresult rv = NS_OK;
--- a/xpcom/build/XREAppData.h
+++ b/xpcom/build/XREAppData.h
@@ -31,16 +31,21 @@ class XREAppData
public:
XREAppData() { }
~XREAppData() { }
XREAppData(const XREAppData& aOther)
{
*this = aOther;
}
+ explicit XREAppData(const StaticXREAppData& aOther)
+ {
+ *this = aOther;
+ }
+
XREAppData& operator=(const StaticXREAppData& aOther);
XREAppData& operator=(const XREAppData& aOther);
XREAppData& operator=(XREAppData&& aOther) = default;
struct NSFreePolicy
{
void operator()(const void* ptr) {
NS_Free(const_cast<void*>(ptr));
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -189,25 +189,28 @@
/**
* Begin an XUL application. Does not return until the user exits the
* application.
*
* @param argc/argv Command-line parameters to pass to the application. On
* Windows, these should be in UTF8. On unix-like platforms
* these are in the "native" character set.
*
- * @param aAppData Information about the application to be run.
+ * @param aConfig Information about the application to be run.
*
* @return A native result code suitable for returning from main().
*
* @note If the binary is linked against the standalone XPCOM glue,
* XPCOMGlueStartup() should be called before this method.
*/
+namespace mozilla {
+struct BootstrapConfig;
+}
XRE_API(int,
- XRE_main, (int argc, char* argv[], const mozilla::XREAppData& aAppData))
+ XRE_main, (int argc, char* argv[], const mozilla::BootstrapConfig& aConfig))
/**
* Given a path relative to the current working directory (or an absolute
* path), return an appropriate nsIFile object.
*
* @note Pass UTF8 strings on Windows... native charset on other platforms.
*/
XRE_API(nsresult,