Backed out 2 changesets (bug 1498742) for build bustages at GMPProcessParent.cpp on a CLOSED TREE

Backed out changeset 5f9d32e26c71 (bug 1498742)
Backed out changeset ffc8d151cf3a (bug 1498742)
This commit is contained in:
Andreea Pavel 2019-06-13 04:38:56 +03:00
Родитель 0f858863b6
Коммит 307e3f181b
24 изменённых файлов: 187 добавлений и 580 удалений

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

@ -1066,8 +1066,6 @@ pref("security.sandbox.gmp.win32k-disable", false);
pref("security.sandbox.content.mac.earlyinit", true);
// Remove this pref once RDD early init is stable on Release.
pref("security.sandbox.rdd.mac.earlyinit", true);
// Remove this pref once GMP early init is stable on Release.
pref("security.sandbox.gmp.mac.earlyinit", true);
// This pref is discussed in bug 1083344, the naming is inspired from its
// Windows counterpart, but on Mac it's an integer which means:

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

@ -209,6 +209,11 @@
#if defined(XP_MACOSX)
# include "nsMacUtilsImpl.h"
# include <CoreServices/CoreServices.h>
// Info.plist key associated with the developer repo path
# define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
// Info.plist key associated with the developer repo object directory
# define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
#endif /* XP_MACOSX */
#ifdef MOZ_X11
@ -1656,7 +1661,7 @@ static bool StartMacOSContentSandbox() {
if (mozilla::IsDevelopmentBuild()) {
nsCOMPtr<nsIFile> repoDir;
rv = nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir));
rv = mozilla::GetRepoDir(getter_AddRefs(repoDir));
if (NS_FAILED(rv)) {
MOZ_CRASH("Failed to get path to repo dir");
}
@ -1665,7 +1670,7 @@ static bool StartMacOSContentSandbox() {
info.testingReadPath3.assign(repoDirPath.get());
nsCOMPtr<nsIFile> objDir;
rv = nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir));
rv = mozilla::GetObjDir(getter_AddRefs(objDir));
if (NS_FAILED(rv)) {
MOZ_CRASH("Failed to get path to build object dir");
}
@ -4022,4 +4027,111 @@ bool StartOpenBSDSandbox(GeckoProcessType type) {
}
#endif
#if !defined(XP_WIN)
bool IsDevelopmentBuild() {
nsCOMPtr<nsIFile> path = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
// If the path doesn't exist, we're a dev build.
return path == nullptr;
}
#endif /* !XP_WIN */
#if defined(XP_MACOSX)
/*
* Helper function to read a string value for a given key from the .app's
* Info.plist.
*/
static nsresult GetStringValueFromBundlePlist(const nsAString& aKey,
nsAutoCString& aValue) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle == nullptr) {
return NS_ERROR_FAILURE;
}
// Read this app's bundle Info.plist as a dictionary
CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(mainBundle);
if (bundleInfoDict == nullptr) {
return NS_ERROR_FAILURE;
}
nsAutoCString keyAutoCString = NS_ConvertUTF16toUTF8(aKey);
CFStringRef key = CFStringCreateWithCString(
kCFAllocatorDefault, keyAutoCString.get(), kCFStringEncodingUTF8);
if (key == nullptr) {
return NS_ERROR_FAILURE;
}
CFStringRef value = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, key);
CFRelease(key);
if (value == nullptr) {
return NS_ERROR_FAILURE;
}
CFIndex valueLength = CFStringGetLength(value);
if (valueLength == 0) {
return NS_ERROR_FAILURE;
}
const char* valueCString =
CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
if (valueCString) {
aValue.Assign(valueCString);
return NS_OK;
}
CFIndex maxLength =
CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
if (!CFStringGetCString(value, valueBuffer, maxLength,
kCFStringEncodingUTF8)) {
free(valueBuffer);
return NS_ERROR_FAILURE;
}
aValue.Assign(valueBuffer);
free(valueBuffer);
return NS_OK;
}
/*
* Helper function for reading a path string from the .app's Info.plist
* and returning a directory object for that path with symlinks resolved.
*/
static nsresult GetDirFromBundlePlist(const nsAString& aKey, nsIFile** aDir) {
nsresult rv;
nsAutoCString dirPath;
rv = GetStringValueFromBundlePlist(aKey, dirPath);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> dir;
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirPath), false,
getter_AddRefs(dir));
NS_ENSURE_SUCCESS(rv, rv);
rv = dir->Normalize();
NS_ENSURE_SUCCESS(rv, rv);
bool isDirectory = false;
rv = dir->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
if (!isDirectory) {
return NS_ERROR_FILE_NOT_DIRECTORY;
}
dir.swap(*aDir);
return NS_OK;
}
nsresult GetRepoDir(nsIFile** aRepoDir) {
MOZ_ASSERT(IsDevelopmentBuild());
return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_REPO_KEY), aRepoDir);
}
nsresult GetObjDir(nsIFile** aObjDir) {
MOZ_ASSERT(IsDevelopmentBuild());
return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
}
#endif /* XP_MACOSX */
} // namespace mozilla

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

@ -48,6 +48,23 @@ class ChildProfilerController;
using mozilla::loader::PScriptCacheChild;
#if !defined(XP_WIN)
// Returns whether or not the currently running build is an unpackaged
// developer build. This check is implemented by looking for omni.ja in the
// the obj/dist dir. We use this routine to detect when the build dir will
// use symlinks to the repo and object dir. On Windows, dev builds don't
// use symlinks.
bool IsDevelopmentBuild();
#endif /* !XP_WIN */
#if defined(XP_MACOSX)
// Return the repo directory and the repo object directory respectively. These
// should only be used on Mac developer builds to determine the path to the
// repo or object directory.
nsresult GetRepoDir(nsIFile** aRepoDir);
nsresult GetObjDir(nsIFile** aObjDir);
#endif /* XP_MACOSX */
namespace ipc {
class URIParams;
} // namespace ipc

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

@ -1990,7 +1990,7 @@ static void CacheSandboxParams(std::vector<std::string>& aCachedParams) {
if (mozilla::IsDevelopmentBuild()) {
// Repo dir
nsCOMPtr<nsIFile> repoDir;
rv = nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir));
rv = mozilla::GetRepoDir(getter_AddRefs(repoDir));
if (NS_FAILED(rv)) {
MOZ_CRASH("Failed to get path to repo dir");
}
@ -2000,7 +2000,7 @@ static void CacheSandboxParams(std::vector<std::string>& aCachedParams) {
// Object dir
nsCOMPtr<nsIFile> objDir;
rv = nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir));
rv = mozilla::GetObjDir(getter_AddRefs(objDir));
if (NS_FAILED(rv)) {
MOZ_CRASH("Failed to get path to build object dir");
}

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

@ -17,7 +17,6 @@
#include "gmp-video-decode.h"
#include "gmp-video-encode.h"
#include "GMPPlatform.h"
#include "GMPProcessParent.h"
#include "mozilla/Algorithm.h"
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/ProcessChild.h"
@ -561,22 +560,16 @@ mozilla::ipc::IPCResult GMPChild::AnswerStartPlugin(const nsString& aAdapter) {
return IPC_FAIL(this, "Can't sandbox GMP.");
}
#endif
bool isChromium = aAdapter.EqualsLiteral("chromium");
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
// If we started the sandbox at launch ("earlyinit"), then we don't
// need to setup sandbox arguments here with SetMacSandboxInfo().
if (!IsMacSandboxStarted()) {
// Use of the chromium adapter indicates we are going to be
// running the Widevine plugin which requires access to the
// WindowServer in the Mac GMP sandbox policy.
if (!SetMacSandboxInfo(isChromium /* allow-window-server */)) {
NS_WARNING("Failed to set Mac GMP sandbox info");
delete platformAPI;
return IPC_FAIL(
this, nsPrintfCString("Failed to set Mac GMP sandbox info.").get());
}
#if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
// Use of the chromium adapter indicates we are going to be
// running the Widevine plugin which requires access to the
// WindowServer in the Mac GMP sandbox policy.
if (!SetMacSandboxInfo(isChromium /* allow-window-server */)) {
NS_WARNING("Failed to set Mac GMP sandbox info");
delete platformAPI;
return IPC_FAIL(
this, nsPrintfCString("Failed to set Mac GMP sandbox info.").get());
}
#endif

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

@ -160,12 +160,6 @@ class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
class MacSandboxStarter : public mozilla::gmp::SandboxStarter {
public:
bool Start(const char* aLibPath) override {
// If we started the sandbox at launch ("earlyinit"),
// then don't try to start the sandbox again.
if (IsMacSandboxStarted()) {
return true;
}
std::string err;
bool rv = mozilla::StartMacSandbox(mInfo, err);
if (!rv) {

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

@ -149,9 +149,6 @@ nsresult GMPParent::LoadProcess() {
if (!mProcess) {
mProcess = new GMPProcessParent(NS_ConvertUTF16toUTF8(path).get());
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
mProcess->SetRequiresWindowServer(mAdapter.EqualsLiteral("chromium"));
#endif
if (!mProcess->Launch(30 * 1000)) {
LOGD("%s: Failed to launch new child process", __FUNCTION__);
mProcess->Delete();

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

@ -18,15 +18,6 @@
#include <string>
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
# include "mozilla/Sandbox.h"
# include "nsMacUtilsImpl.h"
#endif
#if defined(XP_MACOSX)
# include "mozilla/SandboxSettings.h"
#endif /* XP_MACOSX */
using std::string;
using std::vector;
@ -38,45 +29,9 @@ static const int kInvalidFd = -1;
namespace mozilla {
namespace gmp {
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
bool GMPProcessParent::sLaunchWithMacSandbox = true;
bool GMPProcessParent::sMacSandboxGMPLogging = false;
# if defined(DEBUG)
bool GMPProcessParent::sIsMainThreadInitDone = false;
# endif
#endif
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
/* static */
void GMPProcessParent::InitStaticMainThread() {
// The GMPProcessParent constructor is called off the
// main thread. Do main thread initialization here.
MOZ_ASSERT(NS_IsMainThread());
sLaunchWithMacSandbox =
Preferences::GetBool("security.sandbox.gmp.mac.earlyinit", true) &&
(getenv("MOZ_DISABLE_GMP_SANDBOX") == nullptr);
sMacSandboxGMPLogging =
Preferences::GetBool("security.sandbox.logging.enabled") ||
PR_GetEnv("MOZ_SANDBOX_GMP_LOGGING") || PR_GetEnv("MOZ_SANDBOX_LOGGING");
GMP_LOG("GMPProcessParent::InitStaticMainThread: earlyinit=%s, logging=%s",
sLaunchWithMacSandbox ? "true" : "false",
sMacSandboxGMPLogging ? "true" : "false");
# if defined(DEBUG)
sIsMainThreadInitDone = true;
# endif
}
#endif
GMPProcessParent::GMPProcessParent(const std::string& aGMPPath)
: GeckoChildProcessHost(GeckoProcessType_GMPlugin),
mGMPPath(aGMPPath)
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
,
mRequiresWindowServer(false)
#endif
{
: GeckoChildProcessHost(GeckoProcessType_GMPlugin), mGMPPath(aGMPPath) {
MOZ_COUNT_CTOR(GMPProcessParent);
MOZ_ASSERT(sIsMainThreadInitDone == true);
}
GMPProcessParent::~GMPProcessParent() { MOZ_COUNT_DTOR(GMPProcessParent); }
@ -113,21 +68,6 @@ bool GMPProcessParent::Launch(int32_t aTimeoutMs) {
}
args.push_back(WideToUTF8(wGMPPath));
#elif defined(XP_MACOSX) && defined(MOZ_SANDBOX)
// Resolve symlinks in the plugin path. The sandbox prevents
// resolving symlinks in the child process if access to link
// source file is denied.
nsAutoCString normalizedPath;
nsresult rv = NormalizePath(mGMPPath.c_str(), normalizedPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
GMP_LOG(
"GMPProcessParent::Launch: "
"plugin path normaliziation failed for path: %s",
mGMPPath.c_str());
args.push_back(mGMPPath);
} else {
args.push_back(normalizedPath.get());
}
#else
args.push_back(mGMPPath);
#endif
@ -158,108 +98,5 @@ void GMPProcessParent::DoDelete() {
Destroy();
}
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
bool GMPProcessParent::IsMacSandboxLaunchEnabled() {
return sLaunchWithMacSandbox;
}
void GMPProcessParent::SetRequiresWindowServer(bool aRequiresWindowServer) {
mRequiresWindowServer = aRequiresWindowServer;
}
bool GMPProcessParent::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
aInfo.type = MacSandboxType_GMP;
aInfo.hasWindowServer = mRequiresWindowServer;
aInfo.shouldLog = (aInfo.shouldLog || sMacSandboxGMPLogging);
nsAutoCString appPath;
if (!nsMacUtilsImpl::GetAppPath(appPath)) {
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get app path");
return false;
}
aInfo.appPath.assign(appPath.get());
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"plugin dir path: %s",
mGMPPath.c_str());
nsCOMPtr<nsIFile> pluginDir;
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(mGMPPath.c_str()), true,
getter_AddRefs(pluginDir));
if (NS_FAILED(rv)) {
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"NS_NewLocalFile failed for plugin dir, rv=%d",
rv);
return false;
}
rv = pluginDir->Normalize();
if (NS_FAILED(rv)) {
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"failed to normalize plugin dir path, rv=%d",
rv);
return false;
}
nsAutoCString resolvedPluginPath;
pluginDir->GetNativePath(resolvedPluginPath);
aInfo.pluginPath.assign(resolvedPluginPath.get());
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"resolved plugin dir path: %s",
resolvedPluginPath.get());
if (mozilla::IsDevelopmentBuild()) {
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: IsDevelopmentBuild()=true");
// Repo dir
nsCOMPtr<nsIFile> repoDir;
rv = nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir));
if (NS_FAILED(rv)) {
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get repo dir");
return false;
}
nsCString repoDirPath;
Unused << repoDir->GetNativePath(repoDirPath);
aInfo.testingReadPath1 = repoDirPath.get();
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"repo dir path: %s",
repoDirPath.get());
// Object dir
nsCOMPtr<nsIFile> objDir;
rv = nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir));
if (NS_FAILED(rv)) {
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get object dir");
return false;
}
nsCString objDirPath;
Unused << objDir->GetNativePath(objDirPath);
aInfo.testingReadPath2 = objDirPath.get();
GMP_LOG(
"GMPProcessParent::FillMacSandboxInfo: "
"object dir path: %s",
objDirPath.get());
}
return true;
}
nsresult GMPProcessParent::NormalizePath(const char* aPath,
nsACString& aNormalizedPath) {
nsCOMPtr<nsIFile> fileOrDir;
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(aPath), true,
getter_AddRefs(fileOrDir));
NS_ENSURE_SUCCESS(rv, rv);
rv = fileOrDir->Normalize();
NS_ENSURE_SUCCESS(rv, rv);
fileOrDir->GetNativePath(aNormalizedPath);
return NS_OK;
}
#endif
} // namespace gmp
} // namespace mozilla

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

@ -32,28 +32,6 @@ class GMPProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
bool CanShutdown() override { return true; }
const std::string& GetPluginFilePath() { return mGMPPath; }
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
// Init static members on the main thread
static void InitStaticMainThread();
// Read prefs and environment variables to determine
// when and if to start the Mac sandbox for the child
// process. Starting the sandbox at launch is the new
// preferred method. Code to support starting the sandbox
// later at plugin start time should be removed once
// starting at launch is stable and shipping.
bool IsMacSandboxLaunchEnabled() override;
// For process sandboxing purposes, set whether or not this
// instance of the GMP process requires access to the macOS
// window server. At present, Widevine requires window server
// access, but OpenH264 decoding does not.
void SetRequiresWindowServer(bool aRequiresWindowServer);
// Return the sandbox type to be used with this process type.
static MacSandboxType GetMacSandboxType() { return MacSandboxType_GMP; };
#endif
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle;
@ -65,36 +43,6 @@ class GMPProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
std::string mGMPPath;
nsCOMPtr<nsIRunnable> mDeletedCallback;
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
// Indicates whether we'll start the Mac GMP sandbox during
// process launch (earlyinit) which is the new preferred method
// or later in the process lifetime.
static bool sLaunchWithMacSandbox;
// Whether or not Mac sandbox violation logging is enabled.
static bool sMacSandboxGMPLogging;
// Override so we can set GMP-specific sandbox parameters
bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
// For normalizing paths to be compatible with sandboxing.
// We use normalized paths to generate the sandbox ruleset. Once
// the sandbox has been started, resolving symlinks that point to
// allowed directories could require reading paths not allowed by
// the sandbox, so we should only attempt to load plugin libraries
// using normalized paths.
static nsresult NormalizePath(const char* aPath, nsACString& aNormalizedPath);
// Controls whether or not the sandbox will be configured with
// window service access.
bool mRequiresWindowServer;
# if defined(DEBUG)
// Used to assert InitStaticMainThread() is called before the constructor.
static bool sIsMainThreadInitDone;
# endif
#endif
DISALLOW_COPY_AND_ASSIGN(GMPProcessParent);
};

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

@ -13,7 +13,6 @@
#include "GMPVideoDecoderParent.h"
#include "nsIObserverService.h"
#include "GeckoChildProcessHost.h"
#include "GMPProcessParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SyncRunnable.h"
#include "nsXPCOMPrivate.h"
@ -103,17 +102,13 @@ class GMPServiceCreateHelper final : public mozilla::Runnable {
new GeckoMediaPluginServiceParent();
service->Init();
sSingletonService = service;
#if defined(XP_MACOSX)
// GMPProcessParent should only be instantiated in the parent
// so initialization only needs to be done in the parent.
GMPProcessParent::InitStaticMainThread();
#endif
} else {
RefPtr<GeckoMediaPluginServiceChild> service =
new GeckoMediaPluginServiceChild();
service->Init();
sSingletonService = service;
}
ClearOnShutdown(&sSingletonService);
}

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

@ -261,16 +261,15 @@ void RDDProcessHost::DestroyProcess() {
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
/* static */
bool RDDProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
void RDDProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
if (!aInfo.shouldLog && PR_GetEnv("MOZ_SANDBOX_RDD_LOGGING")) {
aInfo.shouldLog = true;
}
return true;
}
bool RDDProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
return RDDProcessHost::StaticFillMacSandboxInfo(aInfo);
void RDDProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
RDDProcessHost::StaticFillMacSandboxInfo(aInfo);
}
/* static */

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

@ -99,7 +99,7 @@ class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
// To allow filling a MacSandboxInfo from the child
// process without an instance of RDDProcessHost.
// Only needed for late-start sandbox enabling.
static bool StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
static void StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
// Return the sandbox type to be used with this process type.
static MacSandboxType GetMacSandboxType();
@ -130,7 +130,7 @@ class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
bool IsMacSandboxLaunchEnabled() override { return sLaunchWithMacSandbox; }
// Override so we can turn on RDD process-specific sandbox logging
bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
void FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
#endif
DISALLOW_COPY_AND_ASSIGN(RDDProcessHost);

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

@ -68,7 +68,6 @@
#endif
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
# include "GMPProcessParent.h"
# include "nsMacUtilsImpl.h"
#endif
@ -371,8 +370,8 @@ bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
PrepareLaunch();
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
if (IsMacSandboxLaunchEnabled() && !AppendMacSandboxParams(aExtraOpts)) {
return false;
if (IsMacSandboxLaunchEnabled()) {
AppendMacSandboxParams(aExtraOpts);
}
#endif
@ -1398,18 +1397,15 @@ void GeckoChildProcessHost::LaunchAndroidService(
#endif
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
bool GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
void GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
MacSandboxInfo info;
if (!FillMacSandboxInfo(info)) {
return false;
}
FillMacSandboxInfo(info);
info.AppendAsParams(aArgs);
return true;
}
// Fill |aInfo| with the flags needed to launch the utility sandbox
/* static */
bool GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
void GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
aInfo.type = GetDefaultMacSandboxType();
aInfo.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
PR_GetEnv("MOZ_SANDBOX_LOGGING");
@ -1419,11 +1415,10 @@ bool GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
MOZ_CRASH("Failed to get app path");
}
aInfo.appPath.assign(appPath.get());
return true;
}
bool GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
return GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
void GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
}
//
@ -1437,9 +1432,9 @@ bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
std::string& aErrorMessage) {
MacSandboxType sandboxType = MacSandboxType_Invalid;
switch (XRE_GetProcessType()) {
// For now, only support early sandbox startup for content,
// RDD, and GMP processes. Add case statements for the additional
// process types once early sandbox startup is implemented for them.
// For now, only support early sandbox startup for content
// processes. Add case statements for the additional process
// types once early sandbox startup is implemented for them.
case GeckoProcessType_Content:
// Content processes don't use GeckoChildProcessHost
// to configure sandboxing so hard code the sandbox type.
@ -1448,9 +1443,6 @@ bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
case GeckoProcessType_RDD:
sandboxType = RDDProcessHost::GetMacSandboxType();
break;
case GeckoProcessType_GMPlugin:
sandboxType = gmp::GMPProcessParent::GetMacSandboxType();
break;
default:
return true;
}

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

@ -140,7 +140,7 @@ class GeckoChildProcessHost : public ChildProcessHost {
// To allow filling a MacSandboxInfo from the child
// process without an instance of RDDProcessHost.
// Only needed for late-start sandbox enabling.
static bool StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
static void StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
// Start the sandbox from the child process.
static bool StartMacSandbox(int aArgc, char** aArgv,
@ -215,12 +215,12 @@ class GeckoChildProcessHost : public ChildProcessHost {
virtual bool IsMacSandboxLaunchEnabled() { return false; }
// Fill a MacSandboxInfo to configure the sandbox
virtual bool FillMacSandboxInfo(MacSandboxInfo& aInfo);
virtual void FillMacSandboxInfo(MacSandboxInfo& aInfo);
// Adds the command line arguments needed to enable
// sandboxing of the child process at startup before
// the child event loop is up.
virtual bool AppendMacSandboxParams(StringVector& aArgs);
virtual void AppendMacSandboxParams(StringVector& aArgs);
#endif
private:

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

@ -52,14 +52,6 @@
# include "WinUtils.h"
#endif
#if defined(XP_MACOSX)
# include "nsMacUtilsImpl.h"
#endif
#if !defined(XP_WIN)
# include "mozilla/SandboxSettings.h"
#endif
#define EXTENSION_SCHEME "moz-extension"
using mozilla::dom::Promise;
using mozilla::ipc::FileDescriptor;
@ -620,7 +612,7 @@ Result<bool, nsresult> ExtensionProtocolHandler::DevRepoContains(
// On the first invocation, set mDevRepo
if (!mAlreadyCheckedDevRepo) {
mAlreadyCheckedDevRepo = true;
MOZ_TRY(nsMacUtilsImpl::GetRepoDir(getter_AddRefs(mDevRepo)));
MOZ_TRY(mozilla::GetRepoDir(getter_AddRefs(mDevRepo)));
if (MOZ_LOG_TEST(gExtProtocolLog, LogLevel::Debug)) {
nsAutoCString repoPath;
Unused << mDevRepo->GetNativePath(repoPath);

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

@ -35,5 +35,4 @@ FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/netwerk/base',
'/xpcom/base',
]

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

@ -7,7 +7,6 @@
#include "mozISandboxSettings.h"
#include "mozilla/Components.h"
#include "mozilla/Omnijar.h"
#include "mozilla/Preferences.h"
#include "prenv.h"
@ -75,14 +74,6 @@ NS_IMETHODIMP SandboxSettings::GetEffectiveContentSandboxLevel(
return NS_OK;
}
#if !defined(XP_WIN)
bool IsDevelopmentBuild() {
nsCOMPtr<nsIFile> path = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
// If the path doesn't exist, we're a dev build.
return path == nullptr;
}
#endif /* !XP_WIN */
} // namespace mozilla
NS_IMPL_COMPONENT_FACTORY(mozISandboxSettings) {

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

@ -25,14 +25,5 @@ int ClampFlashSandboxLevel(const int aLevel);
bool StartOpenBSDSandbox(GeckoProcessType type);
#endif
#if !defined(XP_WIN)
// Returns whether or not the currently running build is an unpackaged
// developer build. This check is implemented by looking for omni.ja in the
// the obj/dist dir. We use this routine to detect when the build dir will
// use symlinks to the repo and object dir. On Windows, dev builds don't
// use symlinks.
bool IsDevelopmentBuild();
#endif /* !XP_WIN */
} // namespace mozilla
#endif // mozilla_SandboxPolicies_h

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

@ -36,7 +36,6 @@ typedef struct _MacSandboxInfo {
void AppendStartupParam(std::vector<std::string>& aParams) const;
void AppendLoggingParam(std::vector<std::string>& aParams) const;
void AppendAppPathParam(std::vector<std::string>& aParams) const;
void AppendPluginPathParam(std::vector<std::string>& aParams) const;
void AppendLevelParam(std::vector<std::string>& aParams) const;
void AppendAudioParam(std::vector<std::string>& aParams) const;
void AppendWindowServerParam(std::vector<std::string>& aParams) const;
@ -77,7 +76,6 @@ namespace mozilla {
bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage);
bool StartMacSandboxIfEnabled(MacSandboxType aSandboxType, int aArgc,
char** aArgv, std::string& aErrorMessage);
bool IsMacSandboxStarted();
#ifdef DEBUG
void AssertMacSandboxEnabled();
#endif /* DEBUG */

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

@ -33,7 +33,9 @@ extern "C" int sandbox_init(const char* profile, uint64_t flags, char** errorbuf
extern "C" int sandbox_init_with_parameters(const char* profile, uint64_t flags,
const char* const parameters[], char** errorbuf);
extern "C" void sandbox_free_error(char* errorbuf);
#ifdef DEBUG
extern "C" int sandbox_check(pid_t pid, const char* operation, int type, ...);
#endif
#define MAC_OS_X_VERSION_10_0_HEX 0x00001000
#define MAC_OS_X_VERSION_10_6_HEX 0x00001060
@ -149,11 +151,6 @@ void MacSandboxInfo::AppendAsParams(std::vector<std::string>& aParams) const {
break;
case MacSandboxType_Utility:
break;
case MacSandboxType_GMP:
this->AppendPluginPathParam(aParams);
this->AppendWindowServerParam(aParams);
this->AppendReadPathParams(aParams);
break;
default:
// Before supporting a new process type, add a case statement
// here to append any neccesary process-type-specific params.
@ -177,11 +174,6 @@ void MacSandboxInfo::AppendAppPathParam(std::vector<std::string>& aParams) const
aParams.push_back(this->appPath);
}
void MacSandboxInfo::AppendPluginPathParam(std::vector<std::string>& aParams) const {
aParams.push_back("-sbPluginPath");
aParams.push_back(this->pluginPath);
}
/* static */
void MacSandboxInfo::AppendFileAccessParam(std::vector<std::string>& aParams,
bool aHasFilePrivileges) {
@ -306,28 +298,14 @@ bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage) {
profile = const_cast<char*>(SandboxPolicyGMP);
params.push_back("SHOULD_LOG");
params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
params.push_back("PLUGIN_BINARY_PATH");
params.push_back(aInfo.pluginBinaryPath.c_str());
params.push_back("APP_PATH");
params.push_back(aInfo.appPath.c_str());
params.push_back("PLUGIN_PATH");
params.push_back(aInfo.pluginPath.c_str());
if (!aInfo.pluginBinaryPath.empty()) {
params.push_back("PLUGIN_BINARY_PATH");
params.push_back(aInfo.pluginBinaryPath.c_str());
}
params.push_back("APP_BINARY_PATH");
params.push_back(aInfo.appBinaryPath.c_str());
params.push_back("HAS_WINDOW_SERVER");
params.push_back(aInfo.hasWindowServer ? "TRUE" : "FALSE");
if (!aInfo.crashServerPort.empty()) {
params.push_back("CRASH_PORT");
params.push_back(aInfo.crashServerPort.c_str());
}
if (!aInfo.testingReadPath1.empty()) {
params.push_back("TESTING_READ_PATH1");
params.push_back(aInfo.testingReadPath1.c_str());
}
if (!aInfo.testingReadPath2.empty()) {
params.push_back("TESTING_READ_PATH2");
params.push_back(aInfo.testingReadPath2.c_str());
}
} else if (aInfo.type == MacSandboxType_Content) {
MOZ_ASSERT(aInfo.level >= 1);
if (aInfo.level >= 1) {
@ -455,7 +433,7 @@ bool GetContentSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
// Read access directories used in testing
int nTestingReadPaths = 0;
std::string testingReadPaths[MAX_CONTENT_TESTING_READ_PATHS] = {};
std::string testingReadPaths[MAX_TESTING_READ_PATHS] = {};
// Collect sandbox params from CLI arguments
for (int i = 0; i < aArgc; i++) {
@ -501,9 +479,7 @@ bool GetContentSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
}
if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
if (nTestingReadPaths >= MAX_CONTENT_TESTING_READ_PATHS) {
MOZ_CRASH("Too many content process -sbTestingReadPath arguments");
}
MOZ_ASSERT(nTestingReadPaths < MAX_TESTING_READ_PATHS);
testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
nTestingReadPaths++;
i++;
@ -595,77 +571,6 @@ bool GetUtilitySandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
return true;
}
bool GetPluginSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aInfo) {
// Ensure we find these paramaters in the command
// line arguments. Return false if any are missing.
bool foundAppPath = false;
bool foundPluginPath = false;
// Read access directories used in testing
int nTestingReadPaths = 0;
std::string testingReadPaths[MAX_GMP_TESTING_READ_PATHS] = {};
// Collect sandbox params from CLI arguments
for (int i = 0; i < aArgc; i++) {
if (strcmp(aArgv[i], "-sbLogging") == 0) {
aInfo.shouldLog = true;
continue;
}
if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
foundAppPath = true;
aInfo.appPath.assign(aArgv[i + 1]);
i++;
continue;
}
if ((strcmp(aArgv[i], "-sbPluginPath") == 0) && (i + 1 < aArgc)) {
foundPluginPath = true;
aInfo.pluginPath.assign(aArgv[i + 1]);
i++;
continue;
}
if (strcmp(aArgv[i], "-sbAllowWindowServer") == 0) {
aInfo.hasWindowServer = true;
continue;
}
if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
if (nTestingReadPaths >= MAX_GMP_TESTING_READ_PATHS) {
MOZ_CRASH("Too many GMP process -sbTestingReadPath arguments");
}
testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
nTestingReadPaths++;
i++;
continue;
}
// Handle crash server positional argument
if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
aInfo.crashServerPort.assign(aArgv[i]);
continue;
}
}
if (!foundPluginPath) {
fprintf(stderr, "GMP sandbox disabled due to "
"missing sandbox CLI plugin path parameter.\n");
return false;
}
if (!foundAppPath) {
fprintf(stderr, "GMP sandbox disabled due to "
"missing sandbox CLI app path parameter.\n");
return false;
}
aInfo.testingReadPath1 = testingReadPaths[0];
aInfo.testingReadPath2 = testingReadPaths[1];
return true;
}
/*
* Returns true if no errors were encountered or if early sandbox startup is
* not enabled for this process. Returns false if an error was encountered.
@ -706,11 +611,6 @@ bool StartMacSandboxIfEnabled(const MacSandboxType aSandboxType, int aArgc, char
return false;
}
break;
case MacSandboxType_GMP:
if (!GetPluginSandboxParamsFromArgs(aArgc, aArgv, info)) {
return false;
}
break;
default:
MOZ_RELEASE_ASSERT(false);
break;
@ -719,8 +619,6 @@ bool StartMacSandboxIfEnabled(const MacSandboxType aSandboxType, int aArgc, char
return StartMacSandbox(info, aErrorMessage);
}
bool IsMacSandboxStarted() { return sandbox_check(getpid(), NULL, 0) == 1; }
#ifdef DEBUG
// sandbox_check returns 1 if the specified process is sandboxed
void AssertMacSandboxEnabled() { MOZ_ASSERT(sandbox_check(getpid(), NULL, 0) == 1); }

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

@ -6,7 +6,7 @@
#ifndef mozilla_SandboxPolicyContent_h
#define mozilla_SandboxPolicyContent_h
#define MAX_CONTENT_TESTING_READ_PATHS 4
#define MAX_TESTING_READ_PATHS 4
namespace mozilla {

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

@ -6,21 +6,16 @@
#ifndef mozilla_SandboxPolicyGMP_h
#define mozilla_SandboxPolicyGMP_h
#define MAX_GMP_TESTING_READ_PATHS 2
namespace mozilla {
static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
(version 1)
(define should-log (param "SHOULD_LOG"))
(define app-path (param "APP_PATH"))
(define plugin-path (param "PLUGIN_PATH"))
(define plugin-binary-path (param "PLUGIN_BINARY_PATH"))
(define crashPort (param "CRASH_PORT"))
(define app-path (param "APP_PATH"))
(define app-binary-path (param "APP_BINARY_PATH"))
(define hasWindowServer (param "HAS_WINDOW_SERVER"))
(define testingReadPath1 (param "TESTING_READ_PATH1"))
(define testingReadPath2 (param "TESTING_READ_PATH2"))
(define (moz-deny feature)
(if (string=? should-log "TRUE")
@ -39,35 +34,18 @@ static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
(if (defined? 'file-map-executable)
(allow file-map-executable file-read*
(subpath "/System/Library")
(subpath "/usr/lib")
(subpath plugin-path)
(subpath "/System/Library/PrivateFrameworks")
(regex #"^/usr/lib/libstdc\+\+\.[^/]*dylib$")
(literal plugin-binary-path)
(literal app-binary-path)
(subpath app-path))
(allow file-read*
(subpath "/System/Library")
(subpath "/usr/lib")
(subpath plugin-path)
(subpath "/System/Library/PrivateFrameworks")
(regex #"^/usr/lib/libstdc\+\+\.[^/]*dylib$")
(literal plugin-binary-path)
(literal app-binary-path)
(subpath app-path)))
(if (defined? 'file-map-executable)
(begin
(when plugin-binary-path
(allow file-read* file-map-executable (subpath plugin-binary-path)))
(when testingReadPath1
(allow file-read* file-map-executable (subpath testingReadPath1)))
(when testingReadPath2
(allow file-read* file-map-executable (subpath testingReadPath2))))
(begin
(when plugin-binary-path
(allow file-read* (subpath plugin-binary-path)))
(when testingReadPath1
(allow file-read* (subpath testingReadPath1)))
(when testingReadPath2
(allow file-read* (subpath testingReadPath2)))))
(if (string? crashPort)
(allow mach-lookup (global-name crashPort)))
(allow signal (target self))
(allow sysctl-read)
(allow iokit-open (iokit-user-client-class "IOHIDParamUserClient"))
@ -75,7 +53,9 @@ static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
(literal "/etc")
(literal "/dev/random")
(literal "/dev/urandom")
(literal "/usr/share/icu/icudt51l.dat"))
(literal "/usr/share/icu/icudt51l.dat")
(subpath "/System/Library/Displays/Overrides")
(subpath "/System/Library/CoreServices/CoreTypes.bundle"))
(if (string=? hasWindowServer "TRUE")
(allow mach-lookup (global-name "com.apple.windowserver.active")))

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

@ -8,18 +8,15 @@
#include "base/command_line.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SandboxSettings.h"
#include "nsDirectoryServiceDefs.h"
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsIProperties.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "prenv.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <sys/sysctl.h>
NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils)
@ -32,11 +29,6 @@ StaticAutoPtr<nsCString> nsMacUtilsImpl::sCachedAppPath;
StaticMutex nsMacUtilsImpl::sCachedAppPathMutex;
#endif
// Info.plist key associated with the developer repo path
#define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
// Info.plist key associated with the developer repo object directory
#define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
// Initialize with Unknown until we've checked if TCSM is available to set
Atomic<nsMacUtilsImpl::TCSMStatus> nsMacUtilsImpl::sTCSMStatus(TCSM_Unknown);
@ -209,121 +201,12 @@ bool nsMacUtilsImpl::GetAppPath(nsCString& aAppPath) {
if (!sCachedAppPath) {
sCachedAppPath = new nsCString(aAppPath);
if (NS_IsMainThread()) {
nsMacUtilsImpl::ClearCachedAppPathOnShutdown();
} else {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"nsMacUtilsImpl::ClearCachedAppPathOnShutdown",
[] { nsMacUtilsImpl::ClearCachedAppPathOnShutdown(); }));
}
ClearOnShutdown(&sCachedAppPath);
}
return true;
}
nsresult nsMacUtilsImpl::ClearCachedAppPathOnShutdown() {
MOZ_ASSERT(NS_IsMainThread());
ClearOnShutdown(&sCachedAppPath);
return NS_OK;
}
/*
* Helper function to read a string value for a given key from the .app's
* Info.plist.
*/
static nsresult GetStringValueFromBundlePlist(const nsAString& aKey,
nsAutoCString& aValue) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle == nullptr) {
return NS_ERROR_FAILURE;
}
// Read this app's bundle Info.plist as a dictionary
CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(mainBundle);
if (bundleInfoDict == nullptr) {
return NS_ERROR_FAILURE;
}
nsAutoCString keyAutoCString = NS_ConvertUTF16toUTF8(aKey);
CFStringRef key = CFStringCreateWithCString(
kCFAllocatorDefault, keyAutoCString.get(), kCFStringEncodingUTF8);
if (key == nullptr) {
return NS_ERROR_FAILURE;
}
CFStringRef value = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, key);
CFRelease(key);
if (value == nullptr) {
return NS_ERROR_FAILURE;
}
CFIndex valueLength = CFStringGetLength(value);
if (valueLength == 0) {
return NS_ERROR_FAILURE;
}
const char* valueCString =
CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
if (valueCString) {
aValue.Assign(valueCString);
return NS_OK;
}
CFIndex maxLength =
CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
if (!CFStringGetCString(value, valueBuffer, maxLength,
kCFStringEncodingUTF8)) {
free(valueBuffer);
return NS_ERROR_FAILURE;
}
aValue.Assign(valueBuffer);
free(valueBuffer);
return NS_OK;
}
/*
* Helper function for reading a path string from the .app's Info.plist
* and returning a directory object for that path with symlinks resolved.
*/
static nsresult GetDirFromBundlePlist(const nsAString& aKey, nsIFile** aDir) {
nsresult rv;
nsAutoCString dirPath;
rv = GetStringValueFromBundlePlist(aKey, dirPath);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> dir;
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirPath), false,
getter_AddRefs(dir));
NS_ENSURE_SUCCESS(rv, rv);
rv = dir->Normalize();
NS_ENSURE_SUCCESS(rv, rv);
bool isDirectory = false;
rv = dir->IsDirectory(&isDirectory);
NS_ENSURE_SUCCESS(rv, rv);
if (!isDirectory) {
return NS_ERROR_FILE_NOT_DIRECTORY;
}
dir.swap(*aDir);
return NS_OK;
}
nsresult nsMacUtilsImpl::GetRepoDir(nsIFile** aRepoDir) {
MOZ_ASSERT(mozilla::IsDevelopmentBuild());
return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_REPO_KEY), aRepoDir);
}
nsresult nsMacUtilsImpl::GetObjDir(nsIFile** aObjDir) {
MOZ_ASSERT(mozilla::IsDevelopmentBuild());
return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
}
# if defined(DEBUG)
// If XPCOM_MEM_BLOAT_LOG or XPCOM_MEM_LEAK_LOG is set to a log file
// path, return the path to the parent directory (where sibling log

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

@ -25,14 +25,9 @@ class nsMacUtilsImpl final : public nsIMacUtils {
nsMacUtilsImpl() {}
// Return the repo directory and the repo object directory respectively.
// These should only be used on Mac developer builds to determine the path
// to the repo or object directory.
static nsresult GetRepoDir(nsIFile** aRepoDir);
static nsresult GetObjDir(nsIFile** aObjDir);
#if defined(MOZ_SANDBOX)
static bool GetAppPath(nsCString& aAppPath);
# ifdef DEBUG
static nsresult GetBloatLogDir(nsCString& aDirectoryPath);
static nsresult GetDirectoryPath(const char* aPath,
@ -58,8 +53,6 @@ class nsMacUtilsImpl final : public nsIMacUtils {
static StaticAutoPtr<nsCString> sCachedAppPath;
// For thread safe setting/checking of sCachedAppPath
static StaticMutex sCachedAppPathMutex;
// Utility method to call ClearOnShutdown() on the main thread
static nsresult ClearCachedAppPathOnShutdown();
#endif
enum TCSMStatus { TCSM_Unknown = 0, TCSM_Available, TCSM_Unavailable };