Skip to content

Commit

Permalink
Bug 977026 - Part 2: B2G loader. r=khuey, r=cyu
Browse files Browse the repository at this point in the history
--HG--
rename : ipc/app/MozillaRuntimeMain.cpp => ipc/contentproc/plugin-container.cpp
  • Loading branch information
ThinkerYzu committed Jul 30, 2014
1 parent 46cefdd commit e9dc84b
Show file tree
Hide file tree
Showing 20 changed files with 1,187 additions and 149 deletions.
167 changes: 167 additions & 0 deletions b2g/app/B2GLoader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 autoindent cindent expandtab: */
/* 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 "nsXPCOMGlue.h"
#include "nsStringGlue.h"
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "BinaryPath.h"
#include "nsAutoPtr.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <dlfcn.h>

#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL

#define ASSERT(x) if (!(x)) { MOZ_CRASH(); }


// Functions being loaded by XPCOMGlue
XRE_ProcLoaderServiceRunType XRE_ProcLoaderServiceRun;
XRE_ProcLoaderClientInitType XRE_ProcLoaderClientInit;

static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_ProcLoaderServiceRun", (NSFuncPtr*) &XRE_ProcLoaderServiceRun },
{ "XRE_ProcLoaderClientInit", (NSFuncPtr*) &XRE_ProcLoaderClientInit },
{ nullptr, nullptr }
};

static int
GetDirnameSlash(const char *aPath, char *aOutDir, int aMaxLen)
{
char *lastSlash = strrchr(aPath, XPCOM_FILE_PATH_SEPARATOR[0]);
if (lastSlash == nullptr) {
return 0;
}
int cpsz = lastSlash - aPath + 1; // include slash
if (aMaxLen <= cpsz) {
return 0;
}
strncpy(aOutDir, aPath, cpsz);
aOutDir[cpsz] = 0;
return cpsz;
}

static bool
GetXPCOMPath(const char *aProgram, char *aOutPath, int aMaxLen)
{
nsAutoArrayPtr<char> progBuf(new char[aMaxLen]);
nsresult rv = mozilla::BinaryPath::Get(aProgram, progBuf);
NS_ENSURE_SUCCESS(rv, false);

int len = GetDirnameSlash(progBuf, aOutPath, aMaxLen);
NS_ENSURE_TRUE(!!len, false);

NS_ENSURE_TRUE((len + sizeof(XPCOM_DLL)) < aMaxLen, false);
char *afterSlash = aOutPath + len;
strcpy(afterSlash, XPCOM_DLL);
return true;
}

static bool
LoadLibxul(const char *aXPCOMPath)
{
nsresult rv;

XPCOMGlueEnablePreload();
rv = XPCOMGlueStartup(aXPCOMPath);
NS_ENSURE_SUCCESS(rv, false);

rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
NS_ENSURE_SUCCESS(rv, false);

return true;
}

static bool
LoadStaticData(const char *aProgram)
{
char xpcomPath[MAXPATHLEN];
bool ok = GetXPCOMPath(aProgram, xpcomPath, MAXPATHLEN);
NS_ENSURE_TRUE(ok, false);

ok = LoadLibxul(xpcomPath);
return ok;
}

/**
* Fork and run parent and child process.
*
* The parent is the b2g process and child for Nuwa.
*/
static int
RunProcesses(int argc, const char *argv[])
{
/*
* The original main() of the b2g process. It is renamed to
* b2g_main() for the b2g loader.
*/
int b2g_main(int argc, const char *argv[]);

int ipcSockets[2] = {-1, -1};
int r = socketpair(AF_LOCAL, SOCK_STREAM, 0, ipcSockets);
ASSERT(r == 0);
int parentSock = ipcSockets[0];
int childSock = ipcSockets[1];

r = fcntl(parentSock, F_SETFL, O_NONBLOCK);
ASSERT(r != -1);
r = fcntl(childSock, F_SETFL, O_NONBLOCK);
ASSERT(r != -1);

pid_t pid = fork();
ASSERT(pid >= 0);
bool isChildProcess = pid == 0;

close(isChildProcess ? parentSock : childSock);

if (isChildProcess) {
/* The Nuwa process */
/* This provides the IPC service of loading Nuwa at the process.
* The b2g process would send a IPC message of loading Nuwa
* as the replacement of forking and executing plugin-container.
*/
return XRE_ProcLoaderServiceRun(getppid(), childSock, argc, argv);
}

// The b2g process
int childPid = pid;
XRE_ProcLoaderClientInit(childPid, parentSock);
return b2g_main(argc, argv);
}

/**
* B2G Loader is responsible for loading the b2g process and the
* Nuwa process. It forks into the parent process, for the b2g
* process, and the child process, for the Nuwa process.
*
* The loader loads libxul and performs initialization of static data
* before forking, so relocation of libxul and static data can be
* shared between the b2g process, the Nuwa process, and the content
* processes.
*/
int
main(int argc, const char* argv[])
{
const char *program = argv[0];
/*
* Before fork(), libxul and static data of Gecko are loaded for
* sharing.
*/
bool ok = LoadStaticData(program);
if (!ok) {
return 255;
}

return RunProcesses(argc, argv);
}
5 changes: 5 additions & 0 deletions b2g/app/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ if not CONFIG['LIBXUL_SDK']:
PROGRAM = CONFIG['MOZ_APP_NAME'] + "-bin"
else:
PROGRAM = CONFIG['MOZ_APP_NAME']
if CONFIG['MOZ_B2G_LOADER']:
SOURCES += [
'B2GLoader.cpp',
]

SOURCES += [
'nsBrowserApp.cpp',
]
Expand Down
45 changes: 42 additions & 3 deletions b2g/app/nsBrowserApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include "nsCOMPtr.h"
#include "nsIFile.h"
Expand Down Expand Up @@ -163,9 +164,22 @@ static int do_main(int argc, char* argv[])
return XRE_main(argc, argv, &sAppData, 0);
}

int main(int argc, char* argv[])
#ifdef MOZ_B2G_LOADER
/*
* The main() in B2GLoader.cpp is the new main function instead of the
* main() here if it is enabled. So, rename it to b2g_man().
*/
#define main b2g_main
#define _CONST const
#else
#define _CONST
#endif

int main(int argc, _CONST char* argv[])
{
#ifndef MOZ_B2G_LOADER
char exePath[MAXPATHLEN];
#endif

#ifdef MOZ_WIDGET_GONK
// This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
Expand All @@ -175,7 +189,9 @@ int main(int argc, char* argv[])
android::ProcessState::self()->startThreadPool();
#endif

nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
nsresult rv;
#ifndef MOZ_B2G_LOADER
rv = mozilla::BinaryPath::Get(argv[0], exePath);
if (NS_FAILED(rv)) {
Output("Couldn't calculate the application directory.\n");
return 255;
Expand All @@ -186,6 +202,7 @@ int main(int argc, char* argv[])
return 255;

strcpy(++lastSlash, XPCOM_DLL);
#endif // MOZ_B2G_LOADER

#if defined(XP_UNIX)
// If the b2g app is launched from adb shell, then the shell will wind
Expand All @@ -209,6 +226,9 @@ int main(int argc, char* argv[])
DllBlocklist_Initialize();
#endif

// B2G loader has already initialized Gecko so we can't initialize
// it again here.
#ifndef MOZ_B2G_LOADER
// We do this because of data in bug 771745
XPCOMGlueEnablePreload();

Expand All @@ -219,6 +239,7 @@ int main(int argc, char* argv[])
}
// Reset exePath so that it is the directory name and not the xpcom dll name
*lastSlash = 0;
#endif // MOZ_B2G_LOADER

rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {
Expand Down Expand Up @@ -253,7 +274,25 @@ int main(int argc, char* argv[])
int result;
{
ScopedLogging log;
result = do_main(argc, argv);
char **_argv;

/*
* Duplicate argument vector to conform non-const argv of
* do_main() since XRE_main() is very stupid with non-const argv.
*/
_argv = new char *[argc + 1];
for (int i = 0; i < argc; i++) {
_argv[i] = strdup(argv[i]);
MOZ_ASSERT(_argv[i] != nullptr);
}
_argv[argc] = nullptr;

result = do_main(argc, _argv);

for (int i = 0; i < argc; i++) {
free(_argv[i]);
}
delete[] _argv;
}

return result;
Expand Down
1 change: 1 addition & 0 deletions b2g/confvars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ MOZ_B2G=1

if test "$OS_TARGET" = "Android"; then
MOZ_NUWA_PROCESS=1
MOZ_B2G_LOADER=1
fi
MOZ_FOLD_LIBS=1

Expand Down
8 changes: 8 additions & 0 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -8614,6 +8614,14 @@ if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
AC_DEFINE(MOZ_NUWA_PROCESS)
fi
AC_SUBST(MOZ_NUWA_PROCESS)
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_B2G_LOADER"; then
if test -z "$MOZ_NUWA_PROCESS"; then
AC_MSG_ERROR([B2G loader works with Nuwa]);
fi
export MOZ_B2G_LOADER
AC_DEFINE(MOZ_B2G_LOADER)
fi
AC_SUBST(MOZ_B2G_LOADER)

AC_SUBST(NSPR_CFLAGS)
AC_SUBST(NSPR_LIBS)
Expand Down
4 changes: 4 additions & 0 deletions ipc/app/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ include $(topsrcdir)/config/config.mk

include $(topsrcdir)/config/rules.mk

ifneq ($(MOZ_WIDGET_TOOLKIT),android)
#LIBS += ../contentproc/$(LIB_PREFIX)plugin-container.$(LIB_SUFFIX)
endif

ifeq ($(OS_ARCH),WINNT) #{
# Note the manifest file exists in the tree, so we use the explicit filename
# here.
Expand Down
Loading

0 comments on commit e9dc84b

Please sign in to comment.