Bug 1904436 - Implement private browser pinning using new Windows taskbar APIs r=nrishel,win-reviewers,rkraesig
Differential Revision: https://phabricator.services.mozilla.com/D214757
This commit is contained in:
@@ -9,10 +9,14 @@
|
|||||||
#include "nsWindowsHelpers.h"
|
#include "nsWindowsHelpers.h"
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include <shobjidl.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
#include "mozilla/ResultVariant.h"
|
#include "mozilla/ResultVariant.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
|
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||||
|
#include "mozilla/widget/WinTaskbar.h"
|
||||||
|
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
|
|
||||||
@@ -27,6 +31,7 @@ static mozilla::LazyLogModule sLog("Windows11TaskbarPinning");
|
|||||||
|
|
||||||
# include <inspectable.h>
|
# include <inspectable.h>
|
||||||
# include <roapi.h>
|
# include <roapi.h>
|
||||||
|
# include <shlobj_core.h>
|
||||||
# include <windows.services.store.h>
|
# include <windows.services.store.h>
|
||||||
# include <windows.foundation.h>
|
# include <windows.foundation.h>
|
||||||
# include <windows.ui.shell.h>
|
# include <windows.ui.shell.h>
|
||||||
@@ -101,8 +106,7 @@ static Result<ComPtr<ITaskbarManager>, HRESULT> InitializeTaskbar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
bool aCheckOnly, const nsAString& aAppUserModelId) {
|
||||||
nsAutoString aShortcutPath) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!NS_IsMainThread(),
|
MOZ_DIAGNOSTIC_ASSERT(!NS_IsMainThread(),
|
||||||
"PinCurrentAppToTaskbarWin11 should be called off main "
|
"PinCurrentAppToTaskbarWin11 should be called off main "
|
||||||
"thread only. It blocks, waiting on things to execute "
|
"thread only. It blocks, waiting on things to execute "
|
||||||
@@ -137,12 +141,38 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
|||||||
// Everything related to the taskbar and pinning must be done on the main /
|
// Everything related to the taskbar and pinning must be done on the main /
|
||||||
// user interface thread or Windows will cause them to fail.
|
// user interface thread or Windows will cause them to fail.
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
"PinCurrentAppToTaskbarWin11", [&event, &hr, &resultStatus, aCheckOnly] {
|
"PinCurrentAppToTaskbarWin11", [&event, &hr, &resultStatus, aCheckOnly,
|
||||||
auto CompletedOperations =
|
aumid = nsString(aAppUserModelId)] {
|
||||||
[&event, &resultStatus](Win11PinToTaskBarResultStatus status) {
|
// We eventualy want to call SetCurrentProcessExplicitAppUserModelID()
|
||||||
resultStatus = status;
|
// on the main thread as it is not thread safe and pinning is called
|
||||||
event.Set();
|
// numerous times in many different places. This is a hack used
|
||||||
};
|
// explicitly for the purpose of re-enabling private browser pinning
|
||||||
|
// as a stopgap and should not be replicated elsewhere.
|
||||||
|
// GenerateAppUserModelId needs to be called on the main thread as
|
||||||
|
// it checks against preferences.
|
||||||
|
nsAutoString primaryAumid;
|
||||||
|
mozilla::widget::WinTaskbar::GenerateAppUserModelID(primaryAumid,
|
||||||
|
false);
|
||||||
|
auto CompletedOperations = [&event, &resultStatus,
|
||||||
|
primaryAumid = nsString(primaryAumid)](
|
||||||
|
Win11PinToTaskBarResultStatus status) {
|
||||||
|
// Set AUMID back and ensure the icon is set correctly
|
||||||
|
HRESULT hr =
|
||||||
|
SetCurrentProcessExplicitAppUserModelID(primaryAumid.get());
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
TASKBAR_PINNING_LOG(LogLevel::Debug,
|
||||||
|
"Taskbar: reverting AUMID after pinning "
|
||||||
|
"operation failed. HRESULT = 0x%lx",
|
||||||
|
hr);
|
||||||
|
}
|
||||||
|
resultStatus = status;
|
||||||
|
event.Set();
|
||||||
|
};
|
||||||
|
|
||||||
|
hr = SetCurrentProcessExplicitAppUserModelID(aumid.get());
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
|
||||||
|
}
|
||||||
|
|
||||||
auto result = InitializeTaskbar();
|
auto result = InitializeTaskbar();
|
||||||
if (result.isErr()) {
|
if (result.isErr()) {
|
||||||
@@ -209,12 +239,22 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
|||||||
// be alive until the async functions complete, so they can be used as
|
// be alive until the async functions complete, so they can be used as
|
||||||
// references.
|
// references.
|
||||||
auto isPinnedCallback = Callback<IAsyncOperationCompletedHandler<
|
auto isPinnedCallback = Callback<IAsyncOperationCompletedHandler<
|
||||||
bool>>([taskbar, &event, &resultStatus, &hr](
|
bool>>([taskbar, &event, &resultStatus, &hr,
|
||||||
|
primaryAumid = nsString(primaryAumid)](
|
||||||
IAsyncOperation<bool>* asyncInfo,
|
IAsyncOperation<bool>* asyncInfo,
|
||||||
AsyncStatus status) mutable -> HRESULT {
|
AsyncStatus status) mutable -> HRESULT {
|
||||||
auto CompletedOperations =
|
auto CompletedOperations =
|
||||||
[&event,
|
[&event, &resultStatus,
|
||||||
&resultStatus](Win11PinToTaskBarResultStatus status) -> HRESULT {
|
primaryAumid](Win11PinToTaskBarResultStatus status) -> HRESULT {
|
||||||
|
// Set AUMID back and ensure the icon is set correctly
|
||||||
|
HRESULT hr =
|
||||||
|
SetCurrentProcessExplicitAppUserModelID(primaryAumid.get());
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
TASKBAR_PINNING_LOG(LogLevel::Debug,
|
||||||
|
"Taskbar: reverting AUMID after pinning "
|
||||||
|
"operation failed. HRESULT = 0x%lx",
|
||||||
|
hr);
|
||||||
|
}
|
||||||
resultStatus = status;
|
resultStatus = status;
|
||||||
event.Set();
|
event.Set();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -336,8 +376,7 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
|||||||
#else // MINGW32 implementation below
|
#else // MINGW32 implementation below
|
||||||
|
|
||||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
bool aCheckOnly, const nsAString& aAppUserModelId) {
|
||||||
nsAutoString aShortcutPath) {
|
|
||||||
return {S_OK, Win11PinToTaskBarResultStatus::NotSupported};
|
return {S_OK, Win11PinToTaskBarResultStatus::NotSupported};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ struct Win11PinToTaskBarResult {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
bool aCheckOnly, const nsAString& aAppUserModelId);
|
||||||
nsAutoString aShortcutPath);
|
|
||||||
|
|
||||||
#endif // SHELL_WINDOWS11TASKBARPINNING_H__
|
#endif // SHELL_WINDOWS11TASKBARPINNING_H__
|
||||||
|
|||||||
@@ -1730,7 +1730,7 @@ static nsresult PinCurrentAppToTaskbarImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto pinWithWin11TaskbarAPIResults =
|
auto pinWithWin11TaskbarAPIResults =
|
||||||
PinCurrentAppToTaskbarWin11(aCheckOnly, aAppUserModelId, shortcutPath);
|
PinCurrentAppToTaskbarWin11(aCheckOnly, aAppUserModelId);
|
||||||
switch (pinWithWin11TaskbarAPIResults.result) {
|
switch (pinWithWin11TaskbarAPIResults.result) {
|
||||||
case Win11PinToTaskBarResultStatus::NotSupported:
|
case Win11PinToTaskBarResultStatus::NotSupported:
|
||||||
// Fall through to the win 10 mechanism
|
// Fall through to the win 10 mechanism
|
||||||
|
|||||||
@@ -992,35 +992,37 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences::GetBool("browser.privateWindowSeparation.enabled", true) &&
|
{
|
||||||
(aInitData->mIsPrivate)) {
|
|
||||||
// Although permanent Private Browsing mode is indeed Private Browsing,
|
// Although permanent Private Browsing mode is indeed Private Browsing,
|
||||||
// we choose to make it look like regular Firefox in terms of the icon
|
// we choose to make it look like regular Firefox in terms of the icon
|
||||||
// it uses (which also means we shouldn't use the Private Browsing
|
// it uses (which also means we shouldn't use the Private Browsing
|
||||||
// AUMID).
|
// AUMID).
|
||||||
if (!StaticPrefs::browser_privatebrowsing_autostart()) {
|
bool usePrivateAumid =
|
||||||
RefPtr<IPropertyStore> pPropStore;
|
Preferences::GetBool("browser.privateWindowSeparation.enabled", true) &&
|
||||||
if (!FAILED(SHGetPropertyStoreForWindow(mWnd, IID_IPropertyStore,
|
(aInitData->mIsPrivate) &&
|
||||||
getter_AddRefs(pPropStore)))) {
|
!StaticPrefs::browser_privatebrowsing_autostart();
|
||||||
PROPVARIANT pv;
|
RefPtr<IPropertyStore> pPropStore;
|
||||||
nsAutoString aumid;
|
if (!FAILED(SHGetPropertyStoreForWindow(mWnd, IID_IPropertyStore,
|
||||||
// make sure we're using the private browsing AUMID so that taskbar
|
getter_AddRefs(pPropStore)))) {
|
||||||
// grouping works properly
|
PROPVARIANT pv;
|
||||||
Unused << NS_WARN_IF(
|
nsAutoString aumid;
|
||||||
!mozilla::widget::WinTaskbar::GenerateAppUserModelID(aumid, true));
|
// Make sure we're using the correct AUMID so that taskbar
|
||||||
if (!FAILED(InitPropVariantFromString(aumid.get(), &pv))) {
|
// grouping works properly
|
||||||
if (!FAILED(pPropStore->SetValue(PKEY_AppUserModel_ID, pv))) {
|
Unused << NS_WARN_IF(!mozilla::widget::WinTaskbar::GenerateAppUserModelID(
|
||||||
pPropStore->Commit();
|
aumid, usePrivateAumid));
|
||||||
}
|
if (!FAILED(InitPropVariantFromString(aumid.get(), &pv))) {
|
||||||
|
if (!FAILED(pPropStore->SetValue(PKEY_AppUserModel_ID, pv))) {
|
||||||
PropVariantClear(&pv);
|
pPropStore->Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PropVariantClear(&pv);
|
||||||
}
|
}
|
||||||
HICON icon = ::LoadIconW(::GetModuleHandleW(nullptr),
|
|
||||||
MAKEINTRESOURCEW(IDI_PBMODE));
|
|
||||||
SetBigIcon(icon);
|
|
||||||
SetSmallIcon(icon);
|
|
||||||
}
|
}
|
||||||
|
HICON icon = ::LoadIconW(
|
||||||
|
::GetModuleHandleW(nullptr),
|
||||||
|
MAKEINTRESOURCEW(usePrivateAumid ? IDI_PBMODE : IDI_APPICON));
|
||||||
|
SetBigIcon(icon);
|
||||||
|
SetSmallIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeviceNotifyHandle = InputDeviceUtils::RegisterNotification(mWnd);
|
mDeviceNotifyHandle = InputDeviceUtils::RegisterNotification(mWnd);
|
||||||
|
|||||||
Reference in New Issue
Block a user