Backed out 4 changesets (bug 1707954) for causing bc failures in ClearOnShutdown.cpp.

CLOSED TREE

Backed out changeset 7cb0db27236c (bug 1707954)
Backed out changeset fd52d202d10b (bug 1707954)
Backed out changeset 55586d8f7bf4 (bug 1707954)
Backed out changeset 49406bdac5ec (bug 1707954)
This commit is contained in:
Marian-Vasile Laza 2021-06-10 09:13:45 +03:00
Родитель ddb9da34fc
Коммит 5c483b46df
9 изменённых файлов: 167 добавлений и 339 удалений

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

@ -128,8 +128,7 @@ namespace mozilla {
LauncherVoidResult LaunchUnelevated(int aArgc, wchar_t* aArgv[]) {
// We need COM to talk to Explorer. Using ProcessRuntime so that
// process-global COM configuration is done correctly
mozilla::mscom::ProcessRuntime mscom(
mozilla::mscom::ProcessRuntime::ProcessCategory::Launcher);
mozilla::mscom::ProcessRuntime mscom(GeckoProcessType_Default);
if (!mscom) {
return LAUNCHER_ERROR_FROM_HRESULT(mscom.GetHResult());
}

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

@ -55,6 +55,7 @@ CubebDeviceEnumerator::CubebDeviceEnumerator()
// Ensure the MTA thread exists and gets instantiated before the
// CubebDeviceEnumerator so that this instance will always gets destructed
// before the MTA thread gets shutdown.
mozilla::mscom::EnsureMTA();
mozilla::mscom::EnsureMTA([&]() -> void {
#endif
int rv = cubeb_register_device_collection_changed(

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

@ -6,25 +6,14 @@
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/Assertions.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/StaticLocalPtr.h"
#include "nsThreadManager.h"
#include "nsThreadUtils.h"
#include "private/pprthred.h"
#include <combaseapi.h>
#if (NTDDI_VERSION < NTDDI_WIN8)
// Win8+ API that we use very carefully
DECLARE_HANDLE(CO_MTA_USAGE_COOKIE);
HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE* pCookie);
#endif // (NTDDI_VERSION < NTDDI_WIN8)
namespace {
class EnterMTARunnable : public mozilla::Runnable {
@ -42,8 +31,8 @@ class BackgroundMTAData {
public:
BackgroundMTAData() {
nsCOMPtr<nsIRunnable> runnable = new EnterMTARunnable();
mozilla::DebugOnly<nsresult> rv = NS_NewNamedThread(
"COM MTA", getter_AddRefs(mThread), runnable.forget());
mozilla::DebugOnly<nsresult> rv =
NS_NewNamedThread("COM MTA", getter_AddRefs(mThread), runnable);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_NewNamedThread failed");
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
@ -69,54 +58,6 @@ class BackgroundMTAData {
namespace mozilla {
namespace mscom {
EnsureMTA::EnsureMTA() {
MOZ_ASSERT(NS_IsMainThread());
// It is possible that we're running so early that we might need to start
// the thread manager ourselves. We do this here to guarantee that we have
// the ability to start the persistent MTA thread at any moment beyond this
// point.
nsresult rv = nsThreadManager::get().Init();
// We intentionally don't check rv unless we need it when
// CoIncremementMTAUsage is unavailable.
// This API is only available beginning with Windows 8. Even though this
// constructor will only be called once, we intentionally use
// StaticDynamicallyLinkedFunctionPtr here to hang onto the ole32 module.
static const StaticDynamicallyLinkedFunctionPtr<
decltype(&::CoIncrementMTAUsage)>
pCoIncrementMTAUsage(L"ole32.dll", "CoIncrementMTAUsage");
if (pCoIncrementMTAUsage) {
// Calling this function initializes the MTA without needing to explicitly
// create a thread and call CoInitializeEx to do it.
// We don't retain the cookie because once we've incremented the MTA, we
// leave it that way for the lifetime of the process.
CO_MTA_USAGE_COOKIE mtaCookie = nullptr;
HRESULT hr = pCoIncrementMTAUsage(&mtaCookie);
MOZ_ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr)) {
return;
}
}
// In the fallback case, we simply initialize our persistent MTA thread.
// Make sure thread manager init succeeded before trying to initialize the
// persistent MTA thread.
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
return;
}
// Before proceeding any further, pump a runnable through the persistent MTA
// thread to ensure that it is up and running and has finished initializing
// the multi-threaded apartment.
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
"EnsureMTA::EnsureMTA()",
[]() { MOZ_RELEASE_ASSERT(IsCurrentThreadExplicitMTA()); }));
SyncDispatchToPersistentThread(runnable);
}
/* static */
RefPtr<EnsureMTA::CreateInstanceAgileRefPromise>
EnsureMTA::CreateInstanceInternal(REFCLSID aClsid, REFIID aIid) {
@ -172,14 +113,14 @@ RefPtr<EnsureMTA::CreateInstanceAgileRefPromise> EnsureMTA::CreateInstance(
return CreateInstanceInternal(localClsid, localIid);
};
nsCOMPtr<nsIThread> mtaThread(GetPersistentMTAThread());
nsCOMPtr<nsIThread> mtaThread(GetMTAThread());
return InvokeAsync(mtaThread->SerialEventTarget(), __func__,
std::move(invoker));
}
/* static */
nsCOMPtr<nsIThread> EnsureMTA::GetPersistentMTAThread() {
nsCOMPtr<nsIThread> EnsureMTA::GetMTAThread() {
static StaticLocalAutoPtr<BackgroundMTAData> sMTAData(
[]() -> BackgroundMTAData* {
BackgroundMTAData* bgData = new BackgroundMTAData();
@ -195,7 +136,7 @@ nsCOMPtr<nsIThread> EnsureMTA::GetPersistentMTAThread() {
SchedulerGroup::Dispatch(
TaskCategory::Other,
NS_NewRunnableFunction("mscom::EnsureMTA::GetPersistentMTAThread",
NS_NewRunnableFunction("mscom::EnsureMTA::GetMTAThread",
std::move(setClearOnShutdown)));
return bgData;
@ -206,57 +147,5 @@ nsCOMPtr<nsIThread> EnsureMTA::GetPersistentMTAThread() {
return sMTAData->GetThread();
}
/* static */
void EnsureMTA::SyncDispatchToPersistentThread(nsIRunnable* aRunnable) {
nsCOMPtr<nsIThread> thread(GetPersistentMTAThread());
MOZ_ASSERT(thread);
if (!thread) {
return;
}
// Note that, due to APC dispatch, we might reenter this function while we
// wait on this event. We therefore need a unique event object for each
// entry into this function. If perf becomes an issue then we will want to
// maintain an array of events where the Nth event is unique to the Nth
// reentry.
nsAutoHandle event(::CreateEventW(nullptr, FALSE, FALSE, nullptr));
if (!event) {
return;
}
HANDLE eventHandle = event.get();
auto eventSetter = [&aRunnable, eventHandle]() -> void {
aRunnable->Run();
::SetEvent(eventHandle);
};
nsresult rv = thread->Dispatch(
NS_NewRunnableFunction("mscom::EnsureMTA::SyncDispatchToPersistentThread",
std::move(eventSetter)),
NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
return;
}
const BOOL alertable = XRE_IsContentProcess() && NS_IsMainThread();
DWORD waitResult;
while ((waitResult = ::WaitForSingleObjectEx(event, INFINITE, alertable)) ==
WAIT_IO_COMPLETION) {
}
MOZ_ASSERT(waitResult == WAIT_OBJECT_0);
}
/**
* While this function currently appears to be redundant, it may become more
* sophisticated in the future. For example, we could optionally dispatch to an
* MTA context if we wanted to utilize the MTA thread pool.
*/
/* static */
void EnsureMTA::SyncDispatch(nsCOMPtr<nsIRunnable>&& aRunnable, Option aOpt) {
SyncDispatchToPersistentThread(aRunnable);
}
} // namespace mscom
} // namespace mozilla

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

@ -40,37 +40,74 @@ struct PreservedStreamDeleter;
} // namespace detail
class ProcessRuntime;
// This class is OK to use as a temporary on the stack.
class MOZ_STACK_CLASS EnsureMTA final {
public:
/**
* This constructor just ensures that the MTA thread is up and running.
*/
EnsureMTA() {
nsCOMPtr<nsIThread> thread = GetMTAThread();
MOZ_ASSERT(thread);
Unused << thread;
}
enum class Option {
Default,
// Forcibly dispatch to the thread returned by GetPersistentMTAThread(),
// even if the current thread is already inside a MTA.
ForceDispatchToPersistentThread,
// Forcibly dispatch to the thread returned by GetMTAThread(), even if the
// current thread is already inside a MTA.
ForceDispatch,
};
/**
* Synchronously run |aClosure| on a thread living in the COM multithreaded
* apartment. If the current thread lives inside the COM MTA, then it runs
* |aClosure| immediately unless |aOpt| ==
* Option::ForceDispatchToPersistentThread.
* |aClosure| immediately unless |aOpt| == Option::ForceDispatch.
*/
template <typename FuncT>
explicit EnsureMTA(FuncT&& aClosure, Option aOpt = Option::Default) {
if (aOpt != Option::ForceDispatchToPersistentThread &&
IsCurrentThreadMTA()) {
if (aOpt != Option::ForceDispatch && IsCurrentThreadMTA()) {
// We're already on the MTA, we can run aClosure directly
aClosure();
return;
}
// In this case we need to run aClosure on a background thread in the MTA
nsCOMPtr<nsIRunnable> runnable(
NS_NewRunnableFunction("EnsureMTA::EnsureMTA", std::move(aClosure)));
SyncDispatch(std::move(runnable), aOpt);
nsCOMPtr<nsIThread> thread = GetMTAThread();
MOZ_ASSERT(thread);
if (!thread) {
return;
}
// Note that we might reenter the EnsureMTA constructor while we wait on
// this event due to APC dispatch, therefore we need a unique event object
// for each entry. If perf becomes an issue then we will want to maintain
// an array of events where the Nth event is unique to the Nth reentry.
nsAutoHandle event(::CreateEventW(nullptr, FALSE, FALSE, nullptr));
if (!event) {
return;
}
HANDLE eventHandle = event.get();
auto eventSetter = [&aClosure, eventHandle]() -> void {
aClosure();
::SetEvent(eventHandle);
};
nsresult rv = thread->Dispatch(
NS_NewRunnableFunction("EnsureMTA", std::move(eventSetter)),
NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
return;
}
DWORD waitResult;
while ((waitResult = ::WaitForSingleObjectEx(event, INFINITE, TRUE)) ==
WAIT_IO_COMPLETION) {
}
MOZ_ASSERT(waitResult == WAIT_OBJECT_0);
}
using CreateInstanceAgileRefPromise =
@ -136,10 +173,7 @@ class MOZ_STACK_CLASS EnsureMTA final {
static RefPtr<CreateInstanceAgileRefPromise> CreateInstanceInternal(
REFCLSID aClsid, REFIID aIid);
static nsCOMPtr<nsIThread> GetPersistentMTAThread();
static void SyncDispatch(nsCOMPtr<nsIRunnable>&& aRunnable, Option aOpt);
static void SyncDispatchToPersistentThread(nsIRunnable* aRunnable);
static nsCOMPtr<nsIThread> GetMTAThread();
// The following function is private in order to force any consumers to be
// declared as friends of EnsureMTA. The intention is to prevent
@ -152,7 +186,7 @@ class MOZ_STACK_CLASS EnsureMTA final {
return;
}
nsCOMPtr<nsIThread> thread(GetPersistentMTAThread());
nsCOMPtr<nsIThread> thread(GetMTAThread());
MOZ_ASSERT(thread);
if (!thread) {
return;
@ -165,14 +199,6 @@ class MOZ_STACK_CLASS EnsureMTA final {
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
/**
* This constructor just ensures that the MTA is up and running. This should
* only be called by ProcessRuntime.
*/
EnsureMTA();
friend class mozilla::mscom::ProcessRuntime;
template <typename T>
friend struct mozilla::mscom::detail::MTADelete;

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

@ -16,15 +16,14 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/Vector.h"
#include "mozilla/WindowsProcessMitigations.h"
#include "mozilla/WindowsVersion.h"
#include "nsWindowsHelpers.h"
#if defined(MOZILLA_INTERNAL_API)
#if defined(MOZILLA_INTERNAL_API) && defined(MOZ_SANDBOX)
# include "mozilla/mscom/EnsureMTA.h"
# if defined(MOZ_SANDBOX)
# include "mozilla/sandboxTarget.h"
# endif // defined(MOZ_SANDBOX)
#endif // defined(MOZILLA_INTERNAL_API)
# include "mozilla/sandboxTarget.h"
# include "nsThreadManager.h"
#endif // defined(MOZILLA_INTERNAL_API) && defined(MOZ_SANDBOX)
#include <accctrl.h>
#include <aclapi.h>
@ -37,18 +36,12 @@ extern "C" void __cdecl SetOaNoCache(void);
namespace mozilla {
namespace mscom {
#if defined(MOZILLA_INTERNAL_API)
ProcessRuntime* ProcessRuntime::sInstance = nullptr;
ProcessRuntime::ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {}
ProcessRuntime::ProcessRuntime(const GeckoProcessType aProcessType)
ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType)
: ProcessRuntime(aProcessType == GeckoProcessType_Default
? ProcessCategory::GeckoBrowserParent
: ProcessCategory::GeckoChild) {}
#endif // defined(MOZILLA_INTERNAL_API)
ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
ProcessRuntime::ProcessRuntime(ProcessRuntime::ProcessCategory aProcessCategory)
: mInitResult(CO_E_NOTINITIALIZED),
mProcessCategory(aProcessCategory)
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
@ -56,38 +49,23 @@ ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
mActCtxRgn(a11y::Compatibility::GetActCtxResourceId())
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
{
#if defined(MOZILLA_INTERNAL_API)
MOZ_DIAGNOSTIC_ASSERT(!sInstance);
sInstance = this;
EnsureMTA();
/**
* From this point forward, all threads in this process are implicitly
* members of the multi-threaded apartment, with the following exceptions:
* 1. If any Win32 GUI APIs were called on the current thread prior to
* executing this constructor, then this thread has already been implicitly
* initialized as the process's main STA thread; or
* 2. A thread explicitly calls CoInitialize(Ex) to specify otherwise.
*/
const bool isCurThreadImplicitMTA = IsCurrentThreadImplicitMTA();
// We only assert that the implicit MTA precondition holds when not running
// as the Gecko parent process.
MOZ_DIAGNOSTIC_ASSERT(aProcessCategory ==
ProcessCategory::GeckoBrowserParent ||
isCurThreadImplicitMTA);
# if defined(MOZ_SANDBOX)
const bool isLockedDownChildProcess =
mProcessCategory == ProcessCategory::GeckoChild && IsWin32kLockedDown();
#if defined(MOZILLA_INTERNAL_API) && defined(MOZ_SANDBOX)
// If our process is running under Win32k lockdown, we cannot initialize
// COM with a single-threaded apartment. This is because STAs create a hidden
// COM with single-threaded apartments. This is because STAs create a hidden
// window, which implicitly requires user32 and Win32k, which are blocked.
// Instead we start the multi-threaded apartment and conduct our process-wide
// COM initialization there.
if (isLockedDownChildProcess) {
// Make sure we're still running with the sandbox's privileged impersonation
// token.
// Instead we start a multi-threaded apartment and conduct our process-wide
// COM initialization on that MTA background thread.
if (mProcessCategory == ProcessCategory::GeckoChild && IsWin32kLockedDown()) {
// It is possible that we're running so early that we might need to start
// the thread manager ourselves.
nsresult rv = nsThreadManager::get().Init();
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
return;
}
// Use the current thread's impersonation token to initialize COM, as
// it might fail otherwise (depending on sandbox policy).
HANDLE rawCurThreadImpToken;
if (!::OpenThreadToken(::GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY,
FALSE, &rawCurThreadImpToken)) {
@ -96,26 +74,51 @@ ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
}
nsAutoHandle curThreadImpToken(rawCurThreadImpToken);
# if defined(DEBUG)
// Ensure that our current token is still an impersonation token (ie, we
// have not yet called RevertToSelf() on this thread).
DWORD len;
TOKEN_TYPE tokenType;
MOZ_RELEASE_ASSERT(
::GetTokenInformation(rawCurThreadImpToken, TokenType, &tokenType,
sizeof(tokenType), &len) &&
len == sizeof(tokenType) && tokenType == TokenImpersonation);
MOZ_ASSERT(::GetTokenInformation(rawCurThreadImpToken, TokenType,
&tokenType, sizeof(tokenType), &len) &&
len == sizeof(tokenType) && tokenType == TokenImpersonation);
# endif // defined(DEBUG)
// Ideally we want our current thread to be running implicitly inside the
// MTA, but if for some wacky reason we did not end up with that, we may
// compensate by completing initialization via EnsureMTA's persistent
// thread.
if (!isCurThreadImplicitMTA) {
InitUsingPersistentMTAThread(curThreadImpToken);
// Create an impersonation token based on the current thread's token
HANDLE rawMtaThreadImpToken = nullptr;
if (!::DuplicateToken(rawCurThreadImpToken, SecurityImpersonation,
&rawMtaThreadImpToken)) {
mInitResult = HRESULT_FROM_WIN32(::GetLastError());
return;
}
nsAutoHandle mtaThreadImpToken(rawMtaThreadImpToken);
SandboxTarget::Instance()->RegisterSandboxStartCallback([]() -> void {
EnsureMTA(
[]() -> void {
// This is a security risk if it fails, so we release assert
MOZ_RELEASE_ASSERT(::RevertToSelf(),
"mscom::ProcessRuntime RevertToSelf failed");
},
EnsureMTA::Option::ForceDispatch);
});
// Impersonate and initialize.
EnsureMTA(
[this, rawMtaThreadImpToken]() -> void {
if (!::SetThreadToken(nullptr, rawMtaThreadImpToken)) {
mInitResult = HRESULT_FROM_WIN32(::GetLastError());
return;
}
InitInsideApartment();
},
EnsureMTA::Option::ForceDispatch);
return;
}
# endif // defined(MOZ_SANDBOX)
#endif // defined(MOZILLA_INTERNAL_API)
#endif // defined(MOZILLA_INTERNAL_API)
mAptRegion.Init(GetDesiredApartmentType(mProcessCategory));
@ -128,94 +131,18 @@ ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
}
InitInsideApartment();
if (FAILED(mInitResult)) {
return;
}
#if defined(MOZILLA_INTERNAL_API)
# if defined(MOZ_SANDBOX)
if (isLockedDownChildProcess) {
// In locked-down child processes, defer PostInit until priv drop
SandboxTarget::Instance()->RegisterSandboxStartCallback([self = this]() {
// Ensure that we're still live and the init was successful before
// calling PostInit()
if (self == sInstance && SUCCEEDED(self->mInitResult)) {
PostInit();
}
});
return;
}
# endif // defined(MOZ_SANDBOX)
PostInit();
#endif // defined(MOZILLA_INTERNAL_API)
}
#if defined(MOZILLA_INTERNAL_API)
ProcessRuntime::~ProcessRuntime() {
MOZ_DIAGNOSTIC_ASSERT(sInstance == this);
sInstance = nullptr;
}
# if defined(MOZ_SANDBOX)
void ProcessRuntime::InitUsingPersistentMTAThread(
const nsAutoHandle& aCurThreadToken) {
// Create an impersonation token based on the current thread's token
HANDLE rawMtaThreadImpToken = nullptr;
if (!::DuplicateToken(aCurThreadToken, SecurityImpersonation,
&rawMtaThreadImpToken)) {
mInitResult = HRESULT_FROM_WIN32(::GetLastError());
return;
}
nsAutoHandle mtaThreadImpToken(rawMtaThreadImpToken);
SandboxTarget::Instance()->RegisterSandboxStartCallback(
[self = this]() -> void {
EnsureMTA(
[]() -> void {
// This is a security risk if it fails, so we release assert
MOZ_RELEASE_ASSERT(::RevertToSelf(),
"mscom::ProcessRuntime RevertToSelf failed");
},
EnsureMTA::Option::ForceDispatchToPersistentThread);
// Ensure that we're still live and the init was successful before
// calling PostInit()
if (self == sInstance && SUCCEEDED(self->mInitResult)) {
PostInit();
}
});
// Impersonate and initialize.
EnsureMTA(
[this, rawMtaThreadImpToken]() -> void {
if (!::SetThreadToken(nullptr, rawMtaThreadImpToken)) {
mInitResult = HRESULT_FROM_WIN32(::GetLastError());
return;
}
InitInsideApartment();
},
EnsureMTA::Option::ForceDispatchToPersistentThread);
}
# endif // defined(MOZ_SANDBOX)
#endif // defined(MOZILLA_INTERNAL_API)
/* static */
COINIT ProcessRuntime::GetDesiredApartmentType(
const ProcessRuntime::ProcessCategory aProcessCategory) {
ProcessRuntime::ProcessCategory aProcessCategory) {
// Gecko processes get single-threaded apartments, others get multithreaded
// apartments. We should revisit the GeckoChild case as soon as we deploy
// Win32k lockdown.
switch (aProcessCategory) {
case ProcessCategory::GeckoBrowserParent:
return COINIT_APARTMENTTHREADED;
case ProcessCategory::GeckoChild:
if (!IsWin32kLockedDown()) {
// If Win32k is not locked down then we probably still need STA.
// We disable DDE since that is not usable from child processes.
return static_cast<COINIT>(COINIT_APARTMENTTHREADED |
COINIT_DISABLE_OLE1DDE);
}
[[fallthrough]];
return COINIT_APARTMENTTHREADED;
default:
return COINIT_MULTITHREADED;
}
@ -230,20 +157,16 @@ void ProcessRuntime::InitInsideApartment() {
}
// We are required to initialize security prior to configuring global options.
mInitResult = InitializeSecurity(mProcessCategory);
MOZ_DIAGNOSTIC_ASSERT(SUCCEEDED(mInitResult));
// Even though this isn't great, we should try to proceed even when
// CoInitializeSecurity has previously been called: the additional settings
// we want to change are important enough that we don't want to skip them.
if (FAILED(mInitResult) && mInitResult != RPC_E_TOO_LATE) {
mInitResult = InitializeSecurity();
MOZ_ASSERT(SUCCEEDED(mInitResult));
if (FAILED(mInitResult)) {
return;
}
RefPtr<IGlobalOptions> globalOpts;
mInitResult =
::CoCreateInstance(CLSID_GlobalOptions, nullptr, CLSCTX_INPROC_SERVER,
IID_IGlobalOptions, getter_AddRefs(globalOpts));
mInitResult = ::CoCreateInstance(CLSID_GlobalOptions, nullptr,
CLSCTX_INPROC_SERVER, IID_IGlobalOptions,
(void**)getter_AddRefs(globalOpts));
MOZ_ASSERT(SUCCEEDED(mInitResult));
if (FAILED(mInitResult)) {
return;
@ -264,16 +187,6 @@ void ProcessRuntime::InitInsideApartment() {
lock.SetInitialized();
}
#if defined(MOZILLA_INTERNAL_API)
/**
* Guaranteed to run *after* the COM (and possible sandboxing) initialization
* has successfully completed and stabilized. This method MUST BE IDEMPOTENT!
*/
/* static */ void ProcessRuntime::PostInit() {
// Currently "roughed-in" but unused.
}
#endif // defined(MOZILLA_INTERNAL_API)
/* static */
DWORD
ProcessRuntime::GetClientThreadId() {
@ -288,9 +201,8 @@ ProcessRuntime::GetClientThreadId() {
return callerTid;
}
/* static */
HRESULT
ProcessRuntime::InitializeSecurity(const ProcessCategory aProcessCategory) {
ProcessRuntime::InitializeSecurity() {
HANDLE rawToken = nullptr;
BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken);
if (!ok) {
@ -347,13 +259,10 @@ ProcessRuntime::InitializeSecurity(const ProcessCategory aProcessCategory) {
return HRESULT_FROM_WIN32(::GetLastError());
}
const bool allowAppContainers =
aProcessCategory == ProcessCategory::GeckoBrowserParent &&
IsWin8OrLater();
BYTE appContainersSid[SECURITY_MAX_SID_SIZE];
DWORD appContainersSidSize = sizeof(appContainersSid);
if (allowAppContainers) {
if (mProcessCategory == ProcessCategory::GeckoBrowserParent &&
IsWin8OrLater()) {
if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr,
appContainersSid, &appContainersSidSize)) {
return HRESULT_FROM_WIN32(::GetLastError());
@ -386,7 +295,8 @@ ProcessRuntime::InitializeSecurity(const ProcessCategory aProcessCategory) {
{nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
reinterpret_cast<LPWSTR>(tokenUser.User.Sid)}});
if (allowAppContainers) {
if (mProcessCategory == ProcessCategory::GeckoBrowserParent &&
IsWin8OrLater()) {
Unused << entries.append(
EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE,
GRANT_ACCESS,

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

@ -12,10 +12,8 @@
# include "mozilla/mscom/ActivationContext.h"
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
#include "mozilla/mscom/ApartmentRegion.h"
#include "nsWindowsHelpers.h"
#if defined(MOZILLA_INTERNAL_API)
# include "nsXULAppAPI.h"
#endif // defined(MOZILLA_INTERNAL_API)
#include "mozilla/WindowsProcessMitigations.h"
#include "nsXULAppAPI.h"
namespace mozilla {
namespace mscom {
@ -34,22 +32,23 @@ class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final {
};
// This constructor is only public when compiled outside of XUL
explicit ProcessRuntime(const ProcessCategory aProcessCategory);
explicit ProcessRuntime(ProcessCategory aProcessCategory);
public:
#if defined(MOZILLA_INTERNAL_API)
ProcessRuntime();
~ProcessRuntime();
#else
~ProcessRuntime() = default;
ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {}
#endif // defined(MOZILLA_INTERNAL_API)
explicit ProcessRuntime(GeckoProcessType aProcessType);
~ProcessRuntime() = default;
explicit operator bool() const { return SUCCEEDED(mInitResult); }
HRESULT GetHResult() const { return mInitResult; }
ProcessRuntime(const ProcessRuntime&) = delete;
ProcessRuntime(ProcessRuntime&) = delete;
ProcessRuntime(ProcessRuntime&&) = delete;
ProcessRuntime& operator=(const ProcessRuntime&) = delete;
ProcessRuntime& operator=(ProcessRuntime&) = delete;
ProcessRuntime& operator=(ProcessRuntime&&) = delete;
/**
@ -59,32 +58,16 @@ class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final {
static DWORD GetClientThreadId();
private:
#if defined(MOZILLA_INTERNAL_API)
explicit ProcessRuntime(const GeckoProcessType aProcessType);
# if defined(MOZ_SANDBOX)
void InitUsingPersistentMTAThread(const nsAutoHandle& aCurThreadToken);
# endif // defined(MOZ_SANDBOX)
#endif // defined(MOZILLA_INTERNAL_API)
void InitInsideApartment();
HRESULT InitializeSecurity();
static COINIT GetDesiredApartmentType(ProcessCategory aProcessCategory);
#if defined(MOZILLA_INTERNAL_API)
static void PostInit();
#endif // defined(MOZILLA_INTERNAL_API)
static HRESULT InitializeSecurity(const ProcessCategory aProcessCategory);
static COINIT GetDesiredApartmentType(const ProcessCategory aProcessCategory);
private:
HRESULT mInitResult;
const ProcessCategory mProcessCategory;
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
ActivationContextRegion mActCtxRgn;
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
ApartmentRegion mAptRegion;
private:
#if defined(MOZILLA_INTERNAL_API)
static ProcessRuntime* sInstance;
#endif // defined(MOZILLA_INTERNAL_API)
};
} // namespace mscom

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

@ -25,6 +25,6 @@ MFBT_API bool& BeginProcessRuntimeInit() {
MFBT_API void EndProcessRuntimeInit() { gLock.UnlockExclusive(); }
} // namespace detail
} // namespace detail
} // namespace mscom
} // namespace mozilla

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

@ -98,7 +98,7 @@ JumpListBuilder::JumpListBuilder()
// Instantiate mJumpListMgr in the multithreaded apartment so that proxied
// calls on that object do not need to interact with the main thread's message
// pump.
mscom::EnsureMTA([&]() {
mscom::EnsureMTA([this]() {
RefPtr<ICustomDestinationList> jumpListMgr;
HRESULT hr = ::CoCreateInstance(
CLSID_DestinationList, nullptr, CLSCTX_INPROC_SERVER,

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

@ -11,6 +11,7 @@
#include <cderr.h>
#include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
@ -27,6 +28,7 @@
using mozilla::IsWin8OrLater;
using mozilla::MakeUnique;
using mozilla::UniquePtr;
using mozilla::mscom::EnsureMTA;
using namespace mozilla::widget;
@ -108,6 +110,15 @@ NS_IMETHODIMP nsFilePicker::Init(mozIDOMWindowProxy* aParent,
* @return true if a file was selected successfully.
*/
bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) {
if (!IsWin8OrLater()) {
// Some Windows 7 users are experiencing a race condition when some dlls
// that are loaded by the file picker cause a crash while attempting to shut
// down the COM multithreaded apartment. By instantiating EnsureMTA, we hold
// an additional reference to the MTA that should prevent this race, since
// the MTA will remain alive until shutdown.
EnsureMTA ensureMTA;
}
RefPtr<IFileOpenDialog> dialog;
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr,
CLSCTX_INPROC_SERVER, IID_IFileOpenDialog,
@ -195,6 +206,15 @@ bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) {
bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
AUTO_PROFILER_LABEL("nsFilePicker::ShowFilePicker", OTHER);
if (!IsWin8OrLater()) {
// Some Windows 7 users are experiencing a race condition when some dlls
// that are loaded by the file picker cause a crash while attempting to shut
// down the COM multithreaded apartment. By instantiating EnsureMTA, we hold
// an additional reference to the MTA that should prevent this race, since
// the MTA will remain alive until shutdown.
EnsureMTA ensureMTA;
}
RefPtr<IFileDialog> dialog;
if (mMode != modeSave) {
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr,