Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit fc30d10

Browse files
committed
Bug 1685213 - Part 4: Convert pin check to async. r=bytesized
Differential Revision: https://phabricator.services.mozilla.com/D106346
1 parent fc0cc70 commit fc30d10

2 files changed

Lines changed: 62 additions & 13 deletions

File tree

browser/components/shell/nsIWindowsShellService.idl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,23 @@ interface nsIWindowsShellService : nsISupports
5757
void checkPinCurrentAppToTaskbar();
5858

5959
/*
60-
* Search for the current executable among taskbar pins, return true if found
60+
* Search for the current executable among taskbar pins
6161
*
62-
* NOTE: This method probably shouldn't be used on the main thread, it
63-
* performs blocking disk I/O.
62+
* NOTE: Can only be run on the main thread, but the actual work occurs on a
63+
* background thread.
6464
*
6565
* NOTE: It is possible for the check to fail even when a taskbar pin refers
6666
* to this executable, if the paths differ due to e.g. symlinks.
6767
* It is also possible for the check to succeed with a shortcut that doesn't
6868
* actually appear on the taskbar.
6969
* These cases should be rare.
70+
*
71+
* @return Promise that always resolves, true if pinned, false otherwise
72+
* @throws NS_ERROR_NOT_SAME_THREAD if not run on the main thread
73+
*
7074
*/
71-
boolean isCurrentAppPinnedToTaskbar();
75+
[implicit_jscontext]
76+
Promise isCurrentAppPinnedToTaskbarAsync();
7277

7378
/*
7479
* Determine where a given shortcut likely appears in the shell.

browser/components/shell/nsWindowsShellService.cpp

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "nsXULAppAPI.h"
2828
#include "mozilla/WindowsVersion.h"
2929
#include "mozilla/dom/Element.h"
30+
#include "mozilla/dom/Promise.h"
31+
#include "mozilla/ErrorResult.h"
3032
#include "mozilla/gfx/2D.h"
3133
#include "WindowsDefaultBrowser.h"
3234

@@ -883,26 +885,23 @@ nsWindowsShellService::CheckPinCurrentAppToTaskbar() {
883885
return PinCurrentAppToTaskbarImpl(/* aCheckOnly */ true);
884886
}
885887

886-
NS_IMETHODIMP
887-
nsWindowsShellService::IsCurrentAppPinnedToTaskbar(/* out */ bool* aIsPinned) {
888-
*aIsPinned = false;
889-
888+
static bool IsCurrentAppPinnedToTaskbarSync() {
890889
wchar_t exePath[MAXPATHLEN] = {};
891890
if (NS_WARN_IF(NS_FAILED(BinaryPath::GetLong(exePath)))) {
892-
return NS_OK;
891+
return false;
893892
}
894893

895894
wchar_t folderChars[MAX_PATH] = {};
896895
HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_APPDATA, nullptr,
897896
SHGFP_TYPE_CURRENT, folderChars);
898897
if (NS_WARN_IF(FAILED(hr))) {
899-
return NS_OK;
898+
return false;
900899
}
901900

902901
nsAutoString folder;
903902
folder.Assign(folderChars);
904903
if (NS_WARN_IF(folder.IsEmpty())) {
905-
return NS_OK;
904+
return false;
906905
}
907906
if (folder[folder.Length() - 1] != '\\') {
908907
folder.AppendLiteral("\\");
@@ -917,12 +916,13 @@ nsWindowsShellService::IsCurrentAppPinnedToTaskbar(/* out */ bool* aIsPinned) {
917916
HANDLE hFindFile = FindFirstFileW(pattern.get(), &findData);
918917
if (hFindFile == INVALID_HANDLE_VALUE) {
919918
Unused << NS_WARN_IF(GetLastError() != ERROR_FILE_NOT_FOUND);
920-
return NS_OK;
919+
return false;
921920
}
922921
// Past this point we don't return until the end of the function,
923922
// when FindClose() is called.
924923

925924
// Check all shortcuts until a match is found
925+
bool isPinned = false;
926926
do {
927927
nsAutoString fileName;
928928
fileName.Assign(folder);
@@ -965,13 +965,57 @@ nsWindowsShellService::IsCurrentAppPinnedToTaskbar(/* out */ bool* aIsPinned) {
965965
// NOTE: Because this compares the path directly, it is possible to
966966
// have a false negative mismatch.
967967
if (wcsnicmp(storedExePath, exePath, MAXPATHLEN) == 0) {
968-
*aIsPinned = true;
968+
isPinned = true;
969969
break;
970970
}
971971
} while (FindNextFileW(hFindFile, &findData));
972972

973973
FindClose(hFindFile);
974974

975+
return isPinned;
976+
}
977+
978+
NS_IMETHODIMP
979+
nsWindowsShellService::IsCurrentAppPinnedToTaskbarAsync(
980+
JSContext* aCx, /* out */ dom::Promise** aPromise) {
981+
if (!NS_IsMainThread()) {
982+
return NS_ERROR_NOT_SAME_THREAD;
983+
}
984+
985+
ErrorResult rv;
986+
RefPtr<dom::Promise> promise =
987+
dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
988+
if (MOZ_UNLIKELY(rv.Failed())) {
989+
return rv.StealNSResult();
990+
}
991+
992+
// A holder to pass the promise through the background task and back to
993+
// the main thread when finished.
994+
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
995+
"IsCurrentAppPinnedToTaskbarAsync promise", promise);
996+
997+
NS_DispatchBackgroundTask(
998+
NS_NewRunnableFunction(
999+
"IsCurrentAppPinnedToTaskbarAsync",
1000+
[promiseHolder = std::move(promiseHolder)] {
1001+
bool isPinned = false;
1002+
1003+
HRESULT hr = CoInitialize(nullptr);
1004+
if (SUCCEEDED(hr)) {
1005+
isPinned = IsCurrentAppPinnedToTaskbarSync();
1006+
CoUninitialize();
1007+
}
1008+
1009+
// Dispatch back to the main thread to resolve the promise.
1010+
NS_DispatchToMainThread(NS_NewRunnableFunction(
1011+
"IsCurrentAppPinnedToTaskbarAsync callback",
1012+
[isPinned, promiseHolder = std::move(promiseHolder)] {
1013+
promiseHolder.get()->get()->MaybeResolve(isPinned);
1014+
}));
1015+
}),
1016+
NS_DISPATCH_EVENT_MAY_BLOCK);
1017+
1018+
promise.forget(aPromise);
9751019
return NS_OK;
9761020
}
9771021

0 commit comments

Comments
 (0)