Bug 1879975 - Adding in logging for taskbar debugging r=nrishel,mpohle

Differential Revision: https://phabricator.services.mozilla.com/D206554
This commit is contained in:
Michael Hughes 2024-04-17 17:51:59 +00:00
parent e85366d893
commit 9057cbea60
3 changed files with 205 additions and 91 deletions

View File

@ -9,6 +9,12 @@
*/
#include "Windows11LimitedAccessFeatures.h"
#include "mozilla/Logging.h"
static mozilla::LazyLogModule sLog("Windows11LimitedAccessFeatures");
#define LAF_LOG(level, msg, ...) MOZ_LOG(sLog, level, (msg, ##__VA_ARGS__))
// MINGW32 is not supported for these features
// Fall back function defined in the #else
#ifndef __MINGW32__
@ -30,11 +36,7 @@ using namespace ABI::Windows;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::ApplicationModel;
struct LimitedAccessFeatureInfo {
const WCHAR* feature;
const WCHAR* token;
const WCHAR* attestation;
};
using namespace mozilla;
/**
* To unlock features, we need a feature identifier, a token, and an
@ -95,26 +97,36 @@ struct LimitedAccessFeatureInfo {
* Windows 11 will then work.
*
*/
struct LimitedAccessFeatureInfo {
const char* debugName;
const WCHAR* feature;
const WCHAR* token;
const WCHAR* attestation;
};
static LimitedAccessFeatureInfo limitedAccessFeatureInfo[] = {{
// Win11LimitedAccessFeatureType::Taskbar
"Win11LimitedAccessFeatureType::Taskbar",
MOZ_WINDOWS_TASKBAR_PINNING_API_FEATURE,
MOZ_WINDOWS_TASKBAR_PINNING_API_KEY,
MOZ_WINDOWS_TASKBAR_PINNING_API_ATTRIBUTION,
}};
static_assert(mozilla::ArrayLength(limitedAccessFeatureInfo) ==
kWin11LimitedAccessFeatureTypeCount);
/**
Implementation of the Win11LimitedAccessFeaturesInterface.
*/
class Win11LimitedAccessFeatures : public Win11LimitedAccessFeaturesInterface {
public:
using AtomicState = mozilla::Atomic<int, mozilla::SequentiallyConsistent>;
using AtomicState = Atomic<int, SequentiallyConsistent>;
mozilla::Result<bool, HRESULT> Unlock(
Win11LimitedAccessFeatureType feature) override;
Result<bool, HRESULT> Unlock(Win11LimitedAccessFeatureType feature) override;
private:
AtomicState& GetState(Win11LimitedAccessFeatureType feature);
mozilla::Result<bool, HRESULT> UnlockImplementation(
Result<bool, HRESULT> UnlockImplementation(
Win11LimitedAccessFeatureType feature);
/**
@ -145,12 +157,20 @@ CreateWin11LimitedAccessFeaturesInterface() {
return result;
}
mozilla::Result<bool, HRESULT> Win11LimitedAccessFeatures::Unlock(
Result<bool, HRESULT> Win11LimitedAccessFeatures::Unlock(
Win11LimitedAccessFeatureType feature) {
AtomicState& atomicState = GetState(feature);
const auto& lafInfo = limitedAccessFeatureInfo[static_cast<int>(feature)];
LAF_LOG(
LogLevel::Debug, "Limited Access Feature Info for %s. Feature %S, %S, %S",
lafInfo.debugName, lafInfo.feature, lafInfo.token, lafInfo.attestation);
int state = atomicState;
if (state != Uninitialized) {
LAF_LOG(LogLevel::Debug, "%s already initialized! State = %s",
lafInfo.debugName, (state == Unlocked) ? "true" : "false");
return (state == Unlocked);
}
@ -177,6 +197,8 @@ Win11LimitedAccessFeatures::AtomicState& Win11LimitedAccessFeatures::GetState(
return mTaskbarState;
default:
LAF_LOG(LogLevel::Debug, "Missing feature type for %d",
static_cast<int>(feature));
MOZ_ASSERT(false,
"Unhandled feature type! Add a new atomic state variable, add "
"that entry to the switch statement above, and add the proper "
@ -185,11 +207,13 @@ Win11LimitedAccessFeatures::AtomicState& Win11LimitedAccessFeatures::GetState(
}
}
mozilla::Result<bool, HRESULT> Win11LimitedAccessFeatures::UnlockImplementation(
Result<bool, HRESULT> Win11LimitedAccessFeatures::UnlockImplementation(
Win11LimitedAccessFeatureType feature) {
ComPtr<ILimitedAccessFeaturesStatics> limitedAccessFeatures;
ComPtr<ILimitedAccessFeatureRequestResult> limitedAccessFeaturesResult;
const auto& lafInfo = limitedAccessFeatureInfo[static_cast<int>(feature)];
HRESULT hr = RoGetActivationFactory(
HStringReference(
RuntimeClass_Windows_ApplicationModel_LimitedAccessFeatures)
@ -197,29 +221,35 @@ mozilla::Result<bool, HRESULT> Win11LimitedAccessFeatures::UnlockImplementation(
IID_ILimitedAccessFeaturesStatics, &limitedAccessFeatures);
if (!SUCCEEDED(hr)) {
return mozilla::Err(hr);
LAF_LOG(LogLevel::Debug, "%s activation error. HRESULT = 0x%lx",
lafInfo.debugName, hr);
return Err(hr);
}
const auto& lafInfo = limitedAccessFeatureInfo[static_cast<int>(feature)];
hr = limitedAccessFeatures->TryUnlockFeature(
HStringReference(lafInfo.feature).Get(),
HStringReference(lafInfo.token).Get(),
HStringReference(lafInfo.attestation).Get(),
&limitedAccessFeaturesResult);
if (!SUCCEEDED(hr)) {
return mozilla::Err(hr);
LAF_LOG(LogLevel::Debug, "%s unlock error. HRESULT = 0x%lx",
lafInfo.debugName, hr);
return Err(hr);
}
LimitedAccessFeatureStatus status;
hr = limitedAccessFeaturesResult->get_Status(&status);
if (!SUCCEEDED(hr)) {
return mozilla::Err(hr);
LAF_LOG(LogLevel::Debug, "%s get status error. HRESULT = 0x%lx",
lafInfo.debugName, hr);
return Err(hr);
}
int state = Unlocked;
if ((status != LimitedAccessFeatureStatus_Available) &&
(status != LimitedAccessFeatureStatus_AvailableWithoutToken)) {
LAF_LOG(LogLevel::Debug, "%s not available. HRESULT = 0x%lx",
lafInfo.debugName, hr);
state = Locked;
}

View File

@ -11,10 +11,10 @@
#include "mozilla/ResultVariant.h"
#include <winerror.h>
#include <windows.h> // for HRESULT
#include "mozilla/DefineEnum.h"
#include <winerror.h>
enum class Win11LimitedAccessFeatureType {
Taskbar,
};
MOZ_DEFINE_ENUM_CLASS(Win11LimitedAccessFeatureType, (Taskbar));
/**
* Class to manage unlocking limited access features on Windows 11.

View File

@ -14,6 +14,13 @@
#include "mozilla/Result.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/Logging.h"
static mozilla::LazyLogModule sLog("Windows11TaskbarPinning");
#define TASKBAR_PINNING_LOG(level, msg, ...) \
MOZ_LOG(sLog, level, (msg, ##__VA_ARGS__))
#ifndef __MINGW32__ // WinRT headers not yet supported by MinGW
# include <wrl.h>
@ -24,6 +31,8 @@
# include <windows.foundation.h>
# include <windows.ui.shell.h>
using namespace mozilla;
/**
* The Win32 SetEvent and WaitForSingleObject functions take HANDLE parameters
* which are typedefs of void*. When using nsAutoHandle, that means if you
@ -54,30 +63,40 @@ using namespace ABI::Windows::UI::Shell;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::ApplicationModel;
static mozilla::Result<ComPtr<ITaskbarManager>, HRESULT> InitializeTaskbar() {
static Result<ComPtr<ITaskbarManager>, HRESULT> InitializeTaskbar() {
ComPtr<IInspectable> taskbarStaticsInspectable;
TASKBAR_PINNING_LOG(LogLevel::Debug, "Initializing taskbar");
HRESULT hr = RoGetActivationFactory(
HStringReference(RuntimeClass_Windows_UI_Shell_TaskbarManager).Get(),
IID_ITaskbarManagerStatics, &taskbarStaticsInspectable);
if (FAILED(hr)) {
return mozilla::Err(hr);
TASKBAR_PINNING_LOG(LogLevel::Debug,
"Taskbar: Failed to activate. HRESULT = 0x%lx", hr);
return Err(hr);
}
ComPtr<ITaskbarManagerStatics> taskbarStatics;
hr = taskbarStaticsInspectable.As(&taskbarStatics);
if (FAILED(hr)) {
return mozilla::Err(hr);
TASKBAR_PINNING_LOG(LogLevel::Debug, "Failed statistics. HRESULT = 0x%lx",
hr);
return Err(hr);
}
ComPtr<ITaskbarManager> taskbarManager;
hr = taskbarStatics->GetDefault(&taskbarManager);
if (FAILED(hr)) {
return mozilla::Err(hr);
TASKBAR_PINNING_LOG(LogLevel::Debug,
"Error getting TaskbarManager. HRESULT = 0x%lx", hr);
return Err(hr);
}
TASKBAR_PINNING_LOG(LogLevel::Debug,
"TaskbarManager retrieved successfully!");
return taskbarManager;
}
@ -95,10 +114,16 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
auto result =
limitedAccessFeatures->Unlock(Win11LimitedAccessFeatureType::Taskbar);
if (result.isErr()) {
return {result.unwrapErr(), Win11PinToTaskBarResultStatus::NotSupported};
auto hr = result.unwrapErr();
TASKBAR_PINNING_LOG(LogLevel::Debug,
"Taskbar unlock: Error. HRESULT = 0x%lx", hr);
return {hr, Win11PinToTaskBarResultStatus::NotSupported};
}
if (result.unwrap() == false) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar unlock: failed. Not supported on this version of Windows.");
return {S_OK, Win11PinToTaskBarResultStatus::NotSupported};
}
}
@ -130,17 +155,38 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
boolean supported;
hr = taskbar->get_IsSupported(&supported);
if (FAILED(hr) || !supported) {
if (FAILED(hr)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: error checking if supported. HRESULT = 0x%lx", hr);
} else {
TASKBAR_PINNING_LOG(LogLevel::Debug, "Taskbar: not supported.");
}
return CompletedOperations(
Win11PinToTaskBarResultStatus::NotSupported);
}
if (aCheckOnly) {
TASKBAR_PINNING_LOG(LogLevel::Debug, "Taskbar: check succeeded.");
return CompletedOperations(Win11PinToTaskBarResultStatus::Success);
}
boolean isAllowed = false;
hr = taskbar->get_IsPinningAllowed(&isAllowed);
if (FAILED(hr) || !isAllowed) {
if (FAILED(hr)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: error checking if pinning is allowed. HRESULT = "
"0x%lx",
hr);
} else {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: is pinning allowed error or isn't allowed right now. "
"It's not clear when it will be allowed. Possibly after a "
"reboot.");
}
return CompletedOperations(
Win11PinToTaskBarResultStatus::NotCurrentlyAllowed);
}
@ -148,6 +194,11 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
ComPtr<IAsyncOperation<bool>> isPinnedOperation = nullptr;
hr = taskbar->IsCurrentAppPinnedAsync(&isPinnedOperation);
if (FAILED(hr)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: is current app pinned operation failed. HRESULT = "
"0x%lx",
hr);
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
@ -157,84 +208,117 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
// resultStatus and event are not defined on the main thread and will
// be alive until the async functions complete, so they can be used as
// references.
auto isPinnedCallback = Callback<IAsyncOperationCompletedHandler<bool>>(
[taskbar, &event, &resultStatus, &hr](
IAsyncOperation<bool>* asyncInfo,
AsyncStatus status) mutable -> HRESULT {
auto CompletedOperations =
[&event, &resultStatus](
Win11PinToTaskBarResultStatus status) -> HRESULT {
resultStatus = status;
event.Set();
return S_OK;
};
auto isPinnedCallback = Callback<IAsyncOperationCompletedHandler<
bool>>([taskbar, &event, &resultStatus, &hr](
IAsyncOperation<bool>* asyncInfo,
AsyncStatus status) mutable -> HRESULT {
auto CompletedOperations =
[&event,
&resultStatus](Win11PinToTaskBarResultStatus status) -> HRESULT {
resultStatus = status;
event.Set();
return S_OK;
};
bool asyncOpSucceeded = status == AsyncStatus::Completed;
if (!asyncOpSucceeded) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
}
bool asyncOpSucceeded = status == AsyncStatus::Completed;
if (!asyncOpSucceeded) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: is pinned operation failed to complete.");
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
unsigned char isCurrentAppPinned = false;
hr = asyncInfo->GetResults(&isCurrentAppPinned);
unsigned char isCurrentAppPinned = false;
hr = asyncInfo->GetResults(&isCurrentAppPinned);
if (FAILED(hr)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: is current app pinned check failed. HRESULT = 0x%lx",
hr);
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
if (isCurrentAppPinned) {
TASKBAR_PINNING_LOG(LogLevel::Debug,
"Taskbar: current app is already pinned.");
return CompletedOperations(
Win11PinToTaskBarResultStatus::AlreadyPinned);
}
ComPtr<IAsyncOperation<bool>> requestPinOperation = nullptr;
hr = taskbar->RequestPinCurrentAppAsync(&requestPinOperation);
if (FAILED(hr)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin current app operation creation failed. "
"HRESULT = 0x%lx",
hr);
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
auto pinAppCallback = Callback<IAsyncOperationCompletedHandler<
bool>>([CompletedOperations, &hr](
IAsyncOperation<bool>* asyncInfo,
AsyncStatus status) -> HRESULT {
bool asyncOpSucceeded = status == AsyncStatus::Completed;
if (!asyncOpSucceeded) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin current app operation did not "
"complete.");
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
unsigned char successfullyPinned = 0;
hr = asyncInfo->GetResults(&successfullyPinned);
if (FAILED(hr) || !successfullyPinned) {
if (FAILED(hr)) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin current app operation failed to pin "
"due to error. HRESULT = 0x%lx",
hr);
} else {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin current app operation failed to pin");
}
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
if (isCurrentAppPinned) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::AlreadyPinned);
}
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin current app operation succeeded");
return CompletedOperations(Win11PinToTaskBarResultStatus::Success);
});
ComPtr<IAsyncOperation<bool>> requestPinOperation = nullptr;
hr = taskbar->RequestPinCurrentAppAsync(&requestPinOperation);
if (FAILED(hr)) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
}
HRESULT pinOperationHR =
requestPinOperation->put_Completed(pinAppCallback.Get());
if (FAILED(pinOperationHR)) {
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: request pin operation failed when setting completion "
"callback. HRESULT = 0x%lx",
hr);
hr = pinOperationHR;
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}
auto pinAppCallback =
Callback<IAsyncOperationCompletedHandler<bool>>(
[CompletedOperations, &hr](
IAsyncOperation<bool>* asyncInfo,
AsyncStatus status) -> HRESULT {
bool asyncOpSucceeded =
status == AsyncStatus::Completed;
if (!asyncOpSucceeded) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
}
unsigned char successfullyPinned = 0;
hr = asyncInfo->GetResults(&successfullyPinned);
if (FAILED(hr) || !successfullyPinned) {
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
}
return CompletedOperations(
Win11PinToTaskBarResultStatus::Success);
});
HRESULT pinOperationHR =
requestPinOperation->put_Completed(pinAppCallback.Get());
if (FAILED(pinOperationHR)) {
hr = pinOperationHR;
return CompletedOperations(
Win11PinToTaskBarResultStatus::Failed);
}
// DO NOT SET event HERE. It will be set in the pin operation
// callback As in, operations are not completed, so don't call
// CompletedOperations
return S_OK;
});
// DO NOT SET event HERE. It will be set in the pin operation
// callback As in, operations are not completed, so don't call
// CompletedOperations
return S_OK;
});
HRESULT isPinnedOperationHR =
isPinnedOperation->put_Completed(isPinnedCallback.Get());
if (FAILED(isPinnedOperationHR)) {
hr = isPinnedOperationHR;
TASKBAR_PINNING_LOG(
LogLevel::Debug,
"Taskbar: is pinned operation failed when setting completion "
"callback. HRESULT = 0x%lx",
hr);
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
}