forked from mirrors/gecko-dev
Prior to this patch, we were sending a boolean from InitContentChild (which creates our StartupCache IPC actors) indicating whether we wanted to collect new entries from a given process or not. This was so that we wouldn't accept PutBuffer requests in these processes, since collecting them in one process would be enough, and we don't want to waste memory. However, we actually want the cache to be available before we can even get that IPC constructor to the child process, so there's a window where we accept new entries no matter what. This patch changes this by sending a boolean argument via the command line indicating that we want to disable the Startupcache in this process entirely. We send this when we didn't load a StartupCache off disk, as this should be the only circumstance in which we're actually collecting a substantial number of entries in content processes. Differential Revision: https://phabricator.services.mozilla.com/D83400
223 lines
6.6 KiB
C++
223 lines
6.6 KiB
C++
/* -*- 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/ipc/IOThreadChild.h"
|
|
|
|
#include "ContentProcess.h"
|
|
#include "base/shared_memory.h"
|
|
#include "mozilla/Preferences.h"
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
# include <stdlib.h>
|
|
# include "mozilla/Sandbox.h"
|
|
#endif
|
|
|
|
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
|
|
# include "mozilla/SandboxSettings.h"
|
|
# include "nsAppDirectoryServiceDefs.h"
|
|
# include "nsDirectoryService.h"
|
|
# include "nsDirectoryServiceDefs.h"
|
|
#endif
|
|
|
|
using mozilla::ipc::IOThreadChild;
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
|
static void SetTmpEnvironmentVariable(nsIFile* aValue) {
|
|
// Save the TMP environment variable so that is is picked up by GetTempPath().
|
|
// Note that we specifically write to the TMP variable, as that is the first
|
|
// variable that is checked by GetTempPath() to determine its output.
|
|
nsAutoString fullTmpPath;
|
|
nsresult rv = aValue->GetPath(fullTmpPath);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return;
|
|
}
|
|
Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
|
|
// We also set TEMP in case there is naughty third-party code that is
|
|
// referencing the environment variable directly.
|
|
Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
|
|
}
|
|
#endif
|
|
|
|
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
|
static void SetUpSandboxEnvironment() {
|
|
MOZ_ASSERT(
|
|
nsDirectoryService::gService,
|
|
"SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
|
|
|
|
// On Windows, a sandbox-writable temp directory is used whenever the sandbox
|
|
// is enabled.
|
|
if (!IsContentSandboxEnabled()) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIFile> sandboxedContentTemp;
|
|
nsresult rv = nsDirectoryService::gService->Get(
|
|
NS_APP_CONTENT_PROCESS_TEMP_DIR, NS_GET_IID(nsIFile),
|
|
getter_AddRefs(sandboxedContentTemp));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return;
|
|
}
|
|
|
|
// Change the gecko defined temp directory to our sandbox-writable one.
|
|
// Undefine returns a failure if the property is not already set.
|
|
Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
|
|
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return;
|
|
}
|
|
|
|
SetTmpEnvironmentVariable(sandboxedContentTemp);
|
|
}
|
|
#endif
|
|
|
|
bool ContentProcess::Init(int aArgc, char* aArgv[]) {
|
|
Maybe<uint64_t> childID;
|
|
Maybe<bool> isForBrowser;
|
|
Maybe<const char*> parentBuildID;
|
|
char* prefsHandle = nullptr;
|
|
char* prefMapHandle = nullptr;
|
|
char* prefsLen = nullptr;
|
|
char* prefMapSize = nullptr;
|
|
char* scacheHandle = nullptr;
|
|
char* scacheSize = nullptr;
|
|
bool wantsScache = true;
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
nsCOMPtr<nsIFile> profileDir;
|
|
#endif
|
|
|
|
for (int i = 1; i < aArgc; i++) {
|
|
if (!aArgv[i]) {
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(aArgv[i], "-appdir") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
nsDependentCString appDir(aArgv[i]);
|
|
mXREEmbed.SetAppDir(appDir);
|
|
|
|
} else if (strcmp(aArgv[i], "-childID") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
char* str = aArgv[i];
|
|
childID = Some(strtoull(str, &str, 10));
|
|
if (str[0] != '\0') {
|
|
return false;
|
|
}
|
|
|
|
} else if (strcmp(aArgv[i], "-isForBrowser") == 0) {
|
|
isForBrowser = Some(true);
|
|
|
|
} else if (strcmp(aArgv[i], "-notForBrowser") == 0) {
|
|
isForBrowser = Some(false);
|
|
|
|
#ifdef XP_WIN
|
|
} else if (strcmp(aArgv[i], "-prefsHandle") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
prefsHandle = aArgv[i];
|
|
} else if (strcmp(aArgv[i], "-prefMapHandle") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
prefMapHandle = aArgv[i];
|
|
} else if (strcmp(aArgv[i], "-scacheHandle") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
scacheHandle = aArgv[i];
|
|
#endif
|
|
|
|
} else if (strcmp(aArgv[i], "-prefsLen") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
prefsLen = aArgv[i];
|
|
} else if (strcmp(aArgv[i], "-prefMapSize") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
prefMapSize = aArgv[i];
|
|
} else if (strcmp(aArgv[i], "-scacheSize") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
scacheSize = aArgv[i];
|
|
} else if (strcmp(aArgv[i], "-noScache") == 0) {
|
|
wantsScache = false;
|
|
} else if (strcmp(aArgv[i], "-safeMode") == 0) {
|
|
gSafeMode = true;
|
|
|
|
} else if (strcmp(aArgv[i], "-parentBuildID") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
parentBuildID = Some(aArgv[i]);
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
} else if (strcmp(aArgv[i], "-profile") == 0) {
|
|
if (++i == aArgc) {
|
|
return false;
|
|
}
|
|
bool flag;
|
|
nsresult rv = XRE_GetFileFromPath(aArgv[i], getter_AddRefs(profileDir));
|
|
if (NS_FAILED(rv) || NS_FAILED(profileDir->Exists(&flag)) || !flag) {
|
|
NS_WARNING("Invalid profile directory passed to content process.");
|
|
profileDir = nullptr;
|
|
}
|
|
#endif /* XP_MACOSX && MOZ_SANDBOX */
|
|
}
|
|
}
|
|
|
|
// Did we find all the mandatory flags?
|
|
if (childID.isNothing() || isForBrowser.isNothing() ||
|
|
parentBuildID.isNothing()) {
|
|
return false;
|
|
}
|
|
|
|
SharedPreferenceDeserializer deserializer;
|
|
if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
|
|
prefsLen, prefMapSize)) {
|
|
return false;
|
|
}
|
|
|
|
if (wantsScache) {
|
|
Unused << mozilla::scache::StartupCache::InitChildSingleton(scacheHandle,
|
|
scacheSize);
|
|
}
|
|
|
|
mContent.Init(IOThreadChild::message_loop(), ParentPid(), *parentBuildID,
|
|
IOThreadChild::TakeChannel(), *childID, *isForBrowser);
|
|
|
|
mXREEmbed.Start();
|
|
#if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
|
|
mContent.SetProfileDir(profileDir);
|
|
# if defined(DEBUG)
|
|
if (IsContentSandboxEnabled()) {
|
|
AssertMacSandboxEnabled();
|
|
}
|
|
# endif /* DEBUG */
|
|
#endif /* XP_MACOSX && MOZ_SANDBOX */
|
|
|
|
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
|
SetUpSandboxEnvironment();
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
// Note: CleanUp() never gets called in non-debug builds because we exit early
|
|
// in ContentChild::ActorDestroy().
|
|
void ContentProcess::CleanUp() { mXREEmbed.Stop(); }
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|