зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1744362 - Part 7: support code for about:third-party r=handyman
Differential Revision: https://phabricator.services.mozilla.com/D164489
This commit is contained in:
Родитель
acc64a126e
Коммит
78bf088bb7
|
@ -495,11 +495,11 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
|
||||||
job = CreateJobAndAssignProcess(process.get());
|
job = CreateJobAndAssignProcess(process.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool disableDynamicBlocklist =
|
bool disableDynamicBlocklist = IsDynamicBlocklistDisabled(
|
||||||
isSafeMode.value() ||
|
isSafeMode.value(),
|
||||||
mozilla::CheckArg(
|
mozilla::CheckArg(
|
||||||
argc, argv, mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch,
|
argc, argv, mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch,
|
||||||
nullptr, mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND;
|
nullptr, mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND);
|
||||||
LauncherVoidResult setupResult = PostCreationSetup(
|
LauncherVoidResult setupResult = PostCreationSetup(
|
||||||
argv[0], process.get(), mainThread.get(), deelevationStatus,
|
argv[0], process.get(), mainThread.get(), deelevationStatus,
|
||||||
isSafeMode.value(), disableDynamicBlocklist, blocklistFileName);
|
isSafeMode.value(), disableDynamicBlocklist, blocklistFileName);
|
||||||
|
|
|
@ -1373,8 +1373,10 @@ bool WindowsProcessLauncher::DoSetup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef HAS_DLL_BLOCKLIST
|
# ifdef HAS_DLL_BLOCKLIST
|
||||||
if (CommandLine::ForCurrentProcess()->HasSwitch(
|
if (IsDynamicBlocklistDisabled(
|
||||||
UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch))) {
|
gSafeMode,
|
||||||
|
CommandLine::ForCurrentProcess()->HasSwitch(UTF8ToWide(
|
||||||
|
mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch)))) {
|
||||||
mCmdLine->AppendLooseValue(
|
mCmdLine->AppendLooseValue(
|
||||||
UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch));
|
UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,18 @@
|
||||||
#include "AboutThirdParty.h"
|
#include "AboutThirdParty.h"
|
||||||
|
|
||||||
#include "AboutThirdPartyUtils.h"
|
#include "AboutThirdPartyUtils.h"
|
||||||
|
#include "base/command_line.h"
|
||||||
|
#include "base/string_util.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/DynamicBlocklist.h"
|
||||||
|
#include "mozilla/GeckoArgs.h"
|
||||||
#include "mozilla/NativeNt.h"
|
#include "mozilla/NativeNt.h"
|
||||||
|
#include "mozilla/ScopeExit.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
|
#include "mozilla/WinDllServices.h"
|
||||||
#include "MsiDatabase.h"
|
#include "MsiDatabase.h"
|
||||||
|
#include "nsAppRunner.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsIWindowsRegKey.h"
|
#include "nsIWindowsRegKey.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
@ -56,6 +63,20 @@ void EnumSubkeys(nsIWindowsRegKey* aRegBase, const CallbackT& aCallback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Span<const DllBlockInfo> GetDynamicBlocklistSpan(
|
||||||
|
RefPtr<DllServices>&& aDllSvc) {
|
||||||
|
if (!aDllSvc) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nt::SharedSection* sharedSection = aDllSvc->GetSharedSection();
|
||||||
|
if (!sharedSection) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sharedSection->GetDynamicBlocklist();
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
InstallLocationComparator::InstallLocationComparator(const nsAString& aFilePath)
|
InstallLocationComparator::InstallLocationComparator(const nsAString& aFilePath)
|
||||||
|
@ -655,6 +676,15 @@ void AboutThirdParty::BackgroundThread() {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
MOZ_ASSERT(mWorkerState == WorkerState::Running);
|
MOZ_ASSERT(mWorkerState == WorkerState::Running);
|
||||||
|
|
||||||
|
auto cleanup = MakeScopeExit(
|
||||||
|
[self = RefPtr{this}] { self->mWorkerState = WorkerState::Done; });
|
||||||
|
|
||||||
|
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||||
|
if (!dllSvc) {
|
||||||
|
// Probably we're shutting down. Bail out before expensive tasks.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KnownModule::EnumAll(
|
KnownModule::EnumAll(
|
||||||
[self = RefPtr{this}](const nsString& aDllPath, KnownModuleType aType) {
|
[self = RefPtr{this}](const nsString& aDllPath, KnownModuleType aType) {
|
||||||
self->AddKnownModule(aDllPath, aType);
|
self->AddKnownModule(aDllPath, aType);
|
||||||
|
@ -663,11 +693,56 @@ void AboutThirdParty::BackgroundThread() {
|
||||||
InstalledApplications apps;
|
InstalledApplications apps;
|
||||||
apps.Collect(mComponentPaths, mLocations);
|
apps.Collect(mComponentPaths, mLocations);
|
||||||
|
|
||||||
mWorkerState = WorkerState::Done;
|
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
Span<const DllBlockInfo> blocklist =
|
||||||
|
GetDynamicBlocklistSpan(std::move(dllSvc));
|
||||||
|
if (blocklist.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto info = blocklist.begin(); info != blocklist.end(); ++info) {
|
||||||
|
if (!info->mName.Buffer || !info->mName.Length ||
|
||||||
|
info->mName.Length > info->mName.MaximumLength ||
|
||||||
|
info->mMaxVersion != DllBlockInfo::ALL_VERSIONS ||
|
||||||
|
info->mFlags != DllBlockInfo::Flags::FLAGS_DEFAULT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString name(info->mName.Buffer, info->mName.Length / sizeof(wchar_t));
|
||||||
|
mDynamicBlocklist.Insert(std::move(name));
|
||||||
|
}
|
||||||
|
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AboutThirdParty::GetBlockedModuleNames(
|
||||||
|
const nsTArray<nsString>& aLoadedModuleNames,
|
||||||
|
nsTArray<nsString>& aBlockedModuleNames) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
aBlockedModuleNames.SetLength(0);
|
||||||
|
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
if (mWorkerState != WorkerState::Done) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// Blocklist entries are case-insensitive
|
||||||
|
nsTHashSet<nsStringCaseInsensitiveHashKey> loadedModuleNameSet;
|
||||||
|
for (const nsString& loadedModuleName : aLoadedModuleNames) {
|
||||||
|
loadedModuleNameSet.Insert(loadedModuleName);
|
||||||
|
}
|
||||||
|
for (const auto& blocklistEntry : mDynamicBlocklist) {
|
||||||
|
// Only return entries that we haven't already tried to load,
|
||||||
|
// because those will already show up in the page
|
||||||
|
if (!loadedModuleNameSet.Contains(blocklistEntry)) {
|
||||||
|
aBlockedModuleNames.AppendElement(blocklistEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP AboutThirdParty::LookupModuleType(const nsAString& aLeafName,
|
NS_IMETHODIMP AboutThirdParty::LookupModuleType(const nsAString& aLeafName,
|
||||||
uint32_t* aResult) {
|
uint32_t* aResult) {
|
||||||
|
static_assert(static_cast<uint32_t>(KnownModuleType::Last) <= 32,
|
||||||
|
"Too many flags in KnownModuleType");
|
||||||
constexpr uint32_t kShellExtensions =
|
constexpr uint32_t kShellExtensions =
|
||||||
1u << static_cast<uint32_t>(KnownModuleType::IconOverlay) |
|
1u << static_cast<uint32_t>(KnownModuleType::IconOverlay) |
|
||||||
1u << static_cast<uint32_t>(KnownModuleType::ContextMenuHandler) |
|
1u << static_cast<uint32_t>(KnownModuleType::ContextMenuHandler) |
|
||||||
|
@ -687,9 +762,15 @@ NS_IMETHODIMP AboutThirdParty::LookupModuleType(const nsAString& aLeafName,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
if (mDynamicBlocklist.Contains(aLeafName)) {
|
||||||
|
*aResult |= nsIAboutThirdParty::ModuleType_BlockedByUser;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
if (!mKnownModules.Get(aLeafName, &flags)) {
|
if (!mKnownModules.Get(aLeafName, &flags)) {
|
||||||
*aResult = nsIAboutThirdParty::ModuleType_Unknown;
|
*aResult |= nsIAboutThirdParty::ModuleType_Unknown;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,6 +784,7 @@ NS_IMETHODIMP AboutThirdParty::LookupModuleType(const nsAString& aLeafName,
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP AboutThirdParty::LookupApplication(
|
NS_IMETHODIMP AboutThirdParty::LookupApplication(
|
||||||
const nsAString& aModulePath, nsIInstalledApplication** aResult) {
|
const nsAString& aModulePath, nsIInstalledApplication** aResult) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
@ -739,6 +821,76 @@ NS_IMETHODIMP AboutThirdParty::LookupApplication(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AboutThirdParty::GetIsDynamicBlocklistAvailable(
|
||||||
|
bool* aIsDynamicBlocklistAvailable) {
|
||||||
|
*aIsDynamicBlocklistAvailable =
|
||||||
|
!GetDynamicBlocklistSpan(DllServices::Get()).IsEmpty();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AboutThirdParty::GetIsDynamicBlocklistDisabled(
|
||||||
|
bool* aIsDynamicBlocklistDisabled) {
|
||||||
|
*aIsDynamicBlocklistDisabled = IsDynamicBlocklistDisabled(
|
||||||
|
gSafeMode, CommandLine::ForCurrentProcess()->HasSwitch(UTF8ToWide(
|
||||||
|
mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch)));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AboutThirdParty::UpdateBlocklist(const nsAString& aLeafName,
|
||||||
|
bool aNewBlockStatus,
|
||||||
|
JSContext* aCx,
|
||||||
|
dom::Promise** aResult) {
|
||||||
|
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
|
||||||
|
MOZ_ASSERT(global);
|
||||||
|
|
||||||
|
ErrorResult result;
|
||||||
|
RefPtr<dom::Promise> promise(dom::Promise::Create(global, result));
|
||||||
|
if (NS_WARN_IF(result.Failed())) {
|
||||||
|
return result.StealNSResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto returnPromise = MakeScopeExit([&] { promise.forget(aResult); });
|
||||||
|
|
||||||
|
if (aNewBlockStatus) {
|
||||||
|
mDynamicBlocklist.Insert(aLeafName);
|
||||||
|
} else {
|
||||||
|
mDynamicBlocklist.Remove(aLeafName);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newTask = MakeUnique<DynamicBlocklistWriter>(promise, mDynamicBlocklist);
|
||||||
|
if (!newTask->IsReady()) {
|
||||||
|
promise->MaybeReject(NS_ERROR_CANNOT_CONVERT_DATA);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<DynamicBlocklistWriter> oldTask(
|
||||||
|
mPendingWriter.exchange(newTask.release()));
|
||||||
|
if (oldTask) {
|
||||||
|
oldTask->Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = NS_DispatchBackgroundTask(
|
||||||
|
NS_NewRunnableFunction(__func__,
|
||||||
|
[self = RefPtr{this}]() {
|
||||||
|
UniquePtr<DynamicBlocklistWriter> task(
|
||||||
|
self->mPendingWriter.exchange(nullptr));
|
||||||
|
if (task) {
|
||||||
|
task->Run();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
promise->MaybeReject(rv);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
#else
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<BackgroundThreadPromise> AboutThirdParty::CollectSystemInfoAsync() {
|
RefPtr<BackgroundThreadPromise> AboutThirdParty::CollectSystemInfoAsync() {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,12 @@
|
||||||
#include "nsInterfaceHashtable.h"
|
#include "nsInterfaceHashtable.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsTHashMap.h"
|
#include "nsTHashMap.h"
|
||||||
|
#include "nsTHashSet.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class DynamicBlocklistWriter;
|
||||||
|
|
||||||
using InstallLocationT =
|
using InstallLocationT =
|
||||||
CompactPair<nsString, nsCOMPtr<nsIInstalledApplication>>;
|
CompactPair<nsString, nsCOMPtr<nsIInstalledApplication>>;
|
||||||
using ComponentPathMapT = nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,
|
using ComponentPathMapT = nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,
|
||||||
|
@ -78,6 +81,11 @@ class AboutThirdParty final : public nsIAboutThirdParty {
|
||||||
ComponentPathMapT mComponentPaths;
|
ComponentPathMapT mComponentPaths;
|
||||||
nsTArray<InstallLocationT> mLocations;
|
nsTArray<InstallLocationT> mLocations;
|
||||||
|
|
||||||
|
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||||
|
Atomic<DynamicBlocklistWriter*> mPendingWriter;
|
||||||
|
nsTHashSet<nsStringCaseInsensitiveHashKey> mDynamicBlocklist;
|
||||||
|
#endif
|
||||||
|
|
||||||
~AboutThirdParty() = default;
|
~AboutThirdParty() = default;
|
||||||
void BackgroundThread();
|
void BackgroundThread();
|
||||||
void AddKnownModule(const nsString& aPath, KnownModuleType aType);
|
void AddKnownModule(const nsString& aPath, KnownModuleType aType);
|
||||||
|
|
|
@ -33,3 +33,5 @@ if CONFIG["ENABLE_TESTS"]:
|
||||||
DIRS += ["tests/gtest"]
|
DIRS += ["tests/gtest"]
|
||||||
|
|
||||||
TEST_DIRS += ["tests/TestShellEx"]
|
TEST_DIRS += ["tests/TestShellEx"]
|
||||||
|
|
||||||
|
include("/ipc/chromium/chromium-config.mozbuild")
|
||||||
|
|
|
@ -21,6 +21,7 @@ interface nsIAboutThirdParty : nsISupports
|
||||||
const unsigned long ModuleType_Unknown = 1 << 0;
|
const unsigned long ModuleType_Unknown = 1 << 0;
|
||||||
const unsigned long ModuleType_IME = 1 << 1;
|
const unsigned long ModuleType_IME = 1 << 1;
|
||||||
const unsigned long ModuleType_ShellExtension = 1 << 2;
|
const unsigned long ModuleType_ShellExtension = 1 << 2;
|
||||||
|
const unsigned long ModuleType_BlockedByUser = 1 << 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a bitwise combination of the ModuleType_* flags
|
* Returns a bitwise combination of the ModuleType_* flags
|
||||||
|
@ -34,6 +35,29 @@ interface nsIAboutThirdParty : nsISupports
|
||||||
*/
|
*/
|
||||||
nsIInstalledApplication lookupApplication(in AString aModulePath);
|
nsIInstalledApplication lookupApplication(in AString aModulePath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of modules that have been blocklisted but have not
|
||||||
|
* attempted to load.
|
||||||
|
*/
|
||||||
|
void getBlockedModuleNames(in Array<AString> aLoadedModuleNames, out Array<AString> aBlockedModuleNames);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if DynamicBlocklist is available.
|
||||||
|
*/
|
||||||
|
readonly attribute bool isDynamicBlocklistAvailable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if DynamicBlocklist is available but disabled.
|
||||||
|
*/
|
||||||
|
readonly attribute bool isDynamicBlocklistDisabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or remove an entry from the dynamic blocklist and save
|
||||||
|
* the resulting file.
|
||||||
|
*/
|
||||||
|
[implicit_jscontext] Promise updateBlocklist(in AString aLeafName,
|
||||||
|
in boolean aNewBlockStatus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a background task to collect system information and resolves
|
* Posts a background task to collect system information and resolves
|
||||||
* the returned promise when the task is finished.
|
* the returned promise when the task is finished.
|
||||||
|
|
|
@ -327,4 +327,13 @@ struct FreeSidDeleter {
|
||||||
// This typedef will work for storing a PSID in a UniquePtr and should make
|
// This typedef will work for storing a PSID in a UniquePtr and should make
|
||||||
// things a bit more readable.
|
// things a bit more readable.
|
||||||
typedef mozilla::UniquePtr<void, FreeSidDeleter> UniqueSidPtr;
|
typedef mozilla::UniquePtr<void, FreeSidDeleter> UniqueSidPtr;
|
||||||
|
|
||||||
|
// One caller of this function is early in startup and several others are not,
|
||||||
|
// so they have different ways of determining the two parameters. This function
|
||||||
|
// exists just so any future code that needs to determine whether the dynamic
|
||||||
|
// blocklist is disabled remembers to check whether safe mode is active.
|
||||||
|
inline bool IsDynamicBlocklistDisabled(bool isSafeMode,
|
||||||
|
bool hasCommandLineDisableArgument) {
|
||||||
|
return isSafeMode || hasCommandLineDisableArgument;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче