Bug 1863636 - Folded shortcut creation required for taskbar tabs into nsWindowsShellService r=mhughes

Differential Revision: https://phabricator.services.mozilla.com/D192998
This commit is contained in:
Nipun Shukla 2023-11-20 16:26:03 +00:00
parent 2b372da017
commit 8a0825c269
3 changed files with 95 additions and 19 deletions

View file

@ -162,6 +162,9 @@ const PREF_PRIVATE_BROWSING_SHORTCUT_CREATED =
// Whether this launch was initiated by the OS. A launch-on-login will contain
// the "os-autostart" flag in the initial launch command line.
let gThisInstanceIsLaunchOnLogin = false;
// Whether this launch was initiated by a taskbar tab shortcut. A launch from
// a taskbar tab shortcut will contain the "taskbar-tab" flag.
let gThisInstanceIsTaskbarTab = false;
/**
* Fission-compatible JSProcess implementations.
@ -1223,6 +1226,7 @@ BrowserGlue.prototype = {
break;
case "app-startup":
this._earlyBlankFirstPaint(subject);
gThisInstanceIsTaskbarTab = subject.handleFlag("taskbar-tab", false);
gThisInstanceIsLaunchOnLogin = subject.handleFlag(
"os-autostart",
false
@ -2601,7 +2605,11 @@ BrowserGlue.prototype = {
classification = "Other";
}
}
// Because of how taskbar tabs work, it may be classifed as a taskbar
// shortcut, in which case we want to overwrite it.
if (gThisInstanceIsTaskbarTab) {
classification = "TaskbarTab";
}
Services.telemetry.scalarSet(
"os.environment.launch_method",
classification

View file

@ -126,6 +126,46 @@ interface nsIWindowsShellService : nsISupports
[implicit_jscontext]
Promise isCurrentAppPinnedToTaskbarAsync(in AString aumid);
/*
* Similar to createShortcut except it removes most of the checking in that
* function that ensures we are pinning a Firefox executable instead allowing
* any shortcut to be pinned.
*
* This function should not be called unless it is certain that it's
* necessary given how few checks there are within.
* @param aShortcutPath
* A path to the .lnk file that should be pinned to the taskbar.
* @throws NS_ERROR_FAILURE
* If the COM service could not be initialized
* @throws NS_ERROR_FILE_NOT_FOUND
* If aShortcutPath cannot be found
* @throws NS_ERROR_NOT_AVAILABLE
* If the taskbar pinning service cannot be initialized
* @throws NS_ERROR_FILE_ACCESS_DENIED
* If the taskbar pins cannot be modified
*/
void pinShortcutToTaskbar(in AString aShortcutPath);
/*
* This function is a counterpart to pinShortcutToTaskbar and allows
* the unpinning of any shortcut, including non-Firefox executables,
* without the checks of createShortcut.
*
* This function should not be called unless it is certain that it's
* necessary given how few checks there are within.
* @param aShortcutPath
* A path to the .lnk file that should be pinned to the taskbar.
* @throws NS_ERROR_FAILURE
* If the COM service could not be initialized
* @throws NS_ERROR_FILE_NOT_FOUND
* If aShortcutPath cannot be found
* @throws NS_ERROR_NOT_AVAILABLE
* If the taskbar pinning service cannot be initialized
* @throws NS_ERROR_FILE_ACCESS_DENIED
* If the taskbar pins cannot be modified
*/
void unpinShortcutFromTaskbar(in AString aShortcutPath);
/*
* Determine where a given shortcut likely appears in the shell.
*

View file

@ -1278,9 +1278,8 @@ static bool IsCurrentAppPinnedToTaskbarSync(const nsAString& aumid) {
return isPinned;
}
static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
const nsAString& aAppUserModelId,
nsAutoString aShortcutPath) {
static nsresult ManageShortcutTaskbarPins(bool aCheckOnly, bool aPinType,
const nsAString& aShortcutPath) {
// This enum is likely only used for Windows telemetry, INT_MAX is chosen to
// avoid confusion with existing uses.
enum PINNEDLISTMODIFYCALLER { PLMC_INT_MAX = INT_MAX };
@ -1325,36 +1324,65 @@ static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
}
};
mozilla::UniquePtr<__unaligned ITEMIDLIST, ILFreeDeleter> path(
ILCreateFromPathW(aShortcutPath.get()));
if (NS_WARN_IF(!path)) {
HRESULT hr = CoInitialize(nullptr);
if (FAILED(hr)) {
return NS_ERROR_FAILURE;
}
const struct ComUninitializer {
~ComUninitializer() { CoUninitialize(); }
} kCUi;
mozilla::UniquePtr<__unaligned ITEMIDLIST, ILFreeDeleter> path(
ILCreateFromPathW(nsString(aShortcutPath).get()));
if (NS_WARN_IF(!path)) {
return NS_ERROR_FILE_NOT_FOUND;
}
IPinnedList3* pinnedList = nullptr;
HRESULT hr =
CoCreateInstance(CLSID_TaskbandPin, nullptr, CLSCTX_INPROC_SERVER,
hr = CoCreateInstance(CLSID_TaskbandPin, NULL, CLSCTX_INPROC_SERVER,
IID_IPinnedList3, (void**)&pinnedList);
if (FAILED(hr) || !pinnedList) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!aCheckOnly) {
bool isPinned = false;
isPinned = IsCurrentAppPinnedToTaskbarSync(aAppUserModelId);
if (!isPinned) {
hr = pinnedList->vtbl->Modify(pinnedList, nullptr, path.get(),
PLMC_INT_MAX);
}
hr = pinnedList->vtbl->Modify(pinnedList, aPinType ? NULL : path.get(),
aPinType ? path.get() : NULL, PLMC_INT_MAX);
}
pinnedList->vtbl->Release(pinnedList);
if (FAILED(hr)) {
return NS_ERROR_FAILURE;
} else {
return NS_OK;
return NS_ERROR_FILE_ACCESS_DENIED;
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::PinShortcutToTaskbar(const nsAString& aShortcutPath) {
const bool pinType = true; // true means pin
const bool runInTestMode = false;
return ManageShortcutTaskbarPins(runInTestMode, pinType, aShortcutPath);
}
NS_IMETHODIMP
nsWindowsShellService::UnpinShortcutFromTaskbar(
const nsAString& aShortcutPath) {
const bool pinType = false; // false means unpin
const bool runInTestMode = false;
return ManageShortcutTaskbarPins(runInTestMode, pinType, aShortcutPath);
}
static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
const nsAString& aAppUserModelId,
nsAutoString aShortcutPath) {
// The behavior here is identical if we're only checking or if we try to pin
// but the app is already pinned so we update the variable accordingly.
if (!aCheckOnly) {
aCheckOnly = !IsCurrentAppPinnedToTaskbarSync(aAppUserModelId);
}
const bool pinType = true; // true means pin
return ManageShortcutTaskbarPins(aCheckOnly, pinType, aShortcutPath);
}
static nsresult PinCurrentAppToTaskbarImpl(