Bug 1306327 - Move reading application.ini to XRE_main. r=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 10 Jan 2017 16:43:23 +0900
changeset 377106 908c2d41eeaafc34697261866d36206bfe896e4b
parent 377105 517720b458ce9f10734b8fbf6943ca1a47066f42
child 377107 6b46b8d889dfcf921c7823655cf1b92c55451c2f
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1306327
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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.
browser/app/nsBrowserApp.cpp
toolkit/xre/Bootstrap.cpp
toolkit/xre/Bootstrap.h
toolkit/xre/nsAndroidStartup.cpp
toolkit/xre/nsAppRunner.cpp
xpcom/build/XREAppData.h
xpcom/build/nsXULAppAPI.h
--- 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,