Bug 1306327 - Use the new XRE Bootstrap API in Firefox for Android. r=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Sat, 17 Dec 2016 06:48:01 +0900
changeset 357845 517720b458ce9f10734b8fbf6943ca1a47066f42
parent 357844 2a0edcbaebeeae1cd4cf1be3b0db127fa3bdd01f
child 357846 908c2d41eeaafc34697261866d36206bfe896e4b
push id10621
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 16:02:43 +0000
treeherdermozilla-aurora@dca7b42e6c67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1306327
milestone53.0a1
Bug 1306327 - Use the new XRE Bootstrap API in Firefox for Android. r=bsmedberg Here, we also modify APKOpen to use the XPCOM glue loading process instead of custom symbol resolution, so that the Bootstrap API can be used in a more straightforward manner.
mozglue/android/APKOpen.cpp
mozglue/android/moz.build
python/mozbuild/mozbuild/frontend/emitter.py
xpcom/glue/standalone/nsXPCOMGlue.cpp
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -28,19 +28,21 @@
 #include <sys/resource.h>
 #include <sys/prctl.h>
 #include "sqlite3.h"
 #include "SQLiteBridge.h"
 #include "NSSBridge.h"
 #include "ElfLoader.h"
 #include "application.ini.h"
 
+#include "mozilla/Bootstrap.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 #include "XREChildData.h"
+#include "nsXPCOMGlue.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 +163,28 @@ getJavaUiThread()
 }
 
 extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_GeckoThread_registerUiThread(JNIEnv*, jclass)
 {
     sJavaUiThread = pthread_self();
 }
 
-static void * xul_handle = nullptr;
+Bootstrap::UniquePtr gBootstrap;
 #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;
 
@@ -209,46 +205,50 @@ delete_mapping(const char *name)
       free(info->name);
       *info = *last;
       --mapping_count;
       break;
     }
   }
 }
 
-static void*
-dlopenAPKLibrary(const char* apkName, const char* libraryName)
+static UniquePtr<char[]>
+getAPKLibraryName(const char* apkName, const char* libraryName)
 {
 #define APK_ASSETS_PATH "!/assets/" ANDROID_CPU_ARCH "/"
   size_t filenameLength = strlen(apkName) +
     sizeof(APK_ASSETS_PATH) + 	// includes \0 terminator
     strlen(libraryName);
   auto file = MakeUnique<char[]>(filenameLength);
   snprintf(file.get(), filenameLength, "%s" APK_ASSETS_PATH "%s",
 	   apkName, libraryName);
-  return __wrap_dlopen(file.get(), RTLD_GLOBAL | RTLD_LAZY);
+  return file;
 #undef APK_ASSETS_PATH
 }
+
+static void*
+dlopenAPKLibrary(const char* apkName, const char* libraryName)
+{
+  return __wrap_dlopen(getAPKLibraryName(apkName, libraryName).get(), RTLD_GLOBAL | RTLD_LAZY);
+}
+
 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");
-  if (!xul_handle) {
+  gBootstrap = GetBootstrap(getAPKLibraryName(apkName, "libxul.so").get());
+  if (!gBootstrap) {
     __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);
-
   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 + \
    (u2.ru_ ## field.tv_usec - u1.ru_ ## field.tv_usec) / 1000)
@@ -257,18 +257,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);
+  gBootstrap->XRE_StartupTimelineRecord(LINKER_INITIALIZED, t0);
+  gBootstrap->XRE_StartupTimelineRecord(LIBRARIES_LOADED, t1);
   return SUCCESS;
 }
 
 static mozglueresult loadNSSLibs(const char *apkName);
 
 static mozglueresult
 loadSQLiteLibs(const char *apkName)
 {
@@ -439,54 +439,40 @@ FreeArgv(char** argv, int argc)
 {
   for (int ix=0; ix < argc; ix++) {
     // String was allocated with strndup, so need to use free to deallocate.
     free(argv[ix]);
   }
   delete[](argv);
 }
 
-typedef void (*GeckoStart_t)(JNIEnv*, char**, int, const StaticXREAppData&);
-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) {
+    if (gBootstrap == nullptr) {
       FreeArgv(argv, argc);
       return;
     }
 
     ElfLoader::Singleton.ExpectShutdown(false);
-    GeckoStart(jenv, argv, argc, sAppData);
+    gBootstrap->GeckoStart(jenv, argv, argc, sAppData);
     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]);
+    gBootstrap->XRE_SetAndroidChildFds(crashFd, ipcFd);
+    gBootstrap->XRE_SetProcessType(argv[argc - 1]);
 
     XREChildData childData;
-    fXRE_InitChildProcess(argc - 1, argv, &childData);
+    gBootstrap->XRE_InitChildProcess(argc - 1, argv, &childData);
   }
 
+  gBootstrap.reset();
   FreeArgv(argv, argc);
 }
 
 extern "C" APKOPEN_EXPORT mozglueresult
 ChildProcessInit(int argc, char* argv[])
 {
   int i;
   for (i = 0; i < (argc - 1); i++) {
@@ -502,20 +488,14 @@ 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]);
+  gBootstrap->XRE_SetProcessType(argv[--argc]);
 
   XREChildData childData;
-  return fXRE_InitChildProcess(argc, argv, &childData);
+  return NS_FAILED(gBootstrap->XRE_InitChildProcess(argc, argv, &childData));
 }
 
--- a/mozglue/android/moz.build
+++ b/mozglue/android/moz.build
@@ -51,8 +51,14 @@ LOCAL_INCLUDES += [
     '/toolkit/components/startup',
     '/xpcom/build',
 ]
 
 DISABLE_STL_WRAPPING = True
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
+
+DEFINES['XPCOM_GLUE'] = True
+
+USE_LIBS += [
+    'xpcomglue',
+]
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -389,16 +389,18 @@ class TreeMetadataEmitter(LoggingMixin):
                 # source dir.
                 moz_build_app = moz_build_app[3:]
             extra_allowed = [
                 (substs.get('MOZ_APP_NAME'), '%s/app' % moz_build_app),
                 ('%s-bin' % substs.get('MOZ_APP_NAME'), '%s/app' % moz_build_app),
             ]
         if substs.get('MOZ_WIDGET_TOOLKIT') != 'android':
             extra_allowed.append((substs.get('MOZ_CHILD_PROCESS_NAME'), 'ipc/app'))
+        else:
+            extra_allowed.append(('mozglue_android', 'mozglue/android'))
 
         if key in ALLOWED_XPCOM_GLUE or key in extra_allowed:
             if not use_xpcom:
                 raise SandboxValidationError(
                     "%s is in the exception list for XPCOM glue dependency but "
                     "doesn't depend on the XPCOM glue. Please adjust the list "
                     "in %s." % (obj.name, __file__), context
                 )
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -74,17 +74,17 @@ static void
 CloseLibHandle(LibHandleType aLibHandle)
 {
   FreeLibrary(aLibHandle);
 }
 
 #else
 #include <dlfcn.h>
 
-#if defined(MOZ_LINKER) && !defined(ANDROID)
+#if defined(MOZ_LINKER)
 extern "C" {
 NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
 NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
 NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
 }
 
 #define dlopen __wrap_dlopen
 #define dlsym __wrap_dlsym
@@ -142,18 +142,20 @@ AppendDependentLib(LibHandleType aLibHan
   d->libHandle = aLibHandle;
 
   sTop = d;
 }
 
 static bool
 ReadDependentCB(pathstr_t aDependentLib)
 {
+#ifndef MOZ_LINKER
   // We do this unconditionally because of data in bug 771745
   ReadAheadLib(aDependentLib);
+#endif
   LibHandleType libHandle = GetLibHandle(aDependentLib);
   if (libHandle) {
     AppendDependentLib(libHandle);
   }
 
   return libHandle;
 }
 
@@ -226,16 +228,21 @@ ns_strrpbrk(const char* string, const ch
 
   return found;
 }
 #endif
 
 static GetFrozenFunctionsFunc
 XPCOMGlueLoad(const char* aXPCOMFile)
 {
+#ifdef MOZ_LINKER
+  if (!ReadDependentCB(aXPCOMFile)) {
+    return nullptr;
+  }
+#else
   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
   // Contents/MacOS. We want to read the list from Contents/Resources, then
   // load the libraries from Contents/MacOS.
@@ -318,16 +325,17 @@ XPCOMGlueLoad(const char* aXPCOMFile)
     }
 
     strcpy(cursor, buffer);
     if (!ReadDependentCB(xpcomDir)) {
       XPCOMGlueUnload();
       return nullptr;
     }
   }
+#endif
 
   GetFrozenFunctionsFunc sym =
     (GetFrozenFunctionsFunc)GetSymbol(sTop->libHandle,
                                       "NS_GetFrozenFunctions");
 
   if (!sym) { // No symbol found.
     XPCOMGlueUnload();
     return nullptr;