Bug 1306327 part B - build a mozilla::Bootstrap API which is used by the various stubs to initialize gecko and run the main loop. Sandboxing init, which is statically linked, still runs in each stub separately. r?glandium draft
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 02 Dec 2016 15:05:46 -0500
changeset 447525 eaa3df21340ed28f551e73f473b7b65f2c76cbff
parent 447524 31fbceca92e42274891d713f1f44c6eeb5ec6eba
child 447526 f383394b3c746a927f71f73902d026cd2db02797
push id38072
push userbsmedberg@mozilla.com
push dateMon, 05 Dec 2016 20:09:44 +0000
reviewersglandium
bugs1306327
milestone53.0a1
Bug 1306327 part B - build a mozilla::Bootstrap API which is used by the various stubs to initialize gecko and run the main loop. Sandboxing init, which is statically linked, still runs in each stub separately. r?glandium UNRESOLVED ISSUES: This likely breaks the LIBFUZZER config. MozReview-Commit-ID: JsJEWy4pfLb
browser/app/nsBrowserApp.cpp
dom/media/gmp/GMPLoader.cpp
dom/media/gmp/GMPLoader.h
intl/lwbrk/gtest/moz.build
ipc/app/MozillaRuntimeMain.cpp
ipc/contentproc/moz.build
ipc/contentproc/plugin-container.cpp
ipc/moz.build
js/xpconnect/shell/xpcshell.cpp
mozglue/android/APKOpen.cpp
toolkit/xre/Bootstrap.cpp
toolkit/xre/Bootstrap.h
toolkit/xre/moz.build
toolkit/xre/nsAndroidStartup.cpp
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsAppRunner.h
toolkit/xre/nsEmbedFunctions.cpp
xpcom/build/BinaryPath.h
xpcom/build/nsXULAppAPI.h
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/glue/standalone/nsXPCOMGlue.h
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -1,51 +1,43 @@
 /* -*- Mode: C++; tab-width: 2; 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 "nsXULAppAPI.h"
-#include "mozilla/XREAppData.h"
+#include "mozilla/Bootstrap.h"
+#include "mozilla/StartupTimeline.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
+
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/resource.h>
 #include <unistd.h>
 #endif
 
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
 
-#include "nsCOMPtr.h"
-#include "nsIFile.h"
-#include "nsStringGlue.h"
-
 #ifdef XP_WIN
-#ifdef MOZ_ASAN
-// ASAN requires firefox.exe to be built with -MD, and it's OK if we don't
-// support Windows XP SP2 in ASAN builds.
-#define XRE_DONT_SUPPORT_XPSP2
-#endif
 #define XRE_WANT_ENVIRON
+#include "nsWindowsWMain.cpp"
 #define strcasecmp _stricmp
 #ifdef MOZ_SANDBOX
 #include "mozilla/sandboxing/SandboxInitialization.h"
+#include "mozilla/sandboxing/sandboxLogging.h"
 #endif
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
-#include "mozilla/Sprintf.h"
-#include "mozilla/Telemetry.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 #ifdef MOZ_LINUX_32_SSE2_STARTUP_ERROR
 #include <cpuid.h>
 #include "mozilla/Unused.h"
 
 static bool
 IsSSE2Available()
@@ -84,29 +76,18 @@ SSE2Check()
   MOZ_UNUSED(write(STDERR_FILENO,
                    sSSE2Message,
                    MOZ_ARRAY_LENGTH(sSSE2Message) - 1));
   // _exit() instead of exit() to avoid running the usual "at exit" code.
   _exit(255);
 }
 #endif
 
-#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \
-  && !(defined(XP_LINUX) && defined(MOZ_SANDBOX))
-#define MOZ_BROWSER_CAN_BE_CONTENTPROC
-#include "../../ipc/contentproc/plugin-container.cpp"
-#endif
-
 using namespace mozilla;
 
-#ifdef XP_MACOSX
-#define kOSXResourcesFolder "Resources"
-#endif
-#define kDesktopFolder "browser"
-
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #ifndef XP_WIN
   vfprintf(stderr, fmt, ap);
 #else
@@ -137,16 +118,17 @@ static void Output(const char *fmt, ... 
     FreeLibrary(user32);
   }
 #endif
 #endif
 
   va_end(ap);
 }
 
+#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
 /**
  * Return true if |arg| matches the given argument name.
  */
 static bool IsArg(const char* arg, const char* s)
 {
   if (*arg == '-')
   {
     if (*++arg == '-')
@@ -156,246 +138,83 @@ static bool IsArg(const char* arg, const
 
 #if defined(XP_WIN)
   if (*arg == '/')
     return !strcasecmp(++arg, s);
 #endif
 
   return false;
 }
-
-XRE_GetFileFromPathType XRE_GetFileFromPath;
-XRE_ParseAppDataType XRE_ParseAppData;
-XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
-XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
-XRE_mainType XRE_main;
-XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
-XRE_XPCShellMainType XRE_XPCShellMain;
-XRE_GetProcessTypeType XRE_GetProcessType;
-XRE_SetProcessTypeType XRE_SetProcessType;
-XRE_InitChildProcessType XRE_InitChildProcess;
-XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
-#ifdef LIBFUZZER
-XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain;
-XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs;
 #endif
 
-static const nsDynamicFunctionLoad kXULFuncs[] = {
-    { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
-    { "XRE_ParseAppData", (NSFuncPtr*) &XRE_ParseAppData },
-    { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
-    { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
-    { "XRE_main", (NSFuncPtr*) &XRE_main },
-    { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
-    { "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
-    { "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType },
-    { "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
-    { "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
-    { "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc },
-#ifdef LIBFUZZER
-    { "XRE_LibFuzzerSetMain", (NSFuncPtr*) &XRE_LibFuzzerSetMain },
-    { "XRE_LibFuzzerGetFuncs", (NSFuncPtr*) &XRE_LibFuzzerGetFuncs },
-#endif
-    { nullptr, nullptr }
-};
-
 #ifdef LIBFUZZER
 int libfuzzer_main(int argc, char **argv);
 
 /* This wrapper is used by the libFuzzer main to call into libxul */
 
 void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc,
                        LibFuzzerTestingFunc* testingFunc) {
   return XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
 }
 #endif
 
-static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
-{
-  nsCOMPtr<nsIFile> appini;
-  nsresult rv;
-  uint32_t mainFlags = 0;
-
-  // 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 = 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 (argc == 2) {
-      Output("Incorrect number of arguments passed to -app");
-      return 255;
-    }
-
-    rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
-    if (NS_FAILED(rv)) {
-      Output("application.ini path not recognized: '%s'", argv[2]);
-      return 255;
-    }
-
-    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];
-    argv += 2;
-    argc -= 2;
-  } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
-    for (int i = 1; i < argc; i++) {
-      argv[i] = argv[i + 1];
-    }
-
-    XREShellData shellData;
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-    shellData.sandboxBrokerServices =
-      sandboxing::GetInitializedBrokerServices();
-#endif
-
-    return XRE_XPCShellMain(--argc, argv, envp, &shellData);
-  }
-
-  XREAppData appData;
-  appData.xreDirectory = xreDirectory;
-
-  if (appini) {
-    rv = XRE_ParseAppData(appini, appData);
-    if (NS_FAILED(rv)) {
-      Output("Couldn't read application.ini");
-      return 255;
-    }
-
-    appini->GetParent(getter_AddRefs(appData.directory));
-  } 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;
-  }
-
-#if defined(HAS_DLL_BLOCKLIST)
-  // The dll blocklist operates in the exe vs. xullib. Pass a flag to
-  // xullib so automated tests can check the result once the browser
-  // is up and running.
-  appData.flags |=
-    DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
-#endif
-
-#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;
-#endif
-
-#ifdef LIBFUZZER
-  if (getenv("LIBFUZZER"))
-    XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
-#endif
-
-  return XRE_main(argc, argv, appData, mainFlags);
-}
-
 static bool
 FileExists(const char *path)
 {
 #ifdef XP_WIN
   wchar_t wideDir[MAX_PATH];
   MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
   DWORD fileAttrs = GetFileAttributesW(wideDir);
   return fileAttrs != INVALID_FILE_ATTRIBUTES;
 #else
   return access(path, R_OK) == 0;
 #endif
 }
 
-static nsresult
-InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
+static Bootstrap::UniquePtr
+InitXPCOMGlue(const char *argv0)
 {
   char exePath[MAXPATHLEN];
 
   nsresult rv = mozilla::BinaryPath::Get(argv0, exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't find the application directory.\n");
-    return rv;
+    return nullptr;
   }
 
   char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
   if (!lastSlash ||
       (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
-    return NS_ERROR_FAILURE;
+    return nullptr;
 
   strcpy(lastSlash + 1, XPCOM_DLL);
 
   if (!FileExists(exePath)) {
     Output("Could not find the Mozilla runtime.\n");
-    return NS_ERROR_FAILURE;
+    return nullptr;
   }
 
   // We do this because of data in bug 771745
   XPCOMGlueEnablePreload();
 
-  rv = XPCOMGlueStartup(exePath);
-  if (NS_FAILED(rv)) {
+  Bootstrap::UniquePtr b = XPCOMGlueStartup(exePath);
+  if (!b) {
     Output("Couldn't load XPCOM.\n");
-    return rv;
-  }
-
-  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't load XRE functions.\n");
-    return rv;
+    return nullptr;
   }
 
-  // This will set this thread as the main thread.
-  NS_LogInit();
-
-  if (xreDirectory) {
-    // chop XPCOM_DLL off exePath
-    *lastSlash = '\0';
+  // chop XPCOM_DLL off exePath
+  *lastSlash = '\0';
 #ifdef XP_MACOSX
-    lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-    strcpy(lastSlash + 1, kOSXResourcesFolder);
+  lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
+  strcpy(lastSlash + 1, kOSXResourcesFolder);
 #endif
-#ifdef XP_WIN
-    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
-                         xreDirectory);
-#else
-    rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
-                               xreDirectory);
-#endif
-  }
 
-  return rv;
+  b->SetXREDirectory(exePath);
+  return b;
 }
 
 int main(int argc, char* argv[], char* envp[])
 {
   mozilla::TimeStamp start = mozilla::TimeStamp::Now();
 
 #ifdef HAS_DLL_BLOCKLIST
   DllBlocklist_Initialize();
@@ -404,64 +223,59 @@ int main(int argc, char* argv[], char* e
   // In order to be effective against AppInit DLLs, the blocklist must be
   // initialized before user32.dll is loaded into the process (bug 932100).
   if (GetModuleHandleA("user32.dll")) {
     fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
   }
 #endif
 #endif
 
+  bool contentproc = false;
+
 #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
-  // We are launching as a content process, delegate to the appropriate
-  // main
-  if (argc > 1 && IsArg(argv[1], "contentproc")) {
+  contentproc = argc > 1 && IsArg(argv[1], "contentproc");
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  sandbox::TargetServices* targetServices = nullptr;
+  if (contentproc) {
     // We need to initialize the sandbox TargetServices before InitXPCOMGlue
     // because we might need the sandbox broker to give access to some files.
-    if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) {
-      Output("Failed to initialize the sandbox target services.");
-      return 255;
+    if (IsSandboxedProcess()) {
+      targetServices = sandboxing::GetInitializedTargetServices();
+      if (!targetServices) {
+        Output("Failed to initialize the sandbox target services.");
+        return 255;
+      }
     }
+  }
+#endif
 #endif
 
-    nsresult rv = InitXPCOMGlue(argv[0], nullptr);
-    if (NS_FAILED(rv)) {
-      return 255;
-    }
-
-    int result = content_process_main(argc, argv);
-
-    // InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
-    NS_LogTerm();
+  // We are launching as a content process, delegate to the appropriate
+  // main
 
-    return result;
-  }
-#endif
-
-
-  nsIFile *xreDirectory;
-
-  nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
-  if (NS_FAILED(rv)) {
+  Bootstrap::UniquePtr bootstrap = InitXPCOMGlue(argv[0]);
+  if (!bootstrap) {
     return 255;
   }
 
-  XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
+  bootstrap->SetDefaultAppData(sAppData);
+  bootstrap->StartupTimelineRecord(mozilla::StartupTimeline::START, start);
 
-#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
-  XRE_EnableSameExecutableForContentProc();
+#ifdef HAS_DLL_BLOCKLIST
+  bootstrap->SetBlocklistEnabled(DllBlocklist_CheckStatus());
 #endif
 
-  int result = do_main(argc, argv, envp, xreDirectory);
-
-  NS_LogTerm();
-
-#ifdef XP_MACOSX
-  // Allow writes again. While we would like to catch writes from static
-  // destructors to allow early exits to use _exit, we know that there is
-  // at least one such write that we don't control (see bug 826029). For
-  // now we enable writes again and early exits will have to use exit instead
-  // of _exit.
-  XRE_StopLateWriteChecks();
+  int result;
+  if (contentproc) {
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    bootstrap->SetSandboxTarget(targetServices);
+    bootstrap->SetSandboxLogger(mozilla::sandboxing::ProvideLogFunction);
 #endif
+    result = bootstrap->ContentProcessMain(argc, argv);
+  } else {
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    bootstrap->SetSandboxBroker(sandboxing::GetInitializedBrokerServices());
+#endif
+    result = bootstrap->AppMain(argc, argv, envp);
+  }
 
   return result;
 }
--- a/dom/media/gmp/GMPLoader.cpp
+++ b/dom/media/gmp/GMPLoader.cpp
@@ -19,18 +19,18 @@
 
 #include "GMPDeviceBinding.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPLoaderImpl : public GMPLoader {
 public:
-  explicit GMPLoaderImpl(SandboxStarter* aStarter)
-    : mSandboxStarter(aStarter)
+  explicit GMPLoaderImpl(UniquePtr<SandboxStarter> aStarter)
+    : mSandboxStarter(Move(aStarter))
     , mAdapter(nullptr)
   {}
   ~GMPLoaderImpl() override = default;
 
   bool Load(const char* aUTF8LibPath,
             uint32_t aUTF8LibPathLen,
             char* aOriginSalt,
             uint32_t aOriginSaltLen,
@@ -44,22 +44,22 @@ public:
 
   void Shutdown() override;
 
 #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
   void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override;
 #endif
 
 private:
-  SandboxStarter* mSandboxStarter;
+  UniquePtr<SandboxStarter> mSandboxStarter;
   UniquePtr<GMPAdapter> mAdapter;
 };
 
-UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter) {
-  return MakeUnique<GMPLoaderImpl>(aStarter);
+UniquePtr<GMPLoader> CreateGMPLoader(UniquePtr<SandboxStarter> aStarter) {
+  return MakeUnique<GMPLoaderImpl>(Move(aStarter));
 }
 
 class PassThroughGMPAdapter : public GMPAdapter {
 public:
   ~PassThroughGMPAdapter() override {
     // Ensure we're always shutdown, even if caller forgets to call GMPShutdown().
     GMPShutdown();
   }
--- a/dom/media/gmp/GMPLoader.h
+++ b/dom/media/gmp/GMPLoader.h
@@ -100,14 +100,14 @@ public:
   // sandbox, which we don't yet know when the GMPLoader and SandboxStarter
   // objects are created.
   virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) = 0;
 #endif
 };
 
 // On Desktop, this function resides in plugin-container.
 // On Mobile, this function resides in XUL.
-UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter);
+UniquePtr<GMPLoader> CreateGMPLoader(UniquePtr<SandboxStarter> aStarter);
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMP_LOADER_H__
--- a/intl/lwbrk/gtest/moz.build
+++ b/intl/lwbrk/gtest/moz.build
@@ -4,9 +4,8 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'TestLineBreak.cpp',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
-
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -1,19 +1,109 @@
 /* -*- 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 "../contentproc/plugin-container.cpp"
+#include "GMPLoader.h"
+#include "mozilla/Bootstrap.h"
+#include "mozilla/WindowsDllBlocklist.h"
+
+#ifdef XP_WIN
+#include <windows.h>
+// we want a wmain entry point
+// but we don't want its DLL load protection, because some plugins can't do it;
+// we'll handle that in ContentProcessMain.
+#define XRE_DONT_PROTECT_DLL_LOAD
+#include "nsWindowsWMain.cpp"
+#else
+#include <unistd.h>
+#endif
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#include "mozilla/sandboxing/sandboxLogging.h"
+#endif
+
+#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
+#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
+#endif
+
+using namespace mozilla;
 
-#include "mozilla/WindowsDllBlocklist.h"
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
+public:
+    virtual bool Start(const char *aLibPath) override {
+        if (IsSandboxedProcess()) {
+            mozilla::sandboxing::LowerSandbox();
+        }
+        return true;
+    }
+};
+#endif
+
+#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
+class MacSandboxStarter : public mozilla::gmp::SandboxStarter {
+public:
+    bool Start(const char *aLibPath) override {
+      std::string err;
+      bool rv = mozilla::StartMacSandbox(mInfo, err);
+      if (!rv) {
+        fprintf(stderr, "sandbox_init() failed! Error \"%s\"\n", err.c_str());
+      }
+      return rv;
+    }
+    void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override {
+      mInfo = *aSandboxInfo;
+    }
+private:
+  MacSandboxInfo mInfo;
+};
+#endif
+
+UniquePtr<mozilla::gmp::SandboxStarter>
+MakeSandboxStarter()
+{
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    return MakeUnique<WinSandboxStarter>();
+#elif defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
+    return MakeUnique<MacSandboxStarter>();
+#else
+    return nullptr;
+#endif
+}
 
 int
 main(int argc, char *argv[])
 {
 #ifdef HAS_DLL_BLOCKLIST
   DllBlocklist_Initialize();
 #endif
 
-  return content_process_main(argc, argv);
+  Bootstrap::UniquePtr bootstrap;
+  XRE_GetBootstrap(bootstrap);
+  if (!bootstrap) {
+    return 1;
+  }
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  // We need to initialize the sandbox TargetServices before InitXPCOMGlue
+  // because we might need the sandbox broker to give access to some files.
+  if (IsSandboxedProcess()) {
+    sandbox::TargetServices* targetServices = sandboxing::GetInitializedTargetServices();
+    if (!targetServices) {
+      return 255;
+    }
+    bootstrap->SetSandboxTarget(targetServices);
+    bootstrap->SetSandboxLogger(mozilla::sandboxing::ProvideLogFunction);
+  }
+#endif
+#if !defined(XP_LINUX) && defined(MOZ_PLUGIN_CONTAINER)
+  // On Windows and MacOS, the GMPLoader lives in plugin-container, so that its
+  // code can be covered by an EME/GMP vendor's voucher.
+  bootstrap->SetGMPLoader(mozilla::gmp::CreateGMPLoader(MakeSandboxStarter()));
+#endif
+
+  return bootstrap->ContentProcessMain(argc, argv);
 }
deleted file mode 100644
--- a/ipc/contentproc/moz.build
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-Library('plugin-container')
-
-SOURCES += [
-    'plugin-container.cpp',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-if CONFIG['OS_ARCH'] == 'WINNT':
-    LOCAL_INCLUDES += [
-        '/toolkit/xre',
-        '/xpcom/base',
-    ]
-
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
-    LOCAL_INCLUDES += [
-        '/security/sandbox/chromium',
-        '/security/sandbox/chromium-shim',
-    ]
deleted file mode 100644
--- a/ipc/contentproc/plugin-container.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: sw=4 ts=4 et :
- * 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 "nsXPCOM.h"
-#include "nsXULAppAPI.h"
-#include "nsAutoPtr.h"
-
-#ifdef XP_WIN
-#include <windows.h>
-// we want a wmain entry point
-// but we don't want its DLL load protection, because we'll handle it here
-#define XRE_DONT_PROTECT_DLL_LOAD
-#include "nsWindowsWMain.cpp"
-#include "nsSetDllDirectory.h"
-#else
-// FIXME/cjones testing
-#include <unistd.h>
-#endif
-
-#include "GMPLoader.h"
-
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-#include "mozilla/sandboxing/SandboxInitialization.h"
-#include "mozilla/sandboxing/sandboxLogging.h"
-#endif
-
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
-public:
-    virtual bool Start(const char *aLibPath) override {
-        if (IsSandboxedProcess()) {
-            mozilla::sandboxing::LowerSandbox();
-        }
-        return true;
-    }
-};
-#endif
-
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-class MacSandboxStarter : public mozilla::gmp::SandboxStarter {
-public:
-    bool Start(const char *aLibPath) override {
-      std::string err;
-      bool rv = mozilla::StartMacSandbox(mInfo, err);
-      if (!rv) {
-        fprintf(stderr, "sandbox_init() failed! Error \"%s\"\n", err.c_str());
-      }
-      return rv;
-    }
-    void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override {
-      mInfo = *aSandboxInfo;
-    }
-private:
-  MacSandboxInfo mInfo;
-};
-#endif
-
-mozilla::gmp::SandboxStarter*
-MakeSandboxStarter()
-{
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-    return new WinSandboxStarter();
-#elif defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-    return new MacSandboxStarter();
-#else
-    return nullptr;
-#endif
-}
-
-int
-content_process_main(int argc, char* argv[])
-{
-    // Check for the absolute minimum number of args we need to move
-    // forward here. We expect the last arg to be the child process type.
-    if (argc < 1) {
-      return 3;
-    }
-
-    XREChildData childData;
-
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-    if (IsSandboxedProcess()) {
-        childData.sandboxTargetServices =
-            mozilla::sandboxing::GetInitializedTargetServices();
-        if (!childData.sandboxTargetServices) {
-            return 1;
-        }
-
-        childData.ProvideLogFunction = mozilla::sandboxing::ProvideLogFunction;
-    }
-#endif
-
-    XRE_SetProcessType(argv[--argc]);
-
-#ifdef XP_WIN
-    // For plugins, this is done in PluginProcessChild::Init, as we need to
-    // avoid it for unsupported plugins.  See PluginProcessChild::Init for
-    // the details.
-    if (XRE_GetProcessType() != GeckoProcessType_Plugin) {
-        mozilla::SanitizeEnvironmentVariables();
-        SetDllDirectoryW(L"");
-    }
-#endif
-#if !defined(XP_LINUX) && defined(MOZ_PLUGIN_CONTAINER)
-    // On Windows and MacOS, the GMPLoader lives in plugin-container, so that its
-    // code can be covered by an EME/GMP vendor's voucher.
-    nsAutoPtr<mozilla::gmp::SandboxStarter> starter(MakeSandboxStarter());
-    if (XRE_GetProcessType() == GeckoProcessType_GMPlugin) {
-        childData.gmpLoader = mozilla::gmp::CreateGMPLoader(starter);
-    }
-#endif
-    nsresult rv = XRE_InitChildProcess(argc, argv, &childData);
-    NS_ENSURE_SUCCESS(rv, 1);
-
-    return 0;
-}
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -15,15 +15,12 @@ if CONFIG['MOZ_ENABLE_DBUS']:
     DIRS += ['dbus']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['unixfd', 'unixsocket']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['hal', 'keystore', 'netd']
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
-    DIRS += ['contentproc']
-
 if CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['mscom']
 
 DIRS += ['app']
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -3,19 +3,19 @@
 /* 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/. */
 
 /* XPConnect JavaScript interactive shell. */
 
 #include <stdio.h>
 
+#include "mozilla/Bootstrap.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
-#include "nsXULAppAPI.h"
 #ifdef XP_MACOSX
 #include "xpcshellMacUtils.h"
 #endif
 #ifdef XP_WIN
 #include <windows.h>
 #include <shlobj.h>
 
 // we want a wmain entry point
@@ -26,16 +26,18 @@
 #include "mozilla/sandboxing/SandboxInitialization.h"
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #endif
 
+using namespace mozilla;
+
 int
 main(int argc, char** argv, char** envp)
 {
 #ifdef MOZ_WIDGET_GTK
     // A default display may or may not be required for xpcshell tests, and so
     // is not created here. Instead we set the command line args, which is a
     // fairly cheap operation.
     gtk_parse_args(&argc, &argv);
@@ -48,22 +50,26 @@ main(int argc, char** argv, char** envp)
     // unbuffer stdout so that output is in the correct order; note that stderr
     // is unbuffered by default
     setbuf(stdout, 0);
 
 #ifdef HAS_DLL_BLOCKLIST
     DllBlocklist_Initialize();
 #endif
 
-    XREShellData shellData;
+    Bootstrap::UniquePtr bootstrap;
+    XRE_GetBootstrap(bootstrap);
+    if (!bootstrap) {
+        fprintf(stderr, "Error: unable to initialize XUL bootstrap.");
+        return 1;
+    }
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
-    shellData.sandboxBrokerServices =
-      mozilla::sandboxing::GetInitializedBrokerServices();
+    bootstrap->SetSandboxBroker(mozilla::sandboxing::GetInitializedBrokerServices());
 #endif
 
-    int result = XRE_XPCShellMain(argc, argv, envp, &shellData);
+    int result = bootstrap->XPCShellMain(argc, argv, envp);
 
 #ifdef XP_MACOSX
     FinishAutoreleasePool();
 #endif
 
     return result;
 }
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -30,17 +30,17 @@
 #include "sqlite3.h"
 #include "SQLiteBridge.h"
 #include "NSSBridge.h"
 #include "ElfLoader.h"
 #include "application.ini.h"
 
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
-#include "XREChildData.h"
+#include "mozilla/Bootstrap.h"
 
 /* Android headers don't define RUSAGE_THREAD */
 #ifndef RUSAGE_THREAD
 #define RUSAGE_THREAD 1
 #endif
 
 #ifndef RELEASE_OR_BETA
 /* Official builds have the debuggable flag set to false, which disables
@@ -161,34 +161,29 @@ getJavaUiThread()
 }
 
 extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_GeckoThread_registerUiThread(JNIEnv*, jclass)
 {
     sJavaUiThread = pthread_self();
 }
 
-static void * xul_handle = nullptr;
+static Bootstrap* bootstrap = nullptr;
+
 #ifndef MOZ_FOLD_LIBS
 static void * sqlite_handle = nullptr;
 static void * nspr_handle = nullptr;
 static void * plc_handle = nullptr;
 #else
 #define sqlite_handle nss_handle
 #define nspr_handle nss_handle
 #define plc_handle nss_handle
 #endif
 static void * nss_handle = nullptr;
 
-template <typename T> inline void
-xul_dlsym(const char *symbolName, T *value)
-{
-  *value = (T) (uintptr_t) __wrap_dlsym(xul_handle, symbolName);
-}
-
 static int mapping_count = 0;
 
 extern "C" void
 report_mapping(char *name, void *base, uint32_t len, uint32_t offset)
 {
   if (mapping_count >= MAX_MAPPING_INFO)
     return;
 
@@ -230,24 +225,35 @@ dlopenAPKLibrary(const char* apkName, co
 static mozglueresult
 loadGeckoLibs(const char *apkName)
 {
   TimeStamp t0 = TimeStamp::Now();
   struct rusage usage1_thread, usage1;
   getrusage(RUSAGE_THREAD, &usage1_thread);
   getrusage(RUSAGE_SELF, &usage1);
 
-  xul_handle = dlopenAPKLibrary(apkName, "libxul.so");
+  void* xul_handle = dlopenAPKLibrary(apkName, "libxul.so");
   if (!xul_handle) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libxul!");
     return FAILURE;
   }
 
-  void (*XRE_StartupTimelineRecord)(int, TimeStamp);
-  xul_dlsym("XRE_StartupTimelineRecord", &XRE_StartupTimelineRecord);
+  GetBootstrapType XRE_GetBootstrap =
+    (GetBootstrapType)(uintptr_t) __wrap_dlsym(xul_handle, "XRE_GetBootstrap");
+  if (!XRE_GetBootstrap) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't find symbol XRE_GetBootstrap");
+    return FAILURE;
+  }
+  Bootstrap::UniquePtr b;
+  XRE_GetBootstrap(b);
+  if (!b) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "XRE_GetBootstrap failed");
+    return FAILURE;
+  }
+  bootstrap = b.release();
 
   TimeStamp t1 = TimeStamp::Now();
   struct rusage usage2_thread, usage2;
   getrusage(RUSAGE_THREAD, &usage2_thread);
   getrusage(RUSAGE_SELF, &usage2);
 
 #define RUSAGE_TIMEDIFF(u1, u2, field) \
   ((u2.ru_ ## field.tv_sec - u1.ru_ ## field.tv_sec) * 1000 + \
@@ -257,18 +263,18 @@ loadGeckoLibs(const char *apkName)
                       (t1 - t0).ToMilliseconds(),
                       RUSAGE_TIMEDIFF(usage1_thread, usage2_thread, utime),
                       RUSAGE_TIMEDIFF(usage1, usage2, utime),
                       RUSAGE_TIMEDIFF(usage1_thread, usage2_thread, stime),
                       RUSAGE_TIMEDIFF(usage1, usage2, stime),
                       usage2_thread.ru_majflt - usage1_thread.ru_majflt,
                       usage2.ru_majflt - usage1.ru_majflt);
 
-  XRE_StartupTimelineRecord(LINKER_INITIALIZED, t0);
-  XRE_StartupTimelineRecord(LIBRARIES_LOADED, t1);
+  bootstrap->StartupTimelineRecord(LINKER_INITIALIZED, t0);
+  bootstrap->StartupTimelineRecord(LIBRARIES_LOADED, t1);
   return SUCCESS;
 }
 
 static mozglueresult loadNSSLibs(const char *apkName);
 
 static mozglueresult
 loadSQLiteLibs(const char *apkName)
 {
@@ -449,43 +455,25 @@ typedef int GeckoProcessType;
 
 extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd)
 {
   int argc = 0;
   char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
 
   if (ipcFd < 0) {
-    GeckoStart_t GeckoStart;
-    xul_dlsym("GeckoStart", &GeckoStart);
-
-    if (GeckoStart == nullptr) {
-      FreeArgv(argv, argc);
-      return;
-    }
-
     ElfLoader::Singleton.ExpectShutdown(false);
-    GeckoStart(jenv, argv, argc, sAppData);
+    bootstrap->SetDefaultAppData(sAppData);
+    bootstrap->AndroidMain(jenv, argc, argv);
     ElfLoader::Singleton.ExpectShutdown(true);
   } else {
-    void (*fXRE_SetAndroidChildFds)(int, int);
-    xul_dlsym("XRE_SetAndroidChildFds", &fXRE_SetAndroidChildFds);
-
-    void (*fXRE_SetProcessType)(char*);
-    xul_dlsym("XRE_SetProcessType", &fXRE_SetProcessType);
-
-    mozglueresult (*fXRE_InitChildProcess)(int, char**, void*);
-    xul_dlsym("XRE_InitChildProcess", &fXRE_InitChildProcess);
-
-    fXRE_SetAndroidChildFds(crashFd, ipcFd);
-    fXRE_SetProcessType(argv[argc - 1]);
-
-    XREChildData childData;
-    fXRE_InitChildProcess(argc - 1, argv, &childData);
+    bootstrap->AndroidChildMain(argc, argv, crashFd, ipcFd);
   }
+  bootstrap->Dispose();
+  bootstrap = nullptr;
 
   FreeArgv(argv, argc);
 }
 
 extern "C" APKOPEN_EXPORT mozglueresult
 ChildProcessInit(int argc, char* argv[])
 {
   int i;
@@ -502,20 +490,13 @@ ChildProcessInit(int argc, char* argv[])
   }
   if (loadSQLiteLibs(argv[i]) != SUCCESS) {
     return FAILURE;
   }
   if (loadGeckoLibs(argv[i]) != SUCCESS) {
     return FAILURE;
   }
 
-  void (*fXRE_SetProcessType)(char*);
-  xul_dlsym("XRE_SetProcessType", &fXRE_SetProcessType);
-
-  mozglueresult (*fXRE_InitChildProcess)(int, char**, void*);
-  xul_dlsym("XRE_InitChildProcess", &fXRE_InitChildProcess);
-
-  fXRE_SetProcessType(argv[--argc]);
-
-  XREChildData childData;
-  return fXRE_InitChildProcess(argc, argv, &childData);
+  bootstrap->AndroidChildMain(argc, argv);
+  bootstrap->Dispose();
+  bootstrap = nullptr;
+  return 0;
 }
-
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/Bootstrap.cpp
@@ -0,0 +1,392 @@
+/* -*- 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 "BinaryPath.h"
+#include "mozilla/AppData.h"
+#include "mozilla/Sprintf.h"
+#include "nsAppRunner.h"
+#include "nsCOMPtr.h"
+#include "nsIFile.h"
+#include "nsString.h"
+#include "nsXULAppAPI.h"
+
+#ifdef XP_WIN
+#include "nsSetDllDirectory.h"
+#endif
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#endif
+
+#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
+#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+#include <android/log.h>
+#include "mozilla/jni/Utils.h"
+#include "chrome/common/ipc_channel.h"
+#endif
+
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+#endif
+
+#define kDesktopFolder "browser"
+
+#ifdef XP_WIN
+#define strcasecmp _stricmp
+#endif
+
+namespace mozilla {
+
+class BootstrapImpl final : public Bootstrap
+{
+public:
+  BootstrapImpl()
+    : mStaticAppData(nullptr)
+#ifdef HAS_DLL_BLOCKLIST
+    , mBlocklistEnabled(false)
+#endif
+  {
+    NS_LogInit();
+  }
+  ~BootstrapImpl()
+  {
+  }
+
+  virtual void Dispose() override
+  {
+    delete this;
+
+    // Terminate logging here instead of the destructor because there are
+    // logged members that are cleaned up.
+    NS_LogTerm();
+
+#ifdef XP_MACOSX
+    // Allow writes again. While we would like to catch writes from static
+    // destructors to allow early exits to use _exit, we know that there is
+    // at least one such write that we don't control (see bug 826029). For
+    // now we enable writes again and early exits will have to use exit instead
+    // of _exit.
+    XRE_StopLateWriteChecks();
+#endif
+  }
+
+#if MOZ_WIDGET_GTK == 2
+  virtual void GlibInit() override
+  {
+    XRE_GlibInit();
+  }
+#endif
+
+  virtual void SetDefaultAppData(const StaticXREAppData& staticAppData) override
+  {
+    mStaticAppData = &staticAppData;
+  }
+
+  virtual void SetXREDirectory(const char* directory) override;
+
+#ifdef HAS_DLL_BLOCKLIST
+  virtual void SetBlocklistEnabled(bool enabled) override
+  {
+    mBlocklistEnabled = enabled;
+  }
+#endif
+
+  virtual void StartupTimelineRecord(int event, mozilla::TimeStamp when) override
+  {
+    XRE_StartupTimelineRecord(event, when);
+  }
+
+#ifdef BOOTSTRAP_HAS_GMPLOADER
+  virtual void SetGMPLoader(mozilla::UniquePtr<mozilla::gmp::GMPLoader> gmpLoader) override
+  {
+    mChildData.gmpLoader = Move(gmpLoader);
+  }
+#endif
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  virtual void SetSandboxTarget(sandbox::TargetServices* target) override
+  {
+    mChildData.sandboxTargetServices = target;
+  }
+  virtual void SetSandboxLogger(mozilla::sandboxing::ProvideLogFunctionCb callback) override
+  {
+    mChildData.ProvideLogFunction = callback;
+  }
+
+  virtual void SetSandboxBroker(sandbox::BrokerServices* broker) override
+  {
+    mSandboxBroker = broker;
+  }
+#endif
+
+  virtual int AppMain(int argc, char* argv[], char* envp[]) override;
+  virtual int ContentProcessMain(int argc, char* argv[]) override;
+  virtual int XPCShellMain(int argc, char* argv[], char* envp[]) override;
+
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void AndroidMain(JNIEnv* jenv, int argc, char* argv[]) override;
+  virtual void AndroidChildMain(int arg, char* argv[], int crashFd, int ipcFd) override;
+#endif
+
+private:
+  const StaticXREAppData* mStaticAppData;
+  nsCOMPtr<nsIFile> mXREDirectory;
+  XREChildData mChildData;
+#ifdef HAS_DLL_BLOCKLIST
+  bool mBlocklistEnabled;
+#endif
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  sandbox::BrokerServices* mSandboxBroker = nullptr;
+#endif
+};
+
+void
+BootstrapImpl::SetXREDirectory(const char* directory)
+{
+#ifdef XP_WIN
+  NS_NewLocalFile(NS_ConvertUTF8toUTF16(directory), false,
+                  getter_AddRefs(mXREDirectory));
+#else
+  NS_NewNativeLocalFile(nsDependentCString(directory), false,
+                        getter_AddRefs(mXREDirectory));
+#endif
+}
+
+/**
+ * Return true if |arg| matches the given argument name.
+ */
+static bool IsArg(const char* arg, const char* s)
+{
+  if (*arg == '-')
+  {
+    if (*++arg == '-')
+      ++arg;
+    return !strcasecmp(arg, s);
+  }
+
+#if defined(XP_WIN)
+  if (*arg == '/')
+    return !strcasecmp(++arg, s);
+#endif
+
+  return false;
+}
+
+int
+BootstrapImpl::AppMain(int argc, char* argv[], char* envp[])
+{
+  nsCOMPtr<nsIFile> appini;
+  nsresult rv;
+  uint32_t mainFlags = 0;
+
+#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
+  XRE_EnableSameExecutableForContentProc();
+#endif
+
+  // 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 = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
+    if (NS_FAILED(rv)) {
+      Output(false, "Invalid path found: '%s'", appDataFile);
+      return 255;
+    }
+  }
+  else if (argc > 1 && IsArg(argv[1], "app")) {
+    if (argc == 2) {
+      Output(false, "Incorrect number of arguments passed to -app");
+      return 255;
+    }
+
+    rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
+    if (NS_FAILED(rv)) {
+      Output(false, "application.ini path not recognized: '%s'", argv[2]);
+      return 255;
+    }
+
+    char appEnv[MAXPATHLEN];
+    SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
+    if (putenv(strdup(appEnv))) {
+      Output(false, "Couldn't set %s.\n", appEnv);
+      return 255;
+    }
+    argv[2] = argv[0];
+    argv += 2;
+    argc -= 2;
+  } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
+    for (int i = 1; i < argc; i++) {
+      argv[i] = argv[i + 1];
+    }
+
+    return XPCShellMain(--argc, argv, envp);
+  }
+
+  XREAppData appData;
+  appData.xreDirectory = mXREDirectory;
+
+#ifdef HAS_DLL_BLOCKLIST
+  // The dll blocklist operates in the exe vs. xullib. Pass a flag to
+  // xullib so automated tests can check the result once the browser
+  if (mBlocklistEnabled) {
+    appData.flags |= NS_XRE_DLL_BLOCKLIST_ENABLED;
+  }
+#endif
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#ifdef MOZ_CONTENT_SANDBOX
+  if (!mSandboxBroker) {
+    Output(false, "Couldn't initialize the broker services.\n");
+    return 255;
+  }
+#endif
+  appData.sandboxBrokerServices = mSandboxBroker;
+#endif
+
+  if (appini) {
+    rv = XRE_ParseAppData(appini, appData);
+    if (NS_FAILED(rv)) {
+      Output(false, "Couldn't read application.ini");
+      return 255;
+    }
+    appini->GetParent(getter_AddRefs(appData.directory));
+  } else {
+    appData = *mStaticAppData;
+    nsCOMPtr<nsIFile> exeFile;
+    rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
+    if (NS_FAILED(rv)) {
+      Output(false, "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;
+  }
+
+#ifdef LIBFUZZER
+  if (getenv("LIBFUZZER"))
+    XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
+#endif
+
+  return XRE_main(argc, argv, appData, mainFlags);
+}
+
+int
+BootstrapImpl::ContentProcessMain(int argc, char* argv[])
+{
+  // Check for the absolute minimum number of args we need to move
+  // forward here. We expect the last arg to be the child process type.
+  if (argc < 1) {
+    return 3;
+  }
+
+  XRE_SetProcessType(argv[--argc]);
+
+#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
+  // This has to happen while we're still single-threaded, and on
+  // B2G that means before the Android Binder library is
+  // initialized.
+  mozilla::SandboxEarlyInit(XRE_GetProcessType());
+#endif
+
+#ifdef XP_WIN
+  // For plugins, this is done in PluginProcessChild::Init, as we need to
+  // avoid it for unsupported plugins.  See PluginProcessChild::Init for
+  // the details.
+  if (XRE_GetProcessType() != GeckoProcessType_Plugin) {
+    mozilla::SanitizeEnvironmentVariables();
+    SetDllDirectoryW(L"");
+  }
+#endif
+  nsresult rv = XRE_InitChildProcess(argc, argv, &mChildData);
+  NS_ENSURE_SUCCESS(rv, 1);
+
+  return 0;
+}
+
+int
+BootstrapImpl::XPCShellMain(int argc, char* argv[], char* envp[])
+{
+  XREShellData shellData;
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  shellData.sandboxBrokerServices = mSandboxBroker;
+#endif
+  return XRE_XPCShellMain(argc, argv, envp, &shellData);
+}
+
+#ifdef MOZ_WIDGET_ANDROID
+#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, MOZ_APP_NAME, args)
+
+void
+BootstrapImpl::AndroidMain(JNIEnv* jenv, int argc, char* argv[])
+{
+  mozilla::jni::SetGeckoThreadEnv(jenv);
+
+#ifdef MOZ_CRASHREPORTER
+  const struct mapping_info *info = getLibraryMapping();
+  while (info->name) {
+    CrashReporter::AddLibraryMapping(info->name, info->base,
+                                     info->len, info->offset);
+    info++;
+  }
+#endif
+
+  if (!argv) {
+    LOG("Failed to get arguments for GeckoStart\n");
+    return;
+  }
+
+  XREAppData appData;
+  appData = *mStaticAppData;
+  int result = XRE_main(argc, argv, appData, 0);
+  if (result) {
+    LOG("XRE_main returned %d", result);
+  }
+}
+
+void
+BootstrapImpl::AndroidChildMain(int argc, char* argv[], int crashFd, int ipcFd)
+{
+#if defined(MOZ_CRASHREPORTER)
+  if (crashFd >= 0) {
+    CrashReporter::SetNotificationPipeForChild(crashFd);
+  }
+#endif // defined(MOZ_CRASHREPORTER)
+  if (ipcFd >= 0) {
+    IPC::Channel::SetClientChannelFd(ipcFd);
+  }
+
+  XRE_SetProcessType(argv[argc - 1]);
+  nsresult rv = XRE_InitChildProcess(argc - 1, argv, &mChildData);
+  if (NS_FAILED(rv)) {
+    LOG("XRE_InitChildProcess failed: nsresult %lx", (unsigned long)rv);
+  }
+}
+#endif // MOZ_WIDGET_ANDROID
+
+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,166 @@
+/* -*- 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 "GMPLoader.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WindowsDllBlocklist.h" // required for HAS_DLL_BLOCKLIST
+#include "nscore.h"
+#include "mozilla/XREAppData.h"
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#include "mozilla/sandboxing/loggingTypes.h"
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+#include <jni.h>
+#endif
+
+#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \
+  && !(defined(XP_LINUX) && defined(MOZ_SANDBOX))
+#define MOZ_BROWSER_CAN_BE_CONTENTPROC
+#endif
+
+#ifdef XP_MACOSX
+#define kOSXResourcesFolder "Resources"
+#endif
+
+#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
+#define BOOTSTRAP_HAS_GMPLOADER
+#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() { }
+
+public:
+  /**
+   * 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();
+    }
+  };
+  typedef mozilla::UniquePtr<Bootstrap, BootstrapDelete> UniquePtr;
+
+#if MOZ_WIDGET_GTK == 2
+  virtual void GlibInit() = 0;
+#endif
+
+  /**
+   * Set the default (compiled-in) browser app data that is used if the command
+   * line doens't contain an -app override.
+   */
+  virtual void SetDefaultAppData(const StaticXREAppData& staticAppData) = 0;
+
+  /**
+   * The calling app has to let us know where it found the platform DLLs.
+   */
+  virtual void SetXREDirectory(const char* directory) = 0;
+
+#ifdef HAS_DLL_BLOCKLIST
+  /**
+   * For later telemetry and unit testing, we record whether the blocklist
+   * was enabled successfully.
+   */
+  virtual void SetBlocklistEnabled(bool enabled) = 0;
+#endif
+
+  /**
+   * Record startup timeline events that happened before XUL loaded.
+   */
+  virtual void StartupTimelineRecord(int event, mozilla::TimeStamp when) = 0;
+
+#ifdef BOOTSTRAP_HAS_GMPLOADER
+  /**
+   * On desktop, the GMPLoader lives in plugin-container, so that its code
+   * can be covered by an EME/GMP vendor's voucher.
+   */
+  virtual void SetGMPLoader(mozilla::UniquePtr<mozilla::gmp::GMPLoader> gmpLoader) = 0;
+#endif
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  /**
+   * For sandboxed child processes, the sandbox target services and logging
+   * are initialized before XUL is loaded and passed in here.
+   */
+  virtual void SetSandboxTarget(sandbox::TargetServices*) = 0;
+  virtual void SetSandboxLogger(mozilla::sandboxing::ProvideLogFunctionCb callback) = 0;
+
+  /**
+   * For parent (main/xpcshell) processes, the sandbox broker services are
+   * initialized before XUL is loaded and passed in here.
+   */
+  virtual void SetSandboxBroker(sandbox::BrokerServices*) = 0;
+#endif
+
+  /**
+   * The guts of starting up the main browser app.
+   */
+  virtual int AppMain(int argc, char* argv[], char* envp[]) = 0;
+  virtual int ContentProcessMain(int argc, char* argv[]) = 0;
+  virtual int XPCShellMain(int argc, char* argv[], char* envp[]) = 0;
+
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void AndroidMain(JNIEnv* jenv, int argc, char* argv[]) = 0;
+
+  /**
+   * @param crashFd Pass -1 when unknown
+   * @param ipcFd Pass -1 when unknown
+   */
+  virtual void AndroidChildMain(int argc, char* argv[],
+                                int crashFd = -1, int ipcFd = -1) = 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.
+ * @note this function will initialize logging and set the XPCOM "main thread".
+ * @note Use the virtual destructor on the returned object before exiting
+ *       the process.
+ */
+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
@@ -17,16 +17,17 @@ XPIDL_SOURCES += [
 if CONFIG['OS_ARCH'] == 'WINNT':
     XPIDL_SOURCES += [
         'nsIWinAppHelper.idl',
     ]
 
 XPIDL_MODULE = 'xulapp'
 
 EXPORTS += ['nsAppRunner.h']
+EXPORTS.mozilla += ['Bootstrap.h']
 
 if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     EXPORTS += ['EventTracer.h']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     UNIFIED_SOURCES += [
         'nsNativeAppSupportWin.cpp',
     ]
@@ -58,22 +59,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3
         'nsGDKErrorHandler.cpp',
     ]
 
 if CONFIG['MOZ_X11']:
     UNIFIED_SOURCES += [
         'nsX11ErrorHandler.cpp',
     ]
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-    UNIFIED_SOURCES += [
-        'nsAndroidStartup.cpp',
-    ]
-
 UNIFIED_SOURCES += [
+    'Bootstrap.cpp',
     'CreateAppData.cpp',
     'nsConsoleWriter.cpp',
     'nsNativeAppSupportBase.cpp',
     'nsSigHandlers.cpp',
     'nsXREDirProvider.cpp',
 ]
 
 # nsAppRunner.cpp and ProfileReset.cpp cannot be built in unified mode because
@@ -140,16 +137,17 @@ if CONFIG['MOZ_BUILD_APP'] == 'browser':
 
 LOCAL_INCLUDES += [
     '../profile',
     '/config',
     '/dom/base',
     '/dom/ipc',
     '/testing/gtest/mozilla',
     '/toolkit/crashreporter',
+    '/xpcom/base',
     '/xpcom/build',
 ]
 
 if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/security/sandbox/chromium',
         '/security/sandbox/chromium-shim',
     ]
deleted file mode 100644
--- a/toolkit/xre/nsAndroidStartup.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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 <android/log.h>
-
-#include <jni.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-
-#include "mozilla/jni/Utils.h"
-#include "nsTArray.h"
-#include "nsString.h"
-#include "nsIFile.h"
-#include "nsAppRunner.h"
-#include "APKOpen.h"
-#include "nsExceptionHandler.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)
-{
-    mozilla::jni::SetGeckoThreadEnv(env);
-
-#ifdef MOZ_CRASHREPORTER
-    const struct mapping_info *info = getLibraryMapping();
-    while (info->name) {
-      CrashReporter::AddLibraryMapping(info->name, info->base,
-                                       info->len, info->offset);
-      info++;
-    }
-#endif
-
-    if (!argv) {
-        LOG("Failed to get arguments for GeckoStart\n");
-        return;
-    }
-
-    XREAppData appData;
-    appData = aAppData;
-
-    int result = XRE_main(argc, argv, appData, 0);
-
-    if (result)
-        LOG("XRE_main returned %d", result);
-}
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -410,26 +410,18 @@ void MozExpectedExit() {
  */
 static void UnexpectedExit() {
   if (!gIsExpectedExit) {
     gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
     MOZ_CRASH("Exit called by third party code.");
   }
 }
 
-/**
- * Output a string to the user.  This method is really only meant to be used to
- * output last-ditch error messages designed for developers NOT END USERS.
- *
- * @param isError
- *        Pass true to indicate severe errors.
- * @param fmt
- *        printf-style format string followed by arguments.
- */
-static void Output(bool isError, const char *fmt, ... )
+void
+Output(bool isError, const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   char *msg = PR_vsmprintf(fmt, ap);
   if (msg)
   {
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -109,16 +109,27 @@ UseParentConsole();
 BOOL
 WinLaunchChild(const wchar_t *exePath, int argc,
                char **argv, HANDLE userToken = nullptr,
                HANDLE *hProcess = nullptr);
 #endif
 
 #define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"
 
+/**
+ * Output a string to the user.  This method is really only meant to be used to
+ * output last-ditch error messages designed for developers NOT END USERS.
+ *
+ * @param isError
+ *        Pass true to indicate severe errors.
+ * @param fmt
+ *        printf-style format string followed by arguments.
+ */
+void Output(bool isError, const char* fmt, ...);
+
 namespace mozilla {
 namespace startup {
 extern GeckoProcessType sChildProcessType;
 } // namespace startup
 } // namespace mozilla
 
 /**
  * Set up platform specific error handling such as suppressing DLL load dialog
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -225,27 +225,16 @@ XRE_ChildProcessTypeToString(GeckoProces
 }
 
 namespace mozilla {
 namespace startup {
 GeckoProcessType sChildProcessType = GeckoProcessType_Default;
 } // namespace startup
 } // namespace mozilla
 
-#if defined(MOZ_WIDGET_ANDROID)
-void
-XRE_SetAndroidChildFds (int crashFd, int ipcFd)
-{
-#if defined(MOZ_CRASHREPORTER)
-  CrashReporter::SetNotificationPipeForChild(crashFd);
-#endif // defined(MOZ_CRASHREPORTER)
-  IPC::Channel::SetClientChannelFd(ipcFd);
-}
-#endif // defined(MOZ_WIDGET_ANDROID)
-
 void
 XRE_SetProcessType(const char* aProcessTypeString)
 {
   static bool called = false;
   if (called) {
     MOZ_CRASH();
   }
   called = true;
@@ -326,19 +315,19 @@ AddContentSandboxLevelAnnotation()
   }
 }
 #endif /* MOZ_CONTENT_SANDBOX && !MOZ_WIDGET_GONK */
 #endif /* MOZ_CRASHREPORTER */
 
 #if defined (XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 namespace {
 class LinuxSandboxStarter : public mozilla::gmp::SandboxStarter {
+public:
   LinuxSandboxStarter() { }
-public:
-  static SandboxStarter* Make() {
+  static UniquePtr<LinuxSandboxStarter> Make() {
     if (mozilla::SandboxInfo::Get().CanSandboxMedia()) {
       return new LinuxSandboxStarter();
     } else {
       // Sandboxing isn't possible, but the parent has already
       // checked that this plugin doesn't require it.  (Bug 1074561)
       return nullptr;
     }
     return nullptr;
@@ -374,21 +363,21 @@ XRE_InitChildProcess(int aArgc,
 #ifdef XP_LINUX
   // On Fennec, the GMPLoader's code resides inside XUL (because for the time
   // being GMPLoader relies upon NSPR, which we can't use in plugin-container
   // on Android), so we create it here inside XUL and pass it to the GMP code.
   //
   // On desktop Linux, the sandbox code lives in a shared library, and
   // the GMPLoader is in libxul instead of executables to avoid unwanted
   // library dependencies.
-  mozilla::gmp::SandboxStarter* starter = nullptr;
+  UniquePtr<mozilla::gmp::SandboxStarter> starter;
 #ifdef MOZ_GMP_SANDBOX
   starter = LinuxSandboxStarter::Make();
 #endif
-  UniquePtr<GMPLoader> loader = CreateGMPLoader(starter);
+  UniquePtr<GMPLoader> loader = CreateGMPLoader(Move(starter));
   GMPProcessChild::SetGMPLoader(loader.get());
 #else
   // On non-Linux platforms, the GMPLoader code resides in plugin-container,
   // and we must forward it through to the GMP code here.
   GMPProcessChild::SetGMPLoader(aChildData->gmpLoader.get());
 #endif
 
 #if defined(XP_WIN)
--- a/xpcom/build/BinaryPath.h
+++ b/xpcom/build/BinaryPath.h
@@ -12,16 +12,22 @@
 #include <windows.h>
 #elif defined(XP_MACOSX)
 #include <CoreFoundation/CoreFoundation.h>
 #elif defined(XP_UNIX)
 #include <sys/stat.h>
 #include <string.h>
 #endif
 
+#ifdef MOZILLA_INTERNAL_API
+#include "nsIFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#endif
+
 namespace mozilla {
 
 class BinaryPath
 {
 public:
 #ifdef XP_WIN
   static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
   {
@@ -150,16 +156,17 @@ private:
     return NS_ERROR_FAILURE;
   }
 
 #else
 #error Oops, you need platform-specific code here
 #endif
 
 public:
+#ifdef MOZILLA_INTERNAL_API
   static nsresult GetFile(const char* aArgv0, nsIFile** aResult)
   {
     nsCOMPtr<nsIFile> lf;
 #ifdef XP_WIN
     wchar_t exePath[MAXPATHLEN];
     nsresult rv = GetW(aArgv0, exePath);
 #else
     char exePath[MAXPATHLEN];
@@ -176,13 +183,14 @@ public:
                                getter_AddRefs(lf));
 #endif
     if (NS_FAILED(rv)) {
       return rv;
     }
     NS_ADDREF(*aResult = lf);
     return NS_OK;
   }
+#endif // MOZILLA_INTERNAL_API
 };
 
 } // namespace mozilla
 
 #endif /* mozilla_BinaryPath_h */
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -400,21 +400,16 @@ static const char* const kGeckoProcessTy
 
 static_assert(MOZ_ARRAY_LENGTH(kGeckoProcessTypeString) ==
               GeckoProcessType_End,
               "Array length mismatch");
 
 XRE_API(const char*,
         XRE_ChildProcessTypeToString, (GeckoProcessType aProcessType))
 
-#if defined(MOZ_WIDGET_ANDROID)
-XRE_API(void,
-        XRE_SetAndroidChildFds, (int crashFd, int ipcFd))
-#endif // defined(MOZ_WIDGET_ANDROID)
-
 XRE_API(void,
         XRE_SetProcessType, (const char* aProcessTypeString))
 
 #if defined(MOZ_CRASHREPORTER)
 // Used in the "master" parent process hosting the crash server
 XRE_API(bool,
         XRE_TakeMinidumpForChild, (uint32_t aChildPid, nsIFile** aDump,
                                    uint32_t* aSequence))
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -12,33 +12,41 @@
 #include "nsXPCOMPrivate.h"
 #include "nsCOMPtr.h"
 #include <stdlib.h>
 #include <stdio.h>
 
 #include "mozilla/FileUtils.h"
 #include "mozilla/Sprintf.h"
 
-using namespace mozilla;
+#ifdef XP_WIN
+#include <windows.h>
+#include <mbstring.h>
+#else
+#include <dlfcn.h>
+#endif
+
+#if defined(MOZ_WIDGET_GTK) && (defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__))
+#define MOZ_GSLICE_INIT
+#include <glib.h>
+#endif
+
+namespace mozilla {
 
 #define XPCOM_DEPENDENT_LIBS_LIST "dependentlibs.list"
 
-static XPCOMFunctions xpcomFunctions;
 static bool do_preload = false;
 
 #if defined(XP_WIN)
 #define READ_TEXTMODE L"rt"
 #else
 #define READ_TEXTMODE "r"
 #endif
 
 #if defined(XP_WIN)
-#include <windows.h>
-#include <mbstring.h>
-
 typedef HINSTANCE LibHandleType;
 
 static LibHandleType
 GetLibHandle(pathstr_t aDependentLib)
 {
   LibHandleType libHandle =
     LoadLibraryExW(aDependentLib, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
 
@@ -60,31 +68,22 @@ GetLibHandle(pathstr_t aDependentLib)
     wprintf(L"Error loading %ls: %s\n", aDependentLib, lpMsgBuf);
     LocalFree(lpMsgBuf);
   }
 #endif
 
   return libHandle;
 }
 
-static NSFuncPtr
+static GetBootstrapType
 GetSymbol(LibHandleType aLibHandle, const char* aSymbol)
 {
-  return (NSFuncPtr)GetProcAddress(aLibHandle, aSymbol);
+  return (GetBootstrapType)GetProcAddress(aLibHandle, aSymbol);
 }
-
-static void
-CloseLibHandle(LibHandleType aLibHandle)
-{
-  FreeLibrary(aLibHandle);
-}
-
 #else
-#include <dlfcn.h>
-
 #if defined(MOZ_LINKER) && !defined(ANDROID)
 extern "C" {
 NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
 NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
 NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
 }
 
 #define dlopen __wrap_dlopen
@@ -105,26 +104,20 @@ GetLibHandle(pathstr_t aDependentLib)
                                    );
   if (!libHandle) {
     fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", aDependentLib,
             dlerror());
   }
   return libHandle;
 }
 
-static NSFuncPtr
+static GetBootstrapType
 GetSymbol(LibHandleType aLibHandle, const char* aSymbol)
 {
-  return (NSFuncPtr)dlsym(aLibHandle, aSymbol);
-}
-
-static void
-CloseLibHandle(LibHandleType aLibHandle)
-{
-  dlclose(aLibHandle);
+  return (GetBootstrapType)dlsym(aLibHandle, aSymbol);
 }
 #endif
 
 struct DependentLib
 {
   LibHandleType libHandle;
   DependentLib* next;
 };
@@ -192,29 +185,16 @@ struct ScopedCloseFileTraits
   {
     if (aFile) {
       fclose(aFile);
     }
   }
 };
 typedef Scoped<ScopedCloseFileTraits> ScopedCloseFile;
 
-static void
-XPCOMGlueUnload()
-{
-  while (sTop) {
-    CloseLibHandle(sTop->libHandle);
-
-    DependentLib* temp = sTop;
-    sTop = sTop->next;
-
-    delete temp;
-  }
-}
-
 #if defined(XP_WIN)
 // like strpbrk but finds the *last* char, not the first
 static const char*
 ns_strrpbrk(const char* string, const char* strCharSet)
 {
   const char* found = nullptr;
   for (; *string; ++string) {
     for (const char* search = strCharSet; *search; ++search) {
@@ -225,17 +205,17 @@ ns_strrpbrk(const char* string, const ch
       }
     }
   }
 
   return found;
 }
 #endif
 
-static GetFrozenFunctionsFunc
+static GetBootstrapType
 XPCOMGlueLoad(const char* aXPCOMFile)
 {
   char xpcomDir[MAXPATHLEN];
 #ifdef XP_WIN
   const char* lastSlash = ns_strrpbrk(aXPCOMFile, "/\\");
 #elif XP_MACOSX
   // On OSX, the dependentlibs.list file lives under Contents/Resources.
   // However, the actual libraries listed in dependentlibs.list live under
@@ -316,67 +296,30 @@ XPCOMGlueLoad(const char* aXPCOMFile)
     }
 
     if (l + size_t(cursor - xpcomDir) > MAXPATHLEN) {
       return nullptr;
     }
 
     strcpy(cursor, buffer);
     if (!ReadDependentCB(xpcomDir, do_preload)) {
-      XPCOMGlueUnload();
       return nullptr;
     }
   }
 
-  GetFrozenFunctionsFunc sym =
-    (GetFrozenFunctionsFunc)GetSymbol(sTop->libHandle,
-                                      "NS_GetFrozenFunctions");
-
-  if (!sym) { // No symbol found.
-    XPCOMGlueUnload();
-    return nullptr;
-  }
-
-  return sym;
-}
-
-nsresult
-XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad* aSymbols)
-{
-  // We don't null-check sXULLibHandle because this might work even
-  // if it is null (same as RTLD_DEFAULT)
-
-  nsresult rv = NS_OK;
-  while (aSymbols->functionName) {
-    char buffer[512];
-    SprintfLiteral(buffer, "%s", aSymbols->functionName);
-
-    *aSymbols->function = (NSFuncPtr)GetSymbol(sTop->libHandle, buffer);
-    if (!*aSymbols->function) {
-      rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
-    }
-
-    ++aSymbols;
-  }
-  return rv;
+  return GetSymbol(sTop->libHandle, "XRE_GetBootstrap");
 }
 
 void
 XPCOMGlueEnablePreload()
 {
   do_preload = true;
 }
 
-#if defined(MOZ_WIDGET_GTK) && (defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__))
-#define MOZ_GSLICE_INIT
-#endif
-
 #ifdef MOZ_GSLICE_INIT
-#include <glib.h>
-
 class GSliceInit {
 public:
   GSliceInit() {
     mHadGSlice = bool(getenv("G_SLICE"));
     if (!mHadGSlice) {
       // Disable the slice allocator, since jemalloc already uses similar layout
       // algorithms, and using a sub-allocator tends to increase fragmentation.
       // This must be done before g_thread_init() is called.
@@ -384,544 +327,47 @@ public:
       // initializers, so this needs to happen before glib is loaded, which is
       // this is hooked in XPCOMGlueStartup before libxul is loaded. This
       // relies on the main executable not depending on glib.
       setenv("G_SLICE", "always-malloc", 1);
     }
   }
 
   ~GSliceInit() {
-#if MOZ_WIDGET_GTK == 2
-    if (sTop) {
-      auto XRE_GlibInit = (void (*)(void)) GetSymbol(sTop->libHandle,
-        "XRE_GlibInit");
-      // Initialize glib enough for G_SLICE to have an effect before it is unset.
-      // unset.
-      XRE_GlibInit();
-    }
-#endif
     if (!mHadGSlice) {
       unsetenv("G_SLICE");
     }
   }
 
 private:
   bool mHadGSlice;
 };
 #endif
 
-nsresult
+Bootstrap::UniquePtr
 XPCOMGlueStartup(const char* aXPCOMFile)
 {
 #ifdef MOZ_GSLICE_INIT
-  GSliceInit gSliceInit;
+  GSliceInit();
 #endif
-  xpcomFunctions.version = XPCOM_GLUE_VERSION;
-  xpcomFunctions.size    = sizeof(XPCOMFunctions);
 
   if (!aXPCOMFile) {
     aXPCOMFile = XPCOM_DLL;
   }
 
-  GetFrozenFunctionsFunc func = XPCOMGlueLoad(aXPCOMFile);
+  GetBootstrapType func = XPCOMGlueLoad(aXPCOMFile);
   if (!func) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  nsresult rv = (*func)(&xpcomFunctions, nullptr);
-  if (NS_FAILED(rv)) {
-    XPCOMGlueUnload();
-    return rv;
-  }
-
-  return NS_OK;
-}
-
-XPCOM_API(nsresult)
-NS_InitXPCOM2(nsIServiceManager** aResult,
-              nsIFile* aBinDirectory,
-              nsIDirectoryServiceProvider* aAppFileLocationProvider)
-{
-  if (!xpcomFunctions.init) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.init(aResult, aBinDirectory, aAppFileLocationProvider);
-}
-
-XPCOM_API(nsresult)
-NS_ShutdownXPCOM(nsIServiceManager* aServMgr)
-{
-  if (!xpcomFunctions.shutdown) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.shutdown(aServMgr);
-}
-
-XPCOM_API(nsresult)
-NS_GetServiceManager(nsIServiceManager** aResult)
-{
-  if (!xpcomFunctions.getServiceManager) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.getServiceManager(aResult);
-}
-
-XPCOM_API(nsresult)
-NS_GetComponentManager(nsIComponentManager** aResult)
-{
-  if (!xpcomFunctions.getComponentManager) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.getComponentManager(aResult);
-}
-
-XPCOM_API(nsresult)
-NS_GetComponentRegistrar(nsIComponentRegistrar** aResult)
-{
-  if (!xpcomFunctions.getComponentRegistrar) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.getComponentRegistrar(aResult);
-}
-
-XPCOM_API(nsresult)
-NS_GetMemoryManager(nsIMemory** aResult)
-{
-  if (!xpcomFunctions.getMemoryManager) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.getMemoryManager(aResult);
-}
-
-XPCOM_API(nsresult)
-NS_NewLocalFile(const nsAString& aPath, bool aFollowLinks, nsIFile** aResult)
-{
-  if (!xpcomFunctions.newLocalFile) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.newLocalFile(aPath, aFollowLinks, aResult);
-}
-
-XPCOM_API(nsresult)
-NS_NewNativeLocalFile(const nsACString& aPath, bool aFollowLinks,
-                      nsIFile** aResult)
-{
-  if (!xpcomFunctions.newNativeLocalFile) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.newNativeLocalFile(aPath, aFollowLinks, aResult);
-}
-
-XPCOM_API(nsresult)
-NS_GetDebug(nsIDebug2** aResult)
-{
-  if (!xpcomFunctions.getDebug) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.getDebug(aResult);
-}
-
-
-XPCOM_API(nsresult)
-NS_StringContainerInit(nsStringContainer& aStr)
-{
-  if (!xpcomFunctions.stringContainerInit) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.stringContainerInit(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_StringContainerInit2(nsStringContainer& aStr, const char16_t* aData,
-                        uint32_t aDataLength, uint32_t aFlags)
-{
-  if (!xpcomFunctions.stringContainerInit2) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.stringContainerInit2(aStr, aData, aDataLength, aFlags);
-}
-
-XPCOM_API(void)
-NS_StringContainerFinish(nsStringContainer& aStr)
-{
-  if (xpcomFunctions.stringContainerFinish) {
-    xpcomFunctions.stringContainerFinish(aStr);
-  }
-}
-
-XPCOM_API(uint32_t)
-NS_StringGetData(const nsAString& aStr, const char16_t** aBuf, bool* aTerm)
-{
-  if (!xpcomFunctions.stringGetData) {
-    *aBuf = nullptr;
-    return 0;
-  }
-  return xpcomFunctions.stringGetData(aStr, aBuf, aTerm);
-}
-
-XPCOM_API(uint32_t)
-NS_StringGetMutableData(nsAString& aStr, uint32_t aLen, char16_t** aBuf)
-{
-  if (!xpcomFunctions.stringGetMutableData) {
-    *aBuf = nullptr;
-    return 0;
-  }
-  return xpcomFunctions.stringGetMutableData(aStr, aLen, aBuf);
-}
-
-XPCOM_API(char16_t*)
-NS_StringCloneData(const nsAString& aStr)
-{
-  if (!xpcomFunctions.stringCloneData) {
-    return nullptr;
-  }
-  return xpcomFunctions.stringCloneData(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_StringSetData(nsAString& aStr, const char16_t* aBuf, uint32_t aCount)
-{
-  if (!xpcomFunctions.stringSetData) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  return xpcomFunctions.stringSetData(aStr, aBuf, aCount);
-}
-
-XPCOM_API(nsresult)
-NS_StringSetDataRange(nsAString& aStr, uint32_t aCutStart, uint32_t aCutLength,
-                      const char16_t* aBuf, uint32_t aCount)
-{
-  if (!xpcomFunctions.stringSetDataRange) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.stringSetDataRange(aStr, aCutStart, aCutLength, aBuf,
-                                           aCount);
-}
-
-XPCOM_API(nsresult)
-NS_StringCopy(nsAString& aDest, const nsAString& aSrc)
-{
-  if (!xpcomFunctions.stringCopy) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.stringCopy(aDest, aSrc);
-}
-
-XPCOM_API(void)
-NS_StringSetIsVoid(nsAString& aStr, const bool aIsVoid)
-{
-  if (xpcomFunctions.stringSetIsVoid) {
-    xpcomFunctions.stringSetIsVoid(aStr, aIsVoid);
-  }
-}
-
-XPCOM_API(bool)
-NS_StringGetIsVoid(const nsAString& aStr)
-{
-  if (!xpcomFunctions.stringGetIsVoid) {
-    return false;
-  }
-  return xpcomFunctions.stringGetIsVoid(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_CStringContainerInit(nsCStringContainer& aStr)
-{
-  if (!xpcomFunctions.cstringContainerInit) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringContainerInit(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_CStringContainerInit2(nsCStringContainer& aStr, const char* aData,
-                         uint32_t aDataLength, uint32_t aFlags)
-{
-  if (!xpcomFunctions.cstringContainerInit2) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringContainerInit2(aStr, aData, aDataLength, aFlags);
-}
-
-XPCOM_API(void)
-NS_CStringContainerFinish(nsCStringContainer& aStr)
-{
-  if (xpcomFunctions.cstringContainerFinish) {
-    xpcomFunctions.cstringContainerFinish(aStr);
-  }
-}
-
-XPCOM_API(uint32_t)
-NS_CStringGetData(const nsACString& aStr, const char** aBuf, bool* aTerm)
-{
-  if (!xpcomFunctions.cstringGetData) {
-    *aBuf = nullptr;
-    return 0;
-  }
-  return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm);
-}
-
-XPCOM_API(uint32_t)
-NS_CStringGetMutableData(nsACString& aStr, uint32_t aLen, char** aBuf)
-{
-  if (!xpcomFunctions.cstringGetMutableData) {
-    *aBuf = nullptr;
-    return 0;
-  }
-  return xpcomFunctions.cstringGetMutableData(aStr, aLen, aBuf);
-}
-
-XPCOM_API(char*)
-NS_CStringCloneData(const nsACString& aStr)
-{
-  if (!xpcomFunctions.cstringCloneData) {
-    return nullptr;
-  }
-  return xpcomFunctions.cstringCloneData(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_CStringSetData(nsACString& aStr, const char* aBuf, uint32_t aCount)
-{
-  if (!xpcomFunctions.cstringSetData) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringSetData(aStr, aBuf, aCount);
-}
-
-XPCOM_API(nsresult)
-NS_CStringSetDataRange(nsACString& aStr, uint32_t aCutStart,
-                       uint32_t aCutLength, const char* aBuf, uint32_t aCount)
-{
-  if (!xpcomFunctions.cstringSetDataRange) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringSetDataRange(aStr, aCutStart, aCutLength, aBuf,
-                                            aCount);
-}
-
-XPCOM_API(nsresult)
-NS_CStringCopy(nsACString& aDest, const nsACString& aSrc)
-{
-  if (!xpcomFunctions.cstringCopy) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringCopy(aDest, aSrc);
-}
-
-XPCOM_API(void)
-NS_CStringSetIsVoid(nsACString& aStr, const bool aIsVoid)
-{
-  if (xpcomFunctions.cstringSetIsVoid) {
-    xpcomFunctions.cstringSetIsVoid(aStr, aIsVoid);
-  }
-}
-
-XPCOM_API(bool)
-NS_CStringGetIsVoid(const nsACString& aStr)
-{
-  if (!xpcomFunctions.cstringGetIsVoid) {
-    return false;
-  }
-  return xpcomFunctions.cstringGetIsVoid(aStr);
-}
-
-XPCOM_API(nsresult)
-NS_CStringToUTF16(const nsACString& aSrc, nsCStringEncoding aSrcEncoding,
-                  nsAString& aDest)
-{
-  if (!xpcomFunctions.cstringToUTF16) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest);
-}
-
-XPCOM_API(nsresult)
-NS_UTF16ToCString(const nsAString& aSrc, nsCStringEncoding aDestEncoding,
-                  nsACString& aDest)
-{
-  if (!xpcomFunctions.utf16ToCString) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest);
-}
-
-XPCOM_API(void*)
-NS_Alloc(size_t aSize)
-{
-  if (!xpcomFunctions.allocFunc) {
-    return nullptr;
-  }
-  return xpcomFunctions.allocFunc(aSize);
-}
-
-XPCOM_API(void*)
-NS_Realloc(void* aPtr, size_t aSize)
-{
-  if (!xpcomFunctions.reallocFunc) {
-    return nullptr;
-  }
-  return xpcomFunctions.reallocFunc(aPtr, aSize);
-}
-
-XPCOM_API(void)
-NS_Free(void* aPtr)
-{
-  if (xpcomFunctions.freeFunc) {
-    xpcomFunctions.freeFunc(aPtr);
-  }
-}
-
-XPCOM_API(void)
-NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr,
-              const char* aFile, int32_t aLine)
-{
-  if (xpcomFunctions.debugBreakFunc) {
-    xpcomFunctions.debugBreakFunc(aSeverity, aStr, aExpr, aFile, aLine);
-  }
-}
-
-XPCOM_API(void)
-NS_LogInit()
-{
-  if (xpcomFunctions.logInitFunc) {
-    xpcomFunctions.logInitFunc();
-  }
-}
-
-XPCOM_API(void)
-NS_LogTerm()
-{
-  if (xpcomFunctions.logTermFunc) {
-    xpcomFunctions.logTermFunc();
-  }
-}
-
-XPCOM_API(void)
-NS_LogAddRef(void* aPtr, nsrefcnt aNewRefCnt,
-             const char* aTypeName, uint32_t aInstanceSize)
-{
-  if (xpcomFunctions.logAddRefFunc)
-    xpcomFunctions.logAddRefFunc(aPtr, aNewRefCnt,
-                                 aTypeName, aInstanceSize);
-}
-
-XPCOM_API(void)
-NS_LogRelease(void* aPtr, nsrefcnt aNewRefCnt, const char* aTypeName)
-{
-  if (xpcomFunctions.logReleaseFunc) {
-    xpcomFunctions.logReleaseFunc(aPtr, aNewRefCnt, aTypeName);
-  }
-}
-
-XPCOM_API(void)
-NS_LogCtor(void* aPtr, const char* aTypeName, uint32_t aInstanceSize)
-{
-  if (xpcomFunctions.logCtorFunc) {
-    xpcomFunctions.logCtorFunc(aPtr, aTypeName, aInstanceSize);
-  }
-}
-
-XPCOM_API(void)
-NS_LogDtor(void* aPtr, const char* aTypeName, uint32_t aInstanceSize)
-{
-  if (xpcomFunctions.logDtorFunc) {
-    xpcomFunctions.logDtorFunc(aPtr, aTypeName, aInstanceSize);
-  }
-}
-
-XPCOM_API(void)
-NS_LogCOMPtrAddRef(void* aCOMPtr, nsISupports* aObject)
-{
-  if (xpcomFunctions.logCOMPtrAddRefFunc) {
-    xpcomFunctions.logCOMPtrAddRefFunc(aCOMPtr, aObject);
-  }
-}
-
-XPCOM_API(void)
-NS_LogCOMPtrRelease(void* aCOMPtr, nsISupports* aObject)
-{
-  if (xpcomFunctions.logCOMPtrReleaseFunc) {
-    xpcomFunctions.logCOMPtrReleaseFunc(aCOMPtr, aObject);
-  }
-}
-
-XPCOM_API(nsresult)
-NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
-                  nsISomeInterface** aStub)
-{
-  if (!xpcomFunctions.getXPTCallStubFunc) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  return xpcomFunctions.getXPTCallStubFunc(aIID, aOuter, aStub);
-}
-
-XPCOM_API(void)
-NS_DestroyXPTCallStub(nsISomeInterface* aStub)
-{
-  if (xpcomFunctions.destroyXPTCallStubFunc) {
-    xpcomFunctions.destroyXPTCallStubFunc(aStub);
-  }
-}
-
-XPCOM_API(nsresult)
-NS_InvokeByIndex(nsISupports* aThat, uint32_t aMethodIndex,
-                 uint32_t aParamCount, nsXPTCVariant* aParams)
-{
-  if (!xpcomFunctions.invokeByIndexFunc) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  return xpcomFunctions.invokeByIndexFunc(aThat, aMethodIndex,
-                                          aParamCount, aParams);
-}
-
-XPCOM_API(bool)
-NS_CycleCollectorSuspect(nsISupports* aObj)
-{
-  if (!xpcomFunctions.cycleSuspectFunc) {
-    return false;
-  }
-
-  return xpcomFunctions.cycleSuspectFunc(aObj);
-}
-
-XPCOM_API(bool)
-NS_CycleCollectorForget(nsISupports* aObj)
-{
-  if (!xpcomFunctions.cycleForgetFunc) {
-    return false;
-  }
-
-  return xpcomFunctions.cycleForgetFunc(aObj);
-}
-
-XPCOM_API(nsPurpleBufferEntry*)
-NS_CycleCollectorSuspect2(void* aObj, nsCycleCollectionParticipant* aCp)
-{
-  if (!xpcomFunctions.cycleSuspect2Func) {
     return nullptr;
   }
 
-  return xpcomFunctions.cycleSuspect2Func(aObj, aCp);
+  Bootstrap::UniquePtr b;
+  (*func)(b);
+
+#if defined(MOZ_GSLICE_INIT) && MOZ_WIDGET_GTK == 2
+  if (b) {
+    b->GlibInit();
+  }
+#endif
+
+  return b;
 }
 
-XPCOM_API(void)
-NS_CycleCollectorSuspect3(void* aObj, nsCycleCollectionParticipant* aCp,
-                          nsCycleCollectingAutoRefCnt* aRefCnt,
-                          bool* aShouldDelete)
-{
-  if (xpcomFunctions.cycleSuspect3Func) {
-    xpcomFunctions.cycleSuspect3Func(aObj, aCp, aRefCnt, aShouldDelete);
-  }
-}
-
-XPCOM_API(bool)
-NS_CycleCollectorForget2(nsPurpleBufferEntry* aEntry)
-{
-  if (!xpcomFunctions.cycleForget2Func) {
-    return false;
-  }
-
-  return xpcomFunctions.cycleForget2Func(aEntry);
-}
+} // namespace mozilla
--- a/xpcom/glue/standalone/nsXPCOMGlue.h
+++ b/xpcom/glue/standalone/nsXPCOMGlue.h
@@ -2,48 +2,30 @@
 /* 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 nsXPCOMGlue_h__
 #define nsXPCOMGlue_h__
 
-#include "nscore.h"
-
-#ifdef XPCOM_GLUE
+#ifdef MOZILLA_INTERNAL_API
+#error This file only makes sense outside of xul.
+#endif
 
-/**
- * The following functions are only available in the standalone glue.
- */
+#include "mozilla/Bootstrap.h"
+
+namespace mozilla {
 
 /**
  * Enabled preloading of dynamically loaded libraries
  */
-extern "C" NS_HIDDEN_(void) XPCOMGlueEnablePreload();
+void XPCOMGlueEnablePreload();
 
 /**
  * Initialize the XPCOM glue by dynamically linking against the XPCOM
  * shared library indicated by xpcomFile.
  */
-extern "C" NS_HIDDEN_(nsresult) XPCOMGlueStartup(const char* aXPCOMFile);
-
-typedef void (*NSFuncPtr)();
-
-struct nsDynamicFunctionLoad
-{
-  const char* functionName;
-  NSFuncPtr* function;
-};
+Bootstrap::UniquePtr XPCOMGlueStartup(const char* aXPCOMFile);
 
-/**
- * Dynamically load functions from libxul.
- *
- * @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
 
-#endif // XPCOM_GLUE
 #endif // nsXPCOMGlue_h__