Merge m-c to fx-team on a CLOSED TREE

This commit is contained in:
Wes Kocher 2014-07-28 17:27:46 -07:00
Родитель 0d3f68895a 39f2cb9cf8
Коммит dc66e0c546
44 изменённых файлов: 2156 добавлений и 342 удалений

248
b2g/app/B2GLoader.cpp Normal file
Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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',
]

Просмотреть файл

@ -17,6 +17,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "nsCOMPtr.h"
#include "nsIFile.h"
@ -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
@ -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;
@ -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
@ -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();
@ -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)) {
@ -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;

Просмотреть файл

@ -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 ====================

Просмотреть файл

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

Просмотреть файл

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

Просмотреть файл

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "97a95feb1d1505c9d179266fee891e600ad8760b",
"revision": "9863517bfb599a39300f5e8c6f94e16189a4c698",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>

Просмотреть файл

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

Просмотреть файл

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

Просмотреть файл

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fadfafa17f5175203b8b9457bfb95e5816f54f58"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

Просмотреть файл

@ -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

Просмотреть файл

@ -8631,6 +8631,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)

Просмотреть файл

@ -169,7 +169,7 @@ public:
}
NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK);
sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs);
sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs, nullptr);
return NS_OK;
}
@ -492,6 +492,85 @@ static btrc_callbacks_t sBtAvrcpCallbacks = {
};
#endif
#if ANDROID_VERSION > 17
class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
{
public:
InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothAvrcpInterface::Init failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Init() MOZ_OVERRIDE
{
if (mRes) {
mRes->Init();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
#endif
class InitA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothA2dpInterface::Init failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Init() MOZ_OVERRIDE
{
#if ANDROID_VERSION > 17
/* Also init AVRCP if it's available, ... */
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
if (!btInf) {
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
return;
}
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
if (!sBtAvrcpInterface) {
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
return;
}
sBtAvrcpInterface->Init(&sBtAvrcpCallbacks,
new InitAvrcpResultHandler(mRes));
#else
/* ...or signal success otherwise. */
if (mRes) {
mRes->Init();
}
#endif
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
/*
* This function will be only called when Bluetooth is turning on.
* It is important to register a2dp callbacks before enable() gets called.
@ -520,30 +599,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
return;
}
int ret = sBtA2dpInterface->Init(&sBtA2dpCallbacks);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("Warning: failed to init a2dp module");
}
#if ANDROID_VERSION > 17
sBtAvrcpInterface = btInf->GetBluetoothAvrcpInterface();
if (!sBtAvrcpInterface) {
BT_LOGR("Error: Bluetooth AVRCP interface not available");
if (aRes) {
aRes->OnError(NS_ERROR_FAILURE);
}
return;
}
ret = sBtAvrcpInterface->Init(&sBtAvrcpCallbacks);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("Warning: failed to init avrcp module");
}
#endif
if (aRes) {
aRes->Init();
}
sBtA2dpInterface->Init(&sBtA2dpCallbacks, new InitA2dpResultHandler(aRes));
}
BluetoothA2dpManager::~BluetoothA2dpManager()
@ -617,6 +673,99 @@ BluetoothA2dpManager::Get()
return sBluetoothA2dpManager;
}
#if ANDROID_VERSION > 17
class CleanupAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
{
public:
CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Cleanup() MOZ_OVERRIDE
{
sBtAvrcpInterface = nullptr;
if (mRes) {
mRes->Deinit();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
#endif
class CleanupA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
(int)aStatus);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void Cleanup() MOZ_OVERRIDE
{
sBtA2dpInterface = nullptr;
#if ANDROID_VERSION > 17
/* Cleanup AVRCP if it's available and initialized, ...*/
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else
#endif
if (mRes) {
/* ...or simply signal success from here. */
mRes->Deinit();
}
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
{
public:
CleanupA2dpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
NS_IMETHOD Run() MOZ_OVERRIDE
{
sBtA2dpInterface = nullptr;
#if ANDROID_VERSION > 17
/* Cleanup AVRCP if it's available and initialized, ...*/
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
} else
#endif
if (mRes) {
/* ...or simply signal success from here. */
mRes->Deinit();
}
return NS_OK;
}
private:
nsRefPtr<BluetoothProfileResultHandler> mRes;
};
// static
void
BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
@ -624,17 +773,14 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
MOZ_ASSERT(NS_IsMainThread());
if (sBtA2dpInterface) {
sBtA2dpInterface->Cleanup();
sBtA2dpInterface = nullptr;
}
#if ANDROID_VERSION > 17
if (sBtAvrcpInterface) {
sBtAvrcpInterface->Cleanup();
sBtAvrcpInterface = nullptr;
}
#endif
if (aRes) {
aRes->Deinit();
sBtA2dpInterface->Cleanup(new CleanupA2dpResultHandler(aRes));
} else if (aRes) {
// We dispatch a runnable here to make the profile resource handler
// behave as if A2DP was initialized.
nsRefPtr<nsRunnable> r = new CleanupA2dpResultHandlerRunnable(aRes);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
}
}
}
@ -647,6 +793,29 @@ BluetoothA2dpManager::HandleShutdown()
sBluetoothA2dpManager = nullptr;
}
void
BluetoothA2dpManager::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
mController = nullptr;
mDeviceAddress.Truncate();
}
class ConnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_LOGR("BluetoothA2dpInterface::Connect failed: %d", (int)aStatus);
NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
sBluetoothA2dpManager->OnConnectError();
}
};
void
BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress,
BluetoothProfileController* aController)
@ -678,14 +847,29 @@ BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress,
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
bt_status_t result = sBtA2dpInterface->Connect(&remoteAddress);
if (BT_STATUS_SUCCESS != result) {
BT_LOGR("Failed to connect: %x", result);
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
return;
}
sBtA2dpInterface->Connect(&remoteAddress, new ConnectResultHandler());
}
void
BluetoothA2dpManager::OnDisconnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
}
class DisconnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
{
public:
void OnError(bt_status_t aStatus) MOZ_OVERRIDE
{
BT_LOGR("BluetoothA2dpInterface::Disconnect failed: %d", (int)aStatus);
NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
sBluetoothA2dpManager->OnDisconnectError();
}
};
void
BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
{
@ -720,12 +904,7 @@ BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
bt_bdaddr_t remoteAddress;
StringToBdAddressType(mDeviceAddress, &remoteAddress);
bt_status_t result = sBtA2dpInterface->Disconnect(&remoteAddress);
if (BT_STATUS_SUCCESS != result) {
BT_LOGR("Failed to disconnect: %x", result);
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
return;
}
sBtA2dpInterface->Disconnect(&remoteAddress, new DisconnectResultHandler());
}
void
@ -957,7 +1136,7 @@ BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_TRACK_CHANGE,
BTRC_NOTIFICATION_TYPE_CHANGED,
&param);
&param, nullptr);
if (mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
param.song_pos = mPosition;
// EVENT_PLAYBACK_POS_CHANGED shall be notified if changed current track
@ -965,7 +1144,7 @@ BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
sBtAvrcpInterface->RegisterNotificationRsp(
BTRC_EVT_PLAY_POS_CHANGED,
BTRC_NOTIFICATION_TYPE_CHANGED,
&param);
&param, nullptr);
}
}
@ -993,7 +1172,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
// always update playstatus first
sBtAvrcpInterface->GetPlayStatusRsp((btrc_play_status_t)aPlayStatus,
aDuration, aPosition);
aDuration, aPosition, nullptr);
// when play status changed, send both play status and position
if (mPlayStatus != aPlayStatus &&
mPlayStatusChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
@ -1002,7 +1181,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_STATUS_CHANGED,
BTRC_NOTIFICATION_TYPE_CHANGED,
&param);
&param, nullptr);
}
if (mPosition != aPosition &&
@ -1012,7 +1191,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_POS_CHANGED,
BTRC_NOTIFICATION_TYPE_CHANGED,
&param);
&param, nullptr);
}
mDuration = aDuration;
@ -1080,7 +1259,7 @@ BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam)
sBtAvrcpInterface->RegisterNotificationRsp((btrc_event_id_t)aEventId,
BTRC_NOTIFICATION_TYPE_INTERIM,
&param);
&param, nullptr);
#endif
}

Просмотреть файл

@ -34,6 +34,9 @@ public:
static void DeinitA2dpInterface(BluetoothProfileResultHandler* aRes);
virtual ~BluetoothA2dpManager();
void OnConnectError();
void OnDisconnectError();
// A2DP-specific functions
void HandleSinkPropertyChanged(const BluetoothSignal& aSignal);

Просмотреть файл

@ -847,6 +847,37 @@ struct interface_traits<BluetoothA2dpInterface>
}
};
typedef
BluetoothInterfaceRunnable0<BluetoothA2dpResultHandler, void>
BluetoothA2dpResultRunnable;
typedef
BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void, bt_status_t>
BluetoothA2dpErrorRunnable;
static nsresult
DispatchBluetoothA2dpResult(
BluetoothA2dpResultHandler* aRes,
void (BluetoothA2dpResultHandler::*aMethod)(),
bt_status_t aStatus)
{
MOZ_ASSERT(aRes);
nsRunnable* runnable;
if (aStatus == BT_STATUS_SUCCESS) {
runnable = new BluetoothA2dpResultRunnable(aRes, aMethod);
} else {
runnable = new BluetoothA2dpErrorRunnable(aRes,
&BluetoothA2dpResultHandler::OnError, aStatus);
}
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
}
return rv;
}
BluetoothA2dpInterface::BluetoothA2dpInterface(
const btav_interface_t* aInterface)
: mInterface(aInterface)
@ -857,28 +888,51 @@ BluetoothA2dpInterface::BluetoothA2dpInterface(
BluetoothA2dpInterface::~BluetoothA2dpInterface()
{ }
bt_status_t
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks)
void
BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks,
BluetoothA2dpResultHandler* aRes)
{
return mInterface->init(aCallbacks);
bt_status_t status = mInterface->init(aCallbacks);
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init,
status);
}
}
void
BluetoothA2dpInterface::Cleanup()
BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
{
mInterface->cleanup();
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
}
bt_status_t
BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr)
void
BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr,
BluetoothA2dpResultHandler* aRes)
{
return mInterface->connect(aBdAddr);
bt_status_t status = mInterface->connect(aBdAddr);
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Connect,
status);
}
}
bt_status_t
BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr)
void
BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr,
BluetoothA2dpResultHandler* aRes)
{
return mInterface->disconnect(aBdAddr);
bt_status_t status = mInterface->disconnect(aBdAddr);
if (aRes) {
DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Disconnect,
status);
}
}
//
@ -897,6 +951,37 @@ struct interface_traits<BluetoothAvrcpInterface>
}
};
typedef
BluetoothInterfaceRunnable0<BluetoothAvrcpResultHandler, void>
BluetoothAvrcpResultRunnable;
typedef
BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void, bt_status_t>
BluetoothAvrcpErrorRunnable;
static nsresult
DispatchBluetoothAvrcpResult(
BluetoothAvrcpResultHandler* aRes,
void (BluetoothAvrcpResultHandler::*aMethod)(),
bt_status_t aStatus)
{
MOZ_ASSERT(aRes);
nsRunnable* runnable;
if (aStatus == BT_STATUS_SUCCESS) {
runnable = new BluetoothAvrcpResultRunnable(aRes, aMethod);
} else {
runnable = new BluetoothAvrcpErrorRunnable(aRes,
&BluetoothAvrcpResultHandler::OnError, aStatus);
}
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
}
return rv;
}
BluetoothAvrcpInterface::BluetoothAvrcpInterface(
const btrc_interface_t* aInterface)
: mInterface(aInterface)
@ -907,86 +992,157 @@ BluetoothAvrcpInterface::BluetoothAvrcpInterface(
BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
{ }
bt_status_t
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks)
void
BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->init(aCallbacks);
bt_status_t status = mInterface->init(aCallbacks);
if (aRes) {
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init,
status);
}
}
void
BluetoothAvrcpInterface::Cleanup()
BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
{
mInterface->cleanup();
if (aRes) {
DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
BT_STATUS_SUCCESS);
}
}
bt_status_t
void
BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
uint32_t aSongLen, uint32_t aSongPos)
uint32_t aSongLen, uint32_t aSongPos,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->get_play_status_rsp(aPlayStatus, aSongLen, aSongPos);
bt_status_t status = mInterface->get_play_status_rsp(aPlayStatus, aSongLen,
aSongPos);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::ListPlayerAppAttrRsp(int aNumAttr,
btrc_player_attr_t* aPAttrs)
void
BluetoothAvrcpInterface::ListPlayerAppAttrRsp(
int aNumAttr, btrc_player_attr_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
bt_status_t status = mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals)
void
BluetoothAvrcpInterface::ListPlayerAppValueRsp(
int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
{
return mInterface->list_player_app_value_rsp(aNumVal, aPVals);
bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::GetPlayerAppValueRsp(btrc_player_settings_t* aPVals)
void
BluetoothAvrcpInterface::GetPlayerAppValueRsp(
btrc_player_settings_t* aPVals, BluetoothAvrcpResultHandler* aRes)
{
return mInterface->get_player_app_value_rsp(aPVals);
bt_status_t status = mInterface->get_player_app_value_rsp(aPVals);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(int aNumAttr,
btrc_player_setting_text_t* aPAttrs)
void
BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(
int aNumAttr, btrc_player_setting_text_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs);
bt_status_t status = mInterface->get_player_app_attr_text_rsp(aNumAttr,
aPAttrs);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(int aNumVal,
btrc_player_setting_text_t* aPVals)
void
BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(
int aNumVal, btrc_player_setting_text_t* aPVals,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->get_player_app_value_text_rsp(aNumVal, aPVals);
bt_status_t status = mInterface->get_player_app_value_text_rsp(aNumVal,
aPVals);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::GetElementAttrRsp(uint8_t aNumAttr,
btrc_element_attr_val_t* aPAttrs)
void
BluetoothAvrcpInterface::GetElementAttrRsp(
uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes)
{
return mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
bt_status_t status = mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::SetPlayerAppValueRsp(btrc_status_t aRspStatus)
void
BluetoothAvrcpInterface::SetPlayerAppValueRsp(
btrc_status_t aRspStatus, BluetoothAvrcpResultHandler* aRes)
{
return mInterface->set_player_app_value_rsp(aRspStatus);
bt_status_t status = mInterface->set_player_app_value_rsp(aRspStatus);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::RegisterNotificationRsp(btrc_event_id_t aEventId,
btrc_notification_type_t aType, btrc_register_notification_t* aPParam)
void
BluetoothAvrcpInterface::RegisterNotificationRsp(
btrc_event_id_t aEventId, btrc_notification_type_t aType,
btrc_register_notification_t* aPParam, BluetoothAvrcpResultHandler* aRes)
{
return mInterface->register_notification_rsp(aEventId, aType, aPParam);
bt_status_t status = mInterface->register_notification_rsp(aEventId, aType,
aPParam);
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, status);
}
}
bt_status_t
BluetoothAvrcpInterface::SetVolume(uint8_t aVolume)
void
BluetoothAvrcpInterface::SetVolume(uint8_t aVolume,
BluetoothAvrcpResultHandler* aRes)
{
#if ANDROID_VERSION >= 19
return mInterface->set_volume(aVolume);
bt_status_t status = mInterface->set_volume(aVolume);
#else
return BT_STATUS_UNSUPPORTED;
bt_status_t status = BT_STATUS_UNSUPPORTED;
#endif
if (aRes) {
DispatchBluetoothAvrcpResult(
aRes, &BluetoothAvrcpResultHandler::SetVolume, status);
}
}
#endif // ANDROID_VERSION >= 18

Просмотреть файл

@ -181,16 +181,37 @@ private:
// Bluetooth Advanced Audio Interface
//
class BluetoothA2dpResultHandler
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothA2dpResultHandler)
virtual ~BluetoothA2dpResultHandler() { }
virtual void OnError(bt_status_t aStatus)
{
BT_WARNING("received error code %d", (int)aStatus);
}
virtual void Init() { }
virtual void Cleanup() { }
virtual void Connect() { }
virtual void Disconnect() { }
};
class BluetoothA2dpInterface
{
public:
friend class BluetoothInterface;
bt_status_t Init(btav_callbacks_t *aCallbacks);
void Cleanup();
void Init(btav_callbacks_t *aCallbacks,
BluetoothA2dpResultHandler* aRes);
void Cleanup(BluetoothA2dpResultHandler* aRes);
bt_status_t Connect(bt_bdaddr_t *aBdAddr);
bt_status_t Disconnect(bt_bdaddr_t *aBdAddr);
void Connect(bt_bdaddr_t *aBdAddr,
BluetoothA2dpResultHandler* aRes);
void Disconnect(bt_bdaddr_t *aBdAddr,
BluetoothA2dpResultHandler* aRes);
protected:
BluetoothA2dpInterface(const btav_interface_t* aInterface);
@ -204,37 +225,79 @@ private:
// Bluetooth AVRCP Interface
//
class BluetoothAvrcpResultHandler
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothAvrcpResultHandler)
virtual ~BluetoothAvrcpResultHandler() { }
virtual void OnError(bt_status_t aStatus)
{
BT_WARNING("received error code %d", (int)aStatus);
}
virtual void Init() { }
virtual void Cleanup() { }
virtual void GetPlayStatusRsp() { }
virtual void ListPlayerAppAttrRsp() { }
virtual void ListPlayerAppValueRsp() { }
virtual void GetPlayerAppValueRsp() { }
virtual void GetPlayerAppAttrTextRsp() { }
virtual void GetPlayerAppValueTextRsp() { }
virtual void GetElementAttrRsp() { }
virtual void SetPlayerAppValueRsp() { }
virtual void RegisterNotificationRsp() { }
virtual void SetVolume() { }
};
class BluetoothAvrcpInterface
{
#if ANDROID_VERSION >= 18
public:
friend class BluetoothInterface;
bt_status_t Init(btrc_callbacks_t* aCallbacks);
void Cleanup();
void Init(btrc_callbacks_t* aCallbacks,
BluetoothAvrcpResultHandler* aRes);
void Cleanup(BluetoothAvrcpResultHandler* aRes);
bt_status_t GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
uint32_t aSongLen, uint32_t aSongPos);
void GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
uint32_t aSongLen, uint32_t aSongPos,
BluetoothAvrcpResultHandler* aRes);
bt_status_t ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs);
bt_status_t ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals);
void ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes);
void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
BluetoothAvrcpResultHandler* aRes);
bt_status_t GetPlayerAppValueRsp(btrc_player_settings_t* aPVals);
bt_status_t GetPlayerAppAttrTextRsp(int aNumAttr,
btrc_player_setting_text_t* aPAttrs);
bt_status_t GetPlayerAppValueTextRsp(int aNumVal,
btrc_player_setting_text_t* aPVals);
void GetPlayerAppValueRsp(btrc_player_settings_t* aPVals,
BluetoothAvrcpResultHandler* aRes);
void GetPlayerAppAttrTextRsp(int aNumAttr,
btrc_player_setting_text_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes);
void GetPlayerAppValueTextRsp(int aNumVal,
btrc_player_setting_text_t* aPVals,
BluetoothAvrcpResultHandler* aRes);
bt_status_t GetElementAttrRsp(uint8_t aNumAttr,
btrc_element_attr_val_t* aPAttrs);
void GetElementAttrRsp(uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
BluetoothAvrcpResultHandler* aRes);
bt_status_t SetPlayerAppValueRsp(btrc_status_t aRspStatus);
void SetPlayerAppValueRsp(btrc_status_t aRspStatus,
BluetoothAvrcpResultHandler* aRes);
bt_status_t RegisterNotificationRsp(btrc_event_id_t aEventId,
btrc_notification_type_t aType,
btrc_register_notification_t* aPParam);
void RegisterNotificationRsp(btrc_event_id_t aEventId,
btrc_notification_type_t aType,
btrc_register_notification_t* aPParam,
BluetoothAvrcpResultHandler* aRes);
bt_status_t SetVolume(uint8_t aVolume);
void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
protected:
BluetoothAvrcpInterface(const btrc_interface_t* aInterface);

Просмотреть файл

@ -78,6 +78,7 @@ static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
static int sHeadsetState;
static const int kBtSampleRate = 8000;
static bool sSwitchDone = true;
static bool sA2dpSwitchDone = true;
namespace mozilla {
namespace dom {
@ -196,6 +197,19 @@ static void ProcessDelayedAudioRoute(SwitchState aState)
sSwitchDone = true;
}
static void ProcessDelayedA2dpRoute(audio_policy_dev_state_t aState, const char *aAddress)
{
if (sA2dpSwitchDone)
return;
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
aState, aAddress);
String8 cmd("bluetooth_enabled=false");
AudioSystem::setParameters(0, cmd);
cmd.setTo("A2dpSuspended=true");
AudioSystem::setParameters(0, cmd);
sA2dpSwitchDone = true;
}
NS_IMPL_ISUPPORTS(AudioManager, nsIAudioManager, nsIObserver)
static void
@ -262,18 +276,18 @@ AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE);
}
} else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) {
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
audioState, aAddress.get());
if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
if (audioState == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE && sA2dpSwitchDone) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE, NewRunnableFunction(&ProcessDelayedA2dpRoute, audioState, aAddress.get()), 1000);
sA2dpSwitchDone = false;
} else {
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
audioState, aAddress.get());
String8 cmd("bluetooth_enabled=true");
AudioSystem::setParameters(0, cmd);
cmd.setTo("A2dpSuspended=false");
AudioSystem::setParameters(0, cmd);
} else {
String8 cmd("bluetooth_enabled=false");
AudioSystem::setParameters(0, cmd);
cmd.setTo("A2dpSuspended=true");
AudioSystem::setParameters(0, cmd);
sA2dpSwitchDone = true;
}
} else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,

Просмотреть файл

@ -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.

Просмотреть файл

@ -4,148 +4,9 @@
* 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"
// FIXME/cjones testing
#if !defined(OS_WIN)
#include <unistd.h>
#endif
#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"
#endif
#if defined(XP_WIN)
#include "sandbox/chromium/base/basictypes.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "mozilla/sandboxTarget.h"
#endif
#ifdef MOZ_WIDGET_GONK
# include <sys/time.h>
# include <sys/resource.h>
# include <binder/ProcessState.h>
# ifdef LOGE_IF
# undef LOGE_IF
# endif
# include <android/log.h>
# define LOGE_IF(cond, ...) \
( (CONDITION(cond)) \
? ((void)__android_log_print(ANDROID_LOG_ERROR, \
"Gecko:MozillaRntimeMain", __VA_ARGS__)) \
: (void)0 )
#endif
#ifdef MOZ_NUWA_PROCESS
#include <binder/ProcessState.h>
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_WIDGET_GONK
static void
InitializeBinder(void *aDummy) {
// Change thread priority to 0 only during calling ProcessState::self().
// The priority is registered to binder driver and used for default Binder
// Thread's priority.
// To change the process's priority to small value need's root permission.
int curPrio = getpriority(PRIO_PROCESS, 0);
int err = setpriority(PRIO_PROCESS, 0, 0);
MOZ_ASSERT(!err);
LOGE_IF(err, "setpriority failed. Current process needs root permission.");
android::ProcessState::self()->startThreadPool();
setpriority(PRIO_PROCESS, 0, curPrio);
}
#endif
#if defined(XP_WIN)
static bool gIsSandboxEnabled = false;
void StartSandboxCallback()
{
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
target_service->LowerToken();
}
}
#endif
#include "../contentproc/plugin-container.cpp"
int
main(int argc, char* argv[])
{
bool isNuwa = false;
for (int i = 1; i < argc; i++) {
isNuwa |= strcmp(argv[i], "-nuwa") == 0;
#if defined(XP_WIN)
gIsSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
#endif
}
#ifdef MOZ_NUWA_PROCESS
if (isNuwa) {
PrepareNuwaProcess();
}
#endif
#ifdef MOZ_WIDGET_GONK
// This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
// receive binder calls, though not necessary to send binder calls.
// ProcessState::Self() also needs to be called once on the main thread to
// register the main thread with the binder driver.
#ifdef MOZ_NUWA_PROCESS
if (!isNuwa) {
InitializeBinder(nullptr);
} else {
NuwaAddFinalConstructor(&InitializeBinder, nullptr);
}
#else
InitializeBinder(nullptr);
#endif
#endif
// 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;
GeckoProcessType proctype = XRE_StringToChildProcessType(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 (proctype != GeckoProcessType_Plugin) {
mozilla::SanitizeEnvironmentVariables();
SetDllDirectory(L"");
}
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
if (!target_service) {
return 1;
}
sandbox::ResultCode result = target_service->Init();
if (result != sandbox::SBOX_ALL_OK) {
return 2;
}
mozilla::SandboxTarget::Instance()->SetStartSandboxCallback(StartSandboxCallback);
}
#endif
nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
NS_ENSURE_SUCCESS(rv, 1);
return 0;
main(int argc, char *argv[]) {
return content_process_main(argc, argv);
}

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 autoindent cindent expandtab: */
// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -18,6 +20,13 @@
#include "base/logging.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "nsLiteralString.h"
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
using namespace mozilla::ipc;
#endif // MOZ_B2G_LOADER
#ifdef MOZ_WIDGET_GONK
/*
@ -188,12 +197,71 @@ bool LaunchApp(const std::vector<std::string>& argv,
wait, process_handle);
}
#ifdef MOZ_B2G_LOADER
/**
* Launch an app using B2g Loader.
*/
static bool
LaunchAppProcLoader(const std::vector<std::string>& argv,
const file_handle_mapping_vector& fds_to_remap,
const environment_map& env_vars_to_set,
ChildPrivileges privs,
ProcessHandle* process_handle) {
size_t i;
scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
for (i = 0; i < argv.size(); i++) {
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
}
argv_cstr[argv.size()] = nullptr;
scoped_array<char*> env_cstr(new char*[env_vars_to_set.size() + 1]);
i = 0;
for (environment_map::const_iterator it = env_vars_to_set.begin();
it != env_vars_to_set.end(); ++it) {
env_cstr[i++] = strdup((it->first + "=" + it->second).c_str());
}
env_cstr[env_vars_to_set.size()] = nullptr;
bool ok = ProcLoaderLoad((const char **)argv_cstr.get(),
(const char **)env_cstr.get(),
fds_to_remap, privs,
process_handle);
MOZ_ASSERT(ok, "ProcLoaderLoad() failed");
for (size_t i = 0; i < env_vars_to_set.size(); i++) {
free(env_cstr[i]);
}
return ok;
}
static bool
IsLaunchingNuwa(const std::vector<std::string>& argv) {
std::vector<std::string>::const_iterator it;
for (it = argv.begin(); it != argv.end(); ++it) {
if (*it == std::string("-nuwa")) {
return true;
}
}
return false;
}
#endif // MOZ_B2G_LOADER
bool LaunchApp(const std::vector<std::string>& argv,
const file_handle_mapping_vector& fds_to_remap,
const environment_map& env_vars_to_set,
ChildPrivileges privs,
bool wait, ProcessHandle* process_handle,
ProcessArchitecture arch) {
#ifdef MOZ_B2G_LOADER
static bool beforeFirstNuwaLaunch = true;
if (!wait && beforeFirstNuwaLaunch && IsLaunchingNuwa(argv)) {
beforeFirstNuwaLaunch = false;
return LaunchAppProcLoader(argv, fds_to_remap, env_vars_to_set,
privs, process_handle);
}
#endif // MOZ_B2G_LOADER
scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
// Illegal to allocate memory after fork and before execvp
InjectiveMultimap fd_shuffle1, fd_shuffle2;

29
ipc/contentproc/moz.build Normal file
Просмотреть файл

@ -0,0 +1,29 @@
# -*- Mode: python; c-basic-offset: 4; 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_NAME = 'plugin-container'
if CONFIG['MOZ_B2G_LOADER']:
FINAL_LIBRARY = 'xul'
SOURCES += [
'plugin-container.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['OS_ARCH'] == 'WINNT':
LOCAL_INCLUDES += [
'/toolkit/xre',
'/xpcom/base',
]
if CONFIG['OS_ARCH'] == 'WINNT':
# For sandbox includes and the include dependencies those have
LOCAL_INCLUDES += [
'/security',
'/security/sandbox',
'/security/sandbox/chromium',
]

Просмотреть файл

@ -0,0 +1,151 @@
/* -*- 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"
// FIXME/cjones testing
#if !defined(OS_WIN)
#include <unistd.h>
#endif
#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"
#endif
#if defined(XP_WIN)
#include "sandbox/chromium/base/basictypes.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "mozilla/sandboxTarget.h"
#endif
#ifdef MOZ_WIDGET_GONK
# include <sys/time.h>
# include <sys/resource.h>
# include <binder/ProcessState.h>
# ifdef LOGE_IF
# undef LOGE_IF
# endif
# include <android/log.h>
# define LOGE_IF(cond, ...) \
( (CONDITION(cond)) \
? ((void)__android_log_print(ANDROID_LOG_ERROR, \
"Gecko:MozillaRntimeMain", __VA_ARGS__)) \
: (void)0 )
#endif
#ifdef MOZ_NUWA_PROCESS
#include <binder/ProcessState.h>
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_WIDGET_GONK
static void
InitializeBinder(void *aDummy) {
// Change thread priority to 0 only during calling ProcessState::self().
// The priority is registered to binder driver and used for default Binder
// Thread's priority.
// To change the process's priority to small value need's root permission.
int curPrio = getpriority(PRIO_PROCESS, 0);
int err = setpriority(PRIO_PROCESS, 0, 0);
MOZ_ASSERT(!err);
LOGE_IF(err, "setpriority failed. Current process needs root permission.");
android::ProcessState::self()->startThreadPool();
setpriority(PRIO_PROCESS, 0, curPrio);
}
#endif
#if defined(XP_WIN)
static bool gIsSandboxEnabled = false;
void StartSandboxCallback()
{
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
target_service->LowerToken();
}
}
#endif
int
content_process_main(int argc, char* argv[])
{
bool isNuwa = false;
for (int i = 1; i < argc; i++) {
isNuwa |= strcmp(argv[i], "-nuwa") == 0;
#if defined(XP_WIN)
gIsSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
#endif
}
#ifdef MOZ_NUWA_PROCESS
if (isNuwa) {
PrepareNuwaProcess();
}
#endif
#ifdef MOZ_WIDGET_GONK
// This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
// receive binder calls, though not necessary to send binder calls.
// ProcessState::Self() also needs to be called once on the main thread to
// register the main thread with the binder driver.
#ifdef MOZ_NUWA_PROCESS
if (!isNuwa) {
InitializeBinder(nullptr);
} else {
NuwaAddFinalConstructor(&InitializeBinder, nullptr);
}
#else
InitializeBinder(nullptr);
#endif
#endif
// 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;
GeckoProcessType proctype = XRE_StringToChildProcessType(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 (proctype != GeckoProcessType_Plugin) {
mozilla::SanitizeEnvironmentVariables();
SetDllDirectory(L"");
}
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
if (!target_service) {
return 1;
}
sandbox::ResultCode result = target_service->Init();
if (result != sandbox::SBOX_ALL_OK) {
return 2;
}
mozilla::SandboxTarget::Instance()->SetStartSandboxCallback(StartSandboxCallback);
}
#endif
nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
NS_ENSURE_SUCCESS(rv, 1);
return 0;
}

35
ipc/glue/PProcLoader.ipdl Normal file
Просмотреть файл

@ -0,0 +1,35 @@
/* -*- 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/. */
namespace mozilla {
namespace ipc {
struct FDRemap {
FileDescriptor fd;
int mapto;
};
protocol PProcLoader
{
child:
/**
* Request B2G loader service to load content process.
*
* It actually calls the main() function of plugin-container.
*/
async Load(nsCString[] argv, nsCString[] env,
FDRemap[] fdsRemap, uint32_t privs,
int32_t cookie);
parent:
/**
* The acknowledgement of Load().
*/
async LoadComplete(int32_t pid, int32_t cookie);
};
}
}

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- 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/. */
@ -5,6 +7,10 @@
#ifndef mozilla_ipc_ProcessUtils_h
#define mozilla_ipc_ProcessUtils_h
#ifdef MOZ_B2G_LOADER
#include "base/process_util.h"
#endif
namespace mozilla {
namespace ipc {
@ -12,6 +18,17 @@ namespace ipc {
// this directly.
void SetThisProcessName(const char *aName);
#ifdef MOZ_B2G_LOADER
// see ProcessUtils_linux.cpp for explaination.
void ProcLoaderClientGeckoInit();
bool ProcLoaderLoad(const char *aArgv[],
const char *aEnvp[],
const base::file_handle_mapping_vector &aFdsRemap,
const base::ChildPrivileges aPrivs,
base::ProcessHandle *aProcessHandle);
#endif /* MOZ_B2G_LOADER */
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- 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/. */
@ -8,6 +10,37 @@
#include <sys/prctl.h>
#ifdef MOZ_B2G_LOADER
#include <sys/types.h>
#include <unistd.h>
#include "nsAutoPtr.h"
#include "mozilla/Assertions.h"
#include "mozilla/ipc/PProcLoaderParent.h"
#include "mozilla/ipc/PProcLoaderChild.h"
#include "mozilla/ipc/Transport.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/ipc/IOThreadChild.h"
#include "mozilla/dom/ContentProcess.h"
#include "base/file_descriptor_shuffle.h"
#include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/DebugOnly.h"
#include "base/process_util.h"
#include "prenv.h"
#include "nsXULAppAPI.h" // export XRE_* functions
#include "nsAppRunner.h"
int content_process_main(int argc, char *argv[]);
extern bool gDisableAndroidLog;
#endif /* MOZ_B2G_LOADER */
namespace mozilla {
namespace ipc {
@ -16,5 +49,522 @@ void SetThisProcessName(const char *aName)
prctl(PR_SET_NAME, (unsigned long)aName, 0uL, 0uL, 0uL);
}
#ifdef MOZ_B2G_LOADER
/**
* How does B2G Loader Work?
*
* <<parent process>> <<child process>>
* ProcLoaderParent -----> ProcLoaderChild
* ^ |
* | load() | content_process_main()
* | V
* ProcLoaderClient Nuwa/plugin-container
* ^
* | ProcLoaderLoad()
* ...
* ContentParent
*
*
* B2G loader includes an IPC protocol PProcLoader for communication
* between client (parent) and server (child). The b2g process is the
* client. It requests the server to load/start the Nuwa process with
* the given arguments, env variables, and file descriptors.
*
* ProcLoaderClientInit() is called by B2G loader to initialize the
* client side, the b2g process. Then the b2g_main() is called to
* start b2g process.
*
* ProcLoaderClientGeckoInit() is called by XRE_main() to create the
* parent actor, |ProcLoaderParent|, of PProcLoader for servicing the
* request to run Nuwa process later once Gecko has been initialized.
*
* ProcLoaderServiceRun() is called by the server process. It starts
* an IOThread and event loop to serve the |ProcLoaderChild|
* implmentation of PProcLoader protocol as the child actor. Once it
* recieves a load() request, it stops the IOThread and event loop,
* then starts running the main function of the content process with
* the given arguments.
*
* NOTE: The server process serves at most one load() request.
*/
using namespace base;
using namespace mozilla::dom;
static bool sProcLoaderClientOnDeinit = false;
static DebugOnly<bool> sProcLoaderClientInitialized = false;
static DebugOnly<bool> sProcLoaderClientGeckoInitialized = false;
static pid_t sProcLoaderPid = 0;
static int sProcLoaderChannelFd = -1;
static PProcLoaderParent *sProcLoaderParent = nullptr;
static MessageLoop *sProcLoaderLoop = nullptr;
static void ProcLoaderClientDeinit();
class ProcLoaderParent : public PProcLoaderParent
{
private:
nsAutoPtr<FileDescriptor> mChannelFd; // To keep a reference.
public:
ProcLoaderParent(FileDescriptor *aFd) : mChannelFd(aFd) {}
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvLoadComplete(const int32_t &aPid,
const int32_t &aCookie) MOZ_OVERRIDE;
virtual void OnChannelError() MOZ_OVERRIDE;
};
void
ProcLoaderParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
static void
_ProcLoaderParentDestroy(PProcLoaderParent *aLoader)
{
aLoader->Close();
delete aLoader;
sProcLoaderClientOnDeinit = false;
}
bool
ProcLoaderParent::RecvLoadComplete(const int32_t &aPid,
const int32_t &aCookie)
{
ProcLoaderClientDeinit();
return true;
}
void
ProcLoaderParent::OnChannelError()
{
if (sProcLoaderClientOnDeinit) {
// Get error for closing while the channel is already error.
return;
}
NS_WARNING("ProcLoaderParent is in channel error");
ProcLoaderClientDeinit();
}
/**
* Initialize the client of B2G loader for loader itself.
*
* The initialization of B2G loader are divided into two stages. First
* stage is to collect child info passed from the main program of the
* loader. Second stage is to initialize Gecko according to info from the
* first stage and make the client of loader service ready.
*
* \param aPeerPid is the pid of the child.
* \param aChannelFd is the file descriptor of the socket used for IPC.
*/
static void
ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd)
{
MOZ_ASSERT(!sProcLoaderClientInitialized, "call ProcLoaderClientInit() more than once");
MOZ_ASSERT(aPeerPid != 0 && aChannelFd != -1, "invalid argument");
sProcLoaderPid = aPeerPid;
sProcLoaderChannelFd = aChannelFd;
sProcLoaderClientInitialized = true;
}
/**
* Initialize the client of B2G loader for Gecko.
*/
void
ProcLoaderClientGeckoInit()
{
MOZ_ASSERT(sProcLoaderClientInitialized, "call ProcLoaderClientInit() at first");
MOZ_ASSERT(!sProcLoaderClientGeckoInitialized,
"call ProcLoaderClientGeckoInit() more than once");
sProcLoaderClientGeckoInitialized = true;
FileDescriptor *fd = new FileDescriptor(sProcLoaderChannelFd);
close(sProcLoaderChannelFd);
sProcLoaderChannelFd = -1;
Transport *transport = OpenDescriptor(*fd, Transport::MODE_CLIENT);
sProcLoaderParent = new ProcLoaderParent(fd);
sProcLoaderParent->Open(transport,
sProcLoaderPid,
XRE_GetIOMessageLoop(),
ParentSide);
sProcLoaderLoop = MessageLoop::current();
}
/**
* Shutdown and destroy the client of B2G loader service.
*/
static void
ProcLoaderClientDeinit()
{
MOZ_ASSERT(sProcLoaderClientGeckoInitialized && sProcLoaderClientInitialized);
sProcLoaderClientGeckoInitialized = false;
sProcLoaderClientInitialized = false;
sProcLoaderClientOnDeinit = true;
MOZ_ASSERT(sProcLoaderParent != nullptr);
PProcLoaderParent *procLoaderParent = sProcLoaderParent;
sProcLoaderParent = nullptr;
sProcLoaderLoop = nullptr;
MessageLoop::current()->
PostTask(FROM_HERE,
NewRunnableFunction(&_ProcLoaderParentDestroy,
procLoaderParent));
}
struct AsyncSendLoadData
{
nsTArray<nsCString> mArgv;
nsTArray<nsCString> mEnv;
nsTArray<FDRemap> mFdsremap;
ChildPrivileges mPrivs;
int mCookie;
};
static void
AsyncSendLoad(AsyncSendLoadData *aLoad)
{
PProcLoaderParent *loader = sProcLoaderParent;
DebugOnly<bool> ok =
loader->SendLoad(aLoad->mArgv, aLoad->mEnv, aLoad->mFdsremap,
aLoad->mPrivs, aLoad->mCookie);
MOZ_ASSERT(ok);
delete aLoad;
}
/**
* Request the loader service, the server, to load Nuwa.
*/
bool
ProcLoaderLoad(const char *aArgv[],
const char *aEnvp[],
const file_handle_mapping_vector &aFdsRemap,
const ChildPrivileges aPrivs,
ProcessHandle *aProcessHandle)
{
static int cookie=0;
int i;
if (sProcLoaderParent == nullptr || sProcLoaderPid == 0) {
return false;
}
AsyncSendLoadData *load = new AsyncSendLoadData();
nsTArray<nsCString> &argv = load->mArgv;
for (i = 0; aArgv[i] != nullptr; i++) {
argv.AppendElement(nsCString(aArgv[i]));
}
nsTArray<nsCString> &env = load->mEnv;
for (i = 0; aEnvp[i] != nullptr; i++) {
env.AppendElement(nsCString(aEnvp[i]));
}
nsTArray<FDRemap> &fdsremap = load->mFdsremap;
for (file_handle_mapping_vector::const_iterator fdmap =
aFdsRemap.begin();
fdmap != aFdsRemap.end();
fdmap++) {
fdsremap.AppendElement(FDRemap(fdmap->first, fdmap->second));
}
load->mPrivs = aPrivs;
load->mCookie = cookie++;
*aProcessHandle = sProcLoaderPid;
sProcLoaderPid = 0;
sProcLoaderLoop->PostTask(FROM_HERE,
NewRunnableFunction(AsyncSendLoad, load));
return true;
}
class ProcLoaderRunnerBase;
static bool sProcLoaderServing = false;
static ProcLoaderRunnerBase *sProcLoaderDispatchedTask = nullptr;
class ProcLoaderRunnerBase
{
public:
virtual int DoWork() = 0;
};
class ProcLoaderNoopRunner : public ProcLoaderRunnerBase {
public:
virtual int DoWork();
};
int
ProcLoaderNoopRunner::DoWork() {
return 0;
}
/**
* The runner to load Nuwa at the current process.
*/
class ProcLoaderLoadRunner : public ProcLoaderRunnerBase {
private:
const nsTArray<nsCString> mArgv;
const nsTArray<nsCString> mEnv;
const nsTArray<FDRemap> mFdsRemap;
const ChildPrivileges mPrivs;
void ShuffleFds();
public:
ProcLoaderLoadRunner(const InfallibleTArray<nsCString>& aArgv,
const InfallibleTArray<nsCString>& aEnv,
const InfallibleTArray<FDRemap>& aFdsRemap,
const ChildPrivileges aPrivs)
: mArgv(aArgv)
, mEnv(aEnv)
, mFdsRemap(aFdsRemap)
, mPrivs(aPrivs) {}
int DoWork();
};
void
ProcLoaderLoadRunner::ShuffleFds()
{
unsigned int i;
InjectiveMultimap fd_shuffle1, fd_shuffle2;
fd_shuffle1.reserve(mFdsRemap.Length());
fd_shuffle2.reserve(mFdsRemap.Length());
for (i = 0; i < mFdsRemap.Length(); i++) {
const FDRemap *map = &mFdsRemap[i];
int fd = map->fd().PlatformHandle();
int tofd = map->mapto();
fd_shuffle1.push_back(InjectionArc(fd, tofd, false));
fd_shuffle2.push_back(InjectionArc(fd, tofd, false));
}
DebugOnly<bool> ok = ShuffleFileDescriptors(&fd_shuffle1);
MOZ_ASSERT(ok, "ShuffleFileDescriptors failed");
CloseSuperfluousFds(fd_shuffle2);
}
int
ProcLoaderLoadRunner::DoWork()
{
unsigned int i;
ShuffleFds();
unsigned int argc = mArgv.Length();
char **argv = new char *[argc + 1];
for (i = 0; i < argc; i++) {
argv[i] = ::strdup(mArgv[i].get());
}
argv[argc] = nullptr;
unsigned int envc = mEnv.Length();
for (i = 0; i < envc; i++) {
PR_SetEnv(mEnv[i].get());
}
SetCurrentProcessPrivileges(mPrivs);
MOZ_ASSERT(content_process_main != nullptr,
"content_process_main not found");
// Start Nuwa (main function)
int ret = content_process_main(argc, argv);
for (i = 0; i < argc; i++) {
free(argv[i]);
}
delete[] argv;
return ret;
}
class ProcLoaderChild : public PProcLoaderChild
{
pid_t mPeerPid;
public:
ProcLoaderChild(pid_t aPeerPid) : mPeerPid(aPeerPid) {}
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvLoad(const InfallibleTArray<nsCString>& aArgv,
const InfallibleTArray<nsCString>& aEnv,
const InfallibleTArray<FDRemap>& aFdsremap,
const uint32_t& aPrivs,
const int32_t& aCookie);
virtual void OnChannelError();
};
void
ProcLoaderChild::ActorDestroy(ActorDestroyReason aWhy)
{
}
static void
_ProcLoaderChildDestroy(ProcLoaderChild *aChild)
{
aChild->Close();
delete aChild;
MessageLoop::current()->Quit();
}
bool
ProcLoaderChild::RecvLoad(const InfallibleTArray<nsCString>& aArgv,
const InfallibleTArray<nsCString>& aEnv,
const InfallibleTArray<FDRemap>& aFdsRemap,
const uint32_t& aPrivs,
const int32_t& aCookie) {
if (!sProcLoaderServing) {
return true;
}
sProcLoaderServing = false;
MOZ_ASSERT(sProcLoaderDispatchedTask == nullptr);
ChildPrivileges privs = static_cast<ChildPrivileges>(aPrivs);
sProcLoaderDispatchedTask =
new ProcLoaderLoadRunner(aArgv, aEnv, aFdsRemap, privs);
SendLoadComplete(mPeerPid, aCookie);
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(_ProcLoaderChildDestroy,
this));
return true;
}
void
ProcLoaderChild::OnChannelError()
{
if (!sProcLoaderServing) {
return;
}
sProcLoaderServing = false;
PProcLoaderChild::OnChannelError();
MOZ_ASSERT(sProcLoaderDispatchedTask == nullptr);
sProcLoaderDispatchedTask = new ProcLoaderNoopRunner();
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(_ProcLoaderChildDestroy,
this));
}
/**
* A helper class which calls NS_LogInit/NS_LogTerm in its scope.
*/
class ScopedLogging
{
public:
ScopedLogging() { NS_LogInit(); }
~ScopedLogging() { NS_LogTerm(); }
};
/**
* Run service of ProcLoader.
*
* \param aPeerPid is the pid of the parent.
* \param aFd is the file descriptor of the socket for IPC.
*
* See the comment near the head of this file.
*/
static int
ProcLoaderServiceRun(pid_t aPeerPid, int aFd,
int aArgc, const char *aArgv[])
{
ScopedLogging logging;
char **_argv;
_argv = new char *[aArgc + 1];
for (int i = 0; i < aArgc; i++) {
_argv[i] = ::strdup(aArgv[i]);
MOZ_ASSERT(_argv[i] != nullptr);
}
_argv[aArgc] = nullptr;
gArgv = _argv;
gArgc = aArgc;
{
gDisableAndroidLog = true;
nsresult rv = XRE_InitCommandLine(aArgc, _argv);
if (NS_FAILED(rv)) {
gDisableAndroidLog = false;
MOZ_CRASH();
}
FileDescriptor fd(aFd);
close(aFd);
MOZ_ASSERT(!sProcLoaderServing);
MessageLoop loop;
nsAutoPtr<ContentProcess> process;
process = new ContentProcess(aPeerPid);
ChildThread *iothread = process->child_thread();
Transport *transport = OpenDescriptor(fd, Transport::MODE_CLIENT);
ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid);
// Pass a message loop to initialize (connect) the channel
// (connection).
loaderChild->Open(transport, aPeerPid, iothread->message_loop());
BackgroundHangMonitor::Prohibit();
sProcLoaderServing = true;
loop.Run();
BackgroundHangMonitor::Allow();
XRE_DeinitCommandLine();
gDisableAndroidLog = false;
}
MOZ_ASSERT(sProcLoaderDispatchedTask != nullptr);
ProcLoaderRunnerBase *task = sProcLoaderDispatchedTask;
sProcLoaderDispatchedTask = nullptr;
int ret = task->DoWork();
delete task;
for (int i = 0; i < aArgc; i++) {
free(_argv[i]);
}
delete[] _argv;
return ret;
}
#endif /* MOZ_B2G_LOADER */
} // namespace ipc
} // namespace mozilla
#ifdef MOZ_B2G_LOADER
void
XRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd)
{
mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd);
}
int
XRE_ProcLoaderServiceRun(pid_t aPeerPid, int aFd,
int aArgc, const char *aArgv[])
{
return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd,
aArgc, aArgv);
}
#endif /* MOZ_B2G_LOADER */

Просмотреть файл

@ -130,12 +130,14 @@ IPDL_SOURCES = [
'PBackground.ipdl',
'PBackgroundSharedTypes.ipdlh',
'PBackgroundTest.ipdl',
'PProcLoader.ipdl',
'ProtocolTypes.ipdlh',
'URIParams.ipdlh',
]
LOCAL_INCLUDES += [
'/toolkit/xre',
'/xpcom/threads',
]

Просмотреть файл

@ -26,4 +26,7 @@ if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_NFC'] or CONFIG[
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
DIRS += ['keystore', 'netd']
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
DIRS += ['contentproc']
TOOL_DIRS += ['app']

Просмотреть файл

@ -47,6 +47,18 @@ from mozlog.structured.structuredlog import StructuredLogger
# not yet present in the mozharness environment
from mozrunner.utils import findInPath as which
# Necessary to set up the global logger in automationutils.py
import logging
log = logging.getLogger()
def resetGlobalLog():
while log.handlers:
log.removeHandler(log.handlers[0])
handler = logging.StreamHandler(sys.stdout)
log.setLevel(logging.INFO)
log.addHandler(handler)
resetGlobalLog()
###########################
# Option for NSPR logging #
###########################

Просмотреть файл

@ -160,3 +160,5 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
'/widget/xremoteclient',
]
if CONFIG['MOZ_B2G_LOADER']:
DEFINES['OMNIJAR_NAME'] = CONFIG['OMNIJAR_NAME']

Просмотреть файл

@ -185,6 +185,10 @@
#include "GTestRunner.h"
#endif
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
@ -3772,6 +3776,10 @@ XREMain::XRE_mainRun()
nsresult rv = NS_OK;
NS_ASSERTION(mScopedXPCom, "Scoped xpcom not initialized.");
#ifdef MOZ_B2G_LOADER
mozilla::ipc::ProcLoaderClientGeckoInit();
#endif
#ifdef NS_FUNCTION_TIMER
// initialize some common services, so we don't pay the cost for these at odd times later on;
// SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs

Просмотреть файл

@ -81,6 +81,11 @@
using mozilla::_ipdltest::IPDLUnitTestProcessChild;
#endif // ifdef MOZ_IPDL_TESTS
#ifdef MOZ_B2G_LOADER
#include "nsLocalFile.h"
#include "nsXREAppData.h"
#endif
using namespace mozilla;
using mozilla::ipc::BrowserProcessSubThread;
@ -815,3 +820,38 @@ XRE_GetWindowsEnvironment()
}
#endif // XP_WIN
#ifdef MOZ_B2G_LOADER
extern const nsXREAppData* gAppData;
/**
* Preload static data of Gecko for B2G loader.
*
* This function is supposed to be called before XPCOM is initialized.
* For now, this function preloads
* - XPT interface Information
*/
void
XRE_ProcLoaderPreload(const char* aProgramDir, const nsXREAppData* aAppData)
{
void PreloadXPT(nsIFile *);
nsresult rv;
nsCOMPtr<nsIFile> omnijarFile;
rv = NS_NewNativeLocalFile(nsCString(aProgramDir),
true,
getter_AddRefs(omnijarFile));
MOZ_ASSERT(NS_SUCCEEDED(rv));
rv = omnijarFile->AppendNative(NS_LITERAL_CSTRING(NS_STRINGIFY(OMNIJAR_NAME)));
MOZ_ASSERT(NS_SUCCEEDED(rv));
/*
* gAppData is required by nsXULAppInfo. The manifest parser
* evaluate flags with the information from nsXULAppInfo.
*/
gAppData = aAppData;
PreloadXPT(omnijarFile);
gAppData = nullptr;
}
#endif /* MOZ_B2G_LOADER */

Просмотреть файл

@ -878,6 +878,10 @@ void mozilla_sampler_unlock()
bool mozilla_sampler_register_thread(const char* aName, void* stackTop)
{
if (sInitCount == 0) {
return false;
}
#if defined(MOZ_WIDGET_GONK) && !defined(MOZ_PROFILING)
// The only way to profile secondary threads on b2g
// is to build with profiling OR have the profiler
@ -895,6 +899,10 @@ bool mozilla_sampler_register_thread(const char* aName, void* stackTop)
void mozilla_sampler_unregister_thread()
{
if (sInitCount == 0) {
return;
}
Sampler::UnregisterCurrentThread();
PseudoStack *stack = tlsPseudoStack.get();
@ -906,6 +914,10 @@ void mozilla_sampler_unregister_thread()
}
void mozilla_sampler_sleep_start() {
if (sInitCount == 0) {
return;
}
PseudoStack *stack = tlsPseudoStack.get();
if (stack == nullptr) {
return;
@ -914,6 +926,10 @@ void mozilla_sampler_sleep_start() {
}
void mozilla_sampler_sleep_end() {
if (sInitCount == 0) {
return;
}
PseudoStack *stack = tlsPseudoStack.get();
if (stack == nullptr) {
return;

Просмотреть файл

@ -101,6 +101,13 @@ Break(const char* aMsg);
#include <stdlib.h>
#endif
#ifdef MOZ_B2G_LOADER
/* Avoid calling Android logger/logd temporarily while running
* B2GLoader to start the child process.
*/
bool gDisableAndroidLog = false;
#endif
using namespace mozilla;
static const char* sMultiprocessDescription = nullptr;
@ -392,6 +399,9 @@ NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr,
#endif
#ifdef ANDROID
#ifdef MOZ_B2G_LOADER
if (!gDisableAndroidLog)
#endif
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", buf.buffer);
#endif

Просмотреть файл

@ -467,6 +467,16 @@ XRE_API(WindowsEnvironmentType,
XRE_GetWindowsEnvironment, ())
#endif // XP_WIN
#ifdef MOZ_B2G_LOADER
XRE_API(int,
XRE_ProcLoaderServiceRun, (pid_t, int, int argc, const char *argv[]));
XRE_API(void,
XRE_ProcLoaderClientInit, (pid_t, int));
XRE_API(void,
XRE_ProcLoaderPreload, (const char* aProgramDir,
const nsXREAppData* aAppData));
#endif // MOZ_B2G_LOADER
XRE_API(int,
XRE_XPCShellMain, (int argc, char** argv, char** envp))

Просмотреть файл

@ -36,6 +36,18 @@
#include "nsIScriptError.h"
#include "nsIXULAppInfo.h"
#include "nsIXULRuntime.h"
#ifdef MOZ_B2G_LOADER
#include "mozilla/XPTInterfaceInfoManager.h"
#endif
#ifdef MOZ_B2G_LOADER
#define XPTONLY_MANIFEST &nsComponentManagerImpl::XPTOnlyManifestManifest
#define XPTONLY_XPT &nsComponentManagerImpl::XPTOnlyManifestXPT
#else
#define XPTONLY_MANIFEST nullptr
#define XPTONLY_XPT nullptr
#endif
using namespace mozilla;
@ -64,36 +76,43 @@ struct ManifestDirective
(nsChromeRegistry::ManifestProcessingContext& cx,
int lineno, char *const *argv,
bool platform, bool contentaccessible);
#ifdef MOZ_B2G_LOADER
// The function to handle the directive for XPT Only parsing.
void (*xptonlyfunc)(nsComponentManagerImpl::XPTOnlyManifestProcessingContext& cx,
int lineno, char *const * argv);
#else
void *xptonlyfunc;
#endif
bool isContract;
};
static const ManifestDirective kParsingTable[] = {
{ "manifest", 1, false, true, true, false,
&nsComponentManagerImpl::ManifestManifest, nullptr },
&nsComponentManagerImpl::ManifestManifest, nullptr, XPTONLY_MANIFEST },
{ "binary-component", 1, true, false, false, false,
&nsComponentManagerImpl::ManifestBinaryComponent, nullptr },
&nsComponentManagerImpl::ManifestBinaryComponent, nullptr, nullptr },
{ "interfaces", 1, true, false, false, false,
&nsComponentManagerImpl::ManifestXPT, nullptr },
&nsComponentManagerImpl::ManifestXPT, nullptr, XPTONLY_XPT },
{ "component", 2, true, false, false, false,
&nsComponentManagerImpl::ManifestComponent, nullptr },
&nsComponentManagerImpl::ManifestComponent, nullptr, nullptr },
{ "contract", 2, true, false, false, false,
&nsComponentManagerImpl::ManifestContract, nullptr, true},
&nsComponentManagerImpl::ManifestContract, nullptr, nullptr, true},
{ "category", 3, true, false, false, false,
&nsComponentManagerImpl::ManifestCategory, nullptr },
&nsComponentManagerImpl::ManifestCategory, nullptr, nullptr },
{ "content", 2, true, true, true, true,
nullptr, &nsChromeRegistry::ManifestContent },
nullptr, &nsChromeRegistry::ManifestContent, nullptr },
{ "locale", 3, true, true, true, false,
nullptr, &nsChromeRegistry::ManifestLocale },
nullptr, &nsChromeRegistry::ManifestLocale, nullptr },
{ "skin", 3, false, true, true, false,
nullptr, &nsChromeRegistry::ManifestSkin },
nullptr, &nsChromeRegistry::ManifestSkin, nullptr },
{ "overlay", 2, true, true, false, false,
nullptr, &nsChromeRegistry::ManifestOverlay },
nullptr, &nsChromeRegistry::ManifestOverlay, nullptr },
{ "style", 2, false, true, false, false,
nullptr, &nsChromeRegistry::ManifestStyle },
nullptr, &nsChromeRegistry::ManifestStyle, nullptr },
{ "override", 2, true, true, true, false,
nullptr, &nsChromeRegistry::ManifestOverride },
nullptr, &nsChromeRegistry::ManifestOverride, nullptr },
{ "resource", 2, true, true, false, false,
nullptr, &nsChromeRegistry::ManifestResource }
nullptr, &nsChromeRegistry::ManifestResource, nullptr }
};
static const char kWhitespace[] = "\t ";
@ -126,8 +145,16 @@ struct AutoPR_smprintf_free
} // anonymous namespace
/**
* If we are pre-loading XPTs, this method may do nothing because the
* console service is not initialized.
*/
void LogMessage(const char* aMsg, ...)
{
if (!nsComponentManagerImpl::gComponentManager) {
return;
}
nsCOMPtr<nsIConsoleService> console =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (!console)
@ -143,6 +170,10 @@ void LogMessage(const char* aMsg, ...)
console->LogMessage(error);
}
/**
* If we are pre-loading XPTs, this method may do nothing because the
* console service is not initialized.
*/
void LogMessageWithContext(FileLocation &aFile,
uint32_t aLineNumber, const char* aMsg, ...)
{
@ -153,6 +184,10 @@ void LogMessageWithContext(FileLocation &aFile,
if (!formatted)
return;
if (!nsComponentManagerImpl::gComponentManager) {
return;
}
nsCString file;
aFile.GetURIString(file);
@ -388,11 +423,23 @@ struct CachedDirective
} // anonymous namespace
/**
* For XPT-Only mode, the parser handles only directives of "manifest"
* and "interfaces", and always call the function given by |xptonlyfunc|
* variable of struct |ManifestDirective|.
*
* This function is safe to be called before the component manager is
* ready if aXPTOnly is true for it don't invoke any component during
* parsing.
*/
void
ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOnly)
ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOnly, bool aXPTOnly)
{
nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, file, aChromeOnly);
nsChromeRegistry::ManifestProcessingContext chromecx(type, file);
#ifdef MOZ_B2G_LOADER
nsComponentManagerImpl::XPTOnlyManifestProcessingContext xptonlycx(file);
#endif
nsresult rv;
NS_NAMED_LITERAL_STRING(kPlatform, "platform");
@ -416,7 +463,12 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
nsAutoString osTarget;
nsAutoString abi;
nsCOMPtr<nsIXULAppInfo> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
nsCOMPtr<nsIXULAppInfo> xapp;
if (!aXPTOnly) {
// Avoid to create any component for XPT only mode.
// No xapp means no ID, version, ..., modifiers checking.
xapp = do_GetService(XULAPPINFO_SERVICE_CONTRACTID);
}
if (xapp) {
nsAutoCString s;
rv = xapp->GetID(s);
@ -516,9 +568,10 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
for (const ManifestDirective* d = kParsingTable;
d < ArrayEnd(kParsingTable);
++d) {
if (!strcmp(d->directive, token)) {
directive = d;
break;
if (!strcmp(d->directive, token) &&
(!aXPTOnly || d->xptonlyfunc)) {
directive = d;
break;
}
}
@ -577,8 +630,9 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
CheckStringFlag(kABI, wtoken, abi, stABI) ||
CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) {
continue;
}
#if defined(MOZ_WIDGET_ANDROID)
bool tablet = false;
@ -619,6 +673,11 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
stABI == eBad)
continue;
#ifdef MOZ_B2G_LOADER
if (aXPTOnly) {
directive->xptonlyfunc(xptonlycx, line, argv);
} else
#endif /* MOZ_B2G_LOADER */
if (directive->regfunc) {
if (GeckoProcessType_Default != XRE_GetProcessType())
continue;
@ -636,7 +695,7 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
(nsChromeRegistry::gChromeRegistry->*(directive->regfunc))
(chromecx, line, argv, platform, contentAccessible);
}
else if (directive->ischrome || !aChromeOnly) {
else if (directive->mgrfunc && (directive->ischrome || !aChromeOnly)) {
if (directive->isContract) {
CachedDirective* cd = contracts.AppendElement();
cd->lineno = line;
@ -646,6 +705,9 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
else
(nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))
(mgrcx, line, argv);
} else {
LogMessageWithContext(file, line,
"No valid manifest directive.");
}
}

Просмотреть файл

@ -13,7 +13,7 @@
class nsIFile;
void ParseManifest(NSLocationType type, mozilla::FileLocation &file,
char* buf, bool aChromeOnly);
char* buf, bool aChromeOnly, bool aXPTOnly=false);
void LogMessage(const char* aMsg, ...);

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsStringEnumerator.h"
#include "mozilla/FileUtils.h"
#include "nsNetUtil.h"
#include "nsDataHashtable.h"
#include <new> // for placement new
@ -104,6 +105,36 @@ NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
#define UID_STRING_LENGTH 39
#ifdef MOZ_B2G_LOADER
typedef nsDataHashtable<nsCStringHashKey, bool> XPTIInfosBookType;
static XPTIInfosBookType *sXPTIInfosBook = nullptr;
static XPTIInfosBookType *
GetXPTIInfosBook()
{
if (sXPTIInfosBook == nullptr) {
sXPTIInfosBook = new XPTIInfosBookType;
}
return sXPTIInfosBook;
}
static bool
IsRegisteredXPTIInfo(FileLocation &aFile)
{
nsAutoCString uri;
aFile.GetURIString(uri);
return GetXPTIInfosBook()->Get(uri);
}
static void
MarkRegisteredXPTIInfo(FileLocation &aFile)
{
nsAutoCString uri;
aFile.GetURIString(uri);
GetXPTIInfosBook()->Put(uri, true);
}
#endif /* MOZ_B2G_LOADER */
nsresult
nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
{
@ -524,11 +555,14 @@ CutExtension(nsCString& path)
path.Cut(0, dotPos + 1);
}
void
nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
FileLocation &aFile,
bool aChromeOnly)
static void
DoRegisterManifest(NSLocationType aType,
FileLocation &aFile,
bool aChromeOnly,
bool aXPTOnly)
{
MOZ_ASSERT(!aXPTOnly ||
nsComponentManagerImpl::gComponentManager == nullptr);
uint32_t len;
FileLocation::Data data;
nsAutoArrayPtr<char> buf;
@ -542,7 +576,7 @@ nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
}
if (NS_SUCCEEDED(rv)) {
buf[len] = '\0';
ParseManifest(aType, aFile, buf, aChromeOnly);
ParseManifest(aType, aFile, buf, aChromeOnly, aXPTOnly);
} else if (NS_BOOTSTRAPPED_LOCATION != aType) {
nsCString uri;
aFile.GetURIString(uri);
@ -550,6 +584,14 @@ nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
}
}
void
nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
FileLocation &aFile,
bool aChromeOnly)
{
DoRegisterManifest(aType, aFile, aChromeOnly, false);
}
void
nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
{
@ -587,14 +629,19 @@ nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, i
RegisterModule(m, &f);
}
void
nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
static void
DoRegisterXPT(FileLocation &aFile)
{
FileLocation f(cx.mFile, argv[0]);
#ifdef MOZ_B2G_LOADER
if (IsRegisteredXPTIInfo(aFile)) {
return;
}
#endif
uint32_t len;
FileLocation::Data data;
nsAutoArrayPtr<char> buf;
nsresult rv = f.GetData(data);
nsresult rv = aFile.GetData(data);
if (NS_SUCCEEDED(rv)) {
rv = data.GetSize(&len);
}
@ -604,13 +651,23 @@ nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, c
}
if (NS_SUCCEEDED(rv)) {
XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf, len);
#ifdef MOZ_B2G_LOADER
MarkRegisteredXPTIInfo(aFile);
#endif
} else {
nsCString uri;
f.GetURIString(uri);
aFile.GetURIString(uri);
LogMessage("Could not read '%s'.", uri.get());
}
}
void
nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
{
FileLocation f(cx.mFile, argv[0]);
DoRegisterXPT(f);
}
void
nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
{
@ -794,6 +851,10 @@ nsresult nsComponentManagerImpl::Shutdown(void)
delete sStaticModules;
delete sModuleLocations;
#ifdef MOZ_B2G_LOADER
delete sXPTIInfosBook;
sXPTIInfosBook = nullptr;
#endif
// Unload libraries
mNativeModuleLoader.UnloadLibraries();
@ -1942,6 +2003,54 @@ nsComponentManagerImpl::GetManifestLocations(nsIArray **aLocations)
return NS_OK;
}
#ifdef MOZ_B2G_LOADER
/* static */
void
nsComponentManagerImpl::XPTOnlyManifestManifest(XPTOnlyManifestProcessingContext &aCx,
int aLineno,
char * const * aArgv)
{
char* file = aArgv[0];
FileLocation f(aCx.mFile, file);
DoRegisterManifest(NS_COMPONENT_LOCATION, f, false, true);
}
/* static */
void
nsComponentManagerImpl::XPTOnlyManifestXPT(XPTOnlyManifestProcessingContext &aCx,
int aLineno,
char * const * aArgv)
{
FileLocation f(aCx.mFile, aArgv[0]);
DoRegisterXPT(f);
}
/**
* To load XPT Interface Information before the component manager is ready.
*
* With this function, B2G loader could XPT interface info. as earier
* as possible to gain benefit of shared memory model of the kernel.
*/
/* static */ void
nsComponentManagerImpl::PreloadXPT(nsIFile *aFile)
{
MOZ_ASSERT(nsComponentManagerImpl::gComponentManager == nullptr);
FileLocation location(aFile, "chrome.manifest");
DoRegisterManifest(NS_COMPONENT_LOCATION, location,
false, true /* aXPTOnly */);
}
void
PreloadXPT(nsIFile *aOmnijarFile)
{
nsComponentManagerImpl::PreloadXPT(aOmnijarFile);
}
#endif /* MOZ_B2G_LOADER */
EXPORT_XPCOM_API(nsresult)
XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation)
{

Просмотреть файл

@ -38,6 +38,10 @@
#include "mozilla/Omnijar.h"
#include "mozilla/Attributes.h"
#ifdef MOZ_B2G_LOADER
#include "mozilla/FileLocation.h"
#endif
struct nsFactoryEntry;
class nsIServiceManager;
struct PRThread;
@ -316,6 +320,30 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
#ifdef MOZ_B2G_LOADER
// Preload XPT interface info for B2G loader.
// This function is called before XPCOM has been initialized.
static void PreloadXPT(nsIFile *aFile);
#endif
#ifdef MOZ_B2G_LOADER
// Parsing functions of directives of manifest for XPT only parsing.
struct XPTOnlyManifestProcessingContext
{
XPTOnlyManifestProcessingContext(mozilla::FileLocation &aFile)
: mFile(aFile)
{ }
~XPTOnlyManifestProcessingContext() { }
mozilla::FileLocation mFile;
};
static void XPTOnlyManifestManifest(XPTOnlyManifestProcessingContext& aCx,
int aLineno, char * const *aArgv);
static void XPTOnlyManifestXPT(XPTOnlyManifestProcessingContext& aCx,
int aLineno, char * const *aArgv);
#endif
private:
~nsComponentManagerImpl();
};

Просмотреть файл

@ -65,6 +65,7 @@ private:
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BackgroundHangManager)
static StaticRefPtr<BackgroundHangManager> sInstance;
static bool sProhibited;
// Lock for access to members of this class
Monitor mLock;
@ -162,6 +163,7 @@ public:
StaticRefPtr<BackgroundHangManager> BackgroundHangManager::sInstance;
bool BackgroundHangManager::sProhibited = false;
ThreadLocal<BackgroundHangThread*> BackgroundHangThread::sTlsKey;
@ -409,8 +411,16 @@ BackgroundHangThread*
BackgroundHangThread::FindThread()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (BackgroundHangManager::sInstance == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
"BackgroundHandleManager is not initialized");
return nullptr;
}
if (sTlsKey.initialized()) {
// Use TLS if available
MOZ_ASSERT(!BackgroundHangManager::sProhibited,
"BackgroundHandleManager is not initialized");
return sTlsKey.get();
}
// If TLS is unavailable, we can search through the thread list
@ -436,6 +446,7 @@ void
BackgroundHangMonitor::Startup()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(!BackgroundHangManager::sProhibited, "Prohibited");
MOZ_ASSERT(!BackgroundHangManager::sInstance, "Already initialized");
ThreadStackHelper::Startup();
BackgroundHangThread::Startup();
@ -447,6 +458,7 @@ void
BackgroundHangMonitor::Shutdown()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(!BackgroundHangManager::sProhibited, "Prohibited");
MOZ_ASSERT(BackgroundHangManager::sInstance, "Not initialized");
/* Scope our lock inside Shutdown() because the sInstance object can
be destroyed as soon as we set sInstance to nullptr below, and
@ -463,7 +475,8 @@ BackgroundHangMonitor::BackgroundHangMonitor(const char* aName,
: mThread(BackgroundHangThread::FindThread())
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (!mThread) {
if (!BackgroundHangManager::sProhibited && !mThread) {
// If sProhibit is true, mThread would be null, and no monitoring.
mThread = new BackgroundHangThread(aName, aTimeoutMs, aMaxTimeoutMs);
}
#endif
@ -473,7 +486,8 @@ BackgroundHangMonitor::BackgroundHangMonitor()
: mThread(BackgroundHangThread::FindThread())
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(mThread, "Thread not initialized for hang monitoring");
MOZ_ASSERT(!BackgroundHangManager::sProhibited || mThread,
"This thread is not initialized for hang monitoring");
#endif
}
@ -485,6 +499,11 @@ void
BackgroundHangMonitor::NotifyActivity()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (mThread == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
"This thread is not initialized for hang monitoring");
return;
}
mThread->NotifyActivity();
#endif
}
@ -493,18 +512,49 @@ void
BackgroundHangMonitor::NotifyWait()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (mThread == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
"This thread is not initialized for hang monitoring");
return;
}
mThread->NotifyWait();
#endif
}
void
BackgroundHangMonitor::Prohibit()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(BackgroundHangManager::sInstance == nullptr,
"The background hang monitor is already initialized");
BackgroundHangManager::sProhibited = true;
#endif
}
void
BackgroundHangMonitor::Allow()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(BackgroundHangManager::sInstance == nullptr,
"The background hang monitor is already initialized");
BackgroundHangManager::sProhibited = false;
#endif
}
/* Because we are iterating through the BackgroundHangThread linked list,
we need to take a lock. Using MonitorAutoLock as a base class makes
sure all of that is taken care of for us. */
BackgroundHangMonitor::ThreadHangStatsIterator::ThreadHangStatsIterator()
: MonitorAutoLock(BackgroundHangManager::sInstance->mLock)
, mThread(BackgroundHangManager::sInstance->mHangThreads.getFirst())
, mThread(BackgroundHangManager::sInstance ?
BackgroundHangManager::sInstance->mHangThreads.getFirst() :
nullptr)
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(BackgroundHangManager::sInstance || BackgroundHangManager::sProhibited,
"Inconsistent state");
#endif
}
Telemetry::ThreadHangStats*

Просмотреть файл

@ -107,6 +107,8 @@ class BackgroundHangThread;
* }
* }
*
* Prohibit() and Allow() make the background hang monitor work safely
* before Startup().
*/
class BackgroundHangMonitor
{
@ -204,6 +206,27 @@ public:
* NotifyActivity when subsequently exiting the wait state.
*/
void NotifyWait();
/**
* Prohibit the hang monitor from activating.
*
* Startup() should not be called between Prohibit() and Allow().
* This function makes the background hang monitor stop monitoring
* threads.
*
* Prohibit() and Allow() can be called before XPCOM is ready. If
* we don't stop monitoring threads it could case errors.
*/
static void Prohibit();
/**
* Allow the hang monitor to run.
*
* Allow() and Prohibit() should be called in pair.
*
* \see Prohibit()
*/
static void Allow();
};
} // namespace mozilla