mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-04 11:26:09 +00:00
9ec086e0e5
COM is required for calls to SHGetFileInfo for moz-icon, but we only currently require that for the file content process. We may want to use it in the future for the privileged about content process, in which case we will have to forgo win32k lockdown there unless moz-icon is remoted. Depends on D112960 Differential Revision: https://phabricator.services.mozilla.com/D112961
197 lines
5.1 KiB
C++
197 lines
5.1 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* 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 "DecodePool.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/DebugOnly.h"
|
|
#include "mozilla/Monitor.h"
|
|
#include "mozilla/ProfilerLabels.h"
|
|
#include "mozilla/SchedulerGroup.h"
|
|
#include "mozilla/Services.h"
|
|
#include "mozilla/StaticPrefs_image.h"
|
|
#include "mozilla/TaskController.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIObserverService.h"
|
|
#include "nsThreadManager.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "nsXPCOMCIDInternal.h"
|
|
#include "prsystem.h"
|
|
|
|
#include "Decoder.h"
|
|
#include "IDecodingTask.h"
|
|
#include "RasterImage.h"
|
|
|
|
#if defined(XP_WIN)
|
|
# include <objbase.h>
|
|
# include "mozilla/WindowsProcessMitigations.h"
|
|
#endif
|
|
|
|
using std::max;
|
|
using std::min;
|
|
|
|
namespace mozilla {
|
|
namespace image {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DecodePool implementation.
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/* static */
|
|
StaticRefPtr<DecodePool> DecodePool::sSingleton;
|
|
/* static */
|
|
uint32_t DecodePool::sNumCores = 0;
|
|
|
|
NS_IMPL_ISUPPORTS(DecodePool, nsIObserver)
|
|
|
|
/* static */
|
|
void DecodePool::Initialize() {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
sNumCores = max<int32_t>(PR_GetNumberOfProcessors(), 1);
|
|
DecodePool::Singleton();
|
|
}
|
|
|
|
/* static */
|
|
DecodePool* DecodePool::Singleton() {
|
|
if (!sSingleton) {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
sSingleton = new DecodePool();
|
|
ClearOnShutdown(&sSingleton);
|
|
}
|
|
|
|
return sSingleton;
|
|
}
|
|
|
|
/* static */
|
|
uint32_t DecodePool::NumberOfCores() { return sNumCores; }
|
|
|
|
#if defined(XP_WIN)
|
|
class IOThreadIniter final : public Runnable {
|
|
public:
|
|
explicit IOThreadIniter() : Runnable("image::IOThreadIniter") {}
|
|
|
|
NS_IMETHOD Run() override {
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
CoInitialize(nullptr);
|
|
|
|
return NS_OK;
|
|
}
|
|
};
|
|
#endif
|
|
|
|
DecodePool::DecodePool() : mMutex("image::IOThread") {
|
|
// Initialize the I/O thread.
|
|
#if defined(XP_WIN)
|
|
// On Windows we use the io thread to get icons from the system. Any thread
|
|
// that makes system calls needs to call CoInitialize. And these system calls
|
|
// (SHGetFileInfo) should only be called from one thread at a time, in case
|
|
// we ever create more than one io thread. If win32k is locked down, we can't
|
|
// call SHGetFileInfo anyway, so we don't need the initializer.
|
|
nsCOMPtr<nsIRunnable> initer =
|
|
IsWin32kLockedDown() ? nullptr : new IOThreadIniter();
|
|
nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread), initer);
|
|
#else
|
|
nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread));
|
|
#endif
|
|
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread,
|
|
"Should successfully create image I/O thread");
|
|
|
|
nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
|
|
if (obsSvc) {
|
|
obsSvc->AddObserver(this, "xpcom-shutdown-threads", false);
|
|
}
|
|
}
|
|
|
|
DecodePool::~DecodePool() {
|
|
MOZ_ASSERT(NS_IsMainThread(), "Must shut down DecodePool on main thread!");
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DecodePool::Observe(nsISupports*, const char* aTopic, const char16_t*) {
|
|
MOZ_ASSERT(strcmp(aTopic, "xpcom-shutdown-threads") == 0, "Unexpected topic");
|
|
|
|
mShuttingDown = true;
|
|
|
|
nsCOMPtr<nsIThread> ioThread;
|
|
|
|
{
|
|
MutexAutoLock lock(mMutex);
|
|
ioThread.swap(mIOThread);
|
|
}
|
|
|
|
if (ioThread) {
|
|
ioThread->Shutdown();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool DecodePool::IsShuttingDown() const { return mShuttingDown; }
|
|
|
|
class DecodingTask final : public Task {
|
|
public:
|
|
explicit DecodingTask(RefPtr<IDecodingTask>&& aTask)
|
|
: Task(false, aTask->Priority() == TaskPriority::eLow
|
|
? EventQueuePriority::Normal
|
|
: EventQueuePriority::MediumHigh),
|
|
mTask(aTask) {}
|
|
|
|
bool Run() override {
|
|
mTask->Run();
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
RefPtr<IDecodingTask> mTask;
|
|
};
|
|
|
|
void DecodePool::AsyncRun(IDecodingTask* aTask) {
|
|
MOZ_ASSERT(aTask);
|
|
|
|
TaskController::Get()->AddTask(
|
|
MakeAndAddRef<DecodingTask>((RefPtr<IDecodingTask>(aTask))));
|
|
}
|
|
|
|
bool DecodePool::SyncRunIfPreferred(IDecodingTask* aTask,
|
|
const nsCString& aURI) {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
MOZ_ASSERT(aTask);
|
|
|
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPreferred",
|
|
GRAPHICS, aURI);
|
|
|
|
if (aTask->ShouldPreferSyncRun()) {
|
|
aTask->Run();
|
|
return true;
|
|
}
|
|
|
|
AsyncRun(aTask);
|
|
return false;
|
|
}
|
|
|
|
void DecodePool::SyncRunIfPossible(IDecodingTask* aTask,
|
|
const nsCString& aURI) {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
MOZ_ASSERT(aTask);
|
|
|
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPossible",
|
|
GRAPHICS, aURI);
|
|
|
|
aTask->Run();
|
|
}
|
|
|
|
already_AddRefed<nsIEventTarget> DecodePool::GetIOEventTarget() {
|
|
MutexAutoLock threadPoolLock(mMutex);
|
|
nsCOMPtr<nsIEventTarget> target = mIOThread;
|
|
return target.forget();
|
|
}
|
|
|
|
} // namespace image
|
|
} // namespace mozilla
|