Bug 1766434 - Make checking for and pinning app to taskbar async on Windows r=bhearsum

Previously `nsIWindowsShellService::{Check,}PinCurrrentAppToTaskbar` was doing
main thread IO. They have been replaced with async versions that do their work
on a background thread.

Differential Revision: https://phabricator.services.mozilla.com/D145244
This commit is contained in:
Barret Rennie
2022-05-05 18:48:44 +00:00
parent 6fe8251756
commit 02c2614389
7 changed files with 120 additions and 49 deletions

View File

@@ -967,7 +967,7 @@ static nsresult GetShortcutPath(int aCSIDL, bool aPrivateBrowsing,
// NS_ERROR_FILE_ALREADY_EXISTS if the shortcut exists but doesn't match the
// current app
// NS_OK if the shortcut matches
static nsresult GetMatchingShortcut(int aCSIDL, const nsAutoString& aAUMID,
static nsresult GetMatchingShortcut(int aCSIDL, const nsAString& aAUMID,
const wchar_t aExePath[MAXPATHLEN],
bool aPrivateBrowsing,
/* out */ nsAutoString& aShortcutPath) {
@@ -1250,17 +1250,11 @@ static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
}
static nsresult PinCurrentAppToTaskbarImpl(bool aCheckOnly,
bool aPrivateBrowsing) {
if (IsWin10OrLater() && !IsWin10Sep2018UpdateOrLater()) {
// First available on 1809
return NS_ERROR_NOT_AVAILABLE;
}
nsAutoString aumid;
if (NS_WARN_IF(!mozilla::widget::WinTaskbar::GenerateAppUserModelID(
aumid, aPrivateBrowsing))) {
return NS_ERROR_FAILURE;
}
bool aPrivateBrowsing,
const nsAString& aAppUserModelId) {
MOZ_DIAGNOSTIC_ASSERT(
!NS_IsMainThread(),
"PinCurrentAppToTaskbarImpl should be called off main thread only");
wchar_t exePath[MAXPATHLEN] = {};
if (NS_WARN_IF(NS_FAILED(BinaryPath::GetLong(exePath)))) {
@@ -1276,8 +1270,8 @@ static nsresult PinCurrentAppToTaskbarImpl(bool aCheckOnly,
// GetMatchingShortcut may fail when the exe path doesn't match, even
// if it refers to the same file. This should be rare, and the worst
// outcome would be failure to pin, so the risk is acceptable.
nsresult rv = GetMatchingShortcut(shortcutCSIDLs[i], aumid, exePath,
aPrivateBrowsing, shortcutPath);
nsresult rv = GetMatchingShortcut(shortcutCSIDLs[i], aAppUserModelId,
exePath, aPrivateBrowsing, shortcutPath);
if (NS_SUCCEEDED(rv)) {
break;
} else {
@@ -1333,8 +1327,9 @@ static nsresult PinCurrentAppToTaskbarImpl(bool aCheckOnly,
// needs an index.
iconIndex--;
rv = CreateShortcutImpl(exeFile, arguments, desc, exeFile, iconIndex, aumid,
FOLDERID_StartMenu, linkName, shortcutPath);
rv = CreateShortcutImpl(exeFile, arguments, desc, exeFile, iconIndex,
aAppUserModelId, FOLDERID_StartMenu, linkName,
shortcutPath);
if (!NS_SUCCEEDED(rv)) {
return NS_ERROR_FILE_NOT_FOUND;
}
@@ -1347,15 +1342,81 @@ static nsresult PinCurrentAppToTaskbarImpl(bool aCheckOnly,
}
}
NS_IMETHODIMP
nsWindowsShellService::PinCurrentAppToTaskbar(bool aPrivateBrowsing = false) {
return PinCurrentAppToTaskbarImpl(/* aCheckOnly */ false, aPrivateBrowsing);
static nsresult PinCurrentAppToTaskbarAsyncImpl(bool aCheckOnly,
bool aPrivateBrowsing,
JSContext* aCx,
dom::Promise** aPromise) {
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
// First available on 1809
if (IsWin10OrLater() && !IsWin10Sep2018UpdateOrLater()) {
return NS_ERROR_NOT_AVAILABLE;
}
ErrorResult rv;
RefPtr<dom::Promise> promise =
dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
if (MOZ_UNLIKELY(rv.Failed())) {
return rv.StealNSResult();
}
nsAutoString aumid;
if (NS_WARN_IF(!mozilla::widget::WinTaskbar::GenerateAppUserModelID(
aumid, aPrivateBrowsing))) {
return NS_ERROR_FAILURE;
}
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
"CheckPinCurrentAppToTaskbarAsync promise", promise);
NS_DispatchBackgroundTask(
NS_NewRunnableFunction(
"CheckPinCurrentAppToTaskbarAsync",
[aCheckOnly, aPrivateBrowsing, aumid = nsString{aumid},
promiseHolder = std::move(promiseHolder)] {
nsresult rv = NS_ERROR_FAILURE;
HRESULT hr = CoInitialize(nullptr);
if (SUCCEEDED(hr)) {
rv = PinCurrentAppToTaskbarImpl(aCheckOnly, aPrivateBrowsing,
aumid);
CoUninitialize();
}
NS_DispatchToMainThread(NS_NewRunnableFunction(
"CheckPinCurrentAppToTaskbarAsync callback",
[rv, promiseHolder = std::move(promiseHolder)] {
dom::Promise* promise = promiseHolder.get()->get();
if (NS_SUCCEEDED(rv)) {
promise->MaybeResolveWithUndefined();
} else {
promise->MaybeReject(rv);
}
}));
}),
NS_DISPATCH_EVENT_MAY_BLOCK);
promise.forget(aPromise);
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::CheckPinCurrentAppToTaskbar(
bool aPrivateBrowsing = false) {
return PinCurrentAppToTaskbarImpl(/* aCheckOnly */ true, aPrivateBrowsing);
nsWindowsShellService::PinCurrentAppToTaskbarAsync(bool aPrivateBrowsing,
JSContext* aCx,
dom::Promise** aPromise) {
return PinCurrentAppToTaskbarAsyncImpl(/* aCheckOnly */ false,
aPrivateBrowsing, aCx, aPromise);
}
NS_IMETHODIMP
nsWindowsShellService::CheckPinCurrentAppToTaskbarAsync(
bool aPrivateBrowsing, JSContext* aCx, dom::Promise** aPromise) {
return PinCurrentAppToTaskbarAsyncImpl(/* aCheckOnly = */ true,
aPrivateBrowsing, aCx, aPromise);
}
static bool IsCurrentAppPinnedToTaskbarSync(const nsAutoString& aumid) {