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 462791 a7dac14f91df3f94ed809465f80833c310a99f0c
parent 462790 be999ce0e4fe0354bd2737504cca7fccf206f94e
child 462792 2a0edcbaebeeae1cd4cf1be3b0db127fa3bdd01f
push id41857
push userbmo:mh+mozilla@glandium.org
push dateWed, 18 Jan 2017 00:24:11 +0000
reviewersbsmedberg
bugs1306327
milestone53.0a1
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__