diff options
Diffstat (limited to 'ipc/glue')
47 files changed, 396 insertions, 183 deletions
diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index 5bcfbd2838..f21f393e2c 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -138,9 +138,8 @@ void BackgroundChildImpl::ProcessingError(Result aCode, const char* aReason) { MOZ_CRASH("Unknown error code!"); } - nsDependentCString reason(aReason); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::ipc_channel_error, reason); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::ipc_channel_error, aReason); MOZ_CRASH_UNSAFE_PRINTF("%s: %s", abortMessage.get(), aReason); } diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index e9d0adbb94..6fcd344ddb 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -148,8 +148,8 @@ void BackgroundParentImpl::ProcessingError(Result aCode, const char* aReason) { GetIPCChannel()->InduceConnectionError(); } } else { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::ipc_channel_error, reason); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::ipc_channel_error, aReason); MOZ_CRASH("in-process BackgroundParent abort due to IPC error"); } @@ -191,26 +191,28 @@ bool BackgroundParentImpl::DeallocPBackgroundTestParent( } auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent( - const LoggingInfo& aLoggingInfo) + const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale) -> already_AddRefed<PBackgroundIDBFactoryParent> { using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent; AssertIsInMainProcess(); AssertIsOnBackgroundThread(); - return AllocPBackgroundIDBFactoryParent(aLoggingInfo); + return AllocPBackgroundIDBFactoryParent(aLoggingInfo, aSystemLocale); } mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor( - PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo) { + PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo, + const nsACString& aSystemLocale) { using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor; AssertIsInMainProcess(); AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); - if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo)) { + if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo, + aSystemLocale)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 42f40a1a2b..c36a8c83af 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -31,11 +31,12 @@ class BackgroundParentImpl : public PBackgroundParent { bool DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) override; already_AddRefed<PBackgroundIDBFactoryParent> - AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo) override; + AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo, + const nsACString& aSystemLocale) override; mozilla::ipc::IPCResult RecvPBackgroundIDBFactoryConstructor( - PBackgroundIDBFactoryParent* aActor, - const LoggingInfo& aLoggingInfo) override; + PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo, + const nsACString& aSystemLocale) override; PBackgroundIndexedDBUtilsParent* AllocPBackgroundIndexedDBUtilsParent() override; diff --git a/ipc/glue/CrashReporterHost.cpp b/ipc/glue/CrashReporterHost.cpp index d4f0c0f968..9fee9187a6 100644 --- a/ipc/glue/CrashReporterHost.cpp +++ b/ipc/glue/CrashReporterHost.cpp @@ -153,27 +153,26 @@ void CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType, getter_AddRefs(promise)); } -void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey, - bool aValue) { +void CrashReporterHost::AddAnnotationBool(CrashReporter::Annotation aKey, + bool aValue) { + MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::Boolean, + "Wrong annotation type"); mExtraAnnotations[aKey] = aValue ? "1"_ns : "0"_ns; } -void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey, - int aValue) { +void CrashReporterHost::AddAnnotationU32(CrashReporter::Annotation aKey, + uint32_t aValue) { + MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::U32, + "Wrong annotation type"); nsAutoCString valueString; valueString.AppendInt(aValue); mExtraAnnotations[aKey] = valueString; } -void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey, - unsigned int aValue) { - nsAutoCString valueString; - valueString.AppendInt(aValue); - mExtraAnnotations[aKey] = valueString; -} - -void CrashReporterHost::AddAnnotation(CrashReporter::Annotation aKey, - const nsACString& aValue) { +void CrashReporterHost::AddAnnotationNSCString(CrashReporter::Annotation aKey, + const nsACString& aValue) { + MOZ_ASSERT(TypeOfAnnotation(aKey) == CrashReporter::AnnotationType::String, + "Wrong annotation type"); mExtraAnnotations[aKey] = aValue; } diff --git a/ipc/glue/CrashReporterHost.h b/ipc/glue/CrashReporterHost.h index 7b71b64cdf..df0af17d43 100644 --- a/ipc/glue/CrashReporterHost.h +++ b/ipc/glue/CrashReporterHost.h @@ -84,10 +84,10 @@ class CrashReporterHost { return CrashReporter::GetIDFromMinidump(targetDump, mDumpID); } - void AddAnnotation(CrashReporter::Annotation aKey, bool aValue); - void AddAnnotation(CrashReporter::Annotation aKey, int aValue); - void AddAnnotation(CrashReporter::Annotation aKey, unsigned int aValue); - void AddAnnotation(CrashReporter::Annotation aKey, const nsACString& aValue); + void AddAnnotationBool(CrashReporter::Annotation aKey, bool aValue); + void AddAnnotationU32(CrashReporter::Annotation aKey, uint32_t aValue); + void AddAnnotationNSCString(CrashReporter::Annotation aKey, + const nsACString& aValue); bool HasMinidump() const { return !mDumpID.IsEmpty(); } const nsString& MinidumpID() const { diff --git a/ipc/glue/EnumSerializer.h b/ipc/glue/EnumSerializer.h index 13c1de3841..989e1127f5 100644 --- a/ipc/glue/EnumSerializer.h +++ b/ipc/glue/EnumSerializer.h @@ -65,12 +65,12 @@ struct EnumSerializer { static bool Read(MessageReader* aReader, paramType* aResult) { uintParamType value; if (!ReadParam(aReader, &value)) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"_ns); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCReadErrorReason, "Bad iter"); return false; } else if (!EnumValidator::IsLegalValue(value)) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"_ns); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCReadErrorReason, "Illegal value"); return false; } *aResult = paramType(value); diff --git a/ipc/glue/ForkServiceChild.cpp b/ipc/glue/ForkServiceChild.cpp index 65560dfaea..09d7c48457 100644 --- a/ipc/glue/ForkServiceChild.cpp +++ b/ipc/glue/ForkServiceChild.cpp @@ -3,11 +3,13 @@ /* 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 "ForkServiceChild.h" #include "ForkServer.h" -#include "mozilla/ipc/IPDLParamTraits.h" +#include "mozilla/Atomics.h" #include "mozilla/Logging.h" #include "mozilla/ipc/GeckoChildProcessHost.h" +#include "mozilla/ipc/IPDLParamTraits.h" #include "mozilla/ipc/ProtocolMessageUtils.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/Services.h" @@ -23,6 +25,7 @@ namespace ipc { extern LazyLogModule gForkServiceLog; mozilla::UniquePtr<ForkServiceChild> ForkServiceChild::sForkServiceChild; +Atomic<bool> ForkServiceChild::sForkServiceUsed; static bool ConfigurePipeFd(int aFd) { int flags = fcntl(aFd, F_GETFD, 0); @@ -55,6 +58,7 @@ void ForkServiceChild::StartForkServer() { return; } + sForkServiceUsed = true; sForkServiceChild = mozilla::MakeUnique<ForkServiceChild>(server.release(), subprocess); } diff --git a/ipc/glue/ForkServiceChild.h b/ipc/glue/ForkServiceChild.h index 73d090d556..9db3dc3828 100644 --- a/ipc/glue/ForkServiceChild.h +++ b/ipc/glue/ForkServiceChild.h @@ -74,6 +74,11 @@ class ForkServiceChild { return child == nullptr || child->mFailed ? nullptr : child; } + /** + * Returns whether the fork server was ever active. Thread-safe. + */ + static bool WasUsed() { return sForkServiceUsed; } + private: // Called when a message is received. void OnMessageReceived(UniquePtr<IPC::Message> message); @@ -81,6 +86,7 @@ class ForkServiceChild { UniquePtr<MiniTransceiver> mTcver; static UniquePtr<ForkServiceChild> sForkServiceChild; + static Atomic<bool> sForkServiceUsed; pid_t mRecvPid; bool mFailed; // The forkserver has crashed or disconnected. GeckoChildProcessHost* mProcess; diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index bde3a9a389..cd03b488ed 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -13,6 +13,7 @@ #include "base/task.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/process_watcher.h" +#include "mozilla/ProcessType.h" #ifdef MOZ_WIDGET_COCOA # include <bsm/libbsm.h> # include <mach/mach_traps.h> @@ -66,6 +67,7 @@ #ifdef XP_WIN # include <stdlib.h> +# include "mozilla/WindowsVersion.h" # include "nsIWinTaskbar.h" # define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" @@ -249,7 +251,7 @@ class BaseProcessLauncher { }; #ifdef XP_WIN -class WindowsProcessLauncher : public BaseProcessLauncher { +class WindowsProcessLauncher final : public BaseProcessLauncher { public: WindowsProcessLauncher(GeckoChildProcessHost* aHost, std::vector<std::string>&& aExtraOpts) @@ -261,8 +263,13 @@ class WindowsProcessLauncher : public BaseProcessLauncher { virtual RefPtr<ProcessHandlePromise> DoLaunch() override; virtual Result<Ok, LaunchError> DoFinishLaunch() override; + private: + void AddApplicationPrefetchArgument(); + mozilla::Maybe<CommandLine> mCmdLine; +# ifdef MOZ_SANDBOX bool mUseSandbox = false; +# endif const Buffer<IMAGE_THUNK_DATA>* mCachedNtdllThunk; }; @@ -343,7 +350,20 @@ class LinuxProcessLauncher : public PosixProcessLauncher { virtual Result<Ok, LaunchError> DoSetup() override; }; typedef LinuxProcessLauncher ProcessLauncher; -# elif +# elif defined(MOZ_WIDGET_UIKIT) +class IosProcessLauncher : public PosixProcessLauncher { + public: + IosProcessLauncher(GeckoChildProcessHost* aHost, + std::vector<std::string>&& aExtraOpts) + : PosixProcessLauncher(aHost, std::move(aExtraOpts)) {} + + protected: + virtual RefPtr<ProcessHandlePromise> DoLaunch() override { + MOZ_CRASH("IosProcessLauncher::DoLaunch not implemented"); + } +}; +typedef IosProcessLauncher ProcessLauncher; +# else # error "Unknown platform" # endif #endif // XP_UNIX @@ -1189,7 +1209,7 @@ Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() { } mLaunchOptions->env_map["LD_LIBRARY_PATH"] = new_ld_lib_path.get(); -# elif XP_DARWIN +# elif XP_MACOSX // With signed production Mac builds, the dynamic linker (dyld) will // ignore dyld environment variables preventing the use of variables // such as DYLD_LIBRARY_PATH and DYLD_INSERT_LIBRARIES. @@ -1212,7 +1232,7 @@ Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() { // Prevent connection attempts to diagnosticd(8) to save cycles. Log // messages can trigger these connection attempts, but access to // diagnosticd is blocked in sandboxed child processes. -# ifdef MOZ_SANDBOX +# if defined(MOZ_SANDBOX) && defined(XP_MACOSX) if (mDisableOSActivityMode) { mLaunchOptions->env_map["OS_ACTIVITY_MODE"] = "disable"; } @@ -1388,6 +1408,97 @@ Result<Ok, LaunchError> MacProcessLauncher::DoFinishLaunch() { #endif // XP_MACOSX #ifdef XP_WIN +void WindowsProcessLauncher::AddApplicationPrefetchArgument() { + // The Application Launch Prefetcher (ALPF) is an ill-documented Windows + // subsystem that's intended to speed up process launching, apparently mostly + // by assuming that a binary is going to want to load the same DLLs as it did + // the last time it launched, and getting those prepped for loading as well. + // + // For most applications, that's a good bet. For Firefox, it's less so, since + // we use the same binary with different arguments to do completely different + // things. Windows does allow applications to take up multiple slots in this + // cache, but the "which bucket does this invocation go in?" mechanism is + // highly unusual: the OS scans the command line and looks for a command-line + // switch of a particular form. + // + // (There is allegedly a way to do this without involving the command line, + // OVERRIDE_PREFETCH_PARAMETER, but it's even more poorly documented.) + + // Applications' different prefetch-cache buckets are named with numbers from + // "1" to some OS-version-determined limit, with an additional implicit "0" + // cache bucket which is used when no valid prefetch cache slot is named. + // + // (The "0" bucket's existence and behavior is not documented, but has been + // confirmed by observing the creation and enumeration of cache files in the + // C:\Windows\Prefetch folder.) + static size_t const kMaxSlotNo = IsWin1122H2OrLater() ? 16 : 8; + + // Determine the prefetch-slot number to be used for the process we're about + // to launch. + // + // This may be changed freely between Firefox versions, as a Firefox update + // will completely invalidate the prefetch cache anyway. + size_t const prefetchSlot = [&]() -> size_t { + switch (mProcessType) { + // This code path is not used when starting the main process... + case GeckoProcessType_Default: + // ...ForkServer is not used on Windows... + case GeckoProcessType_ForkServer: + // ..."End" isn't a process-type, just a limit... + case GeckoProcessType_End: + // ...and any new process-types should be considered explicitly here. + default: + MOZ_ASSERT_UNREACHABLE("Invalid process type"); + return 0; + + // We reserve 1 for the main process as started by the launcher process. + // (See LauncherProcessWin.cpp.) Otherwise, we mostly match the process- + // type enumeration. + case GeckoProcessType_Content: + return 2; + case GeckoProcessType_Socket: + return 3; // usurps IPDLUnitTest + case GeckoProcessType_GMPlugin: + return 4; + case GeckoProcessType_GPU: + return 5; + case GeckoProcessType_RemoteSandboxBroker: + return 6; // usurps VR + case GeckoProcessType_RDD: + return 7; + + case GeckoProcessType_Utility: { + // Continue the enumeration, using the SandboxingKind as a + // probably-passably-precise proxy for the process's purpose. + // + // (On Win10 and earlier, or when sandboxing is not used, this will lump + // all utility processes into slot 8.) +# ifndef MOZ_SANDBOX + size_t const val = 0; +# else + size_t const val = static_cast<size_t>(mSandbox); +# endif + return std::min(kMaxSlotNo, 8 + val); + } + + // These process types are started so rarely that we're not concerned + // about their interaction with the prefetch cache. Lump them together at + // the end (possibly alongside other process types). + case GeckoProcessType_IPDLUnitTest: + case GeckoProcessType_VR: + return kMaxSlotNo; + } + }(); + MOZ_ASSERT(prefetchSlot <= kMaxSlotNo); + + if (prefetchSlot == 0) { + // default; no explicit argument needed + return; + } + + mCmdLine->AppendLooseValue(StringPrintf(L"/prefetch:%zu", prefetchSlot)); +} + Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() { Result<Ok, LaunchError> aError = BaseProcessLauncher::DoSetup(); if (aError.isErr()) { @@ -1568,6 +1679,9 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() { // Process type mCmdLine->AppendLooseValue(UTF8ToWide(ChildProcessType())); + // Prefetch cache hint + AddApplicationPrefetchArgument(); + # ifdef MOZ_SANDBOX if (mUseSandbox) { // Mark the handles to inherit as inheritable. diff --git a/ipc/glue/IPCStreamUtils.cpp b/ipc/glue/IPCStreamUtils.cpp index b884bf5d5d..7d73cfeace 100644 --- a/ipc/glue/IPCStreamUtils.cpp +++ b/ipc/glue/IPCStreamUtils.cpp @@ -131,7 +131,7 @@ bool SerializeIPCStream(already_AddRefed<nsIInputStream> aInputStream, InputStreamHelper::SerializeInputStreamAsPipe(stream, aValue.stream()); if (aValue.stream().type() == InputStreamParams::T__None) { - MOZ_ASSERT_UNREACHABLE("Serializing as a pipe failed"); + // This can fail from OOM, etc. We will likely MOZ_CRASH now return false; } return true; diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp index a7fc135748..16eb897175 100644 --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -473,9 +473,8 @@ MessageChannel::~MessageChannel() { // would be unsafe to invoke our listener's callbacks, and we may be being // destroyed on a thread other than `mWorkerThread`. if (!IsClosedLocked()) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCFatalErrorProtocol, - nsDependentCString(mName)); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCFatalErrorProtocol, mName); switch (mChannelState) { case ChannelConnected: MOZ_CRASH( @@ -537,6 +536,12 @@ int32_t MessageChannel::CurrentNestedInsideSyncTransaction() const { return mTransactionStack->TransactionID(); } +bool MessageChannel::TestOnlyIsTransactionComplete() const { + AssertWorkerThread(); + MonitorAutoLock lock(*mMonitor); + return !mTransactionStack || mTransactionStack->IsComplete(); +} + bool MessageChannel::AwaitingSyncReply() const { mMonitor->AssertCurrentThreadOwns(); return mTransactionStack ? mTransactionStack->AwaitingSyncReply() : false; diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h index 67540b4ac8..a1a5bad916 100644 --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -292,6 +292,11 @@ class MessageChannel : HasResultCodes { void CancelCurrentTransaction() MOZ_EXCLUDES(*mMonitor); + // Return whether the current transaction is complete. + // + // This is intended only for tests. + bool TestOnlyIsTransactionComplete() const MOZ_EXCLUDES(*mMonitor); + // IsClosed and NumQueuedMessages are safe to call from any thread, but // may provide an out-of-date value. bool IsClosed() MOZ_EXCLUDES(*mMonitor) { diff --git a/ipc/glue/MessageLink.cpp b/ipc/glue/MessageLink.cpp index 5505322a2f..0937fde6bf 100644 --- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -98,12 +98,10 @@ void PortLink::SendMessage(UniquePtr<Message> aMessage) { mChan->mMonitor->AssertCurrentThreadOwns(); if (aMessage->size() > IPC::Channel::kMaximumMessageSize) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCMessageName, - nsDependentCString(aMessage->name())); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCMessageSize, - static_cast<unsigned int>(aMessage->size())); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCMessageName, aMessage->name()); + CrashReporter::RecordAnnotationU32( + CrashReporter::Annotation::IPCMessageSize, aMessage->size()); MOZ_CRASH("IPC message size is too large"); } aMessage->AssertAsLargeAsHeader(); diff --git a/ipc/glue/NodeChannel.cpp b/ipc/glue/NodeChannel.cpp index 70e67bc473..169aa91f9b 100644 --- a/ipc/glue/NodeChannel.cpp +++ b/ipc/glue/NodeChannel.cpp @@ -170,12 +170,10 @@ void NodeChannel::AcceptInvite(const NodeName& aRealName, void NodeChannel::SendMessage(UniquePtr<IPC::Message> aMessage) { if (aMessage->size() > IPC::Channel::kMaximumMessageSize) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCMessageName, - nsDependentCString(aMessage->name())); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCMessageSize, - static_cast<unsigned int>(aMessage->size())); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCMessageName, aMessage->name()); + CrashReporter::RecordAnnotationU32( + CrashReporter::Annotation::IPCMessageSize, aMessage->size()); MOZ_CRASH("IPC message size is too large"); } aMessage->AssertAsLargeAsHeader(); diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 94b0079ff7..d0fe4b1731 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -129,7 +129,8 @@ parent: // Only called at startup during mochitests to check the basic infrastructure. async PBackgroundTest(nsCString testArg); - async PBackgroundIDBFactory(LoggingInfo loggingInfo); + async PBackgroundIDBFactory(LoggingInfo loggingInfo, + nsCString systemLocale); async PBackgroundIndexedDBUtils(); diff --git a/ipc/glue/PUtilityAudioDecoder.ipdl b/ipc/glue/PUtilityAudioDecoder.ipdl index 74dbbd2c54..5b4b8711f2 100644 --- a/ipc/glue/PUtilityAudioDecoder.ipdl +++ b/ipc/glue/PUtilityAudioDecoder.ipdl @@ -30,7 +30,6 @@ parent: #ifdef MOZ_WMF_MEDIA_ENGINE async InitVideoBridge(Endpoint<PVideoBridgeChild> endpoint, - GfxVarUpdate[] updates, ContentDeviceData contentDeviceData); async UpdateVar(GfxVarUpdate var); diff --git a/ipc/glue/PUtilityProcess.ipdl b/ipc/glue/PUtilityProcess.ipdl index 585590799f..be8b439514 100644 --- a/ipc/glue/PUtilityProcess.ipdl +++ b/ipc/glue/PUtilityProcess.ipdl @@ -21,6 +21,8 @@ include protocol PSandboxTesting; include "mozilla/ipc/ByteBufUtils.h"; +include GraphicsMessages; + using mozilla::dom::NativeThreadId from "mozilla/dom/NativeThreadId.h"; // Telemetry @@ -98,7 +100,7 @@ child: async TestTelemetryProbes(); - async StartUtilityAudioDecoderService(Endpoint<PUtilityAudioDecoderParent> aEndpoint); + async StartUtilityAudioDecoderService(Endpoint<PUtilityAudioDecoderParent> aEndpoint, GfxVarUpdate[] updates); async StartJSOracleService(Endpoint<PJSOracleChild> aEndpoint); diff --git a/ipc/glue/ProcessChild.cpp b/ipc/glue/ProcessChild.cpp index 724d2b09bf..fe727ffa66 100644 --- a/ipc/glue/ProcessChild.cpp +++ b/ipc/glue/ProcessChild.cpp @@ -21,7 +21,6 @@ #include "nsAppRunner.h" #include "mozilla/AppShutdown.h" -#include "mozilla/ipc/CrashReporterClient.h" #include "mozilla/ipc/IOThreadChild.h" #include "mozilla/GeckoArgs.h" @@ -29,6 +28,8 @@ namespace mozilla { namespace ipc { ProcessChild* ProcessChild::gProcessChild; +StaticMutex ProcessChild::gIPCShutdownStateLock; +nsCString ProcessChild::gIPCShutdownStateAnnotation; static Atomic<bool> sExpectingShutdown(false); @@ -39,6 +40,9 @@ ProcessChild::ProcessChild(ProcessId aParentPid, const nsID& aMessageChannelId) mMessageChannelId(aMessageChannelId) { MOZ_ASSERT(mUILoop, "UILoop should be created by now"); MOZ_ASSERT(!gProcessChild, "should only be one ProcessChild"); + CrashReporter::RegisterAnnotationNSCString( + CrashReporter::Annotation::IPCShutdownState, + &gIPCShutdownStateAnnotation); gProcessChild = this; } @@ -101,14 +105,14 @@ ProcessChild::~ProcessChild() { // we'll get into late IPC shutdown with processes still running. SleepIfEnv("MOZ_TEST_CHILD_EXIT_HANG"); #endif + gIPCShutdownStateAnnotation = ""_ns; gProcessChild = nullptr; } /* static */ void ProcessChild::NotifiedImpendingShutdown() { sExpectingShutdown = true; - CrashReporter::AppendToCrashReportAnnotation( - CrashReporter::Annotation::IPCShutdownState, + ProcessChild::AppendToIPCShutdownStateAnnotation( "NotifiedImpendingShutdown"_ns); } diff --git a/ipc/glue/ProcessChild.h b/ipc/glue/ProcessChild.h index 29948a9127..f881b316cf 100644 --- a/ipc/glue/ProcessChild.h +++ b/ipc/glue/ProcessChild.h @@ -48,6 +48,12 @@ class ProcessChild : public ChildProcess { static bool ExpectingShutdown(); + static void AppendToIPCShutdownStateAnnotation(const nsCString& aStr) { + StaticMutexAutoLock lock(gIPCShutdownStateLock); + gIPCShutdownStateAnnotation.Append(" - "_ns); + gIPCShutdownStateAnnotation.Append(aStr); + } + /** * Exit *now*. Do not shut down XPCOM, do not pass Go, do not run * static destructors, do not collect $200. @@ -63,6 +69,9 @@ class ProcessChild : public ChildProcess { private: static ProcessChild* gProcessChild; + static StaticMutex gIPCShutdownStateLock; + static nsCString gIPCShutdownStateAnnotation + MOZ_GUARDED_BY(gIPCShutdownStateLock); MessageLoop* mUILoop; ProcessId mParentPid; diff --git a/ipc/glue/ProtocolUtils.cpp b/ipc/glue/ProtocolUtils.cpp index bd78dce607..b29221d476 100644 --- a/ipc/glue/ProtocolUtils.cpp +++ b/ipc/glue/ProtocolUtils.cpp @@ -73,23 +73,28 @@ IPCResult IPCResult::FailImpl(NotNull<IProtocol*> actor, const char* where, #endif } +/* static */ +IPCResult IPCResult::FailForTesting(NotNull<IProtocol*> actor, + const char* where, const char* why) { + return IPCResult(false); +} + void AnnotateSystemError() { - int64_t error = 0; + uint32_t error = 0; #if defined(XP_WIN) error = ::GetLastError(); #else error = errno; #endif if (error) { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCSystemError, - nsPrintfCString("%" PRId64, error)); + CrashReporter::RecordAnnotationU32( + CrashReporter::Annotation::IPCSystemError, error); } } #if defined(XP_MACOSX) void AnnotateCrashReportWithErrno(CrashReporter::Annotation tag, int error) { - CrashReporter::AnnotateCrashReport(tag, error); + CrashReporter::RecordAnnotationU32(tag, static_cast<uint32_t>(error)); } #endif // defined(XP_MACOSX) @@ -191,8 +196,8 @@ void FatalError(const char* aMsg, bool aIsParent) { // this process if we're off the main thread. formattedMessage.AppendLiteral("\". Intentionally crashing."); NS_ERROR(formattedMessage.get()); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::IPCFatalErrorMsg, nsDependentCString(aMsg)); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::IPCFatalErrorMsg, aMsg); AnnotateSystemError(); #ifndef FUZZING MOZ_CRASH("IPC FatalError in the parent process!"); diff --git a/ipc/glue/ProtocolUtils.h b/ipc/glue/ProtocolUtils.h index 2a0c64de20..7edce9612b 100644 --- a/ipc/glue/ProtocolUtils.h +++ b/ipc/glue/ProtocolUtils.h @@ -341,6 +341,9 @@ class IProtocol : public HasResultCodes { mozilla::ipc::IPCResult::FailUnsafePrintfImpl( \ WrapNotNull(actor), __func__, nsPrintfCString(format, ##__VA_ARGS__)) +#define IPC_TEST_FAIL(actor) \ + mozilla::ipc::IPCResult::FailForTesting(WrapNotNull(actor), __func__, "") + /** * All message deserializers and message handlers should return this type via * the above macros. We use a less generic name here to avoid conflict with @@ -379,6 +382,10 @@ class IPCResult { return FailImpl(aActor, aWhere, aWhy.get()); } + // Only used in testing. + static IPCResult FailForTesting(NotNull<IProtocol*> aActor, + const char* aWhere, const char* aWhy); + private: static IPCResult FailImpl(NotNull<IProtocol*> aActor, const char* aWhere, const char* aWhy); diff --git a/ipc/glue/UtilityAudioDecoder.cpp b/ipc/glue/UtilityAudioDecoder.cpp index 0b28fd601e..0a294d95f5 100644 --- a/ipc/glue/UtilityAudioDecoder.cpp +++ b/ipc/glue/UtilityAudioDecoder.cpp @@ -6,6 +6,7 @@ #include "mozilla/ProcInfo.h" #include "mozilla/ipc/UtilityAudioDecoder.h" +#include "mozilla/dom/BindingUtils.h" #include "mozilla/ipc/UtilityProcessChild.h" namespace mozilla::ipc { @@ -34,8 +35,7 @@ UtilityActorName GetAudioActorName(const SandboxingKind aSandbox) { nsCString GetChildAudioActorName() { RefPtr<ipc::UtilityProcessChild> s = ipc::UtilityProcessChild::Get(); MOZ_ASSERT(s, "Has UtilityProcessChild"); - return nsCString(dom::WebIDLUtilityActorNameValues::GetString( - GetAudioActorName(s->mSandbox))); + return dom::GetEnumString(GetAudioActorName(s->mSandbox)); } } // namespace mozilla::ipc diff --git a/ipc/glue/UtilityAudioDecoderChild.cpp b/ipc/glue/UtilityAudioDecoderChild.cpp index 88124a1f8b..cc3560e05b 100644 --- a/ipc/glue/UtilityAudioDecoderChild.cpp +++ b/ipc/glue/UtilityAudioDecoderChild.cpp @@ -42,8 +42,8 @@ NS_IMETHODIMP UtilityAudioDecoderChildShutdownObserver::Observe( NS_IMPL_ISUPPORTS(UtilityAudioDecoderChildShutdownObserver, nsIObserver); -static EnumeratedArray<SandboxingKind, SandboxingKind::COUNT, - StaticRefPtr<UtilityAudioDecoderChild>> +static EnumeratedArray<SandboxingKind, StaticRefPtr<UtilityAudioDecoderChild>, + size_t(SandboxingKind::COUNT)> sAudioDecoderChilds; UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind) @@ -56,6 +56,40 @@ UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind) } } +nsresult UtilityAudioDecoderChild::BindToUtilityProcess( + RefPtr<UtilityProcessParent> aUtilityParent) { + Endpoint<PUtilityAudioDecoderChild> utilityAudioDecoderChildEnd; + Endpoint<PUtilityAudioDecoderParent> utilityAudioDecoderParentEnd; + nsresult rv = PUtilityAudioDecoder::CreateEndpoints( + aUtilityParent->OtherPid(), base::GetCurrentProcId(), + &utilityAudioDecoderParentEnd, &utilityAudioDecoderChildEnd); + + if (NS_FAILED(rv)) { + MOZ_ASSERT(false, "Protocol endpoints failure"); + return NS_ERROR_FAILURE; + } + + nsTArray<gfx::GfxVarUpdate> updates; +#ifdef MOZ_WMF_MEDIA_ENGINE + // Only MFCDM process needs gfxVars + if (mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM) { + updates = gfx::gfxVars::FetchNonDefaultVars(); + } +#endif + if (!aUtilityParent->SendStartUtilityAudioDecoderService( + std::move(utilityAudioDecoderParentEnd), std::move(updates))) { + MOZ_ASSERT(false, "StartUtilityAudioDecoder service failure"); + return NS_ERROR_FAILURE; + } + + Bind(std::move(utilityAudioDecoderChildEnd)); + + PROFILER_MARKER_UNTYPED("UtilityAudioDecoderChild::BindToUtilityProcess", IPC, + MarkerOptions(MarkerTiming::IntervalUntilNowFrom( + mAudioDecoderChildStart))); + return NS_OK; +} + void UtilityAudioDecoderChild::ActorDestroy(ActorDestroyReason aReason) { MOZ_ASSERT(NS_IsMainThread()); #ifdef MOZ_WMF_MEDIA_ENGINE @@ -110,15 +144,10 @@ mozilla::ipc::IPCResult UtilityAudioDecoderChild::RecvCompleteCreatedVideoBridge() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM); - mHasCreatedVideoBridge = true; + mHasCreatedVideoBridge = State::Created; return IPC_OK(); } -bool UtilityAudioDecoderChild::HasCreatedVideoBridge() const { - MOZ_ASSERT(NS_IsMainThread()); - return mHasCreatedVideoBridge; -} - void UtilityAudioDecoderChild::OnVarChanged(const gfx::GfxVarUpdate& aVar) { MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM); SendUpdateVar(aVar); @@ -127,7 +156,7 @@ void UtilityAudioDecoderChild::OnVarChanged(const gfx::GfxVarUpdate& aVar) { void UtilityAudioDecoderChild::OnCompositorUnexpectedShutdown() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM); - mHasCreatedVideoBridge = false; + mHasCreatedVideoBridge = State::None; CreateVideoBridge(); } @@ -135,9 +164,11 @@ bool UtilityAudioDecoderChild::CreateVideoBridge() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM); - if (HasCreatedVideoBridge()) { + // Creating or already created, avoiding reinit a bridge. + if (mHasCreatedVideoBridge != State::None) { return true; } + mHasCreatedVideoBridge = State::Creating; // Build content device data first; this ensure that the GPU process is fully // ready. @@ -170,11 +201,10 @@ bool UtilityAudioDecoderChild::CreateVideoBridge() { return false; } - nsTArray<gfx::GfxVarUpdate> updates = gfx::gfxVars::FetchNonDefaultVars(); gpuManager->InitVideoBridge( std::move(parentPipe), layers::VideoBridgeSource::MFMediaEngineCDMProcess); - SendInitVideoBridge(std::move(childPipe), updates, contentDeviceData); + SendInitVideoBridge(std::move(childPipe), contentDeviceData); return true; } #endif diff --git a/ipc/glue/UtilityAudioDecoderChild.h b/ipc/glue/UtilityAudioDecoderChild.h index 4e6a7792b0..0a27cb4ea3 100644 --- a/ipc/glue/UtilityAudioDecoderChild.h +++ b/ipc/glue/UtilityAudioDecoderChild.h @@ -58,32 +58,7 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild UtilityActorName GetActorName() { return GetAudioActorName(mSandbox); } - nsresult BindToUtilityProcess(RefPtr<UtilityProcessParent> aUtilityParent) { - Endpoint<PUtilityAudioDecoderChild> utilityAudioDecoderChildEnd; - Endpoint<PUtilityAudioDecoderParent> utilityAudioDecoderParentEnd; - nsresult rv = PUtilityAudioDecoder::CreateEndpoints( - aUtilityParent->OtherPid(), base::GetCurrentProcId(), - &utilityAudioDecoderParentEnd, &utilityAudioDecoderChildEnd); - - if (NS_FAILED(rv)) { - MOZ_ASSERT(false, "Protocol endpoints failure"); - return NS_ERROR_FAILURE; - } - - if (!aUtilityParent->SendStartUtilityAudioDecoderService( - std::move(utilityAudioDecoderParentEnd))) { - MOZ_ASSERT(false, "StartUtilityAudioDecoder service failure"); - return NS_ERROR_FAILURE; - } - - Bind(std::move(utilityAudioDecoderChildEnd)); - - PROFILER_MARKER_UNTYPED( - "UtilityAudioDecoderChild::BindToUtilityProcess", IPC, - MarkerOptions( - MarkerTiming::IntervalUntilNowFrom(mAudioDecoderChildStart))); - return NS_OK; - } + nsresult BindToUtilityProcess(RefPtr<UtilityProcessParent> aUtilityParent); void ActorDestroy(ActorDestroyReason aReason) override; @@ -96,8 +71,6 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild #ifdef MOZ_WMF_MEDIA_ENGINE mozilla::ipc::IPCResult RecvCompleteCreatedVideoBridge(); - bool HasCreatedVideoBridge() const; - void OnVarChanged(const gfx::GfxVarUpdate& aVar) override; void OnCompositorUnexpectedShutdown() override; @@ -120,7 +93,8 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild #ifdef MOZ_WMF_MEDIA_ENGINE // True if the utility process has created a video bridge with the GPU prcess. // Currently only used for media egine cdm. Main thread only. - bool mHasCreatedVideoBridge = false; + enum class State { None, Creating, Created }; + State mHasCreatedVideoBridge = State::None; #endif TimeStamp mAudioDecoderChildStart; diff --git a/ipc/glue/UtilityAudioDecoderParent.cpp b/ipc/glue/UtilityAudioDecoderParent.cpp index 2eb0936a38..ed6327061b 100644 --- a/ipc/glue/UtilityAudioDecoderParent.cpp +++ b/ipc/glue/UtilityAudioDecoderParent.cpp @@ -42,7 +42,8 @@ namespace mozilla::ipc { -UtilityAudioDecoderParent::UtilityAudioDecoderParent() +UtilityAudioDecoderParent::UtilityAudioDecoderParent( + nsTArray<gfx::GfxVarUpdate>&& aUpdates) : mKind(GetCurrentSandboxingKind()), mAudioDecoderParentStart(TimeStamp::Now()) { #ifdef MOZ_WMF_MEDIA_ENGINE @@ -51,6 +52,9 @@ UtilityAudioDecoderParent::UtilityAudioDecoderParent() profiler_set_process_name(nsCString("MF Media Engine CDM")); gfx::gfxConfig::Init(); gfx::gfxVars::Initialize(); + for (auto& update : aUpdates) { + gfx::gfxVars::ApplyUpdate(update); + } gfx::DeviceManagerDx::Init(); return; } @@ -78,12 +82,12 @@ UtilityAudioDecoderParent::~UtilityAudioDecoderParent() { /* static */ void UtilityAudioDecoderParent::GenericPreloadForSandbox() { -#if defined(MOZ_SANDBOX) && defined(XP_WIN) && defined(MOZ_FFVPX) +#if defined(MOZ_SANDBOX) && defined(XP_WIN) // Preload AV dlls so we can enable Binary Signature Policy // to restrict further dll loads. UtilityProcessImpl::LoadLibraryOrCrash(L"mozavcodec.dll"); UtilityProcessImpl::LoadLibraryOrCrash(L"mozavutil.dll"); -#endif // defined(MOZ_SANDBOX) && defined(XP_WIN) && defined(MOZ_FFVPX) +#endif // defined(MOZ_SANDBOX) && defined(XP_WIN) } /* static */ @@ -141,7 +145,6 @@ UtilityAudioDecoderParent::RecvNewContentRemoteDecoderManager( #ifdef MOZ_WMF_MEDIA_ENGINE mozilla::ipc::IPCResult UtilityAudioDecoderParent::RecvInitVideoBridge( Endpoint<PVideoBridgeChild>&& aEndpoint, - nsTArray<gfx::GfxVarUpdate>&& aUpdates, const ContentDeviceData& aContentDeviceData) { MOZ_ASSERT(mKind == SandboxingKind::MF_MEDIA_ENGINE_CDM); if (!RemoteDecoderManagerParent::CreateVideoBridgeToOtherProcess( @@ -149,10 +152,6 @@ mozilla::ipc::IPCResult UtilityAudioDecoderParent::RecvInitVideoBridge( return IPC_FAIL_NO_REASON(this); } - for (const auto& update : aUpdates) { - gfx::gfxVars::ApplyUpdate(update); - } - gfx::gfxConfig::Inherit( { gfx::Feature::HW_COMPOSITING, @@ -175,6 +174,17 @@ mozilla::ipc::IPCResult UtilityAudioDecoderParent::RecvInitVideoBridge( IPCResult UtilityAudioDecoderParent::RecvUpdateVar( const GfxVarUpdate& aUpdate) { MOZ_ASSERT(mKind == SandboxingKind::MF_MEDIA_ENGINE_CDM); + auto scopeExit = MakeScopeExit( + [self = RefPtr<UtilityAudioDecoderParent>{this}, + location = GetRemoteDecodeInFromKind(mKind), + couldUseHWDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding()] { + if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) { + // The capabilities of the system may have changed, force a refresh by + // re-initializing the PDM. + Unused << self->SendUpdateMediaCodecsSupported( + location, PDMFactory::Supported(true /* force refresh */)); + } + }); gfx::gfxVars::ApplyUpdate(aUpdate); return IPC_OK(); } diff --git a/ipc/glue/UtilityAudioDecoderParent.h b/ipc/glue/UtilityAudioDecoderParent.h index 6996fa0538..7279582fdc 100644 --- a/ipc/glue/UtilityAudioDecoderParent.h +++ b/ipc/glue/UtilityAudioDecoderParent.h @@ -25,7 +25,8 @@ class UtilityAudioDecoderParent final : public PUtilityAudioDecoderParent { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UtilityAudioDecoderParent, override); - UtilityAudioDecoderParent(); + explicit UtilityAudioDecoderParent( + nsTArray<mozilla::gfx::GfxVarUpdate>&& aUpdates); static void GenericPreloadForSandbox(); static void WMFPreloadForSandbox(); @@ -39,7 +40,6 @@ class UtilityAudioDecoderParent final : public PUtilityAudioDecoderParent { #ifdef MOZ_WMF_MEDIA_ENGINE mozilla::ipc::IPCResult RecvInitVideoBridge( Endpoint<PVideoBridgeChild>&& aEndpoint, - nsTArray<mozilla::gfx::GfxVarUpdate>&& aUpdates, const ContentDeviceData& aContentDeviceData); IPCResult RecvUpdateVar(const mozilla::gfx::GfxVarUpdate& aUpdate); diff --git a/ipc/glue/UtilityProcessChild.cpp b/ipc/glue/UtilityProcessChild.cpp index cda3dbc817..d99c2fb361 100644 --- a/ipc/glue/UtilityProcessChild.cpp +++ b/ipc/glue/UtilityProcessChild.cpp @@ -261,11 +261,13 @@ mozilla::ipc::IPCResult UtilityProcessChild::RecvTestTelemetryProbes() { mozilla::ipc::IPCResult UtilityProcessChild::RecvStartUtilityAudioDecoderService( - Endpoint<PUtilityAudioDecoderParent>&& aEndpoint) { + Endpoint<PUtilityAudioDecoderParent>&& aEndpoint, + nsTArray<gfx::GfxVarUpdate>&& aUpdates) { PROFILER_MARKER_UNTYPED( "UtilityProcessChild::RecvStartUtilityAudioDecoderService", MEDIA, MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime))); - mUtilityAudioDecoderInstance = new UtilityAudioDecoderParent(); + mUtilityAudioDecoderInstance = + new UtilityAudioDecoderParent(std::move(aUpdates)); if (!mUtilityAudioDecoderInstance) { return IPC_FAIL(this, "Failed to create UtilityAudioDecoderParent"); } diff --git a/ipc/glue/UtilityProcessChild.h b/ipc/glue/UtilityProcessChild.h index db6db6bba6..42bfc421d0 100644 --- a/ipc/glue/UtilityProcessChild.h +++ b/ipc/glue/UtilityProcessChild.h @@ -63,7 +63,8 @@ class UtilityProcessChild final : public PUtilityProcessChild { mozilla::ipc::IPCResult RecvTestTelemetryProbes(); mozilla::ipc::IPCResult RecvStartUtilityAudioDecoderService( - Endpoint<PUtilityAudioDecoderParent>&& aEndpoint); + Endpoint<PUtilityAudioDecoderParent>&& aEndpoint, + nsTArray<gfx::GfxVarUpdate>&& aUpdates); mozilla::ipc::IPCResult RecvStartJSOracleService( Endpoint<dom::PJSOracleChild>&& aEndpoint); diff --git a/ipc/glue/UtilityProcessHost.cpp b/ipc/glue/UtilityProcessHost.cpp index 6b8a84966e..5f33fac81b 100644 --- a/ipc/glue/UtilityProcessHost.cpp +++ b/ipc/glue/UtilityProcessHost.cpp @@ -107,10 +107,6 @@ bool UtilityProcessHost::Launch(StringVector aExtraOpts) { } mPrefSerializer->AddSharedPrefCmdLineArgs(*this, aExtraOpts); -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - mSandboxLevel = Preferences::GetInt("security.sandbox.utility.level"); -#endif - #ifdef MOZ_WMF_CDM_LPAC_SANDBOX EnsureWidevineL1PathForSandbox(aExtraOpts); #endif diff --git a/ipc/glue/UtilityProcessManager.cpp b/ipc/glue/UtilityProcessManager.cpp index e24fed476b..b4cc4687a3 100644 --- a/ipc/glue/UtilityProcessManager.cpp +++ b/ipc/glue/UtilityProcessManager.cpp @@ -214,8 +214,8 @@ RefPtr<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess( } p->mQueuedPrefs.Clear(); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::UtilityProcessStatus, "Running"_ns); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::UtilityProcessStatus, "Running"); return GenericNonExclusivePromise::CreateAndResolve(true, __func__); }, @@ -592,8 +592,8 @@ void UtilityProcessManager::DestroyProcess(SandboxingKind aSandbox) { mProcesses[aSandbox] = nullptr; - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::UtilityProcessStatus, "Destroyed"_ns); + CrashReporter::RecordAnnotationCString( + CrashReporter::Annotation::UtilityProcessStatus, "Destroyed"); if (NoMoreProcesses()) { sSingleton = nullptr; diff --git a/ipc/glue/UtilityProcessManager.h b/ipc/glue/UtilityProcessManager.h index 60cea016c9..64b0f6504f 100644 --- a/ipc/glue/UtilityProcessManager.h +++ b/ipc/glue/UtilityProcessManager.h @@ -228,7 +228,8 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener { ~ProcessFields() = default; }; - EnumeratedArray<SandboxingKind, SandboxingKind::COUNT, RefPtr<ProcessFields>> + EnumeratedArray<SandboxingKind, RefPtr<ProcessFields>, + size_t(SandboxingKind::COUNT)> mProcesses; RefPtr<ProcessFields> GetProcess(SandboxingKind); diff --git a/ipc/glue/UtilityProcessParent.cpp b/ipc/glue/UtilityProcessParent.cpp index 2860b4704b..ea499eaee8 100644 --- a/ipc/glue/UtilityProcessParent.cpp +++ b/ipc/glue/UtilityProcessParent.cpp @@ -148,7 +148,7 @@ void UtilityProcessParent::ActorDestroy(ActorDestroyReason aWhy) { actorsName += ", "_ns + GetUtilityActorName(actor); } } - mCrashReporter->AddAnnotation( + mCrashReporter->AddAnnotationNSCString( CrashReporter::Annotation::UtilityActorsName, actorsName); } #endif diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index bb23b29a45..7aa29612b8 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -138,7 +138,7 @@ elif CONFIG["OS_ARCH"] in ("DragonFly", "FreeBSD", "NetBSD", "OpenBSD"): EXPORTS.mozilla.ipc += [ "SetProcessTitle.h", ] -elif CONFIG["OS_ARCH"] == "Darwin": +elif CONFIG["TARGET_OS"] == "OSX": UNIFIED_SOURCES += ["ProcessUtils_mac.mm"] else: UNIFIED_SOURCES += [ diff --git a/ipc/glue/test/browser/browser_audio_fallback.toml b/ipc/glue/test/browser/browser_audio_fallback.toml index 0de2a1c9e7..ab2b783e9a 100644 --- a/ipc/glue/test/browser/browser_audio_fallback.toml +++ b/ipc/glue/test/browser/browser_audio_fallback.toml @@ -1,9 +1,14 @@ [DEFAULT] +subsuite = "media-bc" +tags = "media-engine-compatible" support-files = [ "head.js", "head-multiple.js", ] -prefs = ["media.allow-audio-non-utility=true"] +prefs = [ + "media.allow-audio-non-utility=true", + "media.wmf.media-engine.channel-decoder.enabled=false" +] # Set this since we want to continue monitoring the disabling of pref since we # still allow it a little bit. environment = "MOZ_DONT_LOCK_UTILITY_PLZ_FILE_A_BUG=1" diff --git a/ipc/glue/test/browser/browser_audio_fallback_content.toml b/ipc/glue/test/browser/browser_audio_fallback_content.toml index 3efc6409ac..f074ac743d 100644 --- a/ipc/glue/test/browser/browser_audio_fallback_content.toml +++ b/ipc/glue/test/browser/browser_audio_fallback_content.toml @@ -1,4 +1,6 @@ [DEFAULT] +subsuite = "media-bc" +tags = "media-engine-compatible" support-files = [ "head.js", "head-multiple.js", @@ -6,6 +8,7 @@ support-files = [ prefs = [ "media.allow-audio-non-utility=true", "media.rdd-process.enabled=false", + "media.wmf.media-engine.channel-decoder.enabled=false" ] ["browser_utility_multipleAudio_fallback_content.js"] diff --git a/ipc/glue/test/browser/browser_audio_locked.toml b/ipc/glue/test/browser/browser_audio_locked.toml index 9f0607bf5f..82a42ff935 100644 --- a/ipc/glue/test/browser/browser_audio_locked.toml +++ b/ipc/glue/test/browser/browser_audio_locked.toml @@ -1,3 +1,6 @@ [DEFAULT] +subsuite = "media-bc" +tags = "media-engine-compatible" +prefs = ["media.wmf.media-engine.channel-decoder.enabled=false"] ["browser_utility_audio_locked.js"] diff --git a/ipc/glue/test/browser/browser_audio_shutdown.toml b/ipc/glue/test/browser/browser_audio_shutdown.toml index f99fff7830..6dbb8cdf49 100644 --- a/ipc/glue/test/browser/browser_audio_shutdown.toml +++ b/ipc/glue/test/browser/browser_audio_shutdown.toml @@ -1,5 +1,8 @@ [DEFAULT] +subsuite = "media-bc" +tags = "media-engine-compatible" support-files = ["head.js"] +prefs = ["media.wmf.media-engine.channel-decoder.enabled=false"] ["browser_utility_audio_shutdown.js"] support-files = ["../../../../dom/media/test/small-shot.ogg"] diff --git a/ipc/glue/test/browser/browser_child_hang.js b/ipc/glue/test/browser/browser_child_hang.js index cf890a6c61..e74517fbdd 100644 --- a/ipc/glue/test/browser/browser_child_hang.js +++ b/ipc/glue/test/browser/browser_child_hang.js @@ -24,7 +24,7 @@ add_task(async function () { url: "https://example.com/", forceNewProcess: true, }, - async function (browser) { + async function () { // browser.frameLoader.remoteTab.osPid is the child pid; once we // have a way to get notifications about child process termination // events, that could be useful. diff --git a/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js b/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js index 1c7551c623..1662ba06f3 100644 --- a/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js +++ b/ipc/glue/test/browser/browser_utility_audioDecodeCrash.js @@ -22,7 +22,7 @@ async function getAudioDecoderPid(expectation) { async function crashDecoder(expectation) { const audioPid = await getAudioDecoderPid(expectation); - ok(audioPid > 0, `Found an audio decoder ${audioPid}`); + Assert.greater(audioPid, 0, `Found an audio decoder ${audioPid}`); const actorIsAudioDecoder = actorNames => { return actorNames .split(",") diff --git a/ipc/glue/test/browser/browser_utility_audio_shutdown.js b/ipc/glue/test/browser/browser_utility_audio_shutdown.js index a0a4be63f6..046b6914a8 100644 --- a/ipc/glue/test/browser/browser_utility_audio_shutdown.js +++ b/ipc/glue/test/browser/browser_utility_audio_shutdown.js @@ -31,7 +31,7 @@ async function findGenericAudioDecoder() { ); } ); - ok(audioDecoders.length === 1, "Only one audio decoder present"); + Assert.strictEqual(audioDecoders.length, 1, "Only one audio decoder present"); return audioDecoders[0].pid; } @@ -50,7 +50,7 @@ add_task(async function testKill() { ); info("Waiting 15s to trigger mShutdownBlockers assertions"); - await new Promise((resolve, reject) => { + await new Promise(resolve => { /* eslint-disable mozilla/no-arbitrary-setTimeout */ setTimeout(resolve, 15 * 1000); }); @@ -62,12 +62,12 @@ add_task(async function testShutdown() { await runTest("small-shot.ogg", "Utility Generic", "ffvpx audio decoder"); const audioDecoderPid = await findGenericAudioDecoder(); - ok(audioDecoderPid > 0, `Valid PID found: ${audioDecoderPid}`); + Assert.greater(audioDecoderPid, 0, `Valid PID found: ${audioDecoderPid}`); await cleanUtilityProcessShutdown("audioDecoder_Generic"); info("Waiting 15s to trigger mShutdownBlockers assertions"); - await new Promise((resolve, reject) => { + await new Promise(resolve => { /* eslint-disable mozilla/no-arbitrary-setTimeout */ setTimeout(resolve, 15 * 1000); }); diff --git a/ipc/glue/test/browser/browser_utility_filepicker_crashed.js b/ipc/glue/test/browser/browser_utility_filepicker_crashed.js index e8eb83cf30..1cfbb9e591 100644 --- a/ipc/glue/test/browser/browser_utility_filepicker_crashed.js +++ b/ipc/glue/test/browser/browser_utility_filepicker_crashed.js @@ -57,13 +57,18 @@ function openFileDialog() { return pid; })(); - const file = new Promise((resolve, reject) => { + const file = new Promise(resolve => { info("Opening Windows file dialog"); let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); - fp.init(window, "Test: browser_utility_filepicker_crashed.js", fp.modeOpen); + fp.init( + window.browsingContext, + "Test: browser_utility_filepicker_crashed.js", + fp.modeOpen + ); fp.open(result => { - ok( - result == fp.returnCancel, + Assert.equal( + result, + fp.returnCancel, "filepicker should resolve to cancellation" ); resolve(); diff --git a/ipc/glue/test/browser/browser_utility_memoryReport.js b/ipc/glue/test/browser/browser_utility_memoryReport.js index 8cec61b8be..55bc8fbffe 100644 --- a/ipc/glue/test/browser/browser_utility_memoryReport.js +++ b/ipc/glue/test/browser/browser_utility_memoryReport.js @@ -15,11 +15,15 @@ add_task(async () => { const gMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService( Ci.nsIMemoryReporterManager ); - ok(utilityPid !== undefined, `Utility process is running as ${utilityPid}`); + Assert.notStrictEqual( + utilityPid, + undefined, + `Utility process is running as ${utilityPid}` + ); var utilityReports = []; - const performCollection = new Promise((resolve, reject) => { + const performCollection = new Promise(resolve => { // Record the reports from the live memory reporters then process them. let handleReport = function ( aProcess, @@ -56,13 +60,14 @@ add_task(async () => { `Collected ${utilityReports.length} reports from utility process ${utilityPid}` ); ok(!!utilityReports.length, "Collected some reports"); - ok( - utilityReports.filter(r => r.path === "vsize" && r.amount > 0).length === 1, + Assert.strictEqual( + utilityReports.filter(r => r.path === "vsize" && r.amount > 0).length, + 1, "Collected vsize report" ); - ok( - utilityReports.filter(r => r.path === "resident" && r.amount > 0).length === - 1, + Assert.strictEqual( + utilityReports.filter(r => r.path === "resident" && r.amount > 0).length, + 1, "Collected resident report" ); ok( diff --git a/ipc/glue/test/browser/head.js b/ipc/glue/test/browser/head.js index 8acff88273..7520049cd0 100644 --- a/ipc/glue/test/browser/head.js +++ b/ipc/glue/test/browser/head.js @@ -39,7 +39,11 @@ async function getUtilityProcesses(actor = undefined, options = {}) { async function tryGetUtilityPid(actor, options = {}) { let process = await getUtilityProcesses(actor, options); if (!options?.quiet) { - ok(process.length <= 1, `at most one ${actor} process exists`); + Assert.lessOrEqual( + process.length, + 1, + `at most one ${actor} process exists` + ); } return process[0]?.pid; } @@ -47,7 +51,7 @@ async function tryGetUtilityPid(actor, options = {}) { async function checkUtilityExists(actor) { info(`Looking for a running ${actor} utility process`); const utilityPid = await tryGetUtilityPid(actor); - ok(utilityPid > 0, `Found ${actor} utility process ${utilityPid}`); + Assert.greater(utilityPid, 0, `Found ${actor} utility process ${utilityPid}`); return utilityPid; } @@ -60,7 +64,11 @@ async function cleanUtilityProcessShutdown(actor, preferKill = false) { info(`${preferKill ? "Kill" : "Clean shutdown"} Utility Process ${actor}`); const utilityPid = await tryGetUtilityPid(actor); - ok(utilityPid !== undefined, `Must have PID for ${actor} utility process`); + Assert.notStrictEqual( + utilityPid, + undefined, + `Must have PID for ${actor} utility process` + ); const utilityProcessGone = TestUtils.topicObserved( "ipc:utility-shutdown", @@ -332,7 +340,7 @@ async function checkAudioDecoder( const doc = typeof content !== "undefined" ? content.document : document; let audio = doc.querySelector("audio"); const checkPromise = new Promise((resolve, reject) => { - const timeUpdateHandler = async ev => { + const timeUpdateHandler = async () => { const debugInfo = await SpecialPowers.wrap(audio).mozRequestDebugInfo(); const audioDecoderName = debugInfo.decoder.reader.audioDecoderName; @@ -363,7 +371,7 @@ async function checkAudioDecoder( } }; - const startPlaybackHandler = async ev => { + const startPlaybackHandler = async () => { ok( await audio.play().then( _ => true, @@ -375,7 +383,7 @@ async function checkAudioDecoder( audio.addEventListener("timeupdate", timeUpdateHandler, { once: true }); }; - audio.addEventListener("error", async err => { + audio.addEventListener("error", async () => { info( `Received HTML media error: ${audio.error.code}: ${audio.error.message}` ); @@ -483,8 +491,9 @@ async function crashSomeUtility(utilityPid, actorsCheck) { info(`Waiting for utility process ${utilityPid} to go away.`); let [subject, data] = await utilityProcessGone; - ok( - parseInt(data, 10) === utilityPid, + Assert.strictEqual( + parseInt(data, 10), + utilityPid, `Should match the crashed PID ${utilityPid} with ${data}` ); ok( @@ -510,7 +519,7 @@ async function crashSomeUtility(utilityPid, actorsCheck) { ), "Record should be a utility process crash" ); - ok(crash.id === dumpID, "Record should have an ID"); + Assert.strictEqual(crash.id, dumpID, "Record should have an ID"); ok( actorsCheck(crash.metadata.UtilityActorsName), `Record should have the correct actors name for: ${crash.metadata.UtilityActorsName}` @@ -546,8 +555,9 @@ async function crashSomeUtilityActor( ) { // Get PID for utility type const procInfos = await getUtilityProcesses(actor); - ok( - procInfos.length == 1, + Assert.equal( + procInfos.length, + 1, `exactly one ${actor} utility process should be found` ); const utilityPid = procInfos[0].pid; diff --git a/ipc/glue/test/browser/mochitest_audio_off.toml b/ipc/glue/test/browser/mochitest_audio_off.toml index d174ea3939..767be0a4b3 100644 --- a/ipc/glue/test/browser/mochitest_audio_off.toml +++ b/ipc/glue/test/browser/mochitest_audio_off.toml @@ -1,4 +1,6 @@ [DEFAULT] +subsuite = "media" +tags = "media-engine-compatible" run-if = ["os == 'android' && !isolated_process"] # Bug 1771452 support-files = [ "head.js", @@ -7,6 +9,9 @@ support-files = [ "../../../../dom/media/test/small-shot.m4a", "../../../../dom/media/test/small-shot.flac", ] -prefs = ["media.utility-process.enabled=false"] +prefs = [ + "media.utility-process.enabled=false", + "media.wmf.media-engine.channel-decoder.enabled=false" +] ["test_utility_audio_off.html"] diff --git a/ipc/glue/test/browser/mochitest_audio_on.toml b/ipc/glue/test/browser/mochitest_audio_on.toml index 908f4005f1..a06930401e 100644 --- a/ipc/glue/test/browser/mochitest_audio_on.toml +++ b/ipc/glue/test/browser/mochitest_audio_on.toml @@ -1,4 +1,6 @@ [DEFAULT] +subsuite = "media" +tags = "media-engine-compatible" run-if = ["os == 'android' && !isolated_process"] # Bug 1771452 support-files = [ "head.js", @@ -7,6 +9,9 @@ support-files = [ "../../../../dom/media/test/small-shot.m4a", "../../../../dom/media/test/small-shot.flac", ] -prefs = ["media.utility-process.enabled=true"] +prefs = [ + "media.utility-process.enabled=true", + "media.wmf.media-engine.channel-decoder.enabled=false" +] ["test_utility_audio_on.html"] diff --git a/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp b/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp index fff17d63ef..cbb8d30b03 100644 --- a/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp +++ b/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp @@ -30,8 +30,10 @@ TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly) #if defined(XP_DARWIN) TEST(UtilityProcessSandboxing, ParseEnvVar_DisableAppleAudioOnly) { +# if defined(MOZ_APPLEMEDIA) EXPECT_FALSE(IsUtilitySandboxEnabled( "utility:1", SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA)); +# endif EXPECT_TRUE( IsUtilitySandboxEnabled("utility:1", SandboxingKind::GENERIC_UTILITY)); } @@ -51,11 +53,11 @@ TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly_Multiples) { EXPECT_FALSE(IsUtilitySandboxEnabled("utility:1,utility:0,utility:2", SandboxingKind::GENERIC_UTILITY)); -#if defined(XP_DARWIN) +#if defined(MOZ_APPLEMEDIA) EXPECT_FALSE(IsUtilitySandboxEnabled( "utility:1,utility:0,utility:2", SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA)); -#endif // XP_DARWIN +#endif // MOZ_APPLEMEDIA #if defined(XP_WIN) EXPECT_FALSE( IsUtilitySandboxEnabled("utility:1,utility:0,utility:2", diff --git a/ipc/glue/test/utility_process_xpcom/UtilityProcessTest.cpp b/ipc/glue/test/utility_process_xpcom/UtilityProcessTest.cpp index 6c084a3153..9d22d60d0f 100644 --- a/ipc/glue/test/utility_process_xpcom/UtilityProcessTest.cpp +++ b/ipc/glue/test/utility_process_xpcom/UtilityProcessTest.cpp @@ -7,6 +7,7 @@ #if defined(ENABLE_TESTS) # include "mozilla/ipc/UtilityProcessManager.h" # include "mozilla/ipc/UtilityProcessTest.h" +# include "mozilla/dom/ChromeUtilsBinding.h" # include "mozilla/dom/Promise.h" # include "mozilla/ProcInfo.h" # include "mozilla/IntentionalCrash.h" @@ -26,23 +27,17 @@ namespace mozilla::ipc { static UtilityActorName UtilityActorNameFromString( const nsACString& aStringName) { using namespace mozilla::dom; - - // We use WebIDLUtilityActorNames because UtilityActorNames is not designed - // for iteration. - for (size_t i = 0; i < WebIDLUtilityActorNameValues::Count; ++i) { - auto idlName = static_cast<UtilityActorName>(i); - const nsDependentCSubstring idlNameString( - WebIDLUtilityActorNameValues::GetString(idlName)); - if (idlNameString.Equals(aStringName)) { - return idlName; - } + auto idlName = StringToEnum<UtilityActorName>(aStringName); + if (idlName.isSome()) { + return idlName.value(); } MOZ_CRASH("Unknown utility actor name"); } // Find the utility process with the given actor or any utility process if -// the actor is UtilityActorName::EndGuard_. -static SandboxingKind FindUtilityProcessWithActor(UtilityActorName aActorName) { +// aActorName is Nothing(). +static SandboxingKind FindUtilityProcessWithActor( + const Maybe<UtilityActorName>& aActorName) { RefPtr<UtilityProcessManager> utilityProc = UtilityProcessManager::GetSingleton(); MOZ_ASSERT(utilityProc, "No UtilityprocessManager?"); @@ -52,11 +47,11 @@ static SandboxingKind FindUtilityProcessWithActor(UtilityActorName aActorName) { if (!utilityProc->Process(sbKind)) { continue; } - if (aActorName == UtilityActorName::EndGuard_) { + if (aActorName.isNothing()) { return sbKind; } for (auto actor : utilityProc->GetActors(sbKind)) { - if (actor == aActorName) { + if (actor == aActorName.ref()) { return sbKind; } } @@ -236,9 +231,9 @@ UtilityProcessTest::StopProcess(const char* aActorName) { if (aActorName) { const nsDependentCString actorStringName(aActorName); UtilityActorName actorName = UtilityActorNameFromString(actorStringName); - sbKind = FindUtilityProcessWithActor(actorName); + sbKind = FindUtilityProcessWithActor(Some(actorName)); } else { - sbKind = FindUtilityProcessWithActor(UtilityActorName::EndGuard_); + sbKind = FindUtilityProcessWithActor(Nothing()); } if (sbKind == SandboxingKind::COUNT) { |