Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Merge m-c to inbound on a CLOSED TREE
Browse files Browse the repository at this point in the history
  • Loading branch information
KWierso committed Jul 29, 2014
2 parents 6a32bf5 + c8157fd commit 1201f95
Show file tree
Hide file tree
Showing 44 changed files with 2,156 additions and 342 deletions.
248 changes: 248 additions & 0 deletions b2g/app/B2GLoader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/* -*- 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 "application.ini.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;
XRE_ProcLoaderPreloadType XRE_ProcLoaderPreload;
extern XRE_CreateAppDataType XRE_CreateAppData;
extern XRE_GetFileFromPathType XRE_GetFileFromPath;

static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_ProcLoaderServiceRun", (NSFuncPtr*) &XRE_ProcLoaderServiceRun },
{ "XRE_ProcLoaderClientInit", (NSFuncPtr*) &XRE_ProcLoaderClientInit },
{ "XRE_ProcLoaderPreload", (NSFuncPtr*) &XRE_ProcLoaderPreload },
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ 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;
}

/**
* 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;
}

static already_AddRefed<nsIFile>
GetAppIni(int argc, const char *argv[])
{
nsCOMPtr<nsIFile> appini;
nsresult rv;

// 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));
NS_ENSURE_SUCCESS(rv, nullptr);
} else if (argc > 1 && IsArg(argv[1], "app")) {
if (argc == 2) {
return nullptr;
}

rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
NS_ENSURE_SUCCESS(rv, nullptr);

char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
if (putenv(appEnv)) {
return nullptr;
}
}

return appini.forget();
}

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

ok = LoadLibxul(xpcomPath);
NS_ENSURE_TRUE(ok, false);

char progDir[MAXPATHLEN];
ok = GetDirnameSlash(xpcomPath, progDir, MAXPATHLEN);
NS_ENSURE_TRUE(ok, false);

nsCOMPtr<nsIFile> appini = GetAppIni(argc, argv);
const nsXREAppData *appData;
if (appini) {
nsresult rv =
XRE_CreateAppData(appini, const_cast<nsXREAppData**>(&appData));
NS_ENSURE_SUCCESS(rv, false);
} else {
appData = &sAppData;
}

XRE_ProcLoaderPreload(progDir, appData);

if (appini) {
XRE_FreeAppData(const_cast<nsXREAppData*>(appData));
}

return true;
}

/**
* 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(argc, argv);
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
28 changes: 18 additions & 10 deletions b2g/chrome/content/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,25 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
product_model = libcutils.property_get('ro.product.model');
#endif

let software = os_name + ' ' + os_version;
let setting = {
'deviceinfo.os': os_version,
'deviceinfo.software': software,
'deviceinfo.platform_version': appInfo.platformVersion,
'deviceinfo.platform_build_id': appInfo.platformBuildID,
'deviceinfo.hardware': hardware_info,
'deviceinfo.firmware_revision': firmware_revision,
'deviceinfo.product_model': product_model
// Populate deviceinfo settings,
// copying any existing deviceinfo.os into deviceinfo.previous_os
let lock = window.navigator.mozSettings.createLock();
let req = lock.get('deviceinfo.os');
req.onsuccess = req.onerror = () => {
let previous_os = req.result && req.result['deviceinfo.os'] || '';
let software = os_name + ' ' + os_version;
let setting = {
'deviceinfo.os': os_version,
'deviceinfo.previous_os': previous_os,
'deviceinfo.software': software,
'deviceinfo.platform_version': appInfo.platformVersion,
'deviceinfo.platform_build_id': appInfo.platformBuildID,
'deviceinfo.hardware': hardware_info,
'deviceinfo.firmware_revision': firmware_revision,
'deviceinfo.product_model': product_model
}
lock.set(setting);
}
window.navigator.mozSettings.createLock().set(setting);
})();

// =================== DevTools ====================
Expand Down
Loading

0 comments on commit 1201f95

Please sign in to comment.