From b135ca07328bb61f3659b17416c70524ac8fcc18 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Thu, 1 Sep 2022 12:59:32 +0000 Subject: [PATCH] Bug 1780796 - Use one process per platform decoder module sandbox requirements r=alwu,nika,fluent-reviewers,flod Differential Revision: https://phabricator.services.mozilla.com/D152545 --- dom/base/ChromeUtils.cpp | 7 +- dom/chrome-webidl/ChromeUtils.webidl | 4 +- dom/ipc/ContentChild.cpp | 2 +- dom/media/ipc/RemoteDecodeUtils.cpp | 76 +++++++++++++++ dom/media/ipc/RemoteDecodeUtils.h | 28 ++++++ dom/media/ipc/RemoteDecoderChild.cpp | 14 +-- dom/media/ipc/RemoteDecoderManagerChild.cpp | 97 +++++++++++-------- dom/media/ipc/RemoteDecoderManagerChild.h | 8 +- dom/media/ipc/moz.build | 2 + dom/media/platforms/PDMFactory.cpp | 55 +++++++---- dom/media/platforms/PDMFactory.h | 1 + ipc/glue/BackgroundParentImpl.cpp | 30 +++--- ipc/glue/BackgroundParentImpl.h | 1 + ipc/glue/PBackground.ipdl | 4 +- ipc/glue/PUtilityAudioDecoder.ipdl | 3 +- ipc/glue/UtilityAudioDecoderChild.cpp | 24 +++-- ipc/glue/UtilityAudioDecoderChild.h | 25 ++++- ipc/glue/UtilityAudioDecoderParent.cpp | 23 ++++- ipc/glue/UtilityAudioDecoderParent.h | 7 +- ipc/glue/UtilityProcessHost.cpp | 2 +- ipc/glue/UtilityProcessImpl.cpp | 8 +- ipc/glue/UtilityProcessManager.cpp | 12 +-- ipc/glue/UtilityProcessManager.h | 4 +- ipc/glue/UtilityProcessSandboxing.h | 10 +- .../browser_utility_audioDecodeCrash.js | 37 ++++--- .../browser/browser_utility_multipleAudio.js | 16 +-- ipc/glue/test/browser/head.js | 75 +++++++++++--- .../test/browser/test_utility_audio_off.html | 19 +++- .../test/browser/test_utility_audio_on.html | 16 +-- .../common/test/SandboxTestingChild.cpp | 10 +- .../common/test/SandboxTestingChildTests.h | 7 +- security/sandbox/linux/Sandbox.cpp | 2 +- security/sandbox/mac/Sandbox.mm | 5 +- security/sandbox/mac/SandboxPolicyUtility.h | 5 +- .../win/src/sandboxbroker/sandboxBroker.cpp | 13 ++- .../aboutprocesses/content/aboutProcesses.js | 12 ++- .../aboutprocesses/tests/browser/head.js | 2 +- toolkit/components/processtools/ProcInfo.h | 4 +- .../en-US/toolkit/about/aboutProcesses.ftl | 7 +- 39 files changed, 498 insertions(+), 179 deletions(-) create mode 100644 dom/media/ipc/RemoteDecodeUtils.cpp create mode 100644 dom/media/ipc/RemoteDecodeUtils.h diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp index a0ea4b9b2712..035c905cc274 100644 --- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -1033,14 +1033,17 @@ static WebIDLUtilityActorName UtilityActorNameToWebIDL( mozilla::UtilityActorName aType) { // Max is the value of the last enum, not the length, so add one. static_assert(WebIDLUtilityActorNameValues::Count == - static_cast(UtilityActorName::AudioDecoder) + 1, + static_cast(UtilityActorName::AudioDecoder_WMF) + 1, "In order for this static cast to be okay, " "UtilityActorName must match UtilityActorName exactly"); // These must match the similar ones in ProcInfo.h and ChromeUtils.webidl switch (aType) { UTILITYACTORNAME_TO_WEBIDL_CASE(Unknown, Unknown); - UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder, AudioDecoder); + UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_Generic, AudioDecoder_Generic); + UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_AppleMedia, + AudioDecoder_AppleMedia); + UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_WMF, AudioDecoder_WMF); } MOZ_ASSERT(false, "Unhandled case in WebIDLUtilityActorName"); diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl index 72f0551be991..8d1b90dcb4fb 100644 --- a/dom/chrome-webidl/ChromeUtils.webidl +++ b/dom/chrome-webidl/ChromeUtils.webidl @@ -706,7 +706,9 @@ dictionary WindowInfoDictionary { */ enum WebIDLUtilityActorName { "unknown", - "audioDecoder", + "audioDecoder_Generic", + "audioDecoder_AppleMedia", + "audioDecoder_WMF", }; dictionary UtilityActorsDictionary { diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index f42544ea8901..b981142ba840 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -4906,7 +4906,7 @@ 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: + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: OpenBSDFindPledgeUnveilFilePath("pledge.utility-audioDecoder", pledgeFile); OpenBSDFindPledgeUnveilFilePath("unveil.utility-audioDecoder", diff --git a/dom/media/ipc/RemoteDecodeUtils.cpp b/dom/media/ipc/RemoteDecodeUtils.cpp new file mode 100644 index 000000000000..a9c86aff825e --- /dev/null +++ b/dom/media/ipc/RemoteDecodeUtils.cpp @@ -0,0 +1,76 @@ +/* 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 "RemoteDecodeUtils.h" +#include "mozilla/ipc/UtilityProcessChild.h" + +namespace mozilla { + +using SandboxingKind = ipc::SandboxingKind; + +SandboxingKind GetCurrentSandboxingKind() { + MOZ_ASSERT(XRE_IsUtilityProcess()); + return ipc::UtilityProcessChild::GetSingleton()->mSandbox; +} + +SandboxingKind GetSandboxingKindFromLocation(RemoteDecodeIn aLocation) { + switch (aLocation) { + case RemoteDecodeIn::UtilityProcess_Generic: + return SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC; +#ifdef MOZ_APPLEMEDIA + case RemoteDecodeIn::UtilityProcess_AppleMedia: + return SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA; + break; +#endif +#ifdef XP_WIN + case RemoteDecodeIn::UtilityProcess_WMF: + return SandboxingKind::UTILITY_AUDIO_DECODING_WMF; +#endif + default: + MOZ_ASSERT_UNREACHABLE("Unsupported RemoteDecodeIn"); + return SandboxingKind::COUNT; + } +} + +RemoteDecodeIn GetRemoteDecodeInFromKind(SandboxingKind aKind) { + switch (aKind) { + case SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: + return RemoteDecodeIn::UtilityProcess_Generic; +#ifdef MOZ_APPLEMEDIA + case SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA: + return RemoteDecodeIn::UtilityProcess_AppleMedia; +#endif +#ifdef XP_WIN + case SandboxingKind::UTILITY_AUDIO_DECODING_WMF: + return RemoteDecodeIn::UtilityProcess_WMF; +#endif + default: + MOZ_ASSERT_UNREACHABLE("Unsupported SandboxingKind"); + return RemoteDecodeIn::Unspecified; + } +} + +const char* RemoteDecodeInToStr(RemoteDecodeIn aLocation) { + switch (aLocation) { + case RemoteDecodeIn::RddProcess: + return "RDD"; + case RemoteDecodeIn::GpuProcess: + return "GPU"; + case RemoteDecodeIn::UtilityProcess_Generic: + return "Utility Generic"; +#ifdef MOZ_APPLEMEDIA + case RemoteDecodeIn::UtilityProcess_AppleMedia: + return "Utility AppleMedia"; +#endif +#ifdef XP_WIN + case RemoteDecodeIn::UtilityProcess_WMF: + return "Utility WMF"; +#endif + default: + MOZ_ASSERT_UNREACHABLE("Unsupported RemoteDecodeIn"); + return "Unknown"; + } +} + +} // namespace mozilla diff --git a/dom/media/ipc/RemoteDecodeUtils.h b/dom/media/ipc/RemoteDecodeUtils.h new file mode 100644 index 000000000000..30d656bf2bea --- /dev/null +++ b/dom/media/ipc/RemoteDecodeUtils.h @@ -0,0 +1,28 @@ +/* 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 DOM_MEDIA_IPC_REMOTEDECODEUTILS_H_ +#define DOM_MEDIA_IPC_REMOTEDECODEUTILS_H_ + +#include "mozilla/Logging.h" +#include "mozilla/RemoteDecoderManagerChild.h" +#include "mozilla/ipc/UtilityProcessSandboxing.h" + +namespace mozilla { + +inline LazyLogModule gRemoteDecodeLog{"RemoteDecode"}; + +// Return the sandboxing kind of the current utility process. Should only be +// called on the utility process. +ipc::SandboxingKind GetCurrentSandboxingKind(); + +ipc::SandboxingKind GetSandboxingKindFromLocation(RemoteDecodeIn aLocation); + +RemoteDecodeIn GetRemoteDecodeInFromKind(ipc::SandboxingKind aKind); + +const char* RemoteDecodeInToStr(RemoteDecodeIn aLocation); + +} // namespace mozilla + +#endif // DOM_MEDIA_IPC_REMOTEDECODEUTILS_H_ diff --git a/dom/media/ipc/RemoteDecoderChild.cpp b/dom/media/ipc/RemoteDecoderChild.cpp index a3b2f358cc61..d20856f66724 100644 --- a/dom/media/ipc/RemoteDecoderChild.cpp +++ b/dom/media/ipc/RemoteDecoderChild.cpp @@ -7,6 +7,8 @@ #include "RemoteDecoderManagerChild.h" +#include "mozilla/RemoteDecodeUtils.h" + namespace mozilla { RemoteDecoderChild::RemoteDecoderChild(RemoteDecodeIn aLocation) @@ -99,13 +101,11 @@ RefPtr RemoteDecoderChild::Init() { return; } const auto& initResponse = aResponse.get_InitCompletionIPDL(); - mDescription = - initResponse.decoderDescription() + - (GetManager()->Location() == RemoteDecodeIn::UtilityProcess - ? " (Utility remote)"_ns - : GetManager()->Location() == RemoteDecodeIn::RddProcess - ? " (RDD remote)"_ns - : " (GPU remote)"_ns); + mDescription = initResponse.decoderDescription(); + mDescription.Append(" ("); + mDescription.Append(RemoteDecodeInToStr(GetManager()->Location())); + mDescription.Append(" remote)"); + mIsHardwareAccelerated = initResponse.hardware(); mHardwareAcceleratedReason = initResponse.hardwareReason(); mConversion = initResponse.conversion(); diff --git a/dom/media/ipc/RemoteDecoderManagerChild.cpp b/dom/media/ipc/RemoteDecoderManagerChild.cpp index 6709dff5c3c8..c9c059dc688a 100644 --- a/dom/media/ipc/RemoteDecoderManagerChild.cpp +++ b/dom/media/ipc/RemoteDecoderManagerChild.cpp @@ -19,6 +19,7 @@ #include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/ipc/Endpoint.h" #include "mozilla/layers/ISurfaceAllocator.h" +#include "mozilla/ipc/UtilityAudioDecoderChild.h" #include "nsContentUtils.h" #include "nsIObserver.h" #include "mozilla/StaticPrefs_media.h" @@ -192,7 +193,9 @@ RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetSingleton( switch (aLocation) { case RemoteDecodeIn::GpuProcess: case RemoteDecodeIn::RddProcess: - case RemoteDecodeIn::UtilityProcess: + case RemoteDecodeIn::UtilityProcess_Generic: + case RemoteDecodeIn::UtilityProcess_AppleMedia: + case RemoteDecodeIn::UtilityProcess_WMF: return sRemoteDecoderManagerChildForProcesses[aLocation]; default: MOZ_CRASH("Unexpected RemoteDecode variant"); @@ -214,7 +217,9 @@ bool RemoteDecoderManagerChild::Supports( switch (aLocation) { case RemoteDecodeIn::GpuProcess: case RemoteDecodeIn::RddProcess: - case RemoteDecodeIn::UtilityProcess: { + case RemoteDecodeIn::UtilityProcess_AppleMedia: + case RemoteDecodeIn::UtilityProcess_Generic: + case RemoteDecodeIn::UtilityProcess_WMF: { StaticMutexAutoLock lock(sProcessSupportedMutex); supported = sProcessSupported[aLocation]; break; @@ -225,8 +230,10 @@ bool RemoteDecoderManagerChild::Supports( if (!supported) { // We haven't received the correct information yet from either the GPU or // the RDD process nor the Utility process. - if (aLocation == RemoteDecodeIn::UtilityProcess) { - LaunchUtilityProcessIfNeeded(); + if (aLocation == RemoteDecodeIn::UtilityProcess_Generic || + aLocation == RemoteDecodeIn::UtilityProcess_AppleMedia || + aLocation == RemoteDecodeIn::UtilityProcess_WMF) { + LaunchUtilityProcessIfNeeded(aLocation); } if (aLocation == RemoteDecodeIn::RddProcess) { // Ensure the RDD process got started. @@ -274,10 +281,13 @@ RemoteDecoderManagerChild::CreateAudioDecoder( __func__); } - bool useUtilityAudioDecoding = StaticPrefs::media_utility_process_enabled() && - aLocation == RemoteDecodeIn::UtilityProcess; + bool useUtilityAudioDecoding = + StaticPrefs::media_utility_process_enabled() && + (aLocation == RemoteDecodeIn::UtilityProcess_Generic || + aLocation == RemoteDecodeIn::UtilityProcess_AppleMedia || + aLocation == RemoteDecodeIn::UtilityProcess_WMF); RefPtr launchPromise = - useUtilityAudioDecoding ? LaunchUtilityProcessIfNeeded() + useUtilityAudioDecoding ? LaunchUtilityProcessIfNeeded(aLocation) : LaunchRDDProcessIfNeeded(); return launchPromise->Then( @@ -482,7 +492,8 @@ RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() { /* static */ RefPtr -RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded() { +RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded( + RemoteDecodeIn aLocation) { MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(), "Only supported from a content process."); @@ -494,7 +505,7 @@ RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded() { } StaticMutexAutoLock lock(sLaunchMutex); - auto& utilityLaunchPromise = sLaunchPromises[RemoteDecodeIn::UtilityProcess]; + auto& utilityLaunchPromise = sLaunchPromises[aLocation]; if (utilityLaunchPromise) { return utilityLaunchPromise; @@ -515,8 +526,9 @@ RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded() { // IPC connections between *this* content process and the Utility process. RefPtr p = InvokeAsync( - managerThread, __func__, []() -> RefPtr { - auto* rps = GetSingleton(RemoteDecodeIn::UtilityProcess); + managerThread, __func__, + [aLocation]() -> RefPtr { + auto* rps = GetSingleton(aLocation); if (rps && rps->CanSend()) { return GenericNonExclusivePromise::CreateAndResolve(true, __func__); } @@ -528,36 +540,37 @@ RemoteDecoderManagerChild::LaunchUtilityProcessIfNeeded() { __func__); } - return bgActor->SendEnsureUtilityProcessAndCreateBridge()->Then( - managerThread, __func__, - [](ipc::PBackgroundChild:: - EnsureUtilityProcessAndCreateBridgePromise:: - ResolveOrRejectValue&& aResult) - -> RefPtr { - nsCOMPtr managerThread = GetManagerThread(); - if (!managerThread || aResult.IsReject()) { - // The parent process died or we got shutdown - return GenericNonExclusivePromise::CreateAndReject( - NS_ERROR_FAILURE, __func__); - } - nsresult rv = Get<0>(aResult.ResolveValue()); - if (NS_FAILED(rv)) { - return GenericNonExclusivePromise::CreateAndReject(rv, - __func__); - } - OpenRemoteDecoderManagerChildForProcess( - Get<1>(std::move(aResult.ResolveValue())), - RemoteDecodeIn::UtilityProcess); - return GenericNonExclusivePromise::CreateAndResolve(true, - __func__); - }); + return bgActor->SendEnsureUtilityProcessAndCreateBridge(aLocation) + ->Then(managerThread, __func__, + [aLocation](ipc::PBackgroundChild:: + EnsureUtilityProcessAndCreateBridgePromise:: + ResolveOrRejectValue&& aResult) + -> RefPtr { + nsCOMPtr managerThread = + GetManagerThread(); + if (!managerThread || aResult.IsReject()) { + // The parent process died or we got shutdown + return GenericNonExclusivePromise::CreateAndReject( + NS_ERROR_FAILURE, __func__); + } + nsresult rv = Get<0>(aResult.ResolveValue()); + if (NS_FAILED(rv)) { + return GenericNonExclusivePromise::CreateAndReject( + rv, __func__); + } + OpenRemoteDecoderManagerChildForProcess( + Get<1>(std::move(aResult.ResolveValue())), aLocation); + return GenericNonExclusivePromise::CreateAndResolve( + true, __func__); + }); }); p = p->Then( GetCurrentSerialEventTarget(), __func__, - [](const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) { + [aLocation]( + const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) { StaticMutexAutoLock lock(sLaunchMutex); - sLaunchPromises[RemoteDecodeIn::UtilityProcess] = nullptr; + sLaunchPromises[aLocation] = nullptr; return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult, __func__); }); @@ -598,7 +611,9 @@ TrackSupportSet RemoteDecoderManagerChild::GetTrackSupport( #endif return s; } - case RemoteDecodeIn::UtilityProcess: + case RemoteDecodeIn::UtilityProcess_Generic: + case RemoteDecodeIn::UtilityProcess_AppleMedia: + case RemoteDecodeIn::UtilityProcess_WMF: return StaticPrefs::media_utility_process_enabled() ? TrackSupportSet{TrackSupport::Audio} : TrackSupportSet{TrackSupport::None}; @@ -647,7 +662,9 @@ RemoteDecoderManagerChild::RemoteDecoderManagerChild(RemoteDecodeIn aLocation) : mLocation(aLocation) { MOZ_ASSERT(mLocation == RemoteDecodeIn::GpuProcess || mLocation == RemoteDecodeIn::RddProcess || - mLocation == RemoteDecodeIn::UtilityProcess); + mLocation == RemoteDecodeIn::UtilityProcess_Generic || + mLocation == RemoteDecodeIn::UtilityProcess_AppleMedia || + mLocation == RemoteDecodeIn::UtilityProcess_WMF); } /* static */ @@ -809,7 +826,9 @@ void RemoteDecoderManagerChild::SetSupported( switch (aLocation) { case RemoteDecodeIn::GpuProcess: case RemoteDecodeIn::RddProcess: - case RemoteDecodeIn::UtilityProcess: { + case RemoteDecodeIn::UtilityProcess_AppleMedia: + case RemoteDecodeIn::UtilityProcess_Generic: + case RemoteDecodeIn::UtilityProcess_WMF: { StaticMutexAutoLock lock(sProcessSupportedMutex); sProcessSupported[aLocation] = Some(aSupported); break; diff --git a/dom/media/ipc/RemoteDecoderManagerChild.h b/dom/media/ipc/RemoteDecoderManagerChild.h index 435490c8e357..ecbc43973bcf 100644 --- a/dom/media/ipc/RemoteDecoderManagerChild.h +++ b/dom/media/ipc/RemoteDecoderManagerChild.h @@ -12,6 +12,7 @@ #include "mozilla/EnumTypeTraits.h" #include "mozilla/PRemoteDecoderManagerChild.h" #include "mozilla/layers/VideoBridgeUtils.h" +#include "mozilla/ipc/UtilityProcessSandboxing.h" namespace mozilla { @@ -22,7 +23,9 @@ enum class RemoteDecodeIn { Unspecified, RddProcess, GpuProcess, - UtilityProcess, + UtilityProcess_Generic, + UtilityProcess_AppleMedia, + UtilityProcess_WMF, SENTINEL, }; @@ -127,7 +130,8 @@ class RemoteDecoderManagerChild final static void OpenRemoteDecoderManagerChildForProcess( Endpoint&& aEndpoint, RemoteDecodeIn aLocation); - static RefPtr LaunchUtilityProcessIfNeeded(); + static RefPtr LaunchUtilityProcessIfNeeded( + RemoteDecodeIn aLocation); RefPtr mIPDLSelfRef; // The location for decoding, Rdd or Gpu process. diff --git a/dom/media/ipc/moz.build b/dom/media/ipc/moz.build index e638f904a80f..53424922f7f7 100644 --- a/dom/media/ipc/moz.build +++ b/dom/media/ipc/moz.build @@ -26,6 +26,7 @@ EXPORTS.mozilla += [ "RemoteDecoderManagerParent.h", "RemoteDecoderModule.h", "RemoteDecoderParent.h", + "RemoteDecodeUtils.h", "RemoteImageHolder.h", "RemoteMediaData.h", "RemoteMediaDataDecoder.h", @@ -48,6 +49,7 @@ SOURCES += [ "RemoteDecoderManagerParent.cpp", "RemoteDecoderModule.cpp", "RemoteDecoderParent.cpp", + "RemoteDecodeUtils.cpp", "RemoteImageHolder.cpp", "RemoteMediaData.cpp", "RemoteMediaDataDecoder.cpp", diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 0f3fad38d864..94ea88b965e8 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -36,6 +36,8 @@ #include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart #include "nsPrintfCString.h" +#include "mozilla/ipc/UtilityAudioDecoderParent.h" + #ifdef XP_WIN # include "WMFDecoderModule.h" # include "mozilla/WindowsVersion.h" @@ -562,38 +564,44 @@ void PDMFactory::CreateRddPDMs() { } void PDMFactory::CreateUtilityPDMs() { + const ipc::SandboxingKind aKind = + ipc::UtilityAudioDecoderParent::GetSandboxingKind(); #ifdef XP_WIN if (StaticPrefs::media_wmf_enabled() && - StaticPrefs::media_utility_wmf_enabled()) { + StaticPrefs::media_utility_wmf_enabled() && + aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { CreateAndStartupPDM(); } #endif #ifdef MOZ_APPLEMEDIA - if (StaticPrefs::media_utility_applemedia_enabled()) { + if (StaticPrefs::media_utility_applemedia_enabled() && + aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA) { CreateAndStartupPDM(); } #endif + if (aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC) { #ifdef MOZ_FFVPX - if (StaticPrefs::media_ffvpx_enabled() && - StaticPrefs::media_utility_ffvpx_enabled()) { - CreateAndStartupPDM(); - } + if (StaticPrefs::media_ffvpx_enabled() && + StaticPrefs::media_utility_ffvpx_enabled()) { + CreateAndStartupPDM(); + } #endif #ifdef MOZ_FFMPEG - if (StaticPrefs::media_ffmpeg_enabled() && - StaticPrefs::media_utility_ffmpeg_enabled() && - !CreateAndStartupPDM()) { - mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( - FFmpegRuntimeLinker::LinkStatusCode()); - } + if (StaticPrefs::media_ffmpeg_enabled() && + StaticPrefs::media_utility_ffmpeg_enabled() && + !CreateAndStartupPDM()) { + mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( + FFmpegRuntimeLinker::LinkStatusCode()); + } #endif #ifdef MOZ_WIDGET_ANDROID - if (StaticPrefs::media_utility_android_media_codec_enabled()) { - StartupPDM(AndroidDecoderModule::Create(), - StaticPrefs::media_android_media_codec_preferred()); - } + if (StaticPrefs::media_utility_android_media_codec_enabled()) { + StartupPDM(AndroidDecoderModule::Create(), + StaticPrefs::media_android_media_codec_preferred()); + } #endif - CreateAndStartupPDM(); + CreateAndStartupPDM(); + } } void PDMFactory::CreateContentPDMs() { @@ -606,7 +614,18 @@ void PDMFactory::CreateContentPDMs() { } if (StaticPrefs::media_utility_process_enabled()) { - CreateAndStartupPDM(RemoteDecodeIn::UtilityProcess); +#ifdef MOZ_APPLEMEDIA + CreateAndStartupPDM( + RemoteDecodeIn::UtilityProcess_AppleMedia); +#endif +#ifdef XP_WIN + CreateAndStartupPDM( + RemoteDecodeIn::UtilityProcess_WMF); +#endif + // WMF and AppleMedia should be created before Generic because the order + // affects what decoder module would be chose first. + CreateAndStartupPDM( + RemoteDecodeIn::UtilityProcess_Generic); } #ifdef XP_WIN diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h index 95b5df8a0938..c56c11c50654 100644 --- a/dom/media/platforms/PDMFactory.h +++ b/dom/media/platforms/PDMFactory.h @@ -14,6 +14,7 @@ # include "mozilla/EnumSet.h" # include "mozilla/MozPromise.h" # include "mozilla/RefPtr.h" +# include "mozilla/ipc/UtilityProcessSandboxing.h" # include "nsISupports.h" # include "nsStringFwd.h" # include "nsTArray.h" diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index d230a85b248c..d68cae35996a 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -13,6 +13,7 @@ #include "mozilla/Assertions.h" #include "mozilla/RDDProcessManager.h" #include "mozilla/ipc/UtilityProcessManager.h" +#include "mozilla/RemoteDecodeUtils.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/BackgroundSessionStorageServiceParent.h" #include "mozilla/dom/ClientManagerActors.h" @@ -1372,6 +1373,7 @@ BackgroundParentImpl::RecvEnsureRDDProcessAndCreateBridge( mozilla::ipc::IPCResult BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge( + const RemoteDecodeIn& aLocation, EnsureUtilityProcessAndCreateBridgeResolver&& aResolver) { base::ProcessId otherPid = OtherPid(); nsCOMPtr managerThread = GetCurrentSerialEventTarget(); @@ -1380,7 +1382,7 @@ BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge( } NS_DispatchToMainThread(NS_NewRunnableFunction( "BackgroundParentImpl::RecvEnsureUtilityProcessAndCreateBridge()", - [aResolver, managerThread, otherPid]() { + [aResolver, managerThread, otherPid, aLocation]() { RefPtr upm = UtilityProcessManager::GetSingleton(); using Type = Tuple())); } else { - upm->StartAudioDecoding(otherPid)->Then( - managerThread, __func__, - [resolver = std::move(aResolver)]( - mozilla::ipc::UtilityProcessManager::AudioDecodingPromise:: - ResolveOrRejectValue&& aValue) mutable { - if (aValue.IsReject()) { - resolver(Type(aValue.RejectValue(), - Endpoint())); - return; - } - resolver(Type(NS_OK, std::move(aValue.ResolveValue()))); - }); + SandboxingKind sbKind = GetSandboxingKindFromLocation(aLocation); + upm->StartAudioDecoding(otherPid, sbKind) + ->Then(managerThread, __func__, + [resolver = aResolver]( + mozilla::ipc::UtilityProcessManager:: + AudioDecodingPromise::ResolveOrRejectValue&& + aValue) mutable { + if (aValue.IsReject()) { + resolver(Type(aValue.RejectValue(), + Endpoint())); + return; + } + resolver(Type(NS_OK, std::move(aValue.ResolveValue()))); + }); } })); return IPC_OK(); diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 2bad806f128c..0303994852a9 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -386,6 +386,7 @@ class BackgroundParentImpl : public PBackgroundParent { EnsureRDDProcessAndCreateBridgeResolver&& aResolver) override; mozilla::ipc::IPCResult RecvEnsureUtilityProcessAndCreateBridge( + const RemoteDecodeIn& aLocation, EnsureUtilityProcessAndCreateBridgeResolver&& aResolver) override; bool DeallocPEndpointForReportParent( diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 0cc202897553..24c6ea3b6cf7 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -76,6 +76,8 @@ using mozilla::dom::cache::Namespace using class mozilla::dom::SSCacheCopy from "mozilla/dom/PBackgroundSessionStorageCache.h"; +using mozilla::RemoteDecodeIn from "mozilla/RemoteDecoderManagerChild.h"; + namespace mozilla { namespace ipc { @@ -297,7 +299,7 @@ parent: async EnsureRDDProcessAndCreateBridge() returns (nsresult rv, Endpoint aEndpoint); - async EnsureUtilityProcessAndCreateBridge() + async EnsureUtilityProcessAndCreateBridge(RemoteDecodeIn aLocation) returns (nsresult rv, Endpoint aEndpoint); async PWebSocketConnection(uint32_t aListenerId); diff --git a/ipc/glue/PUtilityAudioDecoder.ipdl b/ipc/glue/PUtilityAudioDecoder.ipdl index aeaf7b2b6b3e..740a2227ee16 100644 --- a/ipc/glue/PUtilityAudioDecoder.ipdl +++ b/ipc/glue/PUtilityAudioDecoder.ipdl @@ -6,6 +6,7 @@ include protocol PRemoteDecoderManager; using mozilla::media::MediaCodecsSupported from "MediaCodecsSupport.h"; +using mozilla::RemoteDecodeIn from "mozilla/RemoteDecoderManagerChild.h"; namespace mozilla { @@ -20,7 +21,7 @@ parent: Endpoint endpoint); child: - async UpdateMediaCodecsSupported(MediaCodecsSupported aSupported); + async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported); }; diff --git a/ipc/glue/UtilityAudioDecoderChild.cpp b/ipc/glue/UtilityAudioDecoderChild.cpp index f9b057606139..a8e1f98c3f10 100644 --- a/ipc/glue/UtilityAudioDecoderChild.cpp +++ b/ipc/glue/UtilityAudioDecoderChild.cpp @@ -6,20 +6,24 @@ #include "UtilityAudioDecoderChild.h" +#include "base/basictypes.h" #include "mozilla/AppShutdown.h" #include "mozilla/dom/ContentParent.h" namespace mozilla::ipc { -static StaticRefPtr sAudioDecoderChild; +static EnumeratedArray> + sAudioDecoderChilds; -UtilityAudioDecoderChild::UtilityAudioDecoderChild() { +UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind) + : mSandbox(aKind) { MOZ_ASSERT(NS_IsMainThread()); } void UtilityAudioDecoderChild::ActorDestroy(ActorDestroyReason aReason) { MOZ_ASSERT(NS_IsMainThread()); - sAudioDecoderChild = nullptr; + sAudioDecoderChilds[mSandbox] = nullptr; } void UtilityAudioDecoderChild::Bind( @@ -29,20 +33,22 @@ void UtilityAudioDecoderChild::Bind( } /* static */ -RefPtr UtilityAudioDecoderChild::GetSingleton() { +RefPtr UtilityAudioDecoderChild::GetSingleton( + SandboxingKind aKind) { MOZ_ASSERT(NS_IsMainThread()); bool shutdown = AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown); - if (!sAudioDecoderChild && !shutdown) { - sAudioDecoderChild = new UtilityAudioDecoderChild(); + if (!sAudioDecoderChilds[aKind] && !shutdown) { + sAudioDecoderChilds[aKind] = new UtilityAudioDecoderChild(aKind); } - return sAudioDecoderChild; + return sAudioDecoderChilds[aKind]; } mozilla::ipc::IPCResult UtilityAudioDecoderChild::RecvUpdateMediaCodecsSupported( + const RemoteDecodeIn& aLocation, const media::MediaCodecsSupported& aSupported) { - dom::ContentParent::BroadcastMediaCodecsSupportedUpdate( - RemoteDecodeIn::UtilityProcess, aSupported); + dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(aLocation, + aSupported); return IPC_OK(); } diff --git a/ipc/glue/UtilityAudioDecoderChild.h b/ipc/glue/UtilityAudioDecoderChild.h index a3cf97b076b6..3b5ebdc00db5 100644 --- a/ipc/glue/UtilityAudioDecoderChild.h +++ b/ipc/glue/UtilityAudioDecoderChild.h @@ -11,6 +11,7 @@ #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/UtilityProcessParent.h" +#include "mozilla/ipc/UtilityProcessSandboxing.h" #include "mozilla/ipc/PUtilityAudioDecoderChild.h" #include "PDMFactory.h" @@ -24,9 +25,25 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityAudioDecoderChild, override); mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported( + const RemoteDecodeIn& aLocation, const media::MediaCodecsSupported& aSupported); - UtilityActorName GetActorName() { return UtilityActorName::AudioDecoder; } + UtilityActorName GetActorName() { + switch (mSandbox) { + case UTILITY_AUDIO_DECODING_GENERIC: + return UtilityActorName::AudioDecoder_Generic; +#ifdef MOZ_APPLEMEDIA + case UTILITY_AUDIO_DECODING_APPLE_MEDIA: + return UtilityActorName::AudioDecoder_AppleMedia; +#endif +#ifdef XP_WIN + case UTILITY_AUDIO_DECODING_WMF: + return UtilityActorName::AudioDecoder_WMF; +#endif + default: + MOZ_CRASH("Unexpected mSandbox for GetActorName()"); + } + } nsresult BindToUtilityProcess(RefPtr aUtilityParent) { Endpoint utilityAudioDecoderChildEnd; @@ -54,11 +71,13 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild { void Bind(Endpoint&& aEndpoint); - static RefPtr GetSingleton(); + static RefPtr GetSingleton(SandboxingKind aKind); private: - UtilityAudioDecoderChild(); + explicit UtilityAudioDecoderChild(SandboxingKind aKind); ~UtilityAudioDecoderChild() = default; + + const SandboxingKind mSandbox; }; } // namespace mozilla::ipc diff --git a/ipc/glue/UtilityAudioDecoderParent.cpp b/ipc/glue/UtilityAudioDecoderParent.cpp index 6bae76ca932c..45adcd0f8406 100644 --- a/ipc/glue/UtilityAudioDecoderParent.cpp +++ b/ipc/glue/UtilityAudioDecoderParent.cpp @@ -25,6 +25,9 @@ # include "AndroidDecoderModule.h" #endif +#include "mozilla/ipc/UtilityProcessChild.h" +#include "mozilla/RemoteDecodeUtils.h" + namespace mozilla::ipc { UtilityAudioDecoderParent::UtilityAudioDecoderParent() { @@ -33,14 +36,18 @@ UtilityAudioDecoderParent::UtilityAudioDecoderParent() { } /* static */ -void UtilityAudioDecoderParent::PreloadForSandbox() { +void UtilityAudioDecoderParent::GenericPreloadForSandbox() { #if defined(MOZ_SANDBOX) && defined(OS_WIN) // Preload AV dlls so we can enable Binary Signature Policy // to restrict further dll loads. ::LoadLibraryW(L"mozavcodec.dll"); ::LoadLibraryW(L"mozavutil.dll"); +#endif // defined(MOZ_SANDBOX) && defined(OS_WIN) +} - // WMF +/* static */ +void UtilityAudioDecoderParent::WMFPreloadForSandbox() { +#if defined(MOZ_SANDBOX) && defined(OS_WIN) ::LoadLibraryW(L"mfplat.dll"); ::LoadLibraryW(L"mf.dll"); @@ -56,6 +63,15 @@ void UtilityAudioDecoderParent::PreloadForSandbox() { #endif // defined(MOZ_SANDBOX) && defined(OS_WIN) } +/* static */ +SandboxingKind UtilityAudioDecoderParent::GetSandboxingKind() { + RefPtr me = UtilityProcessChild::GetSingleton(); + if (!me) { + MOZ_CRASH("I cant find myself"); + } + return me->mSandbox; +} + void UtilityAudioDecoderParent::Start( Endpoint&& aEndpoint) { MOZ_ASSERT(NS_IsMainThread()); @@ -71,7 +87,8 @@ void UtilityAudioDecoderParent::Start( #endif auto supported = PDMFactory::Supported(); - Unused << SendUpdateMediaCodecsSupported(std::move(supported)); + Unused << SendUpdateMediaCodecsSupported( + GetRemoteDecodeInFromKind(GetSandboxingKind()), supported); } mozilla::ipc::IPCResult diff --git a/ipc/glue/UtilityAudioDecoderParent.h b/ipc/glue/UtilityAudioDecoderParent.h index d0831a5a3653..d8cb996f4eb2 100644 --- a/ipc/glue/UtilityAudioDecoderParent.h +++ b/ipc/glue/UtilityAudioDecoderParent.h @@ -12,6 +12,8 @@ #include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/PUtilityAudioDecoderParent.h" +#include "mozilla/ipc/UtilityProcessSandboxing.h" + #include "nsThreadManager.h" namespace mozilla::ipc { @@ -24,13 +26,16 @@ class UtilityAudioDecoderParent final : public PUtilityAudioDecoderParent { UtilityAudioDecoderParent(); - static void PreloadForSandbox(); + static void GenericPreloadForSandbox(); + static void WMFPreloadForSandbox(); void Start(Endpoint&& aEndpoint); mozilla::ipc::IPCResult RecvNewContentRemoteDecoderManager( Endpoint&& aEndpoint); + static SandboxingKind GetSandboxingKind(); + private: ~UtilityAudioDecoderParent() = default; }; diff --git a/ipc/glue/UtilityProcessHost.cpp b/ipc/glue/UtilityProcessHost.cpp index 82938583be27..b99860c21174 100644 --- a/ipc/glue/UtilityProcessHost.cpp +++ b/ipc/glue/UtilityProcessHost.cpp @@ -197,7 +197,7 @@ void UtilityProcessHost::InitAfterConnect(bool aSucceeded) { UniquePtr policy; switch (mSandbox) { case SandboxingKind::GENERIC_UTILITY: - case SandboxingKind::UTILITY_AUDIO_DECODING: // TODO: NEW POLICY? + case SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: policy = SandboxBrokerPolicyFactory::GetUtilityProcessPolicy( GetActor()->OtherPid()); break; diff --git a/ipc/glue/UtilityProcessImpl.cpp b/ipc/glue/UtilityProcessImpl.cpp index f50c4ded6b42..a99821e75132 100644 --- a/ipc/glue/UtilityProcessImpl.cpp +++ b/ipc/glue/UtilityProcessImpl.cpp @@ -38,8 +38,12 @@ 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::UTILITY_AUDIO_DECODING) { - UtilityAudioDecoderParent::PreloadForSandbox(); + if (*sandboxingKind == SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC) { + UtilityAudioDecoderParent::GenericPreloadForSandbox(); + } + + if (*sandboxingKind == SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { + UtilityAudioDecoderParent::WMFPreloadForSandbox(); } // Go for it diff --git a/ipc/glue/UtilityProcessManager.cpp b/ipc/glue/UtilityProcessManager.cpp index 12de8ef5d519..ee1f7134ebc4 100644 --- a/ipc/glue/UtilityProcessManager.cpp +++ b/ipc/glue/UtilityProcessManager.cpp @@ -263,18 +263,18 @@ RefPtr UtilityProcessManager::StartUtility( } RefPtr -UtilityProcessManager::StartAudioDecoding(base::ProcessId aOtherProcess) { +UtilityProcessManager::StartAudioDecoding(base::ProcessId aOtherProcess, + SandboxingKind aSandbox) { RefPtr self = this; RefPtr uadc = - UtilityAudioDecoderChild::GetSingleton(); + UtilityAudioDecoderChild::GetSingleton(aSandbox); MOZ_ASSERT(uadc, "Unable to get a singleton for UtilityAudioDecoderChild"); - return StartUtility(uadc, SandboxingKind::UTILITY_AUDIO_DECODING) + return StartUtility(uadc, aSandbox) ->Then( GetMainThreadSerialEventTarget(), __func__, - [self, uadc, aOtherProcess]() { + [self, uadc, aOtherProcess, aSandbox]() { base::ProcessId process = - self->GetProcessParent(SandboxingKind::UTILITY_AUDIO_DECODING) - ->OtherPid(); + self->GetProcessParent(aSandbox)->OtherPid(); if (!uadc->CanSend()) { MOZ_ASSERT(false, "UtilityAudioDecoderChild lost in the middle"); diff --git a/ipc/glue/UtilityProcessManager.h b/ipc/glue/UtilityProcessManager.h index 6767dacb0439..bebb62954dd0 100644 --- a/ipc/glue/UtilityProcessManager.h +++ b/ipc/glue/UtilityProcessManager.h @@ -46,8 +46,8 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener { RefPtr StartUtility(RefPtr aActor, SandboxingKind aSandbox); - RefPtr StartAudioDecoding( - base::ProcessId aOtherProcess); + RefPtr StartAudioDecoding(base::ProcessId aOtherProcess, + SandboxingKind aSandbox); void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost); diff --git a/ipc/glue/UtilityProcessSandboxing.h b/ipc/glue/UtilityProcessSandboxing.h index 6b5f02f37cc5..a83305c8187a 100644 --- a/ipc/glue/UtilityProcessSandboxing.h +++ b/ipc/glue/UtilityProcessSandboxing.h @@ -16,9 +16,15 @@ namespace ipc { // to be updated as well. enum SandboxingKind : uint64_t { - GENERIC_UTILITY, + GENERIC_UTILITY = 0, - UTILITY_AUDIO_DECODING, + UTILITY_AUDIO_DECODING_GENERIC = 1, +#ifdef MOZ_APPLEMEDIA + UTILITY_AUDIO_DECODING_APPLE_MEDIA = 2, +#endif +#ifdef XP_WIN + UTILITY_AUDIO_DECODING_WMF = 3, +#endif COUNT, diff --git a/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js b/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js index 9b8a5322662d..0e4889b3401a 100644 --- a/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js +++ b/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js @@ -3,22 +3,25 @@ "use strict"; -async function getAudioDecoderPid() { +async function getAudioDecoderPid(expectation) { info("Finding a running AudioDecoder"); + + const actor = expectation.replace("Utility ", ""); + let audioDecoderProcess = (await ChromeUtils.requestProcInfo()).children.find( p => p.type === "utility" && - p.utilityActors.find(a => a.actorName === "audioDecoder") + p.utilityActors.find(a => a.actorName === `audioDecoder_${actor}`) ); ok( audioDecoderProcess, - `Found the AudioDecoder process at ${audioDecoderProcess.pid}` + `Found the AudioDecoder ${actor} process at ${audioDecoderProcess.pid}` ); return audioDecoderProcess.pid; } -async function crashDecoder() { - const audioPid = await getAudioDecoderPid(); +async function crashDecoder(expectation) { + const audioPid = await getAudioDecoderPid(expectation); ok(audioPid > 0, `Found an audio decoder ${audioPid}`); const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService( @@ -27,15 +30,15 @@ async function crashDecoder() { ProcessTools.kill(audioPid); } -async function runTest(src, withClose) { +async function runTest(src, withClose, expectation) { info(`Add media tabs: ${src}`); let tab = await addMediaTab(src); info("Play tab"); - await play(tab, true /* expectUtility */); + await play(tab, expectation); info("Crash decoder"); - await crashDecoder(); + await crashDecoder(expectation); if (withClose) { info("Stop tab"); @@ -49,7 +52,7 @@ async function runTest(src, withClose) { } info("Play tab again"); - await play(tab, true); + await play(tab, expectation); info("Stop tab"); await stop(tab); @@ -69,13 +72,15 @@ async function testAudioCrash(withClose) { SimpleTest.expectChildProcessCrash(); - for (let src of [ - "small-shot.ogg", - "small-shot.mp3", - "small-shot.m4a", - "small-shot.flac", - ]) { - await runTest(src, withClose); + const platform = Services.appinfo.OS; + + for (let { src, expectations } of audioTestData()) { + if (!(platform in expectations)) { + info(`Skipping ${src} for ${platform}`); + continue; + } + + await runTest(src, withClose, expectations[platform]); } } diff --git a/ipc/glue/test/browser/browser_utility_multipleAudio.js b/ipc/glue/test/browser/browser_utility_multipleAudio.js index 81342e9d49b0..f109b7d8c421 100644 --- a/ipc/glue/test/browser/browser_utility_multipleAudio.js +++ b/ipc/glue/test/browser/browser_utility_multipleAudio.js @@ -16,19 +16,21 @@ async function runTest(expectUtility) { }); } - for (let src of [ - "small-shot.ogg", - "small-shot.mp3", - "small-shot.m4a", - "small-shot.flac", - ]) { + const platform = Services.appinfo.OS; + + for (let { src, expectations } of audioTestData()) { + if (!(platform in expectations)) { + info(`Skipping ${src} for ${platform}`); + continue; + } + info(`Add media tabs: ${src}`); let tabs = [await addMediaTab(src), await addMediaTab(src)]; let playback = []; info("Play tabs"); for (let tab of tabs) { - playback.push(play(tab, expectUtility)); + playback.push(play(tab, expectUtility ? expectations[platform] : "RDD")); } info("Wait all playback"); diff --git a/ipc/glue/test/browser/head.js b/ipc/glue/test/browser/head.js index 140da6d2bd6d..ad6cf27d3396 100644 --- a/ipc/glue/test/browser/head.js +++ b/ipc/glue/test/browser/head.js @@ -40,6 +40,49 @@ async function cleanUtilityProcessShutdown(utilityPid) { ok(!subject.hasKey("dumpID"), "There should be no dumpID"); } +function audioTestData() { + return [ + { + src: "small-shot.ogg", + expectations: { + Android: "Utility Generic", + Linux: "Utility Generic", + WINNT: "Utility Generic", + Darwin: "Utility Generic", + }, + }, + { + src: "small-shot.mp3", + expectations: { + Android: "Utility Generic", + Linux: "Utility Generic", + WINNT: SpecialPowers.getBoolPref("media.ffvpx.mp3.enabled") + ? "Utility Generic" + : "Utility WMF", + Darwin: "Utility Generic", + }, + }, + { + src: "small-shot.m4a", + expectations: { + // Add Android after Bug 1771196 + Linux: "Utility Generic", + WINNT: "Utility WMF", + Darwin: "Utility AppleMedia", + }, + }, + { + src: "small-shot.flac", + expectations: { + Android: "Utility Generic", + Linux: "Utility Generic", + WINNT: "Utility Generic", + Darwin: "Utility Generic", + }, + }, + ]; +} + async function addMediaTab(src) { const tab = BrowserTestUtils.addTab(gBrowser, "about:blank", { forceNewProcess: true, @@ -50,11 +93,16 @@ async function addMediaTab(src) { return tab; } -async function play(tab, expectUtility, expectContent = false) { +async function play( + tab, + expectUtility, + expectContent = false, + expectJava = false +) { let browser = tab.linkedBrowser; return SpecialPowers.spawn( browser, - [expectUtility, expectContent], + [expectUtility, expectContent, expectJava], checkAudioDecoder ); } @@ -77,25 +125,28 @@ async function createAudioElement(src) { doc.body.appendChild(audio); } -async function checkAudioDecoder(expectUtility, expectContent = false) { +async function checkAudioDecoder( + expectedProcess, + expectContent = false, + expectJava = false +) { const doc = typeof content !== "undefined" ? content.document : document; let audio = doc.querySelector("audio"); const checkPromise = new Promise((resolve, reject) => { const timeUpdateHandler = async ev => { const debugInfo = await SpecialPowers.wrap(audio).mozRequestDebugInfo(); const audioDecoderName = debugInfo.decoder.reader.audioDecoderName; - const isUtility = audioDecoderName.indexOf("(Utility remote)") > 0; - const isRDD = audioDecoderName.indexOf("(RDD remote)") > 0; + const isExpected = + audioDecoderName.indexOf(`(${expectedProcess} remote)`) > 0; const isJavaRemote = audioDecoderName.indexOf("(remote)") > 0; - const isContent = !isUtility && !isRDD; const isOk = - (expectUtility === true && isUtility && !isJavaRemote) || - (expectUtility === false && isRDD && !isJavaRemote) || - (expectContent === true && isContent); + (isExpected && !isJavaRemote && !expectContent && !expectJava) || // Running in Utility/RDD + (expectJava && !isExpected && isJavaRemote) || // Running in Java remote + (expectContent && !isExpected && !isJavaRemote); // Running in Content ok( isOk, - `playback ${audio.src} was from expected decoder ${audioDecoderName}` + `playback ${audio.src} was from decoder '${audioDecoderName}', expected '${expectedProcess}'` ); if (isOk) { @@ -120,7 +171,7 @@ async function checkAudioDecoder(expectUtility, expectContent = false) { async function runMochitestUtilityAudio( src, - { expectUtility, expectContent = false } = {} + { expectUtility, expectContent = false, expectJava = false } = {} ) { info(`Add media: ${src}`); await createAudioElement(src); @@ -128,7 +179,7 @@ async function runMochitestUtilityAudio( ok(audio, "Found an audio element created"); info(`Play media: ${src}`); - await checkAudioDecoder(expectUtility, expectContent); + await checkAudioDecoder(expectUtility, expectContent, expectJava); info(`Pause media: ${src}`); await audio.pause(); diff --git a/ipc/glue/test/browser/test_utility_audio_off.html b/ipc/glue/test/browser/test_utility_audio_off.html index 2bcef568eaa4..7a5ad125255e 100644 --- a/ipc/glue/test/browser/test_utility_audio_off.html +++ b/ipc/glue/test/browser/test_utility_audio_off.html @@ -12,14 +12,25 @@ SimpleTest.waitForExplicitFinish(); (async function() { + const platform = SpecialPowers.Services.appinfo.OS; + for (let {src, expectations} of audioTestData()) { + if (!(platform in expectations)) { + info(`Skipping ${src} for ${platform}`); + continue; + } + + try { + await runMochitestUtilityAudio(src, { expectUtility: "", expectContent: true, expectJava: false }); + } catch (ex) { + ok(false, "Failure"); + } + } + for (let src of [ - "small-shot.ogg", - "small-shot.mp3", "small-shot.m4a", - "small-shot.flac", ]) { try { - await runMochitestUtilityAudio(src, { expectUtility: false, expectContent: true }); + await runMochitestUtilityAudio(src, { expectUtility: "", expectContent: false, expectJava: true }); } catch (ex) { ok(false, "Failure"); } diff --git a/ipc/glue/test/browser/test_utility_audio_on.html b/ipc/glue/test/browser/test_utility_audio_on.html index bff9d1b13896..b97394955708 100644 --- a/ipc/glue/test/browser/test_utility_audio_on.html +++ b/ipc/glue/test/browser/test_utility_audio_on.html @@ -12,13 +12,15 @@ SimpleTest.waitForExplicitFinish(); (async function() { - for (let src of [ - "small-shot.ogg", - "small-shot.mp3", - "small-shot.flac" - ]) { + const platform = SpecialPowers.Services.appinfo.OS; + for (let {src, expectations} of audioTestData()) { + if (!(platform in expectations)) { + info(`Skipping ${src} for ${platform}`); + continue; + } + try { - await runMochitestUtilityAudio(src, { expectUtility: true, expectContent: false }); + await runMochitestUtilityAudio(src, { expectUtility: expectations[platform], expectContent: false, expectJava: false }); } catch (ex) { ok(false, "Failure"); } @@ -29,7 +31,7 @@ SimpleTest.waitForExplicitFinish(); "small-shot.m4a", ]) { try { - await runMochitestUtilityAudio(src, { expectUtility: false, expectContent: true }); + await runMochitestUtilityAudio(src, { expectUtility: "", expectContent: false, expectJava: true }); } catch (ex) { ok(false, "Failure"); } diff --git a/security/sandbox/common/test/SandboxTestingChild.cpp b/security/sandbox/common/test/SandboxTestingChild.cpp index 351fed0669ea..507a66c3411e 100644 --- a/security/sandbox/common/test/SandboxTestingChild.cpp +++ b/security/sandbox/common/test/SandboxTestingChild.cpp @@ -89,8 +89,14 @@ void SandboxTestingChild::Bind(Endpoint&& aEndpoint) { RunTestsGenericUtility(this); break; - case ipc::SandboxingKind::UTILITY_AUDIO_DECODING: - RunTestsUtilityAudioDecoder(this); + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: +#ifdef MOZ_APPLEMEDIA + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA: +#endif +#ifdef XP_WIN + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF: +#endif + RunTestsUtilityAudioDecoder(this, s->mSandbox); break; default: diff --git a/security/sandbox/common/test/SandboxTestingChildTests.h b/security/sandbox/common/test/SandboxTestingChildTests.h index 8138019a38bc..267eb0d6bc40 100644 --- a/security/sandbox/common/test/SandboxTestingChildTests.h +++ b/security/sandbox/common/test/SandboxTestingChildTests.h @@ -764,7 +764,8 @@ void RunTestsGenericUtility(SandboxTestingChild* child) { #endif // XP_MACOSX } -void RunTestsUtilityAudioDecoder(SandboxTestingChild* child) { +void RunTestsUtilityAudioDecoder(SandboxTestingChild* child, + ipc::SandboxingKind aSandbox) { MOZ_ASSERT(child, "No SandboxTestingChild*?"); RunGenericTests(child); @@ -796,7 +797,9 @@ void RunTestsUtilityAudioDecoder(SandboxTestingChild* child) { # elif XP_MACOSX // XP_LINUX RunMacTestLaunchProcess(child); RunMacTestWindowServer(child); - RunMacTestAudioAPI(child, true); + RunMacTestAudioAPI( + child, + aSandbox == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA); # endif // XP_MACOSX #else // XP_UNIX # ifdef XP_WIN diff --git a/security/sandbox/linux/Sandbox.cpp b/security/sandbox/linux/Sandbox.cpp index 6611de216227..3c07377ee15c 100644 --- a/security/sandbox/linux/Sandbox.cpp +++ b/security/sandbox/linux/Sandbox.cpp @@ -754,7 +754,7 @@ void SetUtilitySandbox(int aBroker, ipc::SandboxingKind aKind) { policy = GetUtilitySandboxPolicy(sBroker); break; - case ipc::SandboxingKind::UTILITY_AUDIO_DECODING: + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: policy = GetUtilityAudioDecoderSandboxPolicy(sBroker); break; diff --git a/security/sandbox/mac/Sandbox.mm b/security/sandbox/mac/Sandbox.mm index 83060385987f..7526a8077b01 100644 --- a/security/sandbox/mac/Sandbox.mm +++ b/security/sandbox/mac/Sandbox.mm @@ -288,11 +288,12 @@ 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; - case ipc::SandboxingKind::UTILITY_AUDIO_DECODING: { - profile.append(SandboxPolicyUtilityAudioDecoderAddend); + case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA: { + profile.append(SandboxPolicyUtilityAudioDecoderAppleMediaAddend); params.push_back("MAC_OS_VERSION"); params.push_back(combinedVersion.c_str()); } break; diff --git a/security/sandbox/mac/SandboxPolicyUtility.h b/security/sandbox/mac/SandboxPolicyUtility.h index bca0d300df64..ec10175fda37 100644 --- a/security/sandbox/mac/SandboxPolicyUtility.h +++ b/security/sandbox/mac/SandboxPolicyUtility.h @@ -68,8 +68,9 @@ static const char SandboxPolicyUtility[] = R"SANDBOX_LITERAL( (global-name "com.apple.coreservices.launchservicesd")) )SANDBOX_LITERAL"; -static const char SandboxPolicyUtilityAudioDecoderAddend[] = R"SANDBOX_LITERAL( - ; For Utility AudioDecoder +static const char SandboxPolicyUtilityAudioDecoderAppleMediaAddend[] = + R"SANDBOX_LITERAL( + ; For Utility AudioDecoder AppleMedia codecs (define macosVersion (string->number (param "MAC_OS_VERSION"))) (if (>= macosVersion 1013) (allow mach-lookup diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp index 3e21cd5f6f18..13814db679c5 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -1273,7 +1273,7 @@ bool SandboxBroker::SetSecurityLevelForUtilityProcess( "SetJobLevel should never fail with these arguments, what happened?"); auto lockdownLevel = sandbox::USER_LOCKDOWN; - if (aSandbox == mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING) { + if (aSandbox == mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { lockdownLevel = sandbox::USER_LIMITED; } result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, @@ -1339,10 +1339,14 @@ bool SandboxBroker::SetSecurityLevelForUtilityProcess( // Investigate also why it crashes (no idea where exactly) for MinGW64 builds // // TODO: Bug 1773005 - AAC seems to not work on Windows < 1703 - if (IsWin10CreatorsUpdateOrLater()) { -#if defined(_M_X64) && !defined(__MINGW64__) + if (aSandbox != mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE; + } else { + if (IsWin10CreatorsUpdateOrLater()) { +#if defined(_M_X64) && !defined(__MINGW64__) + mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE; #endif // defined(_M_X64) && !defined(__MINGW64__) + } } if (exceptionModules.isNothing()) { @@ -1373,7 +1377,8 @@ bool SandboxBroker::SetSecurityLevelForUtilityProcess( switch (aSandbox) { case mozilla::ipc::SandboxingKind::GENERIC_UTILITY: - case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING: + case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_GENERIC: + case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF: // Nothing specific to perform yet? break; diff --git a/toolkit/components/aboutprocesses/content/aboutProcesses.js b/toolkit/components/aboutprocesses/content/aboutProcesses.js index fcae4ffc44ec..44fc8e8c2b54 100644 --- a/toolkit/components/aboutprocesses/content/aboutProcesses.js +++ b/toolkit/components/aboutprocesses/content/aboutProcesses.js @@ -864,8 +864,16 @@ var View = { let fluentName; let fluentArgs = {}; switch (data.actorName) { - case "audioDecoder": - fluentName = "about-processes-utility-actor-audio-decoder"; + case "audioDecoder_Generic": + fluentName = "about-processes-utility-actor-audio-decoder-generic"; + break; + + case "audioDecoder_AppleMedia": + fluentName = "about-processes-utility-actor-audio-decoder-applemedia"; + break; + + case "audioDecoder_WMF": + fluentName = "about-processes-utility-actor-audio-decoder-wmf"; break; default: diff --git a/toolkit/components/aboutprocesses/tests/browser/head.js b/toolkit/components/aboutprocesses/tests/browser/head.js index 896edc166821..50b70d21da81 100644 --- a/toolkit/components/aboutprocesses/tests/browser/head.js +++ b/toolkit/components/aboutprocesses/tests/browser/head.js @@ -609,7 +609,7 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) { row.classList.contains("process") && row.nextSibling && row.nextSibling.classList.contains("actor") && - row.nextSibling.actor.actorName === "audioDecoder", + row.nextSibling.actor.actorName === "audioDecoder_Generic", }, ]; for (let finder of processesToBeFound) { diff --git a/toolkit/components/processtools/ProcInfo.h b/toolkit/components/processtools/ProcInfo.h index 9f29f444354b..c427f20eeddb 100644 --- a/toolkit/components/processtools/ProcInfo.h +++ b/toolkit/components/processtools/ProcInfo.h @@ -70,7 +70,9 @@ enum class ProcType { enum class UtilityActorName { Unknown, - AudioDecoder, + AudioDecoder_Generic, + AudioDecoder_AppleMedia, + AudioDecoder_WMF }; /* Get the CPU frequency to use to convert cycle time values to actual time. diff --git a/toolkit/locales/en-US/toolkit/about/aboutProcesses.ftl b/toolkit/locales/en-US/toolkit/about/aboutProcesses.ftl index c9ffad6f473e..1df5b97e2ff5 100644 --- a/toolkit/locales/en-US/toolkit/about/aboutProcesses.ftl +++ b/toolkit/locales/en-US/toolkit/about/aboutProcesses.ftl @@ -122,9 +122,12 @@ about-processes-frame-name-one = Subframe: { $url } # $shortUrl (String) The shared prefix for the subframes in the group. about-processes-frame-name-many = Subframes ({ $number }): { $shortUrl } -# Utility process actor names +## Utility process actor names + about-processes-utility-actor-unknown = Unknown actor -about-processes-utility-actor-audio-decoder = Audio Decoder +about-processes-utility-actor-audio-decoder-generic = Generic Audio Decoder +about-processes-utility-actor-audio-decoder-applemedia = Apple Media Audio Decoder +about-processes-utility-actor-audio-decoder-wmf = Windows Media Framework Audio Decoder ## Displaying CPU (percentage and total) ## Variables: