Bug 1284674 - Remove NUWA r=cyu

MozReview-Commit-ID: GyMRNzOBKw6

--HG--
extra : rebase_source : 293af1cd55f2035ce6a99f4ebf144059c32a2b8f
This commit is contained in:
Alexandre Lissy 2016-08-02 14:54:00 +02:00
parent 3245c78fef
commit 0af5b943b6
86 changed files with 23 additions and 5902 deletions

View File

@ -1,300 +0,0 @@
/* -*- 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 <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
#include "mozilla/UniquePtr.h"
#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 }
};
typedef mozilla::Vector<int> FdArray;
static const int kReservedFileDescriptors = 5;
static const int kBeginReserveFileDescriptor = STDERR_FILENO + 1;
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)
{
auto progBuf = mozilla::MakeUnique<char[]>(aMaxLen);
nsresult rv = mozilla::BinaryPath::Get(aProgram, progBuf.get());
NS_ENSURE_SUCCESS(rv, false);
int len = GetDirnameSlash(progBuf.get(), aOutPath, aMaxLen);
NS_ENSURE_TRUE(!!len, false);
NS_ENSURE_TRUE((len + sizeof(XPCOM_DLL)) < (unsigned)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(strdup(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[], FdArray& aReservedFds)
{
/*
* 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,
aReservedFds);
}
// Reap zombie child process.
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGCHLD, &sa, nullptr);
// The b2g process
int childPid = pid;
XRE_ProcLoaderClientInit(childPid, parentSock, aReservedFds);
return b2g_main(argc, argv);
}
/**
* Reserve the file descriptors that shouldn't be taken for other use for the
* child process.
*/
static void
ReserveFileDescriptors(FdArray& aReservedFds)
{
for (int i = 0; i < kReservedFileDescriptors; i++) {
struct stat fileState;
int target = kBeginReserveFileDescriptor + i;
if (fstat(target, &fileState) == 0) {
MOZ_CRASH("ProcLoader error: a magic file descriptor is occupied.");
}
int fd = open("/dev/null", O_RDWR);
if (fd == -1) {
MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor.");
}
if (!aReservedFds.append(target)) {
MOZ_CRASH("Failed to append to aReservedFds");
}
if (fd == target) {
// No need to call dup2(). We already occupy the desired file descriptor.
continue;
}
if (dup2(fd, target)) {
MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor.");
}
close(fd);
}
}
/**
* 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[])
{
/**
* Reserve file descriptors before loading static data.
*/
FdArray reservedFds;
ReserveFileDescriptors(reservedFds);
/*
* 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, reservedFds);
}

View File

@ -8,10 +8,6 @@ if CONFIG['GAIADIR']:
GeckoProgram(CONFIG['MOZ_APP_NAME'] + "-bin")
else:
GeckoProgram(CONFIG['MOZ_APP_NAME'])
if CONFIG['MOZ_B2G_LOADER']:
SOURCES += [
'B2GLoader.cpp',
]
SOURCES += [
'nsBrowserApp.cpp',

View File

@ -163,22 +163,9 @@ static int do_main(int argc, char* argv[])
return XRE_main(argc, argv, &sAppData, 0);
}
#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[])
int main(int argc, 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
@ -189,7 +176,6 @@ int main(int argc, _CONST char* argv[])
#endif
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");
@ -201,7 +187,6 @@ int main(int argc, _CONST 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
@ -216,9 +201,6 @@ int main(int argc, _CONST 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();
@ -229,7 +211,6 @@ int main(int argc, _CONST 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)) {

View File

@ -53,8 +53,6 @@ MOZ_TOOLKIT_SEARCH=
MOZ_B2G=1
if test "$OS_TARGET" = "Android"; then
MOZ_NUWA_PROCESS=1
MOZ_B2G_LOADER=1
MOZ_ENABLE_WARNINGS_AS_ERRORS=1
fi

View File

@ -48,8 +48,6 @@ MOZ_PLACES=
MOZ_B2G=1
if test "$OS_TARGET" = "Android"; then
MOZ_NUWA_PROCESS=1
MOZ_B2G_LOADER=1
MOZ_ENABLE_WARNINGS_AS_ERRORS=1
fi

View File

@ -166,11 +166,6 @@
#include "nsIAccessibilityService.h"
#endif
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "NuwaChild.h"
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushNotifier.h"
#endif
@ -516,57 +511,6 @@ NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
ContentChild* ContentChild::sSingleton;
// Performs initialization that is not fork-safe, i.e. that must be done after
// forking from the Nuwa process.
void
InitOnContentProcessCreated()
{
#ifdef MOZ_NUWA_PROCESS
// Wait until we are forked from Nuwa
if (IsNuwaProcess()) {
return;
}
nsCOMPtr<nsIPermissionManager> permManager = services::GetPermissionManager();
MOZ_ASSERT(permManager, "Unable to get permission manager");
nsresult rv = permManager->RefreshPermission();
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Failed updating permission in child process");
}
#endif
// This will register cross-process observer.
mozilla::dom::time::InitializeDateCacheCleaner();
}
#ifdef MOZ_NUWA_PROCESS
static void
ResetTransports(void* aUnused)
{
ContentChild* child = ContentChild::GetSingleton();
mozilla::ipc::Transport* transport = child->GetTransport();
int fd = transport->GetFileDescriptor();
transport->ResetFileDescriptor(fd);
nsTArray<IToplevelProtocol*> actors;
child->GetOpenedActors(actors);
for (size_t i = 0; i < actors.Length(); i++) {
IToplevelProtocol* toplevel = actors[i];
transport = toplevel->GetTransport();
fd = transport->GetFileDescriptor();
transport->ResetFileDescriptor(fd);
}
}
#endif
#if defined(MOZ_TASK_TRACER) && defined(MOZ_NUWA_PROCESS)
static void
ReinitTaskTracer(void* /*aUnused*/)
{
mozilla::tasktracer::InitTaskTracer(mozilla::tasktracer::FORKED_AFTER_NUWA);
}
#endif
ContentChild::ContentChild()
: mID(uint64_t(-1))
, mCanOverrideProcessName(true)
@ -642,11 +586,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
// If communications with the parent have broken down, take the process
// down so it's not hanging around.
bool abortOnError = true;
#ifdef MOZ_NUWA_PROCESS
abortOnError &= !IsNuwaProcess();
#endif
GetIPCChannel()->SetAbortOnError(abortOnError);
GetIPCChannel()->SetAbortOnError(true);
#ifdef MOZ_X11
// Send the parent our X socket to act as a proxy reference for our X
@ -663,17 +603,6 @@ ContentChild::Init(MessageLoop* aIOLoop,
SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
InitProcessAttributes();
#if defined(MOZ_TASK_TRACER) && defined (MOZ_NUWA_PROCESS)
if (IsNuwaProcess()) {
NuwaAddConstructor(ReinitTaskTracer, nullptr);
}
#endif
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaAddConstructor(ResetTransports, nullptr);
}
#endif
#ifdef NS_PRINTING
// Force the creation of the nsPrintingProxy so that it's IPC counterpart,
// PrintingParent, is always available for printing initiated from the parent.
@ -687,12 +616,6 @@ void
ContentChild::InitProcessAttributes()
{
#ifdef MOZ_WIDGET_GONK
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false);
return;
}
#endif
if (mIsForApp && !mIsForBrowser) {
SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
} else {
@ -1037,7 +960,8 @@ ContentChild::InitXPCOM()
global->SetInitialProcessData(data);
}
InitOnContentProcessCreated();
// This will register cross-process observer.
mozilla::dom::time::InitializeDateCacheCleaner();
}
PMemoryReportRequestChild*
@ -2282,14 +2206,6 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
}
mIsAlive = false;
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
// The Nuwa cannot go through the full XPCOM shutdown path or deadlock
// will result.
ProcessChild::QuickExit();
}
#endif
XRE_ShutdownChildProcess();
#endif // NS_FREE_PERMANENT_DATA
}
@ -2528,9 +2444,6 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission)
bool
ContentChild::RecvFlushMemory(const nsString& reason)
{
#ifdef MOZ_NUWA_PROCESS
MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady());
#endif
nsCOMPtr<nsIObserverService> os =
mozilla::services::GetObserverService();
if (os) {
@ -2575,31 +2488,6 @@ ContentChild::RecvCycleCollect()
return true;
}
#ifdef MOZ_NUWA_PROCESS
static void
OnFinishNuwaPreparation()
{
// We want to ensure that the PBackground actor gets cloned in the Nuwa
// process before we freeze. Also, we have to do this to avoid deadlock.
// Protocols that are "opened" (e.g. PBackground, PCompositorBridge) block
// the main thread to wait for the IPC thread during the open operation.
// NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
// the Nuwa process is forked. Unless we ensure that the two cannot happen
// at the same time then we risk deadlock. Spinning the event loop here
// guarantees the ordering is safe for PBackground.
while (!BackgroundChild::GetForCurrentThread()) {
if (NS_WARN_IF(!NS_ProcessNextEvent())) {
return;
}
}
// This will create the actor.
Unused << mozilla::dom::NuwaChild::GetSingleton();
MakeNuwaProcess();
}
#endif
static void
PreloadSlowThings()
{
@ -2644,13 +2532,6 @@ ContentChild::RecvAppInit()
PreloadSlowThings();
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
ContentChild::GetSingleton()->RecvGarbageCollect();
MessageLoop::current()->PostTask(NewRunnableFunction(OnFinishNuwaPreparation));
}
#endif
return true;
}
@ -2796,9 +2677,6 @@ ContentChild::RecvNotifyProcessPriorityChanged(
bool
ContentChild::RecvMinimizeMemoryUsage()
{
#ifdef MOZ_NUWA_PROCESS
MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady());
#endif
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
NS_ENSURE_TRUE(mgr, true);

View File

@ -689,9 +689,6 @@ private:
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
};
void
InitOnContentProcessCreated();
uint64_t
NextWindowID();

View File

@ -52,7 +52,6 @@
#include "mozilla/dom/MediaKeySystemAccess.h"
#endif
#include "mozilla/dom/Notification.h"
#include "mozilla/dom/NuwaParent.h"
#include "mozilla/dom/PContentBridgeParent.h"
#include "mozilla/dom/PContentPermissionRequestParent.h"
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
@ -326,11 +325,6 @@ const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID = NS_IC
namespace mozilla {
namespace dom {
#ifdef MOZ_NUWA_PROCESS
int32_t ContentParent::sNuwaPid = 0;
bool ContentParent::sNuwaReady = false;
#endif
#define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
#define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
@ -549,11 +543,6 @@ StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
UniquePtr<SandboxBrokerPolicyFactory> ContentParent::sSandboxBrokerPolicyFactory;
#endif
#ifdef MOZ_NUWA_PROCESS
// The pref updates sent to the Nuwa process.
static nsTArray<PrefSetting>* sNuwaPrefUpdates;
#endif
// This is true when subprocess launching is enabled. This is the
// case between StartUp() and ShutDown() or JoinAllSubprocesses().
static bool sCanLaunchSubprocesses;
@ -601,45 +590,6 @@ static const char* sObserverTopics[] = {
"gmp-changed",
};
#ifdef MOZ_NUWA_PROCESS
// Contains the observer topics that can be sent to the Nuwa process after it
// becomes ready. The ContentParent instance will unregister sObserverTopics
// if not listed in sNuwaSafeObserverTopics.
static const char* sNuwaSafeObserverTopics[] = {
"xpcom-shutdown",
"profile-before-change",
#ifdef MOZ_WIDGET_GONK
"phone-state-changed",
#endif
#ifdef ACCESSIBILITY
"a11y-init-or-shutdown",
#endif
"nsPref:Changed"
};
#endif
/* static */ already_AddRefed<ContentParent>
ContentParent::RunNuwaProcess()
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<ContentParent> nuwaProcess =
new ContentParent(/* aApp = */ nullptr,
/* aOpener = */ nullptr,
/* aIsForBrowser = */ false,
/* aIsForPreallocated = */ true,
/* aIsNuwaProcess = */ true);
if (!nuwaProcess->LaunchSubprocess(PROCESS_PRIORITY_BACKGROUND)) {
return nullptr;
}
nuwaProcess->Init();
#ifdef MOZ_NUWA_PROCESS
sNuwaPid = nuwaProcess->Pid();
sNuwaReady = false;
#endif
return nuwaProcess.forget();
}
// PreallocateAppProcess is called by the PreallocatedProcessManager.
// ContentParent then takes this process back within
// GetNewOrPreallocatedAppProcess.
@ -691,8 +641,6 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp,
}
}
// XXXkhuey Nuwa wants the frame loader to try again later, but the
// frame loader is really not set up to do that ...
NS_WARNING("Unable to use pre-allocated app process");
process = new ContentParent(aApp,
/* aOpener = */ aOpener,
@ -912,11 +860,7 @@ ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
bool
ContentParent::PreallocatedProcessReady()
{
#ifdef MOZ_NUWA_PROCESS
return PreallocatedProcessManager::PreallocatedProcessReady();
#else
return true;
#endif
}
bool
@ -1534,10 +1478,7 @@ ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority)
//
// Bug 943174: use waitid() with WNOWAIT so that, if the process
// did exit, we won't consume its zombie and confuse the
// GeckoChildProcessHost dtor. Also, if the process isn't a
// direct child because of Nuwa this will fail with ECHILD, and we
// need to assume the child is alive in that case rather than
// assuming it's dead (as is otherwise a reasonable fallback).
// GeckoChildProcessHost dtor.
#ifdef MOZ_WIDGET_GONK
siginfo_t info;
info.si_pid = 0;
@ -1598,14 +1539,6 @@ ContentParent::TransformPreallocatedIntoBrowser(ContentParent* aOpener)
void
ContentParent::ShutDownProcess(ShutDownMethod aMethod)
{
#ifdef MOZ_NUWA_PROCESS
if (aMethod == SEND_SHUTDOWN_MESSAGE && IsNuwaProcess()) {
// We shouldn't send shutdown messages to frozen Nuwa processes,
// so just close the channel.
aMethod = CLOSE_CHANNEL;
}
#endif
// Shutting down by sending a shutdown message works differently than the
// other methods. We first call Shutdown() in the child. After the child is
// ready, it calls FinishShutdown() on us. Then we close the channel.
@ -1635,13 +1568,6 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod)
// sequence.
mCalledClose = true;
Close();
#ifdef MOZ_NUWA_PROCESS
// Kill Nuwa process forcibly to break its IPC channels and finalize
// corresponding parents.
if (IsNuwaProcess()) {
KillHard("ShutDownProcess");
}
#endif
}
const ManagedContainer<POfflineCacheUpdateParent>& ocuParents =
@ -1724,10 +1650,6 @@ void
ContentParent::OnChannelError()
{
RefPtr<ContentParent> content(this);
#ifdef MOZ_NUWA_PROCESS
// Handle app or Nuwa process exit before normal channel error handling.
PreallocatedProcessManager::MaybeForgetSpare(this);
#endif
PContentParent::OnChannelError();
}
@ -1929,14 +1851,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
// remove the global remote preferences observers
Preferences::RemoveObserver(this, "");
#ifdef MOZ_NUWA_PROCESS
// Remove the pref update requests.
if (IsNuwaProcess() && sNuwaPrefUpdates) {
delete sNuwaPrefUpdates;
sNuwaPrefUpdates = nullptr;
}
#endif
RecvRemoveGeolocationListener();
mConsoleService = nullptr;
@ -2198,10 +2112,6 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
std::vector<std::string> extraArgs;
if (mIsNuwaProcess) {
extraArgs.push_back("-nuwa");
}
if (!mSubprocess->LaunchAndWaitForProcessHandle(extraArgs)) {
MarkAsDead();
return false;
@ -2227,12 +2137,10 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
ContentParent::ContentParent(mozIApplication* aApp,
ContentParent* aOpener,
bool aIsForBrowser,
bool aIsForPreallocated,
bool aIsNuwaProcess /* = false */)
bool aIsForPreallocated)
: nsIContentParent()
, mOpener(aOpener)
, mIsForBrowser(aIsForBrowser)
, mIsNuwaProcess(aIsNuwaProcess)
{
InitializeMembers(); // Perform common initialization.
@ -2240,20 +2148,13 @@ ContentParent::ContentParent(mozIApplication* aApp,
// true.
MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1);
// Only the preallocated process uses Nuwa.
MOZ_ASSERT_IF(aIsNuwaProcess, aIsForPreallocated);
if (!aIsNuwaProcess && !aIsForPreallocated) {
mMetamorphosed = true;
}
mMetamorphosed = true;
// Insert ourselves into the global linked list of ContentParent objects.
if (!sContentParents) {
sContentParents = new LinkedList<ContentParent>();
}
if (!aIsNuwaProcess) {
sContentParents->insertBack(this);
}
sContentParents->insertBack(this);
if (aApp) {
aApp->GetManifestURL(mAppManifestURL);
@ -2274,83 +2175,10 @@ ContentParent::ContentParent(mozIApplication* aApp,
#endif
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
ChildPrivileges privs = aIsNuwaProcess
? base::PRIVILEGES_INHERIT
: base::PRIVILEGES_DEFAULT;
ChildPrivileges privs = base::PRIVILEGES_DEFAULT;
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs);
}
#ifdef MOZ_NUWA_PROCESS
static const mozilla::ipc::FileDescriptor*
FindFdProtocolFdMapping(const nsTArray<ProtocolFdMapping>& aFds,
ProtocolId aProtoId)
{
for (unsigned int i = 0; i < aFds.Length(); i++) {
if (aFds[i].protocolId() == aProtoId) {
return &aFds[i].fd();
}
}
return nullptr;
}
/**
* This constructor is used for new content process cloned from a template.
*
* For Nuwa.
*/
ContentParent::ContentParent(ContentParent* aTemplate,
const nsAString& aAppManifestURL,
base::ProcessHandle aPid,
InfallibleTArray<ProtocolFdMapping>&& aFds)
: mAppManifestURL(aAppManifestURL)
, mIsForBrowser(false)
, mIsNuwaProcess(false)
{
InitializeMembers(); // Perform common initialization.
sContentParents->insertBack(this);
// From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
// PID along with the warning.
nsDebugImpl::SetMultiprocessMode("Parent");
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
const FileDescriptor* fd = FindFdProtocolFdMapping(aFds, GetProtocolId());
NS_ASSERTION(fd != nullptr, "IPC Channel for PContent is necessary!");
mSubprocess = new GeckoExistingProcessHost(GeckoProcessType_Content,
aPid, *fd);
mSubprocess->LaunchAndWaitForProcessHandle();
// Clone actors routed by aTemplate for this instance.
ProtocolCloneContext cloneContext;
cloneContext.SetContentParent(this);
CloneManagees(aTemplate, &cloneContext);
CloneOpenedToplevels(aTemplate, aFds, aPid, &cloneContext);
Open(mSubprocess->GetChannel(),
base::GetProcId(mSubprocess->GetChildProcessHandle()));
// Set the subprocess's priority (bg if we're a preallocated process, fg
// otherwise). We do this first because we're likely /lowering/ its CPU and
// memory priority, which it has inherited from this process.
ProcessPriority priority;
if (IsPreallocated()) {
priority = PROCESS_PRIORITY_PREALLOC;
} else {
priority = PROCESS_PRIORITY_FOREGROUND;
}
InitInternal(priority,
false, /* Setup Off-main thread compositing */
false /* Send registered chrome */);
ContentProcessManager::GetSingleton()->AddContentProcess(this);
}
#endif // MOZ_NUWA_PROCESS
ContentParent::~ContentParent()
{
if (mForceKillTimer) {
@ -2372,13 +2200,6 @@ ContentParent::~ContentParent()
MOZ_ASSERT(!sAppContentParents ||
sAppContentParents->Get(mAppManifestURL) != this);
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
sNuwaReady = false;
sNuwaPid = 0;
}
#endif
}
void
@ -2491,11 +2312,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
#ifdef MOZ_CONTENT_SANDBOX
bool shouldSandbox = true;
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
shouldSandbox = false;
}
#endif
MaybeFileDesc brokerFd = void_t();
#ifdef XP_LINUX
// XXX: Checking the pref here makes it possible to enable/disable sandboxing
@ -2566,14 +2382,6 @@ ContentParent::IsForApp() const
return !mAppManifestURL.IsEmpty();
}
#ifdef MOZ_NUWA_PROCESS
bool
ContentParent::IsNuwaProcess() const
{
return mIsNuwaProcess;
}
#endif
int32_t
ContentParent::Pid() const
{
@ -2880,125 +2688,6 @@ ContentParent::RecvAudioChannelServiceStatus(
return true;
}
void
ContentParent::ForkNewProcess(bool aBlocking)
{
#ifdef MOZ_NUWA_PROCESS
uint32_t pid;
auto fds = MakeUnique<nsTArray<ProtocolFdMapping>>();
MOZ_ASSERT(IsNuwaProcess() && mNuwaParent);
if (mNuwaParent->ForkNewProcess(pid, mozilla::Move(fds), aBlocking)) {
OnNewProcessCreated(pid, mozilla::Move(fds));
}
#else
NS_ERROR("ContentParent::ForkNewProcess() not implemented!");
#endif
}
#ifdef MOZ_NUWA_PROCESS
// Keep only observer topics listed in sNuwaSafeObserverTopics and unregister
// all the other registered topics.
static void
KeepNuwaSafeObserverTopics(ContentParent* aNuwaContentParent)
{
MOZ_ASSERT(aNuwaContentParent && aNuwaContentParent->IsNuwaProcess());
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs) {
return;
}
size_t topicLength = ArrayLength(sObserverTopics);
for (size_t i = 0; i < topicLength; ++i) {
bool nuwaSafe = false;
size_t safeTopicLength = ArrayLength(sNuwaSafeObserverTopics);
for (size_t j = 0; j < safeTopicLength; j++) {
if (!nsCRT::strcmp(sObserverTopics[i],
sNuwaSafeObserverTopics[j])) {
// In the whitelist: don't need to unregister.
nuwaSafe = true;
break;
}
}
if (!nuwaSafe) {
obs->RemoveObserver(aNuwaContentParent, sObserverTopics[i]);
}
}
}
#endif
void
ContentParent::OnNuwaReady()
{
#ifdef MOZ_NUWA_PROCESS
// Protection from unauthorized IPC message is done in PNuwa protocol.
// Just assert that this actor is really for the Nuwa process.
MOZ_ASSERT(IsNuwaProcess());
sNuwaReady = true;
KeepNuwaSafeObserverTopics(this);
PreallocatedProcessManager::OnNuwaReady();
return;
#else
NS_ERROR("ContentParent::OnNuwaReady() not implemented!");
return;
#endif
}
void
ContentParent::OnNewProcessCreated(uint32_t aPid,
UniquePtr<nsTArray<ProtocolFdMapping>>&& aFds)
{
#ifdef MOZ_NUWA_PROCESS
// Protection from unauthorized IPC message is done in PNuwa protocol.
// Just assert that this actor is really for the Nuwa process.
MOZ_ASSERT(IsNuwaProcess());
RefPtr<ContentParent> content;
content = new ContentParent(this,
MAGIC_PREALLOCATED_APP_MANIFEST_URL,
aPid,
Move(*aFds.get()));
content->Init();
size_t numNuwaPrefUpdates = sNuwaPrefUpdates ?
sNuwaPrefUpdates->Length() : 0;
// Resend pref updates to the forked child.
for (size_t i = 0; i < numNuwaPrefUpdates; i++) {
mozilla::Unused << content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i));
}
// Update offline settings.
bool isOffline, isLangRTL, haveBidiKeyboards;
bool isConnected;
InfallibleTArray<nsString> unusedDictionaries;
ClipboardCapabilities clipboardCaps;
DomainPolicyClone domainPolicy;
StructuredCloneData initialData;
RecvGetXPCOMProcessAttributes(&isOffline, &isConnected,
&isLangRTL, &haveBidiKeyboards,
&unusedDictionaries,
&clipboardCaps, &domainPolicy, &initialData);
mozilla::Unused << content->SendSetOffline(isOffline);
mozilla::Unused << content->SendSetConnectivity(isConnected);
MOZ_ASSERT(!clipboardCaps.supportsSelectionClipboard() &&
!clipboardCaps.supportsFindClipboard(),
"Unexpected values");
PreallocatedProcessManager::PublishSpareProcess(content);
return;
#else
NS_ERROR("ContentParent::OnNewProcessCreated() not implemented!");
return;
#endif
}
// We want ContentParent to show up in CC logs for debugging purposes, but we
// don't actually cycle collect it.
NS_IMPL_CYCLE_COLLECTION_0(ContentParent)
@ -3057,16 +2746,6 @@ ContentParent::Observe(nsISupports* aSubject,
if (!mIsAlive || !mSubprocess)
return NS_OK;
// The Nuwa process unregisters the topics after it becomes ready except for
// the ones listed in sNuwaSafeObserverTopics. If the topic needs to be
// observed by the Nuwa process, either for:
// 1. The topic is safe for the Nuwa process, either:
// 1.1 The state can safely happen (only run on the main thread) in the Nuwa
// process (e.g. "a11y-init-or-shutdown"), or
// 1.2 The topic doesn't send an IPC message (e.g. "xpcom-shutdown").
// 2. The topic needs special handling (e.g. nsPref:Changed),
// add the topic to sNuwaSafeObserverTopics and then handle it if necessary.
// listening for memory pressure event
if (!strcmp(aTopic, "memory-pressure") &&
!StringEndsWith(nsDependentString(aData),
@ -3080,22 +2759,9 @@ ContentParent::Observe(nsISupports* aSubject,
PrefSetting pref(strData, null_t(), null_t());
Preferences::GetPreference(&pref);
#ifdef MOZ_NUWA_PROCESS
if (IsReadyNuwaProcess()) {
// Don't send the pref update to the Nuwa process. Save the update
// to send to the forked child.
if (!sNuwaPrefUpdates) {
sNuwaPrefUpdates = new nsTArray<PrefSetting>();
}
sNuwaPrefUpdates->AppendElement(pref);
} else if (!SendPreferenceUpdate(pref)) {
return NS_ERROR_NOT_AVAILABLE;
}
#else
if (!SendPreferenceUpdate(pref)) {
return NS_ERROR_NOT_AVAILABLE;
}
#endif
}
else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
NS_ConvertUTF16toUTF8 dataStr(aData);
@ -3524,11 +3190,6 @@ void
ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
{
aName.Truncate();
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
aName.AssignLiteral("(Nuwa)");
} else
#endif
if (IsPreallocated()) {
aName.AssignLiteral("(Preallocated)");
} else if (mIsForBrowser) {
@ -4642,10 +4303,6 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx,
if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
return NS_ERROR_UNEXPECTED;
}
if (IsReadyNuwaProcess()) {
// Nuwa won't receive frame messages after it is frozen.
return NS_OK;
}
if (!SendAsyncMessage(nsString(aMessage), cpows, Principal(aPrincipal), data)) {
return NS_ERROR_UNEXPECTED;
}

View File

@ -7,7 +7,6 @@
#ifndef mozilla_dom_ContentParent_h
#define mozilla_dom_ContentParent_h
#include "mozilla/dom/NuwaParent.h"
#include "mozilla/dom/PContentParent.h"
#include "mozilla/dom/nsIContentParent.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
@ -101,17 +100,6 @@ class ContentParent final : public PContentParent
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
public:
#ifdef MOZ_NUWA_PROCESS
static int32_t NuwaPid()
{
return sNuwaPid;
}
static bool IsNuwaReady()
{
return sNuwaReady;
}
#endif
virtual bool IsContentParent() const override { return true; }
@ -151,8 +139,6 @@ public:
*/
static already_AddRefed<ContentParent> PreallocateAppProcess();
static already_AddRefed<ContentParent> RunNuwaProcess();
/**
* Get or create a content process for the given TabContext. aFrameElement
* should be the frame/iframe element with which this process will
@ -367,20 +353,6 @@ public:
return mIsForBrowser;
}
#ifdef MOZ_NUWA_PROCESS
bool IsNuwaProcess() const;
#endif
// A shorthand for checking if the Nuwa process is ready.
bool IsReadyNuwaProcess() const
{
#ifdef MOZ_NUWA_PROCESS
return IsNuwaProcess() && IsNuwaReady();
#else
return false;
#endif
}
GeckoChildProcessHost* Process() const
{
return mSubprocess;
@ -547,8 +519,6 @@ public:
virtual bool HandleWindowsMessages(const Message& aMsg) const override;
void SetNuwaParent(NuwaParent* aNuwaParent) { mNuwaParent = aNuwaParent; }
void ForkNewProcess(bool aBlocking);
virtual bool RecvCreateWindow(PBrowserParent* aThisTabParent,
@ -596,8 +566,6 @@ protected:
virtual void ActorDestroy(ActorDestroyReason why) override;
void OnNuwaForkTimeout();
bool ShouldContinueFromReplyTimeout() override;
private:
@ -644,15 +612,7 @@ private:
ContentParent(mozIApplication* aApp,
ContentParent* aOpener,
bool aIsForBrowser,
bool aIsForPreallocated,
bool aIsNuwaProcess = false);
#ifdef MOZ_NUWA_PROCESS
ContentParent(ContentParent* aTemplate,
const nsAString& aAppManifestURL,
base::ProcessHandle aPid,
InfallibleTArray<ProtocolFdMapping>&& aFds);
#endif
bool aIsForPreallocated);
// The common initialization for the constructors.
void InitializeMembers();
@ -1061,11 +1021,6 @@ private:
virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) override;
// Callbacks from NuwaParent.
void OnNuwaReady();
void OnNewProcessCreated(uint32_t aPid,
UniquePtr<nsTArray<ProtocolFdMapping>>&& aFds);
virtual bool RecvCreateFakeVolume(const nsString& aFsName,
const nsString& aMountPoint) override;
@ -1229,7 +1184,6 @@ private:
bool mSendPermissionUpdates;
bool mIsForBrowser;
bool mIsNuwaProcess;
// These variables track whether we've called Close() and KillHard() on our
// channel.
@ -1241,9 +1195,6 @@ private:
friend class CrashReporterParent;
// Allows NuwaParent to access OnNuwaReady() and OnNewProcessCreated().
friend class NuwaParent;
RefPtr<nsConsoleService> mConsoleService;
nsConsoleService* GetConsoleService();
@ -1255,17 +1206,8 @@ private:
ScopedClose mChildXSocketFdDup;
#endif
#ifdef MOZ_NUWA_PROCESS
static int32_t sNuwaPid;
static bool sNuwaReady;
#endif
PProcessHangMonitorParent* mHangMonitorActor;
// NuwaParent and ContentParent hold strong references to each other. The
// cycle will be broken when either actor is destroyed.
RefPtr<NuwaParent> mNuwaParent;
#ifdef MOZ_ENABLE_PROFILER_SPS
RefPtr<mozilla::ProfileGatherer> mGatherer;
#endif

View File

@ -1,256 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ContentChild.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "mozilla/dom/ContentChild.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/ProtocolUtils.h"
#if defined(MOZ_CONTENT_SANDBOX)
#if defined(XP_LINUX)
#include "mozilla/Sandbox.h"
#include "mozilla/SandboxInfo.h"
#elif defined(XP_MACOSX)
#include "mozilla/Sandbox.h"
#endif
#endif
#include "mozilla/unused.h"
#include "nsXULAppAPI.h"
#include "NuwaChild.h"
using namespace mozilla::ipc;
using namespace mozilla::dom;
namespace mozilla {
namespace dom {
#ifdef MOZ_NUWA_PROCESS
namespace {
class CallNuwaSpawn: public Runnable
{
public:
NS_IMETHOD Run()
{
NuwaSpawn();
if (IsNuwaProcess()) {
return NS_OK;
}
// In the new process.
ContentChild* child = ContentChild::GetSingleton();
child->InitProcessAttributes();
// Perform other after-fork initializations.
InitOnContentProcessCreated();
return NS_OK;
}
};
static void
DoNuwaFork()
{
NuwaSpawnPrepare(); // NuwaSpawn will be blocked.
{
nsCOMPtr<nsIRunnable> callSpawn(new CallNuwaSpawn());
NS_DispatchToMainThread(callSpawn);
}
// IOThread should be blocked here for waiting NuwaSpawn().
NuwaSpawnWait(); // Now! NuwaSpawn can go.
// Here, we can make sure the spawning was finished.
}
/**
* This function should keep IO thread in a stable state and freeze it
* until the spawning is finished.
*/
static void
RunNuwaFork()
{
if (NuwaCheckpointCurrentThread()) {
DoNuwaFork();
}
}
static bool sNuwaForking = false;
void
NuwaFork()
{
if (sNuwaForking) { // No reentry.
return;
}
sNuwaForking = true;
MessageLoop* ioloop = XRE_GetIOMessageLoop();
ioloop->PostTask(NewRunnableFunction(RunNuwaFork));
}
} // Anonymous namespace.
#endif
NuwaChild* NuwaChild::sSingleton;
NuwaChild*
NuwaChild::GetSingleton()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sSingleton) {
PNuwaChild* nuwaChild =
BackgroundChild::GetForCurrentThread()->SendPNuwaConstructor();
MOZ_ASSERT(nuwaChild);
sSingleton = static_cast<NuwaChild*>(nuwaChild);
}
return sSingleton;
}
bool
NuwaChild::RecvFork()
{
#ifdef MOZ_NUWA_PROCESS
if (!IsNuwaProcess()) {
NS_ERROR(
nsPrintfCString(
"Terminating child process %d for unauthorized IPC message: "
"RecvFork(%d)", getpid()).get());
return false;
}
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableFunction(&NuwaFork);
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return true;
#else
NS_ERROR("NuwaChild::RecvFork() not implemented!");
return false;
#endif
}
} // namespace dom
} // namespace mozilla
extern "C" {
#if defined(MOZ_NUWA_PROCESS)
NS_EXPORT void
GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
size_t aInfoListSize,
size_t* aInfoSize)
{
size_t i = 0;
mozilla::dom::ContentChild* content =
mozilla::dom::ContentChild::GetSingleton();
aInfoList[i].protoId = content->GetProtocolId();
aInfoList[i].originFd =
content->GetTransport()->GetFileDescriptor();
i++;
IToplevelProtocol* actors[NUWA_TOPLEVEL_MAX];
size_t count = content->GetOpenedActorsUnsafe(actors, ArrayLength(actors));
for (size_t j = 0; j < count; j++) {
IToplevelProtocol* actor = actors[j];
if (i >= aInfoListSize) {
NS_RUNTIMEABORT("Too many top level protocols!");
}
aInfoList[i].protoId = actor->GetProtocolId();
aInfoList[i].originFd =
actor->GetTransport()->GetFileDescriptor();
i++;
}
if (i > NUWA_TOPLEVEL_MAX) {
NS_RUNTIMEABORT("Too many top level protocols!");
}
*aInfoSize = i;
}
class RunAddNewIPCProcess : public mozilla::Runnable
{
public:
RunAddNewIPCProcess(pid_t aPid,
nsTArray<mozilla::ipc::ProtocolFdMapping>& aMaps)
: mPid(aPid)
{
mMaps.SwapElements(aMaps);
}
NS_IMETHOD Run()
{
NuwaChild::GetSingleton()->SendAddNewProcess(mPid, mMaps);
MOZ_ASSERT(sNuwaForking);
sNuwaForking = false;
return NS_OK;
}
private:
pid_t mPid;
nsTArray<mozilla::ipc::ProtocolFdMapping> mMaps;
};
/**
* AddNewIPCProcess() is called by Nuwa process to tell the parent
* process that a new process is created.
*
* In the newly created process, ResetContentChildTransport() is called to
* reset fd for the IPC Channel and the session.
*/
NS_EXPORT void
AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize)
{
nsTArray<mozilla::ipc::ProtocolFdMapping> maps;
for (size_t i = 0; i < aInfoListSize; i++) {
int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT];
mozilla::ipc::FileDescriptor fd(_fd);
mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd);
maps.AppendElement(map);
}
RefPtr<RunAddNewIPCProcess> runner = new RunAddNewIPCProcess(aPid, maps);
NS_DispatchToMainThread(runner);
}
NS_EXPORT void
OnNuwaProcessReady()
{
NuwaChild* nuwaChild = NuwaChild::GetSingleton();
MOZ_ASSERT(nuwaChild);
mozilla::Unused << nuwaChild->SendNotifyReady();
}
NS_EXPORT void
AfterNuwaFork()
{
SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
mozilla::SandboxEarlyInit(XRE_GetProcessType(), /* isNuwa: */ false);
#endif
}
#endif // MOZ_NUWA_PROCESS
}

View File

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_NuwaChild_h
#define mozilla_dom_NuwaChild_h
#include "mozilla/Assertions.h"
#include "mozilla/dom/PNuwaChild.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
class NuwaChild: public mozilla::dom::PNuwaChild
{
public:
virtual bool RecvFork() override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override
{ }
static NuwaChild* GetSingleton();
private:
static NuwaChild* sSingleton;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_NuwaChild_h

View File

@ -1,260 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/unused.h"
#include "nsThreadUtils.h"
#include "NuwaParent.h"
using namespace mozilla::ipc;
using namespace mozilla::dom;
using namespace IPC;
namespace mozilla {
namespace dom {
/*static*/ NuwaParent*
NuwaParent::Alloc() {
RefPtr<NuwaParent> actor = new NuwaParent();
return actor.forget().take();
}
/*static*/ bool
NuwaParent::ActorConstructed(mozilla::dom::PNuwaParent *aActor)
{
NuwaParent* actor = static_cast<NuwaParent*>(aActor);
actor->ActorConstructed();
return true;
}
/*static*/ bool
NuwaParent::Dealloc(mozilla::dom::PNuwaParent *aActor)
{
RefPtr<NuwaParent> actor = dont_AddRef(static_cast<NuwaParent*>(aActor));
return true;
}
NuwaParent::NuwaParent()
: mBlocked(false)
, mMonitor("NuwaParent")
, mClonedActor(nullptr)
, mWorkerThread(do_GetCurrentThread())
, mNewProcessPid(0)
{
AssertIsOnBackgroundThread();
}
NuwaParent::~NuwaParent()
{
// Both the worker thread and the main thread (ContentParent) hold a ref to
// this. The instance may be destroyed on either thread.
MOZ_ASSERT(!mContentParent);
}
inline void
NuwaParent::AssertIsOnWorkerThread()
{
nsCOMPtr<nsIThread> currentThread = do_GetCurrentThread();
MOZ_ASSERT(currentThread == mWorkerThread);
}
bool
NuwaParent::ActorConstructed()
{
AssertIsOnWorkerThread();
MOZ_ASSERT(Manager());
MOZ_ASSERT(!mContentParent);
mContentParent = BackgroundParent::GetContentParent(Manager());
if (!mContentParent) {
return false;
}
// mContentParent is guaranteed to be alive. It's safe to set its backward ref
// to this.
mContentParent->SetNuwaParent(this);
return true;
}
mozilla::ipc::IProtocol*
NuwaParent::CloneProtocol(Channel* aChannel,
ProtocolCloneContext* aCtx)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<NuwaParent> self = this;
MonitorAutoLock lock(mMonitor);
// Alloc NuwaParent on the worker thread.
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([self] () -> void
{
MonitorAutoLock lock(self->mMonitor);
// XXX Calling NuwaParent::Alloc() leads to a compilation error. Use
// self->Alloc() as a workaround.
self->mClonedActor = self->Alloc();
lock.Notify();
});
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(mWorkerThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
while (!mClonedActor) {
lock.Wait();
}
RefPtr<NuwaParent> actor = mClonedActor;
mClonedActor = nullptr;
// mManager of the cloned actor is assigned after returning from this method.
// We can't call ActorConstructed() right after Alloc() in the above runnable.
// To be safe we dispatch a runnable to the current thread to do it.
runnable = NS_NewRunnableFunction([actor] () -> void
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIRunnable> nested = NS_NewRunnableFunction([actor] () -> void
{
AssertIsOnBackgroundThread();
// Call NuwaParent::ActorConstructed() on the worker thread.
actor->ActorConstructed();
// The actor can finally be deleted after fully constructed.
mozilla::Unused << actor->Send__delete__(actor);
});
MOZ_ASSERT(nested);
MOZ_ALWAYS_SUCCEEDS(actor->mWorkerThread->Dispatch(nested, NS_DISPATCH_NORMAL));
});
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return actor;
}
void
NuwaParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnWorkerThread();
RefPtr<NuwaParent> self = this;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([self] () -> void
{
// These extra nsRefPtr serve as kungFuDeathGrip to keep both objects from
// deletion in breaking the ref cycle.
RefPtr<ContentParent> contentParent = self->mContentParent;
contentParent->SetNuwaParent(nullptr);
// Need to clear the ref to ContentParent on the main thread.
self->mContentParent = nullptr;
});
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
bool
NuwaParent::RecvNotifyReady()
{
#ifdef MOZ_NUWA_PROCESS
if (!mContentParent || !mContentParent->IsNuwaProcess()) {
NS_ERROR("Received NotifyReady() message from a non-Nuwa process.");
return false;
}
// Creating a NonOwningRunnableMethod here is safe because refcount changes of
// mContentParent have to go the the main thread. The mContentParent will
// be alive when the runnable runs.
nsCOMPtr<nsIRunnable> runnable =
NewNonOwningRunnableMethod(mContentParent.get(),
&ContentParent::OnNuwaReady);
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return true;
#else
NS_ERROR("NuwaParent::RecvNotifyReady() not implemented!");
return false;
#endif
}
bool
NuwaParent::RecvAddNewProcess(const uint32_t& aPid,
nsTArray<ProtocolFdMapping>&& aFds)
{
#ifdef MOZ_NUWA_PROCESS
if (!mContentParent || !mContentParent->IsNuwaProcess()) {
NS_ERROR("Received AddNewProcess() message from a non-Nuwa process.");
return false;
}
mNewProcessPid = aPid;
mNewProcessFds->SwapElements(aFds);
MonitorAutoLock lock(mMonitor);
if (mBlocked) {
// Unblock ForkNewProcess().
mMonitor.Notify();
mBlocked = false;
} else {
nsCOMPtr<nsIRunnable> runnable =
NewNonOwningRunnableMethod<
uint32_t,
UniquePtr<nsTArray<ProtocolFdMapping>>&& >(
mContentParent.get(),
&ContentParent::OnNewProcessCreated,
mNewProcessPid,
Move(mNewProcessFds));
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
return true;
#else
NS_ERROR("NuwaParent::RecvAddNewProcess() not implemented!");
return false;
#endif
}
bool
NuwaParent::ForkNewProcess(uint32_t& aPid,
UniquePtr<nsTArray<ProtocolFdMapping>>&& aFds,
bool aBlocking)
{
MOZ_ASSERT(mWorkerThread);
MOZ_ASSERT(NS_IsMainThread());
mNewProcessFds = Move(aFds);
RefPtr<NuwaParent> self = this;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([self] () -> void
{
mozilla::Unused << self->SendFork();
});
MOZ_ASSERT(runnable);
MOZ_ALWAYS_SUCCEEDS(mWorkerThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
if (!aBlocking) {
return false;
}
MonitorAutoLock lock(mMonitor);
mBlocked = true;
while (mBlocked) {
// This will be notified in NuwaParent::RecvAddNewProcess().
lock.Wait();
}
if (!mNewProcessPid) {
return false;
}
aPid = mNewProcessPid;
aFds = Move(mNewProcessFds);
mNewProcessPid = 0;
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -1,73 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_NuwaParent_h
#define mozilla_dom_NuwaParent_h
#include "base/message_loop.h"
#include "mozilla/dom/PNuwaParent.h"
#include "mozilla/Monitor.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace dom {
class ContentParent;
class NuwaParent : public mozilla::dom::PNuwaParent
{
public:
explicit NuwaParent();
// Called on the main thread.
bool ForkNewProcess(uint32_t& aPid,
UniquePtr<nsTArray<ProtocolFdMapping>>&& aFds,
bool aBlocking);
// Called on the background thread.
bool ActorConstructed();
// Both the worker thread and the main thread hold a ref to this.
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NuwaParent)
// Functions to be invoked by the manager of this actor to alloc/dealloc the
// actor.
static NuwaParent* Alloc();
static bool ActorConstructed(mozilla::dom::PNuwaParent *aActor);
static bool Dealloc(mozilla::dom::PNuwaParent *aActor);
protected:
virtual ~NuwaParent();
virtual bool RecvNotifyReady() override;
virtual bool RecvAddNewProcess(const uint32_t& aPid,
nsTArray<ProtocolFdMapping>&& aFds) override;
virtual mozilla::ipc::IProtocol*
CloneProtocol(Channel* aChannel,
ProtocolCloneContext* aCtx) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
private:
void AssertIsOnWorkerThread();
bool mBlocked;
mozilla::Monitor mMonitor;
NuwaParent* mClonedActor;
nsCOMPtr<nsIThread> mWorkerThread;
uint32_t mNewProcessPid;
UniquePtr<nsTArray<ProtocolFdMapping>> mNewProcessFds;
// The mutual reference will be broken on the main thread.
RefPtr<ContentParent> mContentParent;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_NuwaParent_h

View File

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include ProtocolTypes;
namespace mozilla {
namespace dom {
sync protocol PNuwa
{
manager PBackground;
child:
// Ask the Nuwa process to create a new child process.
async Fork();
// This message will be sent to non-Nuwa process, or to Nuwa process during
// test.
async __delete__();
parent:
async NotifyReady();
sync AddNewProcess(uint32_t pid, ProtocolFdMapping[] aFds);
};
} // namespace layout
} // namespace mozilla

View File

@ -14,19 +14,10 @@
#include "ProcessPriorityManager.h"
#include "nsServiceManagerUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
#endif
// This number is fairly arbitrary ... the intention is to put off
// launching another app process until the last one has finished
// loading its content, to reduce CPU/memory/IO contention.
#define DEFAULT_ALLOCATE_DELAY 1000
#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds.
using namespace mozilla;
using namespace mozilla::hal;
@ -53,31 +44,6 @@ public:
void AllocateNow();
already_AddRefed<ContentParent> Take();
#ifdef MOZ_NUWA_PROCESS
public:
void ScheduleDelayedNuwaFork();
void DelayedNuwaFork();
void PublishSpareProcess(ContentParent* aContent);
void MaybeForgetSpare(ContentParent* aContent);
bool IsNuwaReady();
void OnNuwaReady();
bool PreallocatedProcessReady();
already_AddRefed<ContentParent> GetSpareProcess();
private:
void NuwaFork();
// initialization off the critical path of app startup.
CancelableRunnable* mPreallocateAppProcessTask;
// The array containing the preallocated processes. 4 as the inline storage size
// should be enough so we don't need to grow the AutoTArray.
AutoTArray<RefPtr<ContentParent>, 4> mSpareProcesses;
// Nuwa process is ready for creating new process.
bool mIsNuwaReady;
#endif
private:
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
@ -117,11 +83,6 @@ NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver)
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
:
#ifdef MOZ_NUWA_PROCESS
mPreallocateAppProcessTask(nullptr)
, mIsNuwaReady(false)
,
#endif
mEnabled(false)
, mShutdown(false)
{}
@ -137,11 +98,6 @@ PreallocatedProcessManagerImpl::Init()
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
/* weakRef = */ false);
}
#ifdef MOZ_B2G_LOADER
if (!mozilla::ipc::ProcLoaderIsInitialized()) {
Disable();
} else
#endif
{
RereadPrefs();
}
@ -190,11 +146,7 @@ PreallocatedProcessManagerImpl::Enable()
}
mEnabled = true;
#ifdef MOZ_NUWA_PROCESS
ScheduleDelayedNuwaFork();
#else
AllocateAfterDelay();
#endif
}
void
@ -230,174 +182,6 @@ PreallocatedProcessManagerImpl::AllocateNow()
mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
}
#ifdef MOZ_NUWA_PROCESS
void
PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
{
MOZ_ASSERT(NS_IsMainThread());
if (mPreallocateAppProcessTask) {
// Make sure there is only one request running.
return;
}
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
this, &PreallocatedProcessManagerImpl::DelayedNuwaFork);
mPreallocateAppProcessTask = task;
MessageLoop::current()->PostDelayedTask(task.forget(),
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
DEFAULT_ALLOCATE_DELAY));
}
void
PreallocatedProcessManagerImpl::DelayedNuwaFork()
{
MOZ_ASSERT(NS_IsMainThread());
mPreallocateAppProcessTask = nullptr;
if (!mIsNuwaReady) {
if (!mPreallocatedAppProcess && !mShutdown && mEnabled) {
mPreallocatedAppProcess = ContentParent::RunNuwaProcess();
}
// else mPreallocatedAppProcess is starting. It will NuwaFork() when ready.
} else if (mSpareProcesses.IsEmpty()) {
NuwaFork();
}
}
/**
* Get a spare ContentParent from mSpareProcesses list.
*/
already_AddRefed<ContentParent>
PreallocatedProcessManagerImpl::GetSpareProcess()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mIsNuwaReady) {
return nullptr;
}
if (mSpareProcesses.IsEmpty()) {
// After this call, there should be a spare process.
mPreallocatedAppProcess->ForkNewProcess(true);
}
RefPtr<ContentParent> process = mSpareProcesses.LastElement();
mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1);
if (mSpareProcesses.IsEmpty() && mIsNuwaReady) {
NS_ASSERTION(mPreallocatedAppProcess != nullptr,
"Nuwa process is not present!");
ScheduleDelayedNuwaFork();
}
return process.forget();
}
static bool
TestCaseEnabled()
{
return Preferences::GetBool("dom.ipc.preallocatedProcessManager.testMode");
}
static void
SendTestOnlyNotification(const char* aMessage)
{
if (!TestCaseEnabled()) {
return;
}
AutoSafeJSContext cx;
nsString message;
message.AppendPrintf("%s", aMessage);
nsCOMPtr<nsIMessageBroadcaster> ppmm =
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
mozilla::Unused << ppmm->BroadcastAsyncMessage(
message, JS::NullHandleValue, JS::NullHandleValue, cx, 1);
}
static void
KillOrCloseProcess(ContentParent* aProcess)
{
if (TestCaseEnabled()) {
// KillHard() the process because we don't want the process to abort when we
// close the IPC channel while it's still running and creating actors.
aProcess->KillHard("Killed by test case.");
}
else {
aProcess->Close();
}
}
/**
* Publish a ContentParent to spare process list.
*/
void
PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
{
MOZ_ASSERT(NS_IsMainThread());
SendTestOnlyNotification("TEST-ONLY:nuwa-add-new-process");
mSpareProcesses.AppendElement(aContent);
}
void
PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent)
{
MOZ_ASSERT(NS_IsMainThread());
if (mSpareProcesses.RemoveElement(aContent)) {
return;
}
if (aContent == mPreallocatedAppProcess) {
mPreallocatedAppProcess = nullptr;
mIsNuwaReady = false;
while (mSpareProcesses.Length() > 0) {
RefPtr<ContentParent> process = mSpareProcesses[mSpareProcesses.Length() - 1];
KillOrCloseProcess(aContent);
mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1);
}
ScheduleDelayedNuwaFork();
}
}
bool
PreallocatedProcessManagerImpl::IsNuwaReady()
{
return mIsNuwaReady;
}
void
PreallocatedProcessManagerImpl::OnNuwaReady()
{
NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!");
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
hal::PROCESS_PRIORITY_MASTER);
mIsNuwaReady = true;
SendTestOnlyNotification("TEST-ONLY:nuwa-ready");
NuwaFork();
}
bool
PreallocatedProcessManagerImpl::PreallocatedProcessReady()
{
return !mSpareProcesses.IsEmpty();
}
void
PreallocatedProcessManagerImpl::NuwaFork()
{
mPreallocatedAppProcess->ForkNewProcess(false);
}
#endif
void
PreallocatedProcessManagerImpl::Disable()
{
@ -407,23 +191,7 @@ PreallocatedProcessManagerImpl::Disable()
mEnabled = false;
#ifdef MOZ_NUWA_PROCESS
// Cancel pending fork.
if (mPreallocateAppProcessTask) {
mPreallocateAppProcessTask->Cancel();
mPreallocateAppProcessTask = nullptr;
}
#endif
if (mPreallocatedAppProcess) {
#ifdef MOZ_NUWA_PROCESS
while (mSpareProcesses.Length() > 0){
RefPtr<ContentParent> process = mSpareProcesses[0];
KillOrCloseProcess(process);
mSpareProcesses.RemoveElementAt(0);
}
mIsNuwaReady = false;
#endif
mPreallocatedAppProcess->Close();
mPreallocatedAppProcess = nullptr;
}
@ -460,11 +228,7 @@ namespace mozilla {
/* static */ void
PreallocatedProcessManager::AllocateAfterDelay()
{
#ifdef MOZ_NUWA_PROCESS
GetPPMImpl()->ScheduleDelayedNuwaFork();
#else
GetPPMImpl()->AllocateAfterDelay();
#endif
}
/* static */ void
@ -482,44 +246,7 @@ PreallocatedProcessManager::AllocateNow()
/* static */ already_AddRefed<ContentParent>
PreallocatedProcessManager::Take()
{
#ifdef MOZ_NUWA_PROCESS
return GetPPMImpl()->GetSpareProcess();
#else
return GetPPMImpl()->Take();
#endif
}
#ifdef MOZ_NUWA_PROCESS
/* static */ void
PreallocatedProcessManager::PublishSpareProcess(ContentParent* aContent)
{
GetPPMImpl()->PublishSpareProcess(aContent);
}
/* static */ void
PreallocatedProcessManager::MaybeForgetSpare(ContentParent* aContent)
{
GetPPMImpl()->MaybeForgetSpare(aContent);
}
/* static */ void
PreallocatedProcessManager::OnNuwaReady()
{
GetPPMImpl()->OnNuwaReady();
}
/* static */ bool
PreallocatedProcessManager::IsNuwaReady()
{
return GetPPMImpl()->IsNuwaReady();
}
/*static */ bool
PreallocatedProcessManager::PreallocatedProcessReady()
{
return GetPPMImpl()->PreallocatedProcessReady();
}
#endif
} // namespace mozilla

View File

@ -78,14 +78,6 @@ public:
*/
static already_AddRefed<ContentParent> Take();
#ifdef MOZ_NUWA_PROCESS
static void PublishSpareProcess(ContentParent* aContent);
static void MaybeForgetSpare(ContentParent* aContent);
static bool IsNuwaReady();
static void OnNuwaReady();
static bool PreallocatedProcessReady();
#endif
private:
PreallocatedProcessManager();
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);

View File

@ -526,13 +526,6 @@ already_AddRefed<ParticularProcessPriorityManager>
ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
ContentParent* aContentParent)
{
#ifdef MOZ_NUWA_PROCESS
// Do not attempt to change the priority of the Nuwa process
if (aContentParent->IsNuwaProcess()) {
return nullptr;
}
#endif
RefPtr<ParticularProcessPriorityManager> pppm;
uint64_t cpId = aContentParent->ChildID();
mParticularManagers.Get(cpId, &pppm);

View File

@ -24,9 +24,6 @@
#include "mozilla/IMEStateManager.h"
#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/URIUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
@ -456,41 +453,6 @@ PreloadSlowThingsPostFork(void* aUnused)
}
#ifdef MOZ_NUWA_PROCESS
class MessageChannelAutoBlock MOZ_STACK_CLASS
{
public:
MessageChannelAutoBlock()
{
SetMessageChannelBlocked(true);
}
~MessageChannelAutoBlock()
{
SetMessageChannelBlocked(false);
}
private:
void SetMessageChannelBlocked(bool aBlock)
{
if (!IsNuwaProcess()) {
return;
}
mozilla::dom::ContentChild* content =
mozilla::dom::ContentChild::GetSingleton();
if (aBlock) {
content->GetIPCChannel()->Block();
} else {
content->GetIPCChannel()->Unblock();
}
// Other IPC channels do not perform the checks through Block() and
// Unblock().
}
};
#endif
static bool sPreloaded = false;
/*static*/ void
@ -513,12 +475,6 @@ TabChild::PreloadSlowThings()
return;
}
#ifdef MOZ_NUWA_PROCESS
// Temporarily block the IPC channels to the chrome process when we are
// preloading.
MessageChannelAutoBlock autoblock;
#endif
// Just load and compile these scripts, but don't run them.
tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
// Load, compile, and run these scripts.
@ -529,15 +485,7 @@ TabChild::PreloadSlowThings()
sPreallocatedTab = tab;
ClearOnShutdown(&sPreallocatedTab);
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaAddFinalConstructor(PreloadSlowThingsPostFork, nullptr);
} else {
PreloadSlowThingsPostFork(nullptr);
}
#else
PreloadSlowThingsPostFork(nullptr);
#endif
}
/*static*/ already_AddRefed<TabChild>

View File

@ -10,6 +10,7 @@
#include "mozIApplication.h"
#include "nsCOMPtr.h"
#include "mozilla/BasePrincipal.h"
#include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h"
namespace mozilla {

View File

@ -61,6 +61,7 @@
#include "nsPrincipal.h"
#include "nsIPromptFactory.h"
#include "nsIURI.h"
#include "nsIWindowWatcher.h"
#include "nsIWebBrowserChrome.h"
#include "nsIXULBrowserWindow.h"
#include "nsIXULWindow.h"
@ -108,6 +109,8 @@ using namespace mozilla::widget;
using namespace mozilla::jsipc;
using namespace mozilla::gfx;
using mozilla::Unused;
// The flags passed by the webProgress notifications are 16 bits shifted
// from the ones registered by webProgressListeners.
#define NOTIFY_FLAG_SHIFT 16

View File

@ -35,8 +35,6 @@ EXPORTS.mozilla.dom += [
'FilePickerParent.h',
'nsIContentChild.h',
'nsIContentParent.h',
'NuwaChild.h',
'NuwaParent.h',
'PermissionMessageUtils.h',
'TabChild.h',
'TabContext.h',
@ -65,8 +63,6 @@ UNIFIED_SOURCES += [
'FilePickerParent.cpp',
'nsIContentChild.cpp',
'nsIContentParent.cpp',
'NuwaChild.cpp',
'NuwaParent.cpp',
'PermissionMessageUtils.cpp',
'PreallocatedProcessManager.cpp',
'ProcessPriorityManager.cpp',
@ -107,7 +103,6 @@ IPDL_SOURCES += [
'PDocumentRenderer.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
'PNuwa.ipdl',
'PPluginWidget.ipdl',
'PProcessHangMonitor.ipdl',
'PScreenManager.ipdl',

View File

@ -13,10 +13,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android'
[test_cpow_cookies.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_NuwaProcessCreation.html]
skip-if = toolkit != 'gonk'
[test_NuwaProcessDeadlock.html]
skip-if = toolkit != 'gonk'
[test_child_docshell.html]
skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf
[test_CrashService_crash.html]

View File

@ -1,68 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
Test if Nuwa process created successfully.
-->
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="setup()">
<script type="application/javascript;version=1.7">
"use strict";
function runTest()
{
info("Shut down processes by disabling process prelaunch");
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', false);
info("Launch the Nuwa process");
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsISyncMessageSender);
let seenNuwaReady = false;
let msgHandler = {
receiveMessage: function receiveMessage(msg) {
msg = SpecialPowers.wrap(msg);
if (msg.name == 'TEST-ONLY:nuwa-ready') {
is(seenNuwaReady, false, "The Nuwa process is launched");
seenNuwaReady = true;
} else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') {
ok(true, "Got nuwa-add-new-process");
is(seenNuwaReady, true, "The preallocated process is launched from the Nuwa process");
shutdown();
}
}
};
function shutdown() {
info("Shut down the test case");
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.removeMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
SimpleTest.finish();
}
cpmm.addMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.addMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
// Setting this pref to true should cause us to prelaunch a process.
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true);
}
function setup()
{
info("Set up preferences for testing the Nuwa process.");
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
'set': [
['dom.ipc.preallocatedProcessManager.testMode', true]
]
}, runTest);
}
</script>
</body>
</html>

View File

@ -1,69 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
Test if Nuwa process created successfully.
-->
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="setup()">
<script type="application/javascript;version=1.7">
"use strict";
function runTest()
{
info("Shut down processes by disabling process prelaunch");
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', false);
info("Launch the Nuwa process");
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsISyncMessageSender);
let seenNuwaReady = false;
let msgHandler = {
receiveMessage: function receiveMessage(msg) {
msg = SpecialPowers.wrap(msg);
if (msg.name == 'TEST-ONLY:nuwa-ready') {
is(seenNuwaReady, false, "The Nuwa process is launched");
seenNuwaReady = true;
} else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') {
ok(true, "Got nuwa-add-new-process");
is(seenNuwaReady, true, "The preallocated process is launched from the Nuwa process");
shutdown();
}
}
};
function shutdown() {
info("Shut down the test case");
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.removeMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
SimpleTest.finish();
}
cpmm.addMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.addMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
// Setting this pref to true should cause us to prelaunch a process.
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true);
}
function setup()
{
info("Set up preferences for testing the Nuwa process.");
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
'set': [
['dom.ipc.preallocatedProcessManager.testMode', true],
['dom.ipc.processPrelaunch.testMode', true] // For testing deadlock
]
}, runTest);
}
</script>
</body>
</html>

View File

@ -615,16 +615,9 @@ DOMStorageDBParent::Observe(const char* aTopic,
const nsACString& aOriginScope)
{
if (mIPCOpen) {
#ifdef MOZ_NUWA_PROCESS
if (!(static_cast<ContentParent*>(Manager())->IsNuwaProcess() &&
ContentParent::IsNuwaReady())) {
#endif
mozilla::Unused << SendObserve(nsDependentCString(aTopic),
nsString(aOriginAttributesPattern),
nsCString(aOriginScope));
#ifdef MOZ_NUWA_PROCESS
}
#endif
}
return NS_OK;

View File

@ -59,10 +59,6 @@
#include "OSFileConstants.h"
#include "xpcpublic.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "Principal.h"
#include "SharedWorker.h"
#include "WorkerDebuggerManager.h"
@ -2494,13 +2490,6 @@ WorkerThreadPrimaryRunnable::Run()
{
using mozilla::ipc::BackgroundChild;
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
NuwaFreezeCurrentThread();
}
#endif
char stackBaseGuess;
PR_SetCurrentThreadName("DOM Worker");

View File

@ -564,10 +564,6 @@ bool ImageBridgeChild::IsCreated()
return GetSingleton() != nullptr;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
static void ReleaseImageClientNow(ImageClient* aClient,
PImageContainerChild* aChild)
{

View File

@ -14,10 +14,6 @@
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
#include "nsThreadUtils.h" // fo NS_IsMainThread
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_WIDGET_GONK
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "SBMChild", ## args)
#endif
@ -103,14 +99,6 @@ ConnectSharedBufferManagerInChildProcess(mozilla::ipc::Transport* aTransport,
XRE_GetIOMessageLoop(),
ipc::ChildSide);
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
SharedBufferManagerChild::sSharedBufferManagerChildThread
->message_loop()->PostTask(NewRunnableFunction(NuwaMarkCurrentThread,
(void (*)(void *))nullptr,
(void *)nullptr));
}
#endif
}
PSharedBufferManagerChild*

View File

@ -17,10 +17,6 @@
#include "nsXPCOMCIDInternal.h"
#include "prsystem.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "gfxPrefs.h"
#include "Decoder.h"
@ -69,12 +65,6 @@ public:
MOZ_ASSERT(!NS_IsMainThread());
mThreadNaming.SetThreadPoolName(NS_LITERAL_CSTRING("ImgDecoder"));
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(static_cast<void(*)(void*)>(nullptr), nullptr);
}
#endif // MOZ_NUWA_PROCESS
}
/// Shut down the provided decode pool thread.
@ -271,15 +261,6 @@ DecodePool::DecodePool()
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread,
"Should successfully create image I/O thread");
#ifdef MOZ_NUWA_PROCESS
rv = mIOThread->Dispatch(NS_NewRunnableFunction([]() -> void {
NuwaMarkCurrentThread(static_cast<void(*)(void*)>(nullptr), nullptr);
}), NS_DISPATCH_NORMAL);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv),
"Should register decode IO thread with Nuwa process");
#endif
nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
if (obsSvc) {
obsSvc->AddObserver(this, "xpcom-shutdown-threads", false);

View File

@ -24,12 +24,6 @@
#include "prenv.h"
#include "prmem.h"
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
using namespace mozilla::ipc;
#endif // MOZ_B2G_LOADER
#ifdef MOZ_WIDGET_GONK
/*
* AID_APP is the first application UID used by Android. We're using
@ -160,71 +154,12 @@ 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;
mozilla::UniquePtr<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;
mozilla::UniquePtr<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
mozilla::UniquePtr<char*[]> argv_cstr(new char*[argv.size() + 1]);
// Illegal to allocate memory after fork and before execvp
InjectiveMultimap fd_shuffle1, fd_shuffle2;

View File

@ -23,17 +23,8 @@ ChildThread::ChildThread(Thread::Options options)
ChildThread::~ChildThread() {
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
bool ChildThread::Run() {
bool r = StartWithOptions(options_);
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
message_loop()->PostTask(NewRunnableFunction(&ChildThread::MarkThread));
}
#endif
return r;
}
@ -42,15 +33,6 @@ void ChildThread::OnChannelError() {
owner_loop_->PostTask(task.forget());
}
#ifdef MOZ_NUWA_PROCESS
void ChildThread::MarkThread() {
NuwaMarkCurrentThread(nullptr, nullptr);
if (!NuwaCheckpointCurrentThread()) {
NS_RUNTIMEABORT("Should not be here!");
}
}
#endif
void ChildThread::OnMessageReceived(IPC::Message&& msg) {
}

View File

@ -42,10 +42,6 @@ class ChildThread : public IPC::Channel::Listener,
virtual void OnMessageReceived(IPC::Message&& msg);
virtual void OnChannelError();
#ifdef MOZ_NUWA_PROCESS
static void MarkThread();
#endif
// The message loop used to run tasks on the thread that started this thread.
MessageLoop* owner_loop_;

View File

@ -5,8 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
Library('plugin-container')
if CONFIG['MOZ_B2G_LOADER']:
FINAL_LIBRARY = 'xul'
SOURCES += [
'plugin-container.cpp',

View File

@ -55,11 +55,6 @@
#endif // MOZ_WIDGET_GONK
#ifdef MOZ_NUWA_PROCESS
#include <binder/ProcessState.h>
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_WIDGET_GONK
static void
InitializeBinder(void *aDummy) {
@ -150,11 +145,6 @@ content_process_main(int argc, char* argv[])
return 3;
}
bool isNuwa = false;
for (int i = 1; i < argc; i++) {
isNuwa |= strcmp(argv[i], "-nuwa") == 0;
}
XREChildData childData;
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
@ -171,20 +161,11 @@ content_process_main(int argc, char* argv[])
XRE_SetProcessType(argv[--argc]);
#ifdef MOZ_NUWA_PROCESS
if (isNuwa) {
PrepareNuwaProcess();
}
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
// This has to happen while we're still single-threaded, and on
// B2G that means before the Android Binder library is
// initialized. Additional special handling is needed for Nuwa:
// the Nuwa process itself needs to be unsandboxed, and the same
// single-threadedness condition applies to its children; see also
// AfterNuwaFork().
mozilla::SandboxEarlyInit(XRE_GetProcessType(), isNuwa);
// initialized.
mozilla::SandboxEarlyInit(XRE_GetProcessType());
#endif
#ifdef MOZ_WIDGET_GONK
@ -193,16 +174,8 @@ content_process_main(int argc, char* argv[])
// 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
#ifdef XP_WIN
// For plugins, this is done in PluginProcessChild::Init, as we need to

View File

@ -29,7 +29,6 @@
#include "mozilla/dom/GamepadTestChannelChild.h"
#endif
#include "mozilla/dom/MessagePortChild.h"
#include "mozilla/dom/NuwaChild.h"
#include "mozilla/ipc/PBackgroundTestChild.h"
#include "mozilla/ipc/PSendStreamChild.h"
#include "mozilla/layout/VsyncChild.h"
@ -75,7 +74,6 @@ using mozilla::dom::asmjscache::PAsmJSCacheEntryChild;
using mozilla::dom::cache::PCacheChild;
using mozilla::dom::cache::PCacheStorageChild;
using mozilla::dom::cache::PCacheStreamControlChild;
using mozilla::dom::PNuwaChild;
// -----------------------------------------------------------------------------
// BackgroundChildImpl::ThreadLocal
@ -409,21 +407,6 @@ BackgroundChildImpl::DeallocPMessagePortChild(PMessagePortChild* aActor)
return true;
}
PNuwaChild*
BackgroundChildImpl::AllocPNuwaChild()
{
return new mozilla::dom::NuwaChild();
}
bool
BackgroundChildImpl::DeallocPNuwaChild(PNuwaChild* aActor)
{
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
PSendStreamChild*
BackgroundChildImpl::AllocPSendStreamChild()
{

View File

@ -140,12 +140,6 @@ protected:
virtual bool
DeallocPMessagePortChild(PMessagePortChild* aActor) override;
virtual PNuwaChild*
AllocPNuwaChild() override;
virtual bool
DeallocPNuwaChild(PNuwaChild* aActor) override;
virtual PSendStreamChild*
AllocPSendStreamChild() override;

View File

@ -22,7 +22,6 @@
#include "mozilla/dom/GamepadEventChannelParent.h"
#include "mozilla/dom/GamepadTestChannelParent.h"
#endif
#include "mozilla/dom/NuwaParent.h"
#include "mozilla/dom/PBlobParent.h"
#include "mozilla/dom/PGamepadEventChannelParent.h"
#include "mozilla/dom/PGamepadTestChannelParent.h"
@ -66,9 +65,7 @@ using mozilla::dom::cache::PCacheStreamControlParent;
using mozilla::dom::FileSystemBase;
using mozilla::dom::FileSystemRequestParent;
using mozilla::dom::MessagePortParent;
using mozilla::dom::NuwaParent;
using mozilla::dom::PMessagePortParent;
using mozilla::dom::PNuwaParent;
using mozilla::dom::UDPSocketParent;
namespace {
@ -297,24 +294,6 @@ BackgroundParentImpl::DeallocPFileDescriptorSetParent(
return true;
}
PNuwaParent*
BackgroundParentImpl::AllocPNuwaParent()
{
return mozilla::dom::NuwaParent::Alloc();
}
bool
BackgroundParentImpl::RecvPNuwaConstructor(PNuwaParent* aActor)
{
return mozilla::dom::NuwaParent::ActorConstructed(aActor);
}
bool
BackgroundParentImpl::DeallocPNuwaParent(PNuwaParent *aActor)
{
return mozilla::dom::NuwaParent::Dealloc(aActor);
}
PSendStreamParent*
BackgroundParentImpl::AllocPSendStreamParent()
{

View File

@ -101,15 +101,6 @@ protected:
virtual bool
DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override;
virtual PNuwaParent*
AllocPNuwaParent() override;
virtual bool
RecvPNuwaConstructor(PNuwaParent* aActor) override;
virtual bool
DeallocPNuwaParent(PNuwaParent* aActor) override;
virtual PSendStreamParent*
AllocPSendStreamParent() override;

View File

@ -1227,56 +1227,3 @@ GeckoChildProcessHost::GetQueuedMessages(std::queue<IPC::Message>& queue)
}
bool GeckoChildProcessHost::sRunSelfAsContentProc(false);
#ifdef MOZ_NUWA_PROCESS
using mozilla::ipc::GeckoExistingProcessHost;
using mozilla::ipc::FileDescriptor;
GeckoExistingProcessHost::
GeckoExistingProcessHost(GeckoProcessType aProcessType,
base::ProcessHandle aProcess,
const FileDescriptor& aFileDescriptor,
ChildPrivileges aPrivileges)
: GeckoChildProcessHost(aProcessType, aPrivileges)
, mExistingProcessHandle(aProcess)
, mExistingFileDescriptor(aFileDescriptor)
{
NS_ASSERTION(aFileDescriptor.IsValid(),
"Expected file descriptor to be valid");
}
GeckoExistingProcessHost::~GeckoExistingProcessHost()
{
// Bug 943174: If we don't do this, ~GeckoChildProcessHost will try
// to wait on a process that isn't a direct child, and bad things
// will happen.
SetAlreadyDead();
}
bool
GeckoExistingProcessHost::PerformAsyncLaunch(StringVector aExtraOpts,
base::ProcessArchitecture aArch)
{
if (!OpenPrivilegedHandle(base::GetProcId(mExistingProcessHandle))) {
NS_RUNTIMEABORT("can't open handle to child process");
}
MonitorAutoLock lock(mMonitor);
mProcessState = PROCESS_CREATED;
lock.Notify();
return true;
}
void
GeckoExistingProcessHost::InitializeChannel()
{
CreateChannel(mExistingFileDescriptor);
MonitorAutoLock lock(mMonitor);
mProcessState = CHANNEL_INITIALIZED;
lock.Notify();
}
#endif /* MOZ_NUWA_PROCESS */

View File

@ -212,28 +212,6 @@ private:
static bool sRunSelfAsContentProc;
};
#ifdef MOZ_NUWA_PROCESS
class GeckoExistingProcessHost final : public GeckoChildProcessHost
{
public:
GeckoExistingProcessHost(GeckoProcessType aProcessType,
base::ProcessHandle aProcess,
const FileDescriptor& aFileDescriptor,
ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT);
~GeckoExistingProcessHost();
virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()) override;
virtual void InitializeChannel() override;
private:
base::ProcessHandle mExistingProcessHandle;
mozilla::ipc::FileDescriptor mExistingFileDescriptor;
};
#endif /* MOZ_NUWA_PROCESS */
} /* namespace ipc */
} /* namespace mozilla */

View File

@ -201,18 +201,6 @@ class MessageChannel : HasResultCodes
sIsPumpingMessages = aIsPumping;
}
#ifdef MOZ_NUWA_PROCESS
void Block() {
MOZ_ASSERT(mLink);
mLink->Block();
}
void Unblock() {
MOZ_ASSERT(mLink);
mLink->Unblock();
}
#endif
#ifdef OS_WIN
struct MOZ_STACK_CLASS SyncStackFrame
{

View File

@ -11,18 +11,6 @@
#include "mozilla/ipc/ProtocolUtils.h"
#include "chrome/common/ipc_channel.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/PNuwa.h"
#include "mozilla/hal_sandbox/PHal.h"
#ifdef DEBUG
#include "jsprf.h"
extern "C" char* PrintJSStack();
#endif
#endif
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "nsDebug.h"
@ -68,10 +56,6 @@ ProcessLink::ProcessLink(MessageChannel *aChan)
, mTransport(nullptr)
, mIOLoop(nullptr)
, mExistingListener(nullptr)
#ifdef MOZ_NUWA_PROCESS
, mIsToNuwaProcess(false)
, mIsBlocked(false)
#endif
{
}
@ -130,17 +114,6 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid
mIOLoop->PostTask(NewNonOwningRunnableMethod(this, &ProcessLink::OnTakeConnectedChannel));
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess() && NS_IsMainThread() &&
Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) {
// The pref value is turned on in a deadlock test against the Nuwa
// process. The sleep here makes it easy to trigger the deadlock
// that an IPC channel is still opening but the worker loop is
// already frozen.
sleep(5);
}
#endif
// Should not wait here if something goes wrong with the channel.
while (!mChan->Connected() && mChan->mChannelState != ChannelError) {
mChan->mMonitor->Wait();
@ -172,42 +145,6 @@ ProcessLink::SendMessage(Message *msg)
mChan->AssertWorkerThread();
mChan->mMonitor->AssertCurrentThreadOwns();
#ifdef MOZ_NUWA_PROCESS
// Parent to child: check whether we are sending some unexpected message to
// the Nuwa process.
if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) {
switch (msg->type()) {
case mozilla::dom::PNuwa::Msg_Fork__ID:
case mozilla::dom::PNuwa::Reply_AddNewProcess__ID:
case mozilla::dom::PContent::Msg_NotifyPhoneStateChange__ID:
case mozilla::dom::PContent::Msg_ActivateA11y__ID:
case mozilla::hal_sandbox::PHal::Msg_NotifyNetworkChange__ID:
case GOODBYE_MESSAGE_TYPE:
break;
default:
#ifdef DEBUG
MOZ_CRASH();
#else
// In optimized build, message will be dropped.
printf_stderr("Sending message to frozen Nuwa");
return;
#endif
}
}
#if defined(DEBUG)
// Nuwa to parent: check whether we are currently blocked.
if (IsNuwaProcess() && mIsBlocked) {
char* jsstack = PrintJSStack();
printf_stderr("Fatal error: sending a message to the chrome process"
"with a blocked IPC channel from \n%s",
jsstack ? jsstack : "<no JS stack>");
JS_smprintf_free(jsstack);
MOZ_CRASH();
}
#endif
#endif
mIOLoop->PostTask(NewNonOwningRunnableMethod<Message*>(mTransport, &Transport::Send, msg));
}
@ -397,10 +334,6 @@ ProcessLink::OnChannelConnected(int32_t peer_pid)
if (mExistingListener)
mExistingListener->OnChannelConnected(peer_pid);
#ifdef MOZ_NUWA_PROCESS
mIsToNuwaProcess = (peer_pid == mozilla::dom::ContentParent::NuwaPid());
#endif
if (notifyChannel) {
mChan->OnChannelConnected(peer_pid);
}

View File

@ -163,12 +163,6 @@ class MessageLink
virtual bool Unsound_IsClosed() const = 0;
virtual uint32_t Unsound_NumQueuedMessages() const = 0;
#ifdef MOZ_NUWA_PROCESS
// To be overridden by ProcessLink.
virtual void Block() {}
virtual void Unblock() {}
#endif
protected:
MessageChannel *mChan;
};
@ -216,23 +210,10 @@ class ProcessLink
virtual bool Unsound_IsClosed() const override;
virtual uint32_t Unsound_NumQueuedMessages() const override;
#ifdef MOZ_NUWA_PROCESS
void Block() override {
mIsBlocked = true;
}
void Unblock() override {
mIsBlocked = false;
}
#endif
protected:
Transport* mTransport;
MessageLoop* mIOLoop; // thread where IO happens
Transport::Listener* mExistingListener; // channel's previous listener
#ifdef MOZ_NUWA_PROCESS
bool mIsToNuwaProcess;
bool mIsBlocked;
#endif
};
class ThreadLink : public MessageLink

View File

@ -25,10 +25,6 @@
#include "nsXULAppAPI.h"
#include "prthread.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using base::TimeTicks;
using namespace mozilla::ipc;
@ -108,11 +104,7 @@ MessagePump::Run(MessagePump::Delegate* aDelegate)
did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
if (did_work && delayed_work_time_.is_null()
#ifdef MOZ_NUWA_PROCESS
&& (!IsNuwaReady() || !IsNuwaProcess())
#endif
)
if (did_work && delayed_work_time_.is_null())
mDelayedWorkTimer->Cancel();
if (!keep_running_)
@ -132,9 +124,6 @@ if (did_work && delayed_work_time_.is_null()
NS_ProcessNextEvent(thisThread, true);
}
#ifdef MOZ_NUWA_PROCESS
if (!IsNuwaReady() || !IsNuwaProcess())
#endif
mDelayedWorkTimer->Cancel();
keep_running_ = true;
@ -166,11 +155,6 @@ MessagePump::ScheduleWorkForNestedLoop()
void
MessagePump::ScheduleDelayedWork(const base::TimeTicks& aDelayedTime)
{
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaReady() && IsNuwaProcess())
return;
#endif
// To avoid racing on mDelayedWorkTimer, we need to be on the same thread as
// ::Run().
MOZ_RELEASE_ASSERT(NS_GetCurrentThread() == mThread ||

View File

@ -17,7 +17,6 @@ include protocol PGamepadEventChannel;
include protocol PGamepadTestChannel;
include protocol PMessagePort;
include protocol PCameras;
include protocol PNuwa;
include protocol PQuota;
include protocol PSendStream;
include protocol PServiceWorkerManager;
@ -61,7 +60,6 @@ sync protocol PBackground
manages PGamepadTestChannel;
manages PMessagePort;
manages PCameras;
manages PNuwa;
manages PQuota;
manages PSendStream;
manages PServiceWorkerManager;
@ -94,8 +92,6 @@ parent:
async PMessagePort(nsID uuid, nsID destinationUuid, uint32_t sequenceId);
async PNuwa();
async PSendStream();
async MessagePortForceClose(nsID uuid, nsID destinationUuid, uint32_t sequenceId);

View File

@ -7,10 +7,6 @@
#ifndef mozilla_ipc_ProcessUtils_h
#define mozilla_ipc_ProcessUtils_h
#ifdef MOZ_B2G_LOADER
#include "base/process_util.h"
#endif
namespace mozilla {
namespace ipc {
@ -18,17 +14,6 @@ namespace ipc {
// this directly.
void SetThisProcessName(const char *aName);
#ifdef MOZ_B2G_LOADER
// see ProcessUtils_linux.cpp for explaination.
void ProcLoaderClientGeckoInit();
bool ProcLoaderIsInitialized();
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

View File

@ -10,41 +10,6 @@
#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 "mozilla/UniquePtr.h"
#include "mozilla/unused.h"
#include "base/process_util.h"
#include "base/eintr_wrapper.h"
#include "mozilla/Preferences.h"
#include "prenv.h"
#include "nsXULAppAPI.h" // export XRE_* functions
#include "nsAppRunner.h"
int content_process_main(int argc, char *argv[]);
typedef mozilla::Vector<int> FdArray;
#endif /* MOZ_B2G_LOADER */
namespace mozilla {
namespace ipc {
@ -54,574 +19,6 @@ 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 mozilla::dom;
using base::ChildPrivileges;
using base::InjectionArc;
using base::InjectiveMultimap;
using base::ProcessHandle;
using base::ProcessId;
using base::SetCurrentProcessPrivileges;
using base::ShuffleFileDescriptors;
using base::file_handle_mapping_vector;
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 mozilla::UniquePtr<FdArray> sReservedFds;
static void ProcLoaderClientDeinit();
/**
* Some file descriptors, like the child IPC channel FD, must be opened at
* specific numbers. To ensure this, we pre-reserve kReservedFileDescriptors FDs
* starting from kBeginReserveFileDescriptor so that operations like
* __android_log_print() won't take these magic FDs.
*/
static const size_t kReservedFileDescriptors = 5;
static const int kBeginReserveFileDescriptor = STDERR_FILENO + 1;
class ProcLoaderParent : public PProcLoaderParent
{
public:
ProcLoaderParent() {}
virtual ~ProcLoaderParent() {}
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual bool RecvLoadComplete(const int32_t &aPid,
const int32_t &aCookie) override;
};
void
ProcLoaderParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (aWhy == AbnormalShutdown) {
NS_WARNING("ProcLoaderParent is destroyed abnormally.");
}
if (sProcLoaderClientOnDeinit) {
// Get error for closing while the channel is already error.
return;
}
// Destroy self asynchronously.
ProcLoaderClientDeinit();
}
static void
_ProcLoaderParentDestroy(PProcLoaderParent *aLoader)
{
delete aLoader;
sProcLoaderClientOnDeinit = false;
}
bool
ProcLoaderParent::RecvLoadComplete(const int32_t &aPid,
const int32_t &aCookie)
{
return true;
}
static void
CloseFileDescriptors(FdArray& aFds)
{
for (size_t i = 0; i < aFds.length(); i++) {
Unused << HANDLE_EINTR(close(aFds[i]));
}
}
/**
* 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");
if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
kill(sProcLoaderPid, SIGKILL);
sProcLoaderPid = 0;
close(sProcLoaderChannelFd);
sProcLoaderChannelFd = -1;
return;
}
sProcLoaderClientGeckoInitialized = true;
TransportDescriptor fd;
fd.mFd = base::FileDescriptor(sProcLoaderChannelFd, /*auto_close=*/ false);
sProcLoaderChannelFd = -1;
UniquePtr<Transport> transport = OpenDescriptor(fd, Transport::MODE_CLIENT);
sProcLoaderParent = new ProcLoaderParent();
sProcLoaderParent->Open(transport.get(),
sProcLoaderPid,
XRE_GetIOMessageLoop(),
ParentSide);
sProcLoaderLoop = MessageLoop::current();
}
bool ProcLoaderIsInitialized()
{
return sProcLoaderPid != 0;
}
/**
* 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(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(FileDescriptor(fdmap->first), fdmap->second));
}
load->mPrivs = aPrivs;
load->mCookie = cookie++;
*aProcessHandle = sProcLoaderPid;
sProcLoaderPid = 0;
sProcLoaderLoop->PostTask(NewRunnableFunction(AsyncSendLoad, load));
return true;
}
class ProcLoaderRunnerBase;
static bool sProcLoaderServing = false;
static ProcLoaderRunnerBase *sProcLoaderDispatchedTask = nullptr;
class ProcLoaderRunnerBase
{
public:
virtual int DoWork() = 0;
virtual ~ProcLoaderRunnerBase() {}
};
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;
MOZ_ASSERT(mFdsRemap.Length() <= kReservedFileDescriptors);
InjectiveMultimap fd_shuffle;
fd_shuffle.reserve(mFdsRemap.Length());
for (i = 0; i < mFdsRemap.Length(); i++) {
const FDRemap *map = &mFdsRemap[i];
auto rawFD = map->fd().ClonePlatformHandle();
int tofd = map->mapto();
// The FD that is dup2()'d from needs to be closed after shuffling.
fd_shuffle.push_back(InjectionArc(rawFD.get(), tofd, /*in_close=*/true));
// Erase from sReservedFds we will use.
for (int* toErase = sReservedFds->begin();
toErase < sReservedFds->end();
toErase++) {
if (tofd == *toErase) {
sReservedFds->erase(toErase);
break;
}
}
}
DebugOnly<bool> ok = ShuffleFileDescriptors(&fd_shuffle);
// Close the FDs that are reserved but not used after
// ShuffleFileDescriptors().
MOZ_ASSERT(sReservedFds);
CloseFileDescriptors(*sReservedFds);
sReservedFds = nullptr;
// Note that we don'e call ::base::CloseSuperfluousFds() here, assuming that
// The file descriptor inherited from the parent are also necessary for us.
}
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);
// 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) override;
virtual bool RecvLoad(InfallibleTArray<nsCString>&& aArgv,
InfallibleTArray<nsCString>&& aEnv,
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(InfallibleTArray<nsCString>&& aArgv,
InfallibleTArray<nsCString>&& aEnv,
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(
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(
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[],
FdArray& aReservedFds)
{
// Make a copy of aReservedFds. It will be used when we dup() the magic file
// descriptors when ProcLoaderChild::RecvLoad() runs.
sReservedFds = MakeUnique<FdArray>(mozilla::Move(aReservedFds));
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;
{
nsresult rv = XRE_InitCommandLine(aArgc, _argv);
if (NS_FAILED(rv)) {
MOZ_CRASH();
}
mozilla::LogModule::Init();
TransportDescriptor fd;
fd.mFd = base::FileDescriptor(aFd, /*auto_close =*/false);
MOZ_ASSERT(!sProcLoaderServing);
MessageLoop loop;
nsAutoPtr<ContentProcess> process;
process = new ContentProcess(aPeerPid);
ChildThread *iothread = process->child_thread();
UniquePtr<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.get(), aPeerPid, iothread->message_loop());
BackgroundHangMonitor::Prohibit();
sProcLoaderServing = true;
loop.Run();
BackgroundHangMonitor::Allow();
XRE_DeinitCommandLine();
}
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, FdArray& aReservedFds)
{
// We already performed fork(). It's safe to free the "danger zone" of file
// descriptors .
mozilla::ipc::CloseFileDescriptors(aReservedFds);
mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd);
}
int
XRE_ProcLoaderServiceRun(pid_t aPeerPid, int aFd,
int aArgc, const char *aArgv[],
FdArray& aReservedFds)
{
return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd,
aArgc, aArgv,
aReservedFds);
}
#endif /* MOZ_B2G_LOADER */

View File

@ -2357,10 +2357,6 @@ HOST_CXXFLAGS=`echo \
AC_SUBST(_DEPEND_CFLAGS)
AC_SUBST(MOZ_SYSTEM_NSPR)
if test -n "$MOZ_NUWA_PROCESS"; then
AC_DEFINE(MOZ_NUWA_PROCESS)
fi
OS_CFLAGS="$CFLAGS"
OS_CXXFLAGS="$CXXFLAGS"
OS_CPPFLAGS="$CPPFLAGS"

View File

@ -1296,26 +1296,12 @@ HelperThread::destroy()
threadData.reset();
}
#ifdef MOZ_NUWA_PROCESS
extern "C" {
MFBT_API bool IsNuwaProcess();
MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void*), void* arg);
}
#endif
/* static */
void
HelperThread::ThreadMain(void* arg)
{
PR_SetCurrentThreadName("JS Helper");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
MOZ_ASSERT(NuwaMarkCurrentThread != nullptr);
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
//See bug 1104658.
//Set the FPU control word to be the same as the main thread's, or math
//computations on this thread may use incorrect precision rules during

View File

@ -1121,10 +1121,6 @@ class Watchdog
mozilla::Atomic<int32_t> mMinScriptRunTimeSeconds;
};
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time"
#define PREF_MAX_SCRIPT_RUN_TIME_CHROME "dom.max_chrome_script_run_time"
@ -1282,13 +1278,6 @@ WatchdogMain(void* arg)
{
PR_SetCurrentThreadName("JS Watchdog");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
NuwaFreezeCurrentThread();
}
#endif
Watchdog* self = static_cast<Watchdog*>(arg);
WatchdogManager* manager = self->Manager();

View File

@ -69,10 +69,6 @@
#include "nsAnimationManager.h"
#include "nsIDOMEvent.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using namespace mozilla;
using namespace mozilla::widget;
using namespace mozilla::ipc;
@ -865,15 +861,6 @@ CreateVsyncRefreshTimer()
return;
}
#ifdef MOZ_NUWA_PROCESS
// NUWA process will just use software timer. Use NuwaAddFinalConstructor()
// to register a callback to create the vsync-base refresh timer after a
// process is created.
if (IsNuwaProcess()) {
NuwaAddFinalConstructor(&CreateContentVsyncRefreshTimer, nullptr);
return;
}
#endif
// If this process is not created by NUWA, just create the vsync timer here.
CreateContentVsyncRefreshTimer(nullptr);
}

View File

@ -64,9 +64,6 @@ if CONFIG['OS_TARGET'] == 'Linux':
# For mremap
DEFINES['_GNU_SOURCE'] = True
if CONFIG['MOZ_NUWA_PROCESS'] and CONFIG['MOZ_JEMALLOC4']:
DEFINES['pthread_mutex_lock'] = '__real_pthread_mutex_lock'
if CONFIG['GNU_CC']:
CFLAGS += ['-std=gnu99']

View File

@ -35,9 +35,6 @@ DEFINES['MOZ_JEMALLOC_IMPL'] = True
if CONFIG['OS_TARGET'] == 'Linux':
NO_PGO = True
if CONFIG['MOZ_NUWA_PROCESS']:
DEFINES['pthread_mutex_lock'] = '__real_pthread_mutex_lock';
LOCAL_INCLUDES += [
'/memory/build',
]

View File

@ -259,11 +259,6 @@ void
DMDFuncs::StatusMsg(const char* aFmt, va_list aAp)
{
#ifdef ANDROID
#ifdef MOZ_B2G_LOADER
// Don't call __android_log_vprint() during initialization, or the magic file
// descriptors will be occupied by android logcat.
if (gIsDMDInitialized)
#endif
__android_log_vprint(ANDROID_LOG_INFO, "DMD", aFmt, aAp);
#else
// The +64 is easily enough for the "DMD[<pid>] " prefix and the NUL.

View File

@ -307,18 +307,6 @@ pthread_atfork(void (*aPrepare)(void), void (*aParent)(void),
}
#endif
#ifdef MOZ_NUWA_PROCESS
#include <pthread.h>
/* NUWA builds have jemalloc built with
* -Dpthread_mutex_lock=__real_pthread_mutex_lock */
int
__real_pthread_mutex_lock(pthread_mutex_t* aMutex)
{
return pthread_mutex_lock(aMutex);
}
#endif
MOZ_END_EXTERN_C
size_t parseNumber(Buffer aBuf)

File diff suppressed because it is too large Load Diff

View File

@ -1,201 +0,0 @@
/* -*- 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/. */
#ifndef __NUWA_H_
#define __NUWA_H_
#include <setjmp.h>
#include <unistd.h>
#include "mozilla/Types.h"
/**
* Nuwa is a goddess who created mankind according to her figure in the
* ancient Chinese mythology.
*/
// Max number of top level protocol that can be handled by Nuwa process.
#ifndef NUWA_TOPLEVEL_MAX
#define NUWA_TOPLEVEL_MAX 8
#endif
struct NuwaProtoFdInfo {
int protoId;
int originFd;
int newFds[2];
};
#define NUWA_NEWFD_PARENT 0
#define NUWA_NEWFD_CHILD 1
extern "C" {
/**
* The following 3 methods are used to synchronously spawn the Nuwa process.
* The typical usage is:
*
* The IPC thread The main thread
* 1. Receives the request.
* 2. NuwaSpawnPrepare().
* 3. Request main thread to
* spawn. --------------------------------------+
* 4. NuwaSpawnWait(). V
* 5. NuwaSpawn() to clone all
* the threads in the Nuwa
* process (including main
* & IPC threads).
* 6. NuwaSpawn() finishes and
* +-------------------------------------- signals NuwaSpawnWait().
* V
* 7. NuwaSpawnWait() returns.
*/
/**
* Prepare for spawning a new process. The calling thread (typically the IPC
* thread) will block further requests to spawn a new process.
*/
MFBT_API void NuwaSpawnPrepare();
/**
* Called on the thread that receives the request. Used to wait until
* NuwaSpawn() finishes and maintain the stack of the calling thread.
*/
MFBT_API void NuwaSpawnWait();
/**
* Spawn a new content process, called in the Nuwa process. This has to run on
* the main thread.
*
* @return The process ID of the new process.
*/
MFBT_API pid_t NuwaSpawn();
/**
* The following methods are for marking threads created in the Nuwa process so
* they can be frozen and then recreated in the spawned process. All threads
* except the main thread must be marked by one of the following 4 methods;
* otherwise, we have a thread that is created but unknown to us. The Nuwa
* process will never become ready and this needs to be fixed.
*/
/**
* Mark the current thread as supporting Nuwa. The thread will implicitly freeze
* by calling a blocking method such as pthread_mutex_lock() or epoll_wait().
*
* @param recreate The custom function that will be called in the spawned
* process, after the thread is recreated. Can be nullptr if no
* custom function to be called after the thread is recreated.
* Note that this function is called duing thread recreation
* while other threads are frozen. It must not perform any
* action (e.g. acquiring a mutex) that might depend on another
* thread that is still blocked.
* @param arg The argument passed to the custom function. Can be nullptr.
*/
MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
/**
* Mark the current thread as not supporting Nuwa. The calling thread will not
* be automatically cloned from the Nuwa process to spawned process. If this
* thread needs to be created in the spawned process, use NuwaAddConstructor()
* or NuwaAddFinalConstructor() to do it.
*/
MFBT_API void NuwaSkipCurrentThread();
/**
* Force the current thread to freeze explicitly at the current point.
*/
MFBT_API void NuwaFreezeCurrentThread();
/**
* Helper functions for the NuwaCheckpointCurrentThread() macro.
*/
MFBT_API jmp_buf* NuwaCheckpointCurrentThread1();
MFBT_API bool NuwaCheckpointCurrentThread2(int setjmpCond);
/**
* Set the point to recover after thread recreation. The calling thread is not
* blocked. This is used for the thread that cannot freeze (i.e. the IPC
* thread).
*/
#define NuwaCheckpointCurrentThread() \
NuwaCheckpointCurrentThread2(setjmp(*NuwaCheckpointCurrentThread1()))
/**
* The following methods are called in the initialization stage of the Nuwa
* process.
*/
/**
* Prepare for making the Nuwa process.
*/
MFBT_API void PrepareNuwaProcess();
/**
* Make the current process a Nuwa process. Start to freeze the threads.
*/
MFBT_API void MakeNuwaProcess();
/**
* Register a method to be invoked after a new process is spawned. The method
* will be invoked on the main thread *before* recreating the other threads.
* The registered method must not perform any action (e.g. acquiring a mutex)
* that might depend on another thread that has not yet been recreated.
*
* @param construct The method to be invoked.
* @param arg The argument passed to the method.
*/
MFBT_API void NuwaAddConstructor(void (*construct)(void *), void *arg);
/**
* Register a method to be invoked after a new process is spawned and threads
* are recreated. The method will be invoked on the main thread *after*
* the other threads are recreated and fully functional.
*
* @param construct The method to be invoked.
* @param arg The argument passed to the method.
*/
MFBT_API void NuwaAddFinalConstructor(void (*construct)(void *), void *arg);
/**
* Register a method to be invoked after the current thread is recreated in the
* spawned process. Note that this function is called while other threads are
* frozen. It must not perform any action (e.g. acquiring a mutex) that might
* depend on another thread that is still blocked.
*
* @param construct The method to be invoked.
* @param arg The argument passed to the method.
*/
MFBT_API void NuwaAddThreadConstructor(void (*construct)(void *), void *arg);
/**
* The methods to query the Nuwa-related states.
*/
/**
* @return If the current process is the Nuwa process.
*/
MFBT_API bool IsNuwaProcess();
/**
* @return If the Nuwa process is ready for spawning new processes.
*/
MFBT_API bool IsNuwaReady();
#if defined(DEBUG)
/**
* Asserts that aThread is not frozen.
*/
MFBT_API void NuwaAssertNotFrozen(unsigned int aThread,
const char* aThreadName);
#else
#define NuwaAssertNotFrozen(aThread, aThreadName) do {} while(0);
#endif
};
#endif /* __NUWA_H_ */

View File

@ -54,14 +54,6 @@ if not CONFIG['JS_STANDALONE']:
'version',
]
if CONFIG['MOZ_NUWA_PROCESS']:
EXPORTS.ipc += [
'Nuwa.h',
]
SOURCES += [
'Nuwa.cpp',
]
EXPORTS.mozilla += [
'arm.h',
'mips.h',

View File

@ -35,9 +35,6 @@
#include "nsStreamUtils.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
@ -545,23 +542,6 @@ Predictor::GetInterface(const nsIID &iid, void **result)
return QueryInterface(iid, result);
}
#ifdef MOZ_NUWA_PROCESS
namespace {
class NuwaMarkPredictorThreadRunner : public Runnable
{
NS_IMETHODIMP Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
return NS_OK;
}
};
} // namespace
#endif
// Predictor::nsICacheEntryMetaDataVisitor
#define SEEN_META_DATA "predictor::seen"
@ -770,11 +750,6 @@ Predictor::MaybeCleanupOldDBFiles()
rv = NS_NewNamedThread("NetPredictClean", getter_AddRefs(ioThread));
RETURN_IF_FAILED(rv);
#ifdef MOZ_NUWA_PROCESS
nsCOMPtr<nsIRunnable> nuwaRunner = new NuwaMarkPredictorThreadRunner();
ioThread->Dispatch(nuwaRunner, NS_DISPATCH_NORMAL);
#endif
RefPtr<PredictorOldCleanupRunner> runner =
new PredictorOldCleanupRunner(ioThread, dbFile);
ioThread->Dispatch(runner, NS_DISPATCH_NORMAL);

View File

@ -17,9 +17,6 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsISystemProxySettings.h"
#include "nsContentUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
//-----------------------------------------------------------------------------
@ -764,11 +761,6 @@ nsPACMan::NamePACThread()
{
MOZ_ASSERT(!NS_IsMainThread(), "wrong thread");
PR_SetCurrentThreadName("Proxy Resolution");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
}
nsresult

View File

@ -783,19 +783,9 @@ nsSocketTransportService::MarkTheLastElementOfPendingQueue()
mServingPendingQueue = false;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
NS_IMETHODIMP
nsSocketTransportService::Run()
{
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
SOCKET_LOG(("STS thread init %d sockets\n", gMaxCount));
psm::InitializeSSLServerCertVerificationThreads();

View File

@ -434,40 +434,6 @@ nsOutputStreamTransport::IsNonBlocking(bool *result)
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
class STSThreadPoolListener final : public nsIThreadPoolListener
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITHREADPOOLLISTENER
STSThreadPoolListener() {}
protected:
~STSThreadPoolListener() {}
};
NS_IMPL_ISUPPORTS(STSThreadPoolListener, nsIThreadPoolListener)
NS_IMETHODIMP
STSThreadPoolListener::OnThreadCreated()
{
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
STSThreadPoolListener::OnThreadShuttingDown()
{
return NS_OK;
}
#endif // MOZ_NUWA_PROCESS
//-----------------------------------------------------------------------------
// nsStreamTransportService
//-----------------------------------------------------------------------------
@ -488,11 +454,6 @@ nsStreamTransportService::Init()
mPool->SetThreadLimit(25);
mPool->SetIdleThreadLimit(1);
mPool->SetIdleThreadTimeout(PR_SecondsToInterval(30));
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
mPool->SetListener(new STSThreadPoolListener());
}
#endif
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();

View File

@ -27,10 +27,6 @@
#include "mozilla/Base64.h"
#include "mozilla/Telemetry.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include <cutils/properties.h>
#endif
@ -451,19 +447,6 @@ nsNotifyAddrListener::Observe(nsISupports *subject,
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
class NuwaMarkLinkMonitorThreadRunner : public Runnable
{
NS_IMETHODIMP Run() override
{
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
return NS_OK;
}
};
#endif
nsresult
nsNotifyAddrListener::Init(void)
{
@ -486,11 +469,6 @@ nsNotifyAddrListener::Init(void)
rv = NS_NewNamedThread("Link Monitor", getter_AddRefs(mThread), this);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef MOZ_NUWA_PROCESS
nsCOMPtr<nsIRunnable> runner = new NuwaMarkLinkMonitorThreadRunner();
mThread->Dispatch(runner, NS_DISPATCH_NORMAL);
#endif
return NS_OK;
}

View File

@ -4991,15 +4991,6 @@ if test -f "${srcdir}/${MOZ_BUILD_APP}/configure.in" ; then
rm -f $tmpscript
fi
dnl We need to wrap dlopen and related functions on Android because we use
dnl our own linker.
dnl This configuration will only work on Android SDK 11 and above: Bug 1220184.
if test "$OS_TARGET" = Android; then
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
MOZ_GLUE_WRAP_LDFLAGS="${MOZ_GLUE_WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_mutex_trylock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2"
fi
fi
AC_SUBST_LIST(MOZ_GLUE_WRAP_LDFLAGS)
export MOZ_GLUE_WRAP_LDFLAGS
@ -6306,20 +6297,6 @@ AC_SUBST_LIST(MOZ_BZ2_LIBS)
AC_SUBST_LIST(MOZ_PNG_CFLAGS)
AC_SUBST_LIST(MOZ_PNG_LIBS)
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
export MOZ_NUWA_PROCESS
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(MOZ_SYSTEM_NSPR)
AC_SUBST(MOZ_SYSTEM_NSS)

View File

@ -506,19 +506,8 @@ SetCurrentProcessSandbox(UniquePtr<sandbox::bpf_dsl::Policy> aPolicy)
}
void
SandboxEarlyInit(GeckoProcessType aType, bool aIsNuwa)
SandboxEarlyInit(GeckoProcessType aType)
{
// Bug 1168555: Nuwa isn't reliably single-threaded at this point;
// it starts an IPC I/O thread and then shuts it down before calling
// the plugin-container entry point, but that thread may not have
// finished exiting. If/when any type of sandboxing is used for the
// Nuwa process (e.g., unsharing the network namespace there instead
// of for each content process, to save memory), this will need to be
// changed by moving the SandboxEarlyInit call to an earlier point.
if (aIsNuwa) {
return;
}
const SandboxInfo info = SandboxInfo::Get();
if (info.Test(SandboxInfo::kUnexpectedThreads)) {
return;

View File

@ -25,7 +25,7 @@
namespace mozilla {
// This must be called early, while the process is still single-threaded.
MOZ_SANDBOX_EXPORT void SandboxEarlyInit(GeckoProcessType aType, bool aIsNuwa);
MOZ_SANDBOX_EXPORT void SandboxEarlyInit(GeckoProcessType aType);
#ifdef MOZ_CONTENT_SANDBOX
// Call only if SandboxInfo::CanSandboxContent() returns true.

View File

@ -1414,10 +1414,6 @@ Extension.prototype = extend(Object.create(ExtensionData.prototype), {
broadcast(msg, data) {
return new Promise(resolve => {
let count = Services.ppmm.childCount;
if (AppConstants.MOZ_NUWA_PROCESS) {
// The nuwa process is frozen, so don't expect it to answer.
count--;
}
Services.ppmm.addMessageListener(msg + "Complete", function listener() {
count--;
if (count == 0) {

View File

@ -319,13 +319,6 @@ this.AppConstants = Object.freeze({
#endif
SOURCE_REVISION_URL: "@MOZ_SOURCE_URL@",
MOZ_NUWA_PROCESS:
#ifdef MOZ_NUWA_PROCESS
true,
#else
false,
#endif
HAVE_USR_LIB64_DIR:
#ifdef HAVE_USR_LIB64_DIR
true,

View File

@ -167,9 +167,6 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
'/widget/xremoteclient',
]
if CONFIG['MOZ_B2G_LOADER']:
DEFINES['OMNIJAR_NAME'] = CONFIG['OMNIJAR_NAME']
CXXFLAGS += CONFIG['TK_CFLAGS']
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']

View File

@ -195,10 +195,6 @@
#include "base/command_line.h"
#include "GTestRunner.h"
#ifdef MOZ_B2G_LOADER
#include "ProcessUtils.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNIWrappers.h"
#endif
@ -3954,10 +3950,6 @@ 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

View File

@ -90,11 +90,6 @@
using mozilla::_ipdltest::IPDLUnitTestProcessChild;
#endif // ifdef MOZ_IPDL_TESTS
#ifdef MOZ_B2G_LOADER
#include "nsLocalFile.h"
#include "nsXREAppData.h"
#endif
#ifdef MOZ_JPROF
#include "jprof.h"
#endif
@ -949,40 +944,3 @@ XRE_InstallX11ErrorHandler()
#endif
}
#endif
#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_RELEASE_ASSERT(NS_SUCCEEDED(rv));
rv = omnijarFile->AppendNative(NS_LITERAL_CSTRING(NS_STRINGIFY(OMNIJAR_NAME)));
MOZ_RELEASE_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 */

View File

@ -30,10 +30,6 @@ class ThreadInfo {
virtual void SetPendingDelete();
bool IsPendingDelete() const { return mPendingDelete; }
#ifdef MOZ_NUWA_PROCESS
void SetThreadId(int aThreadId) { mThreadId = aThreadId; }
#endif
#ifndef SPS_STANDALONE
/**
* May be null for the main thread if the profiler was started during startup

View File

@ -92,10 +92,6 @@
#include <string.h>
#include <list>
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#define SIGNAL_SAVE_PROFILE SIGUSR2
using namespace mozilla;
@ -300,18 +296,6 @@ static void* SignalSender(void* arg) {
// Taken from platform_thread_posix.cc
prctl(PR_SET_NAME, "SamplerThread", 0, 0, 0);
#ifdef MOZ_NUWA_PROCESS
// If the Nuwa process is enabled, we need to mark and freeze the sampler
// thread in the Nuwa process and have this thread recreated in the spawned
// child.
if(IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
// Freeze the thread here so the spawned child will get the correct tgid
// from the getpid() call below.
NuwaFreezeCurrentThread();
}
#endif
int vm_tgid_ = getpid();
DebugOnly<int> my_tid = gettid();
@ -500,18 +484,6 @@ void Sampler::Stop() {
}
}
#ifdef MOZ_NUWA_PROCESS
static void
UpdateThreadId(void* aThreadInfo) {
ThreadInfo* info = static_cast<ThreadInfo*>(aThreadInfo);
// Note that this function is called during thread recreation. Only the thread
// calling this method is running. We can't try to acquire
// Sampler::sRegisteredThreadsMutex because it could be held by another
// thread.
info->SetThreadId(gettid());
}
#endif
bool Sampler::RegisterCurrentThread(const char* aName,
PseudoStack* aPseudoStack,
bool aIsMainThread, void* stackTop)
@ -543,20 +515,6 @@ bool Sampler::RegisterCurrentThread(const char* aName,
sRegisteredThreads->push_back(info);
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
if (info->IsMainThread()) {
// Main thread isn't a marked thread. Register UpdateThreadId() to
// NuwaAddConstructor(), which runs before all other threads are
// recreated.
NuwaAddConstructor(UpdateThreadId, info);
} else {
// Register UpdateThreadInfo() to be run when the thread is recreated.
NuwaAddThreadConstructor(UpdateThreadId, info);
}
}
#endif
return true;
}

View File

@ -26,10 +26,6 @@
#define LOG(args...) \
__android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args)
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using namespace mozilla;
namespace {
@ -123,12 +119,6 @@ public:
{
MOZ_ASSERT(!NS_IsMainThread());
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
int triggerResetTimeout = -1;
bool memoryPressure;
nsresult rv = CheckForMemoryPressure(&memoryPressure);

View File

@ -63,10 +63,6 @@
#include "libui/InputReader.h"
#include "libui/InputDispatcher.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "mozilla/Preferences.h"
#include "GeckoProfiler.h"
@ -909,11 +905,6 @@ nsAppShell::Init()
obsServ->AddObserver(this, "network-connection-state-changed", false);
}
#ifdef MOZ_NUWA_PROCESS
// Make sure main thread was woken up after Nuwa fork.
NuwaAddConstructor((void (*)(void *))&NotifyEvent, nullptr);
#endif
// Delay initializing input devices until the screen has been
// initialized (and we know the resolution).
return rv;

View File

@ -1246,10 +1246,6 @@ enum ccType
ShutdownCC /* Shutdown CC, used for finding leaks. */
};
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
////////////////////////////////////////////////////////////////////////
// Top level structure for the cycle collector.
////////////////////////////////////////////////////////////////////////

View File

@ -1926,12 +1926,6 @@ nsMemoryReporterManager::HandleChildReport(
nsMemoryReporterManager::StartChildReport(mozilla::dom::ContentParent* aChild,
const PendingProcessesState* aState)
{
#ifdef MOZ_NUWA_PROCESS
if (aChild->IsNuwaProcess()) {
return false;
}
#endif
if (!aChild->IsAlive()) {
MEMORY_REPORTING_LOG("StartChildReports (gen=%u): child exited before"
" its report was started\n",
@ -1984,7 +1978,7 @@ nsMemoryReporterManager::EndProcessReport(uint32_t aGeneration, bool aSuccess)
RefPtr<ContentParent> nextChild;
nextChild.swap(s->mChildrenPending.LastElement());
s->mChildrenPending.TruncateLength(s->mChildrenPending.Length() - 1);
// Start report (if the child is still alive and not Nuwa).
// Start report (if the child is still alive).
if (StartChildReport(nextChild, s)) {
++s->mNumProcessesRunning;
MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): started child report"

View File

@ -508,18 +508,6 @@ XRE_API(void,
XRE_API(void,
XRE_StopLateWriteChecks, (void))
#ifdef MOZ_B2G_LOADER
XRE_API(int,
XRE_ProcLoaderServiceRun, (pid_t, int, int argc, const char* argv[],
mozilla::Vector<int>& aReservedFds));
XRE_API(void,
XRE_ProcLoaderClientInit, (pid_t, int,
mozilla::Vector<int>& aReservedFds));
XRE_API(void,
XRE_ProcLoaderPreload, (const char* aProgramDir,
const nsXREAppData* aAppData));
#endif // MOZ_B2G_LOADER
XRE_API(void,
XRE_EnableSameExecutableForContentProc, ())

View File

@ -37,18 +37,6 @@
#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;
@ -78,21 +66,14 @@ struct ManifestDirective
void (nsChromeRegistry::*regfunc)(
nsChromeRegistry::ManifestProcessingContext& aCx,
int aLineNo, char* const* aArgv, int aFlags);
#ifdef MOZ_B2G_LOADER
// The function to handle the directive for XPT Only parsing.
void (*xptonlyfunc)(
nsComponentManagerImpl::XPTOnlyManifestProcessingContext& aCx,
int aLineNo, char* const* aArgv);
#else
void* xptonlyfunc;
#endif
bool isContract;
};
static const ManifestDirective kParsingTable[] = {
{
"manifest", 1, false, false, true, true, false,
&nsComponentManagerImpl::ManifestManifest, nullptr, XPTONLY_MANIFEST
&nsComponentManagerImpl::ManifestManifest, nullptr, nullptr
},
{
"binary-component", 1, true, true, false, false, false,
@ -100,7 +81,7 @@ static const ManifestDirective kParsingTable[] = {
},
{
"interfaces", 1, false, true, false, false, false,
&nsComponentManagerImpl::ManifestXPT, nullptr, XPTONLY_XPT
&nsComponentManagerImpl::ManifestXPT, nullptr, nullptr
},
{
"component", 2, false, true, false, false, false,
@ -484,9 +465,6 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
nsComponentManagerImpl::ManifestProcessingContext mgrcx(aType, aFile,
aChromeOnly);
nsChromeRegistry::ManifestProcessingContext chromecx(aType, aFile);
#ifdef MOZ_B2G_LOADER
nsComponentManagerImpl::XPTOnlyManifestProcessingContext xptonlycx(aFile);
#endif
nsresult rv;
NS_NAMED_LITERAL_STRING(kPlatform, "platform");
@ -775,11 +753,6 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
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;

View File

@ -107,36 +107,6 @@ 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) {
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
@ -682,12 +652,6 @@ nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& aCx,
static void
DoRegisterXPT(FileLocation& aFile)
{
#ifdef MOZ_B2G_LOADER
if (IsRegisteredXPTIInfo(aFile)) {
return;
}
#endif
uint32_t len;
FileLocation::Data data;
UniquePtr<char[]> buf;
@ -701,9 +665,6 @@ DoRegisterXPT(FileLocation& aFile)
}
if (NS_SUCCEEDED(rv)) {
XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf.get(), len);
#ifdef MOZ_B2G_LOADER
MarkRegisteredXPTIInfo(aFile);
#endif
} else {
nsCString uri;
aFile.GetURIString(uri);
@ -911,10 +872,6 @@ nsresult nsComponentManagerImpl::Shutdown(void)
delete sStaticModules;
delete sModuleLocations;
#ifdef MOZ_B2G_LOADER
delete sXPTIInfosBook;
sXPTIInfosBook = nullptr;
#endif
// Unload libraries
mNativeModuleLoader.UnloadLibraries();
@ -2072,52 +2029,6 @@ 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_APP_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);
FileLocation location(aFile, "chrome.manifest");
DoRegisterManifest(NS_APP_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)
{

View File

@ -40,10 +40,6 @@
#include "mozilla/Omnijar.h"
#include "mozilla/Attributes.h"
#ifdef MOZ_B2G_LOADER
#include "mozilla/FileLocation.h"
#endif
struct nsFactoryEntry;
class nsIServiceManager;
struct PRThread;
@ -334,31 +330,6 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
#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();
};

View File

@ -14,9 +14,6 @@
#include "mozilla/Telemetry.h"
#include "mozilla/ThreadHangStats.h"
#include "mozilla/ThreadLocal.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#include "prinrval.h"
#include "prthread.h"
@ -59,12 +56,6 @@ private:
{
PR_SetCurrentThreadName("BgHangManager");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
/* We do not hold a reference to BackgroundHangManager here
because the monitor thread only exists as long as the
BackgroundHangManager instance exists. We stop the monitor

View File

@ -23,10 +23,6 @@
#include "nsExceptionHandler.h"
#endif
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef XP_WIN
#include <windows.h>
#endif
@ -184,12 +180,6 @@ ThreadMain(void*)
{
PR_SetCurrentThreadName("Hang Monitor");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
MonitorAutoLock lock(*gMonitor);
// In order to avoid issues with the hang monitor incorrectly triggering

View File

@ -386,10 +386,6 @@ TimerThread::Shutdown()
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
namespace {
struct MicrosecondsToInterval
@ -413,12 +409,6 @@ TimerThread::Run()
{
PR_SetCurrentThreadName("Timer");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
MonitorAutoLock lock(mMonitor);
// We need to know how many microseconds give a positive PRIntervalTime. This
@ -446,11 +436,7 @@ TimerThread::Run()
bool forceRunThisTimer = forceRunNextTimer;
forceRunNextTimer = false;
if (mSleeping
#ifdef MOZ_NUWA_PROCESS
|| IsNuwaProcess() // Don't fire timers or deadlock will result.
#endif
) {
if (mSleeping) {
// Sleep for 0.1 seconds while not firing timers.
uint32_t milliseconds = 100;
if (ChaosMode::isActive(ChaosFeature::TimerScheduling)) {

View File

@ -43,10 +43,6 @@
#include "mozilla/dom/ContentChild.h"
#endif
#ifdef MOZ_NUWA_PROCESS
#include "private/pprthred.h"
#endif
#ifdef XP_LINUX
#include <sys/time.h>
#include <sys/resource.h>
@ -677,12 +673,6 @@ nsThread::PutEvent(already_AddRefed<nsIRunnable> aEvent, nsNestedEventTarget* aT
LeakRefPtr<nsIRunnable> event(Move(aEvent));
nsCOMPtr<nsIThreadObserver> obs;
#ifdef MOZ_NUWA_PROCESS
// On debug build or when tests are enabled, assert that we are not about to
// create a deadlock in the Nuwa process.
NuwaAssertNotFrozen(PR_GetThreadID(mThread), PR_GetThreadName(mThread));
#endif
{
MutexAutoLock lock(mLock);
nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot;

View File

@ -14,9 +14,6 @@
#include "mozilla/Atomics.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Logging.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
#ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracerImpl.h"
using namespace mozilla::tasktracer;