Bug 1306327 - Add a new XRE Bootstrap API that wraps all the XRE methods. r=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 15 Dec 2016 16:46:18 +0900
changeset 377103 a7dac14f91df3f94ed809465f80833c310a99f0c
parent 377102 be999ce0e4fe0354bd2737504cca7fccf206f94e
child 377104 2a0edcbaebeeae1cd4cf1be3b0db127fa3bdd01f
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 - Add a new XRE Bootstrap API that wraps all the XRE methods. r=bsmedberg This is the first step towards changing how nsBrowserApp and other current XPCOM glue users start up Gecko. The goal here is to expose the same API via a single object with a VTable instead of the current XPCOM glue machinery. Instead of creating an entirely new API and changing everything to use it, we go forward with smaller steps for a more comprehensible transition.
toolkit/xre/Bootstrap.cpp
toolkit/xre/Bootstrap.h
toolkit/xre/moz.build
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/glue/standalone/nsXPCOMGlue.h
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/Bootstrap.cpp
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "mozilla/Bootstrap.h"
+#include "nsXPCOM.h"
+
+namespace mozilla {
+
+class BootstrapImpl final : public Bootstrap
+{
+protected:
+  virtual void Dispose() override
+  {
+    delete this;
+  }
+
+public:
+  BootstrapImpl()
+  {
+  }
+
+  ~BootstrapImpl()
+  {
+  }
+
+  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 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);
+  }
+
+  virtual GeckoProcessType XRE_GetProcessType() override {
+    return ::XRE_GetProcessType();
+  }
+
+  virtual void XRE_SetProcessType(const char* aProcessTypeString) override {
+    ::XRE_SetProcessType(aProcessTypeString);
+  }
+
+  virtual nsresult XRE_InitChildProcess(int argc, char* argv[], const XREChildData* aChildData) override {
+    return ::XRE_InitChildProcess(argc, argv, aChildData);
+  }
+
+  virtual void XRE_EnableSameExecutableForContentProc() override {
+    ::XRE_EnableSameExecutableForContentProc();
+  }
+
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void GeckoStart(JNIEnv* aEnv, char** argv, int argc, const StaticXREAppData& aAppData) override {
+    ::GeckoStart(aEnv, argv, argc, aAppData);
+  }
+
+  virtual void XRE_SetAndroidChildFds(int aCrashFd, int aIPCFd) override {
+    ::XRE_SetAndroidChildFds(aCrashFd, aIPCFd);
+  }
+#endif
+
+#ifdef LIBFUZZER
+  virtual void XRE_LibFuzzerSetMain(int argc, char** argv, LibFuzzerMain aMain) override {
+    ::XRE_LibFuzzerSetMain(argc, argv, aMain);
+  }
+
+  virtual void XRE_LibFuzzerGetFuncs(const char* aModuleName, LibFuzzerInitFunc* aInitFunc, LibFuzzerTestingFunc* aTestingFunc) override {
+    ::XRE_LibFuzzerGetFuncs(aModuleName, aInitFunc, aTestingFunc);
+  }
+#endif
+
+#ifdef MOZ_IPDL_TESTS
+  virtual int XRE_RunIPDLTest(int argc, char **argv) override {
+    return ::XRE_RunIPDLTest(argc, argv);
+  }
+#endif
+};
+
+extern "C" NS_EXPORT void NS_FROZENCALL
+XRE_GetBootstrap(Bootstrap::UniquePtr& b)
+{
+  static bool sBootstrapInitialized = false;
+  MOZ_RELEASE_ASSERT(!sBootstrapInitialized);
+
+  sBootstrapInitialized = true;
+  b.reset(new BootstrapImpl());
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/Bootstrap.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/**
+ * This file represents the only external interface exposed from libxul. It
+ * is used by the various stub binaries (nsBrowserApp, xpcshell,
+ * plugin-container) to initialize XPCOM and start their main loop.
+ */
+
+#ifndef mozilla_Bootstrap_h
+#define mozilla_Bootstrap_h
+
+#include "mozilla/UniquePtr.h"
+#include "nscore.h"
+#include "nsXULAppAPI.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+#include "jni.h"
+
+extern "C" NS_EXPORT
+void GeckoStart(JNIEnv* aEnv, char** argv, int argc, const mozilla::StaticXREAppData& aAppData);
+#endif
+
+namespace mozilla {
+
+/**
+ * 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:
+  Bootstrap() { }
+
+  // Because of allocator mismatches, code outside libxul shouldn't delete a
+  // Bootstrap instance. Use Dispose().
+  virtual ~Bootstrap() { }
+
+  /**
+   * Destroy and deallocate this Bootstrap instance.
+   */
+  virtual void Dispose() = 0;
+
+  /**
+   * Helper class to use with UniquePtr.
+   */
+  class BootstrapDelete
+  {
+  public:
+    constexpr BootstrapDelete() { }
+    void operator()(Bootstrap* aPtr) const
+    {
+      aPtr->Dispose();
+    }
+  };
+
+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 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;
+
+  virtual nsresult XRE_InitChildProcess(int argc, char* argv[], const XREChildData* aChildData) = 0;
+
+  virtual void XRE_EnableSameExecutableForContentProc() = 0;
+
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void GeckoStart(JNIEnv* aEnv, char** argv, int argc, const StaticXREAppData& aAppData) = 0;
+
+  virtual void XRE_SetAndroidChildFds(int aCrashFd, int aIPCFd) = 0;
+#endif
+
+#ifdef LIBFUZZER
+  virtual void XRE_LibFuzzerSetMain(int argc, char** argv, LibFuzzerMain aMain) = 0;
+
+  virtual void XRE_LibFuzzerGetFuncs(const char* aModuleName, LibFuzzerInitFunc* aInitFunc, LibFuzzerTestingFunc* aTestingFunc) = 0;
+#endif
+
+#ifdef MOZ_IPDL_TESTS
+  virtual int XRE_RunIPDLTest(int argc, char **argv) = 0;
+#endif
+};
+
+/**
+ * Creates and returns the singleton instnace of the bootstrap object.
+ * @param `b` is an outparam. We use a parameter and not a return value
+ *        because MSVC doesn't let us return a c++ class from a function with
+ *        "C" linkage. On failure this will be null.
+ * @note This function may only be called once and will crash if called again.
+ */
+extern "C" NS_EXPORT void NS_FROZENCALL
+XRE_GetBootstrap(Bootstrap::UniquePtr& b);
+typedef void (*GetBootstrapType)(Bootstrap::UniquePtr&);
+
+} // namespace mozilla
+
+#endif // mozilla_Bootstrap_h
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -21,16 +21,18 @@ if CONFIG['OS_ARCH'] == 'WINNT':
 
 XPIDL_MODULE = 'xulapp'
 
 EXPORTS += [
     'nsAppRunner.h',
     'nsIAppStartupNotifier.h',
 ]
 
+EXPORTS.mozilla += ['Bootstrap.h']
+
 if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     EXPORTS += ['EventTracer.h']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     UNIFIED_SOURCES += [
         'nsNativeAppSupportWin.cpp',
     ]
     DEFINES['PROXY_PRINTING'] = 1
@@ -75,16 +77,17 @@ if CONFIG['MOZ_X11']:
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     UNIFIED_SOURCES += [
         'nsAndroidStartup.cpp',
     ]
 
 UNIFIED_SOURCES += [
+    'Bootstrap.cpp',
     'CreateAppData.cpp',
     'nsAppStartupNotifier.cpp',
     'nsConsoleWriter.cpp',
     'nsEmbeddingModule.cpp',
     'nsNativeAppSupportBase.cpp',
     'nsSigHandlers.cpp',
     'nsXREDirProvider.cpp',
 ]
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -422,16 +422,38 @@ XPCOMGlueStartup(const char* aXPCOMFile)
   if (NS_FAILED(rv)) {
     XPCOMGlueUnload();
     return rv;
   }
 
   return NS_OK;
 }
 
+namespace mozilla {
+
+Bootstrap::UniquePtr
+GetBootstrap(const char* aXPCOMFile)
+{
+  if (NS_FAILED(XPCOMGlueStartup(aXPCOMFile))) {
+    return nullptr;
+  }
+
+  GetBootstrapType func = (GetBootstrapType)GetSymbol(sTop->libHandle, "XRE_GetBootstrap");
+  if (!func) {
+    return nullptr;
+  }
+
+  Bootstrap::UniquePtr b;
+  (*func)(b);
+
+  return b;
+}
+
+} // namespace mozilla
+
 XPCOM_API(nsresult)
 NS_InitXPCOM2(nsIServiceManager** aResult,
               nsIFile* aBinDirectory,
               nsIDirectoryServiceProvider* aAppFileLocationProvider)
 {
   if (!xpcomFunctions.init) {
     return NS_ERROR_NOT_INITIALIZED;
   }
--- a/xpcom/glue/standalone/nsXPCOMGlue.h
+++ b/xpcom/glue/standalone/nsXPCOMGlue.h
@@ -6,16 +6,18 @@
 
 #ifndef nsXPCOMGlue_h__
 #define nsXPCOMGlue_h__
 
 #include "nscore.h"
 
 #ifdef XPCOM_GLUE
 
+#include "mozilla/Bootstrap.h"
+
 /**
  * The following functions are only available in the standalone glue.
  */
 
 /**
  * Initialize the XPCOM glue by dynamically linking against the XPCOM
  * shared library indicated by xpcomFile.
  */
@@ -35,10 +37,20 @@ struct nsDynamicFunctionLoad
  * @throws NS_ERROR_NOT_INITIALIZED if XPCOMGlueStartup() was not called or
  *         if the libxul DLL was not found.
  * @throws NS_ERROR_LOSS_OF_SIGNIFICANT_DATA if only some of the required
  *         functions were found.
  */
 extern "C" NS_HIDDEN_(nsresult)
 XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad* aSymbols);
 
+namespace mozilla {
+
+/**
+ * Initialize the XPCOM glue by dynamically linking against the XPCOM
+ * shared library indicated by xpcomFile and return a Bootstrap instance.
+ */
+NS_HIDDEN_(Bootstrap::UniquePtr) GetBootstrap(const char* aXPCOMFile);
+
+} // namespace mozilla
+
 #endif // XPCOM_GLUE
 #endif // nsXPCOMGlue_h__