Backed out 13 changesets (bug 1788596) for causing build bustage in toolkit/components/processtools/ProcInfo_common.cpp CLOSED TREE

Backed out changeset 620c85305800 (bug 1788596)
Backed out changeset 1f64776a859a (bug 1788596)
Backed out changeset 707e4c9c8801 (bug 1788596)
Backed out changeset 2221a97ebe97 (bug 1788596)
Backed out changeset d50fd0551159 (bug 1788596)
Backed out changeset 7e2ad8c47afb (bug 1788596)
Backed out changeset f87c5fb2c36f (bug 1788596)
Backed out changeset 61dd9a9eb714 (bug 1788596)
Backed out changeset a67c4ea1c8b3 (bug 1788596)
Backed out changeset 1be7af1214cf (bug 1788596)
Backed out changeset e99c7089bf93 (bug 1788596)
Backed out changeset 9a87f108548b (bug 1788596)
Backed out changeset 3dd59224f38b (bug 1788596)
This commit is contained in:
Sandor Molnar 2022-10-06 16:28:46 +03:00
parent 222834fe9a
commit 9e30e89e90
38 changed files with 178 additions and 416 deletions

View File

@ -4923,6 +4923,13 @@ bool StartOpenBSDSandbox(GeckoProcessType type, ipc::SandboxingKind kind) {
MOZ_RELEASE_ASSERT(kind <= SandboxingKind::COUNT,
"Should define a sandbox");
switch (kind) {
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
OpenBSDFindPledgeUnveilFilePath("pledge.utility-audioDecoder",
pledgeFile);
OpenBSDFindPledgeUnveilFilePath("unveil.utility-audioDecoder",
unveilFile);
break;
case ipc::SandboxingKind::GENERIC_UTILITY:
default:
OpenBSDFindPledgeUnveilFilePath("pledge.utility", pledgeFile);

View File

@ -17,7 +17,7 @@ SandboxingKind GetCurrentSandboxingKind() {
SandboxingKind GetSandboxingKindFromLocation(RemoteDecodeIn aLocation) {
switch (aLocation) {
case RemoteDecodeIn::UtilityProcess_Generic:
return SandboxingKind::GENERIC_UTILITY;
return SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC;
#ifdef MOZ_APPLEMEDIA
case RemoteDecodeIn::UtilityProcess_AppleMedia:
return SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA;
@ -39,7 +39,7 @@ SandboxingKind GetSandboxingKindFromLocation(RemoteDecodeIn aLocation) {
RemoteDecodeIn GetRemoteDecodeInFromKind(SandboxingKind aKind) {
switch (aKind) {
case SandboxingKind::GENERIC_UTILITY:
case SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
return RemoteDecodeIn::UtilityProcess_Generic;
#ifdef MOZ_APPLEMEDIA
case SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA:

View File

@ -574,7 +574,7 @@ void PDMFactory::CreateUtilityPDMs() {
CreateAndStartupPDM<AppleDecoderModule>();
}
#endif
if (aKind == ipc::SandboxingKind::GENERIC_UTILITY) {
if (aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC) {
#ifdef MOZ_FFVPX
if (StaticPrefs::media_ffvpx_enabled() &&
StaticPrefs::media_utility_ffvpx_enabled()) {

View File

@ -21,21 +21,6 @@
namespace mozilla::ipc {
NS_IMETHODIMP UtilityAudioDecoderChildShutdownObserver::Observe(
nsISupports* aSubject, const char* aTopic, const char16_t* aData) {
MOZ_ASSERT(strcmp(aTopic, "ipc:utility-shutdown") == 0);
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
if (observerService) {
observerService->RemoveObserver(this, "ipc:utility-shutdown");
}
UtilityAudioDecoderChild::Shutdown(mSandbox);
return NS_OK;
}
NS_IMPL_ISUPPORTS(UtilityAudioDecoderChildShutdownObserver, nsIObserver);
static EnumeratedArray<SandboxingKind, SandboxingKind::COUNT,
StaticRefPtr<UtilityAudioDecoderChild>>
sAudioDecoderChilds;
@ -48,21 +33,16 @@ UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind)
gfx::gfxVars::AddReceiver(this);
}
#endif
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
if (observerService) {
auto* obs = new UtilityAudioDecoderChildShutdownObserver(aKind);
observerService->AddObserver(obs, "ipc:utility-shutdown", false);
}
}
void UtilityAudioDecoderChild::ActorDestroy(ActorDestroyReason aReason) {
MOZ_ASSERT(NS_IsMainThread());
sAudioDecoderChilds[mSandbox] = nullptr;
#ifdef MOZ_WMF_MEDIA_ENGINE
if (mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM) {
gfx::gfxVars::RemoveReceiver(this);
}
#endif
Shutdown(mSandbox);
}
void UtilityAudioDecoderChild::Bind(
@ -71,11 +51,6 @@ void UtilityAudioDecoderChild::Bind(
MOZ_ASSERT(ok);
}
/* static */
void UtilityAudioDecoderChild::Shutdown(SandboxingKind aKind) {
sAudioDecoderChilds[aKind] = nullptr;
}
/* static */
RefPtr<UtilityAudioDecoderChild> UtilityAudioDecoderChild::GetSingleton(
SandboxingKind aKind) {

View File

@ -23,22 +23,6 @@
namespace mozilla::ipc {
class UtilityAudioDecoderChildShutdownObserver : public nsIObserver {
public:
explicit UtilityAudioDecoderChildShutdownObserver(SandboxingKind aKind)
: mSandbox(aKind){};
NS_DECL_ISUPPORTS
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) override;
private:
virtual ~UtilityAudioDecoderChildShutdownObserver() = default;
const SandboxingKind mSandbox;
};
// This controls performing audio decoding on the utility process and it is
// intended to live on the main process side
class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild
@ -56,7 +40,7 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild
UtilityActorName GetActorName() {
switch (mSandbox) {
case GENERIC_UTILITY:
case UTILITY_AUDIO_DECODING_GENERIC:
return UtilityActorName::AudioDecoder_Generic;
#ifdef MOZ_APPLEMEDIA
case UTILITY_AUDIO_DECODING_APPLE_MEDIA:
@ -101,8 +85,6 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild
void Bind(Endpoint<PUtilityAudioDecoderChild>&& aEndpoint);
static void Shutdown(SandboxingKind aKind);
static RefPtr<UtilityAudioDecoderChild> GetSingleton(SandboxingKind aKind);
#ifdef MOZ_WMF_MEDIA_ENGINE

View File

@ -46,10 +46,8 @@ UtilityAudioDecoderParent::UtilityAudioDecoderParent() {
return;
}
#endif
if (GetCurrentSandboxingKind() != SandboxingKind::GENERIC_UTILITY) {
nsDebugImpl::SetMultiprocessMode("Utility AudioDecoder");
profiler_set_process_name(nsCString("Utility AudioDecoder"));
}
nsDebugImpl::SetMultiprocessMode("Utility AudioDecoder");
profiler_set_process_name(nsCString("Utility AudioDecoder"));
}
/* static */

View File

@ -12,7 +12,6 @@
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/Preferences.h"
#include "mozilla/RemoteDecoderManagerParent.h"
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
# include "mozilla/Sandbox.h"
@ -37,25 +36,23 @@
#include "mozilla/FOGIPC.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/Services.h"
namespace mozilla::ipc {
using namespace layers;
static StaticMutex sUtilityProcessChildMutex;
static StaticRefPtr<UtilityProcessChild> sUtilityProcessChild
MOZ_GUARDED_BY(sUtilityProcessChildMutex);
static StaticRefPtr<UtilityProcessChild> sUtilityProcessChild;
UtilityProcessChild::UtilityProcessChild() {
nsDebugImpl::SetMultiprocessMode("Utility");
StaticMutexAutoLock lock(sUtilityProcessChildMutex);
sUtilityProcessChild = this;
}
UtilityProcessChild::~UtilityProcessChild() = default;
/* static */
RefPtr<UtilityProcessChild> UtilityProcessChild::GetSingleton() {
MOZ_ASSERT(XRE_IsUtilityProcess());
StaticMutexAutoLock lock(sUtilityProcessChildMutex);
if (!sUtilityProcessChild) {
sUtilityProcessChild = new UtilityProcessChild();
@ -110,13 +107,6 @@ bool UtilityProcessChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
// now resolve the pending promise of process startup
SendInitCompleted();
RunOnShutdown(
[] {
StaticMutexAutoLock lock(sUtilityProcessChildMutex);
sUtilityProcessChild = nullptr;
},
ShutdownPhase::XPCOMShutdownFinal);
return true;
}
@ -245,21 +235,12 @@ void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
mProfilerController = nullptr;
}
uint32_t timeout = 0;
if (mUtilityAudioDecoderInstance) {
mUtilityAudioDecoderInstance = nullptr;
timeout = 10 * 1000;
}
// Wait until all RemoteDecoderManagerParent have closed.
// It is still possible some may not have clean up yet, and we might hit
// timeout. Our xpcom-shutdown listener should take care of cleaning the
// reference of our singleton.
//
// FIXME: Should move from using AsyncBlockers to proper
// nsIAsyncShutdownService once it is not JS, see bug 1760855
mShutdownBlockers.WaitUntilClear(timeout)->Then(
GetCurrentSerialEventTarget(), __func__, [&]() {
mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/)
->Then(GetCurrentSerialEventTarget(), __func__, [&]() {
# ifdef XP_WIN
{
RefPtr<DllServices> dllSvc(DllServices::Get());
@ -267,6 +248,13 @@ void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
}
# endif // defined(XP_WIN)
{
StaticMutexAutoLock lock(sUtilityProcessChildMutex);
if (sUtilityProcessChild) {
sUtilityProcessChild = nullptr;
}
}
ipc::CrashReporterClient::DestroySingleton();
XRE_ShutdownChildProcess();
});

View File

@ -37,6 +37,10 @@ class UtilityProcessChild final : public PUtilityProcessChild {
mozilla::ipc::IPCResult RecvInitProfiler(
Endpoint<PProfilerChild>&& aEndpoint);
mozilla::ipc::IPCResult RecvNewContentRemoteDecoderManager(
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint,
const bool& aAllowHardwareDecoding);
mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref);
mozilla::ipc::IPCResult RecvRequestMemoryReport(

View File

@ -197,6 +197,7 @@ void UtilityProcessHost::InitAfterConnect(bool aSucceeded) {
UniquePtr<SandboxBroker::Policy> policy;
switch (mSandbox) {
case SandboxingKind::GENERIC_UTILITY:
case SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
policy = SandboxBrokerPolicyFactory::GetUtilityProcessPolicy(
GetActor()->OtherPid());
break;
@ -237,7 +238,7 @@ void UtilityProcessHost::Shutdown() {
mShutdownRequested = true;
// The channel might already be closed if we got here unexpectedly.
if (mUtilityProcessParent->CanSend()) {
if (!mChannelClosed) {
mUtilityProcessParent->Close();
}
@ -262,6 +263,7 @@ void UtilityProcessHost::Shutdown() {
void UtilityProcessHost::OnChannelClosed() {
MOZ_ASSERT(NS_IsMainThread());
mChannelClosed = true;
RejectPromise();
if (!mShutdownRequested && mListener) {

View File

@ -130,6 +130,7 @@ class UtilityProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
UniquePtr<ipc::SharedPreferenceSerializer> mPrefSerializer{};
bool mShutdownRequested = false;
bool mChannelClosed = false;
void RejectPromise();
void ResolvePromise();

View File

@ -38,8 +38,7 @@ bool UtilityProcessImpl::Init(int aArgc, char* aArgv[]) {
// lower the sandbox in processes where the policy will prevent loading.
::LoadLibraryW(L"winmm.dll");
if (*sandboxingKind == SandboxingKind::GENERIC_UTILITY) {
// Preload audio generic libraries required for ffmpeg only
if (*sandboxingKind == SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC) {
UtilityAudioDecoderParent::GenericPreloadForSandbox();
}

View File

@ -27,7 +27,7 @@ class UtilityProcessImpl final : public ipc::ProcessChild {
void CleanUp() override;
private:
RefPtr<UtilityProcessChild> mUtility = UtilityProcessChild::GetSingleton();
RefPtr<UtilityProcessChild> mUtility = new UtilityProcessChild();
#if defined(XP_WIN)
mozilla::mscom::ProcessRuntime mCOMRuntime;

View File

@ -266,7 +266,7 @@ RefPtr<UtilityProcessManager::StartRemoteDecodingUtilityPromise>
UtilityProcessManager::StartProcessForRemoteMediaDecoding(
base::ProcessId aOtherProcess, SandboxingKind aSandbox) {
// Not supported kinds.
if (aSandbox != SandboxingKind::GENERIC_UTILITY
if (aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC
#ifdef MOZ_APPLEMEDIA
&& aSandbox != SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
#endif
@ -410,6 +410,7 @@ void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
}
mObserver = nullptr;
sSingleton = nullptr;
}
RefPtr<ProcessFields> p = GetProcess(aSandbox);
@ -431,10 +432,6 @@ void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) {
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::UtilityProcessStatus, "Destroyed"_ns);
if (NoMoreProcesses()) {
sSingleton = nullptr;
}
}
Maybe<base::ProcessId> UtilityProcessManager::ProcessPid(

View File

@ -98,16 +98,6 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
}
}
Span<const UtilityActorName> GetActors(
const RefPtr<UtilityProcessParent>& aParent) {
for (auto& p : mProcesses) {
if (p && p->mProcessParent && p->mProcessParent == aParent) {
return p->mActors;
}
}
return {};
}
Span<const UtilityActorName> GetActors(GeckoChildProcessHost* aHost) {
for (auto& p : mProcesses) {
if (p && p->mProcess == aHost) {

View File

@ -76,20 +76,9 @@ void UtilityProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
if (mCrashReporter) {
#if defined(MOZ_SANDBOX)
RefPtr<mozilla::ipc::UtilityProcessManager> upm =
mozilla::ipc::UtilityProcessManager::GetSingleton();
if (upm) {
Span<const UtilityActorName> actors = upm->GetActors(this);
nsAutoCString actorsName;
if (!actors.IsEmpty()) {
actorsName += GetUtilityActorName(actors.First<1>()[0]);
for (const auto& actor : actors.From(1)) {
actorsName += ", "_ns + GetUtilityActorName(actor);
}
}
mCrashReporter->AddAnnotation(
CrashReporter::Annotation::UtilityActorsName, actorsName);
}
mCrashReporter->AddAnnotation(
CrashReporter::Annotation::UtilityProcessSandboxingKind,
(unsigned int)mHost->mSandbox);
#endif
}

View File

@ -16,16 +16,17 @@ namespace ipc {
// to be updated as well.
enum SandboxingKind : uint64_t {
GENERIC_UTILITY,
GENERIC_UTILITY = 0,
UTILITY_AUDIO_DECODING_GENERIC = 1,
#ifdef MOZ_APPLEMEDIA
UTILITY_AUDIO_DECODING_APPLE_MEDIA,
UTILITY_AUDIO_DECODING_APPLE_MEDIA = 2,
#endif
#ifdef XP_WIN
UTILITY_AUDIO_DECODING_WMF,
UTILITY_AUDIO_DECODING_WMF = 3,
#endif
#ifdef MOZ_WMF_MEDIA_ENGINE
MF_MEDIA_ENGINE_CDM,
MF_MEDIA_ENGINE_CDM = 4,
#endif
COUNT,

View File

@ -7,8 +7,6 @@ support-files =
../../../../dom/media/test/small-shot.mp3
../../../../dom/media/test/small-shot.m4a
../../../../dom/media/test/small-shot.flac
skip-if =
!crashreporter
[browser_utility_crashReporter.js]
skip-if =
!crashreporter

View File

@ -1,6 +0,0 @@
[DEFAULT]
support-files = head.js
[browser_utility_audio_shutdown.js]
support-files =
../../../../dom/media/test/small-shot.ogg

View File

@ -23,11 +23,11 @@ async function getAudioDecoderPid(expectation) {
async function crashDecoder(expectation) {
const audioPid = await getAudioDecoderPid(expectation);
ok(audioPid > 0, `Found an audio decoder ${audioPid}`);
const actorIsAudioDecoder = actorNames => {
return actorNames.startsWith("audio-decoder-");
};
info(`Crashing audio decoder ${audioPid}`);
await crashSomeUtility(audioPid, actorIsAudioDecoder);
const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
Ci.nsIProcessToolsService
);
ProcessTools.kill(audioPid);
}
async function runTest(src, withClose, expectation) {

View File

@ -1,76 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// The purpose of that test is to reproduce edge case behaviors that one can
// have while running whole ipc/glue/test/browser/ suite but that could this
// way be intermittent and hard to diagnose. By having such a test we make sure
// it is cleanly reproduced and wont regress somewhat silently.
"use strict";
async function runTest(src, expectation) {
info(`Add media tabs: ${src}`);
let tab = await addMediaTab(src);
info("Play tab");
await play(tab, expectation);
info("Stop tab");
await stop(tab);
info("Remove tab");
await BrowserTestUtils.removeTab(tab);
}
async function findGenericAudioDecoder() {
const audioDecoders = (await ChromeUtils.requestProcInfo()).children.filter(
p => {
return (
p.type === "utility" &&
p.utilityActors.find(a => a.actorName === "audioDecoder_Generic")
);
}
);
ok(audioDecoders.length === 1, "Only one audio decoder present");
return audioDecoders[0].pid;
}
add_setup(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [["media.utility-process.enabled", true]],
});
});
add_task(async function testKill() {
await runTest("small-shot.ogg", "Utility Generic");
const audioDecoderPid = await findGenericAudioDecoder();
ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`);
await cleanUtilityProcessShutdown(audioDecoderPid, /* preferKill */ true);
info("Waiting 15s to trigger mShutdownBlockers assertions");
await new Promise((resolve, reject) => {
/* eslint-disable mozilla/no-arbitrary-setTimeout */
setTimeout(resolve, 15 * 1000);
});
ok(true, "Waited 15s to trigger mShutdownBlockers assertions: over");
});
add_task(async function testShutdown() {
await runTest("small-shot.ogg", "Utility Generic");
const audioDecoderPid = await findGenericAudioDecoder();
ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`);
await cleanUtilityProcessShutdown(audioDecoderPid);
info("Waiting 15s to trigger mShutdownBlockers assertions");
await new Promise((resolve, reject) => {
/* eslint-disable mozilla/no-arbitrary-setTimeout */
setTimeout(resolve, 15 * 1000);
});
ok(true, "Waited 15s to trigger mShutdownBlockers assertions: over");
});

View File

@ -3,36 +3,70 @@
"use strict";
async function startAndCrashUtility(actors, actorsCheck) {
const utilityPid = await startUtilityProcess(actors);
await crashSomeUtility(utilityPid, actorsCheck);
}
add_task(async () => {
SimpleTest.expectChildProcessCrash();
const utilityPid = await startUtilityProcess();
// When running full suite, previous audio decoding tests might have left some
// running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() {
await killPendingUtilityProcess();
});
const crashMan = Services.crashmanager;
const utilityProcessGone = TestUtils.topicObserved("ipc:utility-shutdown");
add_task(async function utilityNoActor() {
await startAndCrashUtility(0, actorNames => {
return actorNames === undefined;
});
});
info("prune any previous crashes");
const future = new Date(Date.now() + 1000 * 60 * 60 * 24);
await crashMan.pruneOldCrashes(future);
add_task(async function utilityOneActor() {
await startAndCrashUtility(1, actorNames => {
return actorNames === kGenericUtilityActor;
});
});
info("crash Utility Process");
const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
Ci.nsIProcessToolsService
);
ProcessTools.crash(utilityPid);
add_task(async function utilityManyActors() {
await startAndCrashUtility(42, actorNames => {
return (
actorNames ===
Array(42)
.fill("unknown")
.join(", ")
info("Waiting for utility process to go away.");
let [subject, data] = await utilityProcessGone;
ok(
parseInt(data, 10) === utilityPid,
`Should match the crashed PID ${utilityPid} with ${data}`
);
ok(
subject instanceof Ci.nsIPropertyBag2,
"Subject needs to be a nsIPropertyBag2 to clean up properly"
);
const dumpID = subject.getPropertyAsAString("dumpID");
ok(dumpID, "There should be a dumpID");
await crashMan.ensureCrashIsPresent(dumpID);
await crashMan.getCrashes().then(crashes => {
is(crashes.length, 1, "There should be only one record");
const crash = crashes[0];
ok(
crash.isOfType(
crashMan.processTypes[Ci.nsIXULRuntime.PROCESS_TYPE_UTILITY],
crashMan.CRASH_TYPE_CRASH
),
"Record should be a utility process crash"
);
ok(crash.id === dumpID, "Record should have an ID");
ok(
parseInt(crash.metadata.UtilityProcessSandboxingKind, 10) ===
kGenericUtility,
"Record should have the sandboxing kind value"
);
});
let minidumpDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile);
minidumpDirectory.append("minidumps");
let dumpfile = minidumpDirectory.clone();
dumpfile.append(dumpID + ".dmp");
if (dumpfile.exists()) {
info(`Removal of ${dumpfile.path}`);
dumpfile.remove(false);
}
let extrafile = minidumpDirectory.clone();
extrafile.append(dumpID + ".extra");
info(`Removal of ${extrafile.path}`);
if (extrafile.exists()) {
extrafile.remove(false);
}
});

View File

@ -3,12 +3,6 @@
"use strict";
// When running full suite, previous audio decoding tests might have left some
// running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() {
await utilityProcessTest().stopProcess();
});
add_task(async () => {
const utilityPid = await startUtilityProcess();
@ -29,7 +23,7 @@ add_task(async () => {
aAmount,
aDescription
) {
const expectedProcess = `Utility (pid: ${utilityPid}, sandboxingKind: ${kGenericUtilitySandbox})`;
const expectedProcess = `Utility (pid: ${utilityPid}, sandboxingKind: ${kGenericUtility})`;
if (aProcess !== expectedProcess) {
return;
}

View File

@ -10,12 +10,6 @@ Services.scriptloader.loadSubScript(
this
);
// When running full suite, previous audio decoding tests might have left some
// running and this might interfere with our testing
add_setup(async function ensureNoExistingProcess() {
await killPendingUtilityProcess();
});
add_task(async () => {
const utilityPid = await startUtilityProcess();

View File

@ -9,15 +9,14 @@ const utilityProcessTest = () => {
);
};
const kGenericUtilitySandbox = 0;
const kGenericUtilityActor = "unknown";
const kGenericUtility = 0x0;
async function startUtilityProcess(actors) {
async function startUtilityProcess() {
info("Start a UtilityProcess");
return utilityProcessTest().startProcess(actors);
return utilityProcessTest().startProcess();
}
async function cleanUtilityProcessShutdown(utilityPid, preferKill = false) {
async function cleanUtilityProcessShutdown(utilityPid) {
info(`CleanShutdown Utility Process ${utilityPid}`);
ok(utilityPid !== undefined, "Utility needs to be defined");
@ -25,17 +24,7 @@ async function cleanUtilityProcessShutdown(utilityPid, preferKill = false) {
"ipc:utility-shutdown",
(subject, data) => parseInt(data, 10) === utilityPid
);
if (preferKill) {
SimpleTest.expectChildProcessCrash();
info(`Kill Utility Process ${utilityPid}`);
const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
Ci.nsIProcessToolsService
);
ProcessTools.kill(utilityPid);
} else {
await utilityProcessTest().stopProcess();
}
await utilityProcessTest().stopProcess();
let [subject, data] = await utilityProcessGone;
ok(
@ -51,25 +40,6 @@ async function cleanUtilityProcessShutdown(utilityPid, preferKill = false) {
ok(!subject.hasKey("dumpID"), "There should be no dumpID");
}
async function killPendingUtilityProcess() {
let audioDecoderProcesses = (
await ChromeUtils.requestProcInfo()
).children.filter(p => {
return (
p.type === "utility" &&
p.utilityActors.find(a => a.actorName.startsWith("audioDecoder_Generic"))
);
});
info(`audioDecoderProcesses=${JSON.stringify(audioDecoderProcesses)}`);
for (let audioDecoderProcess of audioDecoderProcesses) {
info(`Stopping audio decoder PID ${audioDecoderProcess.pid}`);
await cleanUtilityProcessShutdown(
audioDecoderProcess.pid,
/* preferKill */ true
);
}
}
function audioTestData() {
return [
{
@ -186,26 +156,16 @@ async function checkAudioDecoder(
}
};
const startPlaybackHandler = async ev => {
ok(
await audio.play().then(
_ => true,
_ => false
),
"audio started playing"
);
audio.addEventListener("timeupdate", timeUpdateHandler, { once: true });
};
audio.addEventListener("canplaythrough", startPlaybackHandler, {
once: true,
});
audio.addEventListener("timeupdate", timeUpdateHandler, { once: true });
});
// We need to make sure the decoder is ready before play()ing otherwise we
// could get into bad situations
audio.load();
ok(
await audio.play().then(
_ => true,
_ => false
),
"audio started playing"
);
return checkPromise;
}
@ -227,77 +187,3 @@ async function runMochitestUtilityAudio(
info(`Remove media: ${src}`);
document.body.removeChild(audio);
}
async function crashSomeUtility(utilityPid, actorsCheck) {
SimpleTest.expectChildProcessCrash();
const crashMan = Services.crashmanager;
const utilityProcessGone = TestUtils.topicObserved(
"ipc:utility-shutdown",
(subject, data) => {
info(`ipc:utility-shutdown: data=${data} subject=${subject}`);
return parseInt(data, 10) === utilityPid;
}
);
info("prune any previous crashes");
const future = new Date(Date.now() + 1000 * 60 * 60 * 24);
await crashMan.pruneOldCrashes(future);
info("crash Utility Process");
const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
Ci.nsIProcessToolsService
);
info(`Crash Utility Process ${utilityPid}`);
ProcessTools.crash(utilityPid);
info(`Waiting for utility process ${utilityPid} to go away.`);
let [subject, data] = await utilityProcessGone;
ok(
parseInt(data, 10) === utilityPid,
`Should match the crashed PID ${utilityPid} with ${data}`
);
ok(
subject instanceof Ci.nsIPropertyBag2,
"Subject needs to be a nsIPropertyBag2 to clean up properly"
);
const dumpID = subject.getPropertyAsAString("dumpID");
ok(dumpID, "There should be a dumpID");
await crashMan.ensureCrashIsPresent(dumpID);
await crashMan.getCrashes().then(crashes => {
is(crashes.length, 1, "There should be only one record");
const crash = crashes[0];
ok(
crash.isOfType(
crashMan.processTypes[Ci.nsIXULRuntime.PROCESS_TYPE_UTILITY],
crashMan.CRASH_TYPE_CRASH
),
"Record should be a utility process crash"
);
ok(crash.id === dumpID, "Record should have an ID");
ok(
actorsCheck(crash.metadata.UtilityActorsName),
`Record should have the correct actors name for: ${crash.metadata.UtilityActorsName}`
);
});
let minidumpDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile);
minidumpDirectory.append("minidumps");
let dumpfile = minidumpDirectory.clone();
dumpfile.append(dumpID + ".dmp");
if (dumpfile.exists()) {
info(`Removal of ${dumpfile.path}`);
dumpfile.remove(false);
}
let extrafile = minidumpDirectory.clone();
extrafile.append(dumpID + ".extra");
info(`Removal of ${extrafile.path}`);
if (extrafile.exists()) {
extrafile.remove(false);
}
}

View File

@ -4,5 +4,5 @@
# 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/.
BROWSER_CHROME_MANIFESTS += ["browser.ini", "browser_audio_shutdown.ini"]
BROWSER_CHROME_MANIFESTS += ["browser.ini"]
MOCHITEST_MANIFESTS += ["mochitest_audio_off.ini", "mochitest_audio_on.ini"]

View File

@ -8,12 +8,11 @@
# include "mozilla/ipc/UtilityProcessTest.h"
# include "mozilla/ipc/UtilityProcessManager.h"
# include "mozilla/dom/Promise.h"
# include "mozilla/ProcInfo.h"
namespace mozilla::ipc {
NS_IMETHODIMP
UtilityProcessTest::StartProcess(int32_t aUnknownActors, JSContext* aCx,
UtilityProcessTest::StartProcess(JSContext* aCx,
mozilla::dom::Promise** aOutPromise) {
NS_ENSURE_ARG(aOutPromise);
*aOutPromise = nullptr;
@ -35,18 +34,9 @@ UtilityProcessTest::StartProcess(int32_t aUnknownActors, JSContext* aCx,
utilityProc->LaunchProcess(SandboxingKind::GENERIC_UTILITY)
->Then(
GetCurrentSerialEventTarget(), __func__,
[promise, utilityProc, aUnknownActors]() {
[promise, utilityProc]() {
Maybe<int32_t> utilityPid =
utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY);
if (aUnknownActors > 0) {
RefPtr<UtilityProcessParent> utilityParent =
utilityProc->GetProcessParent(
SandboxingKind::GENERIC_UTILITY);
for (int32_t i = 0; i < aUnknownActors; i++) {
utilityProc->RegisterActor(utilityParent,
UtilityActorName::Unknown);
}
}
if (utilityPid.isSome()) {
promise->MaybeResolve(*utilityPid);
} else {

View File

@ -6,7 +6,7 @@
Classes = [
{
'cid': '{0a4478f4-c5ae-4fb1-8686-d5b09fb99afb}',
'cid': '{4505abd8-2718-44a0-96b6-6af66b07cc9f}',
'contract_ids': ['@mozilla.org/utility-process-test;1'],
'type': 'mozilla::ipc::UtilityProcessTest',
'headers': ['mozilla/ipc/UtilityProcessTest.h'],

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl"
[scriptable, uuid(0a4478f4-c5ae-4fb1-8686-d5b09fb99afb)]
[scriptable, uuid(4505abd8-2718-44a0-96b6-6af66b07cc9f)]
interface nsIUtilityProcessTest : nsISupports
{
/**
@ -14,7 +14,7 @@ interface nsIUtilityProcessTest : nsISupports
* Allowing to start Utility Process from JS code.
*/
[implicit_jscontext]
Promise startProcess([optional] in int32_t unknownActors);
Promise startProcess();
/**
* ** Test-only Method **

View File

@ -87,12 +87,13 @@ void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
switch (s->mSandbox) {
case ipc::SandboxingKind::GENERIC_UTILITY:
RunTestsGenericUtility(this);
break;
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
#ifdef MOZ_APPLEMEDIA
[[fallthrough]];
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA:
#endif
#ifdef XP_WIN
[[fallthrough]];
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
#endif
RunTestsUtilityAudioDecoder(this, s->mSandbox);

View File

@ -754,6 +754,10 @@ void SetUtilitySandbox(int aBroker, ipc::SandboxingKind aKind) {
policy = GetUtilitySandboxPolicy(sBroker);
break;
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
policy = GetUtilityAudioDecoderSandboxPolicy(sBroker);
break;
default:
MOZ_ASSERT(false, "Invalid SandboxingKind");
break;

View File

@ -2090,6 +2090,26 @@ class UtilitySandboxPolicy : public SandboxPolicyCommon {
case __NR_getrusage:
return Allow();
// Pass through the common policy.
default:
return SandboxPolicyCommon::EvaluateSyscall(sysno);
}
}
};
UniquePtr<sandbox::bpf_dsl::Policy> GetUtilitySandboxPolicy(
SandboxBrokerClient* aMaybeBroker) {
return UniquePtr<sandbox::bpf_dsl::Policy>(
new UtilitySandboxPolicy(aMaybeBroker));
}
class UtilityAudioDecoderSandboxPolicy final : public UtilitySandboxPolicy {
public:
explicit UtilityAudioDecoderSandboxPolicy(SandboxBrokerClient* aBroker)
: UtilitySandboxPolicy(aBroker) {}
ResultExpr EvaluateSyscall(int sysno) const override {
switch (sysno) {
// Required by FFmpeg
case __NR_get_mempolicy:
return Allow();
@ -2106,15 +2126,15 @@ class UtilitySandboxPolicy : public SandboxPolicyCommon {
// Pass through the common policy.
default:
return SandboxPolicyCommon::EvaluateSyscall(sysno);
return UtilitySandboxPolicy::EvaluateSyscall(sysno);
}
}
};
UniquePtr<sandbox::bpf_dsl::Policy> GetUtilitySandboxPolicy(
UniquePtr<sandbox::bpf_dsl::Policy> GetUtilityAudioDecoderSandboxPolicy(
SandboxBrokerClient* aMaybeBroker) {
return UniquePtr<sandbox::bpf_dsl::Policy>(
new UtilitySandboxPolicy(aMaybeBroker));
new UtilityAudioDecoderSandboxPolicy(aMaybeBroker));
}
} // namespace mozilla

View File

@ -41,6 +41,9 @@ UniquePtr<sandbox::bpf_dsl::Policy> GetSocketProcessSandboxPolicy(
UniquePtr<sandbox::bpf_dsl::Policy> GetUtilitySandboxPolicy(
SandboxBrokerClient* aMaybeBroker);
UniquePtr<sandbox::bpf_dsl::Policy> GetUtilityAudioDecoderSandboxPolicy(
SandboxBrokerClient* aMaybeBroker);
} // namespace mozilla
#endif

View File

@ -288,6 +288,7 @@ bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage) {
switch (aInfo.utilityKind) {
case ipc::SandboxingKind::GENERIC_UTILITY:
case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
// Nothing to do here specifically
break;

View File

@ -15,13 +15,16 @@ function test() {
// For UtilityProcess, allow constructing a string made of the process type
// and the sandbox variant we want to test, e.g.,
// utility:0 for GENERIC_UTILITY
// utility:1 for AppleMedia/WMF on macOS/Windows
var processTypes = ["tab", "socket", "rdd", "gmplugin", "utility:0", "gpu"];
const platform = SpecialPowers.Services.appinfo.OS;
if (platform === "WINNT" || platform === "Darwin") {
processTypes.push("utility:1");
}
// utility:1 for UTILITY_AUDIO_DECODER
var processTypes = [
"tab",
"socket",
"rdd",
"gmplugin",
"utility:0",
"utility:1",
"gpu",
];
// A callback called after each test-result.
let sandboxTestResult = (subject, topic, data) => {

View File

@ -1409,6 +1409,7 @@ bool SandboxBroker::SetSecurityLevelForUtilityProcess(
switch (aSandbox) {
case mozilla::ipc::SandboxingKind::GENERIC_UTILITY:
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC:
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
#if MOZ_WMF_MEDIA_ENGINE
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:

View File

@ -76,9 +76,6 @@ enum class UtilityActorName {
MfMediaEngineCDM,
};
// String that will be used e.g. to annotate crash reports
nsCString GetUtilityActorName(const UtilityActorName aActorName);
/* Get the CPU frequency to use to convert cycle time values to actual time.
* @returns the TSC (Time Stamp Counter) frequency in MHz, or 0 if converting
* cycle time values should not be attempted. */

View File

@ -41,19 +41,4 @@ RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
return promise;
}
nsCString GetUtilityActorName(const UtilityActorName aActorName) {
switch (aActorName) {
case UtilityActorName::Unknown:
return "unknown"_ns;
case UtilityActorName::AudioDecoder_Generic:
return "audio-decoder-generic"_ns;
case UtilityActorName::AudioDecoder_AppleMedia:
return "audio-decoder-applemedia"_ns;
case UtilityActorName::AudioDecoder_WMF:
return "audio-decoder-wmf"_ns;
case UtilityActorName::MfMediaEngineCDM:
return "mf-media-engine"_ns;
}
}
} // namespace mozilla

View File

@ -987,9 +987,9 @@ UtilityProcessStatus:
Status of the Utility process, can be set to "Running" or "Destroyed"
type: string
UtilityActorsName:
UtilityProcessSandboxingKind:
description: >
Comma-separated list of IPC actors name running on this Utility process instance
The SandboxingKind passed for this Utility process instance
type: integer
ping: true