diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp index 8f58ddf397ef..1917fd994271 100644 --- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -1071,7 +1071,7 @@ 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::JSOracle) + 1, + static_cast(UtilityActorName::WindowsUtils) + 1, "In order for this static cast to be okay, " "UtilityActorName must match UtilityActorName exactly"); @@ -1084,6 +1084,7 @@ static WebIDLUtilityActorName UtilityActorNameToWebIDL( UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder_WMF, AudioDecoder_WMF); UTILITYACTORNAME_TO_WEBIDL_CASE(MfMediaEngineCDM, MfMediaEngineCDM); UTILITYACTORNAME_TO_WEBIDL_CASE(JSOracle, JSOracle); + UTILITYACTORNAME_TO_WEBIDL_CASE(WindowsUtils, WindowsUtils); } MOZ_ASSERT(false, "Unhandled case in WebIDLUtilityActorName"); diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl index f8f0b02ee7c3..5b417e0c139d 100644 --- a/dom/chrome-webidl/ChromeUtils.webidl +++ b/dom/chrome-webidl/ChromeUtils.webidl @@ -728,6 +728,7 @@ enum WebIDLUtilityActorName { "audioDecoder_WMF", "mfMediaEngineCDM", "jSOracle", + "windowsUtils", }; dictionary UtilityActorsDictionary { diff --git a/dom/system/windows/PWindowsUtils.ipdl b/dom/system/windows/PWindowsUtils.ipdl new file mode 100644 index 000000000000..98fc516fbc4a --- /dev/null +++ b/dom/system/windows/PWindowsUtils.ipdl @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* 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/. */ + +namespace mozilla { +namespace dom { + +// Manager of utility actors that run in the windows utility process. +protocol PWindowsUtils { +}; + +} // namespace dom +} // namespace mozilla diff --git a/dom/system/windows/WindowsUtilsChild.h b/dom/system/windows/WindowsUtilsChild.h new file mode 100644 index 000000000000..4f1bbff99cb5 --- /dev/null +++ b/dom/system/windows/WindowsUtilsChild.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_WindowsUtilsChild_h__ +#define mozilla_dom_WindowsUtilsChild_h__ + +#include "mozilla/dom/PWindowsUtilsChild.h" + +namespace mozilla::dom { + +// Manager for utilities in the WindowsUtils utility process. +class WindowsUtilsChild final : public PWindowsUtilsChild { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsUtilsChild, override); + + protected: + ~WindowsUtilsChild() = default; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_WindowsUtilsChild_h__ diff --git a/dom/system/windows/WindowsUtilsParent.h b/dom/system/windows/WindowsUtilsParent.h new file mode 100644 index 000000000000..bc447a116759 --- /dev/null +++ b/dom/system/windows/WindowsUtilsParent.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_WindowsUtilsParent_h__ +#define mozilla_dom_WindowsUtilsParent_h__ + +#include "mozilla/dom/PWindowsUtilsParent.h" +#include "mozilla/ProcInfo.h" +#include "mozilla/ipc/Endpoint.h" +#include "mozilla/ipc/UtilityProcessParent.h" + +namespace mozilla::dom { + +// Main-process manager for utilities in the WindowsUtils utility process. +class WindowsUtilsParent final : public PWindowsUtilsParent { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsUtilsParent, override); + + nsresult BindToUtilityProcess( + RefPtr aUtilityParent) { + Endpoint parentEnd; + Endpoint childEnd; + nsresult rv = PWindowsUtils::CreateEndpoints(base::GetCurrentProcId(), + aUtilityParent->OtherPid(), + &parentEnd, &childEnd); + + if (NS_FAILED(rv)) { + MOZ_ASSERT(false, "Protocol endpoints failure"); + return NS_ERROR_FAILURE; + } + + if (!aUtilityParent->SendStartWindowsUtilsService(std::move(childEnd))) { + MOZ_ASSERT(false, "SendStartWindowsUtilsService failed"); + return NS_ERROR_FAILURE; + } + + DebugOnly ok = parentEnd.Bind(this); + MOZ_ASSERT(ok); + return NS_OK; + } + + UtilityActorName GetActorName() { return UtilityActorName::WindowsUtils; } + + protected: + ~WindowsUtilsParent() = default; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_WindowsUtilsParent_h__ diff --git a/dom/system/windows/moz.build b/dom/system/windows/moz.build index 45131af39e92..b04f5c352cfc 100644 --- a/dom/system/windows/moz.build +++ b/dom/system/windows/moz.build @@ -4,8 +4,22 @@ # 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/. -SOURCES += ["nsHapticFeedback.cpp", "WindowsLocationProvider.cpp"] +EXPORTS.mozilla.dom += [ + "WindowsUtilsChild.h", + "WindowsUtilsParent.h", +] + +UNIFIED_SOURCES += [ + "nsHapticFeedback.cpp", + "WindowsLocationProvider.cpp", +] + +IPDL_SOURCES += [ + "PWindowsUtils.ipdl", +] LOCAL_INCLUDES += ["/dom/geolocation"] +include("/ipc/chromium/chromium-config.mozbuild") + FINAL_LIBRARY = "xul" diff --git a/ipc/glue/PUtilityProcess.ipdl b/ipc/glue/PUtilityProcess.ipdl index a42e708a6a40..c40e3247f43e 100644 --- a/ipc/glue/PUtilityProcess.ipdl +++ b/ipc/glue/PUtilityProcess.ipdl @@ -10,6 +10,10 @@ include protocol PProfiler; include protocol PUtilityAudioDecoder; include protocol PJSOracle; +#if defined(XP_WIN) +include protocol PWindowsUtils; +#endif + #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) include protocol PSandboxTesting; #endif @@ -85,6 +89,10 @@ child: async StartJSOracleService(Endpoint aEndpoint); +#if defined(XP_WIN) + async StartWindowsUtilsService(Endpoint aEndpoint); +#endif + #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) async InitSandboxTesting(Endpoint aEndpoint); #endif diff --git a/ipc/glue/UtilityProcessChild.cpp b/ipc/glue/UtilityProcessChild.cpp index 93dacfa28eb6..22e5e4275ee7 100644 --- a/ipc/glue/UtilityProcessChild.cpp +++ b/ipc/glue/UtilityProcessChild.cpp @@ -28,6 +28,7 @@ #if defined(XP_WIN) # include "mozilla/WinDllServices.h" +# include "mozilla/dom/WindowsUtilsChild.h" #endif #include "nsDebugImpl.h" @@ -249,6 +250,20 @@ mozilla::ipc::IPCResult UtilityProcessChild::RecvStartJSOracleService( return IPC_OK(); } +#ifdef XP_WIN +mozilla::ipc::IPCResult UtilityProcessChild::RecvStartWindowsUtilsService( + Endpoint&& aEndpoint) { + mWindowsUtilsInstance = new dom::WindowsUtilsChild(); + if (!mWindowsUtilsInstance) { + return IPC_FAIL(this, "Failed to create WindowsUtilsChild"); + } + + [[maybe_unused]] bool ok = std::move(aEndpoint).Bind(mWindowsUtilsInstance); + MOZ_ASSERT(ok); + return IPC_OK(); +} +#endif + void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) { if (AbnormalShutdown == aWhy) { NS_WARNING("Shutting down Utility process early due to a crash!"); diff --git a/ipc/glue/UtilityProcessChild.h b/ipc/glue/UtilityProcessChild.h index eadded6f1bff..5a646c4d72c0 100644 --- a/ipc/glue/UtilityProcessChild.h +++ b/ipc/glue/UtilityProcessChild.h @@ -63,6 +63,11 @@ class UtilityProcessChild final : public PUtilityProcessChild { mozilla::ipc::IPCResult RecvStartJSOracleService( Endpoint&& aEndpoint); +#ifdef XP_WIN + mozilla::ipc::IPCResult RecvStartWindowsUtilsService( + Endpoint&& aEndpoint); +#endif + AsyncBlockers& AsyncShutdownService() { return mShutdownBlockers; } void ActorDestroy(ActorDestroyReason aWhy) override; @@ -80,6 +85,10 @@ class UtilityProcessChild final : public PUtilityProcessChild { RefPtr mProfilerController; RefPtr mUtilityAudioDecoderInstance{}; RefPtr mJSOracleInstance{}; +#ifdef XP_WIN + RefPtr mWindowsUtilsInstance; +#endif + AsyncBlockers mShutdownBlockers; }; diff --git a/ipc/glue/UtilityProcessManager.cpp b/ipc/glue/UtilityProcessManager.cpp index 1af6a06e3d21..945ae97ebaa1 100644 --- a/ipc/glue/UtilityProcessManager.cpp +++ b/ipc/glue/UtilityProcessManager.cpp @@ -21,6 +21,10 @@ #include "nsAppRunner.h" #include "nsContentUtils.h" +#ifdef XP_WIN +# include "mozilla/dom/WindowsUtilsParent.h" +#endif + #include "mozilla/GeckoArgs.h" namespace mozilla::ipc { @@ -373,6 +377,44 @@ UtilityProcessManager::StartJSOracle(dom::JSOracleParent* aParent) { return StartUtility(RefPtr{aParent}, SandboxingKind::GENERIC_UTILITY); } +#ifdef XP_WIN + +// Windows Utils + +RefPtr +UtilityProcessManager::GetWindowsUtilsPromise() { + RefPtr self = this; + if (!mWindowsUtils) { + mWindowsUtils = new dom::WindowsUtilsParent(); + } + + RefPtr wup = mWindowsUtils; + MOZ_ASSERT(wup, "Unable to get a singleton for WindowsUtils"); + return StartUtility(wup, SandboxingKind::WINDOWS_UTILS) + ->Then( + GetMainThreadSerialEventTarget(), __func__, + [self, wup]() { + if (!wup->CanSend()) { + MOZ_ASSERT(false, "WindowsUtilsParent can't send"); + return WindowsUtilsPromise::CreateAndReject(NS_ERROR_FAILURE, + __func__); + } + return WindowsUtilsPromise::CreateAndResolve(wup, __func__); + }, + [self](nsresult aError) { + if (!self->IsShutdown()) { + MOZ_ASSERT_UNREACHABLE( + "PWindowsUtils: failure when starting actor"); + } + NS_WARNING("StartUtility rejected promise for PWindowsUtils"); + return WindowsUtilsPromise::CreateAndReject(aError, __func__); + }); +} + +void UtilityProcessManager::ReleaseWindowsUtils() { mWindowsUtils = nullptr; } + +#endif // XP_WIN + bool UtilityProcessManager::IsProcessLaunching(SandboxingKind aSandbox) { MOZ_ASSERT(NS_IsMainThread()); diff --git a/ipc/glue/UtilityProcessManager.h b/ipc/glue/UtilityProcessManager.h index 70c763546c66..bcedbdc9753a 100644 --- a/ipc/glue/UtilityProcessManager.h +++ b/ipc/glue/UtilityProcessManager.h @@ -20,7 +20,8 @@ class MemoryReportingProcess; namespace dom { class JSOracleParent; -} +class WindowsUtilsParent; +} // namespace dom namespace ipc { @@ -37,6 +38,9 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener { MozPromise, nsresult, true>; using JSOraclePromise = GenericNonExclusivePromise; + using WindowsUtilsPromise = + MozPromise, nsresult, true>; + static void Initialize(); static void Shutdown(); @@ -56,6 +60,15 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener { RefPtr StartJSOracle(mozilla::dom::JSOracleParent* aParent); +#ifdef XP_WIN + // Get the (possibly already resolved) promise for the Windows utility + // process actor. Creates the process if it is not running. + RefPtr GetWindowsUtilsPromise(); + // Releases the WindowsUtils actor so that it can be destroyed. + // Subsequent attempts to use WindowsUtils will create a new process. + void ReleaseWindowsUtils(); +#endif + void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost); // Returns the platform pid for this utility sandbox process. @@ -197,6 +210,10 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener { RefPtr GetProcess(SandboxingKind); bool NoMoreProcesses(); uint16_t AliveProcesses(); + +#ifdef XP_WIN + RefPtr mWindowsUtils; +#endif // XP_WIN }; } // namespace ipc diff --git a/ipc/glue/UtilityProcessSandboxing.h b/ipc/glue/UtilityProcessSandboxing.h index 2c644bf044fe..7aac77e0e993 100644 --- a/ipc/glue/UtilityProcessSandboxing.h +++ b/ipc/glue/UtilityProcessSandboxing.h @@ -27,6 +27,10 @@ enum SandboxingKind : uint64_t { #ifdef MOZ_WMF_MEDIA_ENGINE MF_MEDIA_ENGINE_CDM, #endif +#ifdef XP_WIN + WINDOWS_UTILS, +#endif + COUNT, }; diff --git a/toolkit/components/processtools/ProcInfo.h b/toolkit/components/processtools/ProcInfo.h index ce4bd1d9b2df..5f565de2f65e 100644 --- a/toolkit/components/processtools/ProcInfo.h +++ b/toolkit/components/processtools/ProcInfo.h @@ -75,6 +75,7 @@ enum class UtilityActorName { AudioDecoder_WMF, MfMediaEngineCDM, JSOracle, + WindowsUtils, }; // String that will be used e.g. to annotate crash reports diff --git a/toolkit/components/processtools/ProcInfo_common.cpp b/toolkit/components/processtools/ProcInfo_common.cpp index 5a44775cb7cc..3936f3cee983 100644 --- a/toolkit/components/processtools/ProcInfo_common.cpp +++ b/toolkit/components/processtools/ProcInfo_common.cpp @@ -55,6 +55,8 @@ nsCString GetUtilityActorName(const UtilityActorName aActorName) { return "mf-media-engine"_ns; case UtilityActorName::JSOracle: return "js-oracle"_ns; + case UtilityActorName::WindowsUtils: + return "windows-utils"_ns; } return "unknown"_ns; } diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 3f80ad2a9b19..5e413296f08c 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -16,6 +16,7 @@ #include "mozilla/ChaosMode.h" #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/IOInterposer.h" +#include "mozilla/ipc/UtilityProcessChild.h" #include "mozilla/Likely.h" #include "mozilla/MemoryChecking.h" #include "mozilla/Poison.h" @@ -5976,16 +5977,28 @@ bool XRE_IsE10sParentProcess() { #undef GECKO_PROCESS_TYPE bool XRE_UseNativeEventProcessing() { + switch (XRE_GetProcessType()) { #if defined(XP_MACOSX) || defined(XP_WIN) - if (XRE_IsRDDProcess() || XRE_IsSocketProcess() || XRE_IsUtilityProcess()) { - return false; + case GeckoProcessType_RDD: + case GeckoProcessType_Socket: + return false; + case GeckoProcessType_Utility: { +# if defined(XP_WIN) + auto upc = mozilla::ipc::UtilityProcessChild::Get(); + MOZ_ASSERT(upc); + // WindowsUtils is for Windows APIs, which typically require a Windows + // native event loop. + return upc->mSandbox == mozilla::ipc::SandboxingKind::WINDOWS_UTILS; +# else + return false; +# endif // defined(XP_WIN) + } +#endif // defined(XP_MACOSX) || defined(XP_WIN) + case GeckoProcessType_Content: + return StaticPrefs::dom_ipc_useNativeEventProcessing_content(); + default: + return true; } -#endif - if (XRE_IsContentProcess()) { - return StaticPrefs::dom_ipc_useNativeEventProcessing_content(); - } - - return true; } namespace mozilla {