Backed out 2 changesets (bug 1893458, bug 1890634) for causing bustages at TaskbarPinningMetricsTests.cpp. CLOSED TREE
Backed out changeset 29ad5906bfb0 (bug 1890634) Backed out changeset bfcfe75b775a (bug 1893458)
This commit is contained in:
@@ -78,105 +78,3 @@ background_update:
|
||||
- background-update
|
||||
- metrics
|
||||
lifetime: application
|
||||
|
||||
pinning.windows:
|
||||
shortcut_created:
|
||||
type: event
|
||||
description: >
|
||||
Event to record when a shortcut is created for the purpose of pinning
|
||||
to the taskbar on Windows.
|
||||
extra_keys:
|
||||
result:
|
||||
description: >
|
||||
Readable result of the pinning attempt. Can be: Error,
|
||||
File Not Found, or Success.
|
||||
type: string
|
||||
private_browsing:
|
||||
description: >
|
||||
True when the shortcut is for a private browser.
|
||||
type: boolean
|
||||
error:
|
||||
description: >
|
||||
Present and true when shortcut creation failed for an unknown reason.
|
||||
type: boolean
|
||||
success:
|
||||
description: >
|
||||
Present and true when shortcut creation succeeded.
|
||||
type: boolean
|
||||
file_not_found:
|
||||
description: >
|
||||
Present and true when shortcut creation failed due to the file not
|
||||
being found (NS_ERROR_FILE_NOT_FOUND).
|
||||
type: boolean
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1890634
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1890634
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- install-update@mozilla.com
|
||||
expires: never
|
||||
lifetime: ping
|
||||
|
||||
pinned_to_taskbar:
|
||||
type: event
|
||||
description: >
|
||||
Event to record when the user pins to the taskbar using Windows 11 APIs,
|
||||
including if there was an error.
|
||||
extra_keys:
|
||||
result:
|
||||
description: >
|
||||
Readable result of the pinning attempt. Can be: Not Supported,
|
||||
Success, Already Pinned, Not Currently Allowed, Error, ErrorLimitedAccessFeatures, or LimitedAccessFeaturesLocked
|
||||
type: string
|
||||
not_supported:
|
||||
description: >
|
||||
Present and true when Windows 11 pinning is not supported.
|
||||
type: boolean
|
||||
success:
|
||||
description: >
|
||||
Present and true when Windows 11 pinning succeeded.
|
||||
type: boolean
|
||||
already_pinned:
|
||||
description: >
|
||||
Present and true when Windows 11 pinning was previously successful.
|
||||
type: boolean
|
||||
not_currently_allowed:
|
||||
description: >
|
||||
Present and true when Windows 11 pinning is not currently allowed.
|
||||
type: boolean
|
||||
error_limited_access_features:
|
||||
description: >
|
||||
Present and true when the limited access feature unlock process generated an error.
|
||||
type: boolean
|
||||
limited_access_features_locked:
|
||||
description: >
|
||||
Present and true when the limited access feature unlock process generated an error.
|
||||
type: boolean
|
||||
error:
|
||||
description: >
|
||||
Present and true when Windows 11 pinning failed.
|
||||
type: boolean
|
||||
private_browsing:
|
||||
description: >
|
||||
True when pinning is for private-firefox.
|
||||
type: boolean
|
||||
number_of_attempts:
|
||||
description: >
|
||||
The number of times that pinning with the taskbar pinning apis was attempted.
|
||||
type: quantity
|
||||
fallback_pinning_success:
|
||||
description: >
|
||||
Success or Error; valid when using the taskbar pinning api failed and indicates if the fallback to the older mechanism succeeded or not.
|
||||
type: string
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1890634
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1890634
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- install-update@mozilla.com
|
||||
expires: never
|
||||
lifetime: ping
|
||||
|
||||
@@ -100,18 +100,6 @@ static Result<ComPtr<ITaskbarManager>, HRESULT> InitializeTaskbar() {
|
||||
return taskbarManager;
|
||||
}
|
||||
|
||||
static bool IsStatusToRetry(Win11PinToTaskBarResultStatus status) {
|
||||
switch (status) {
|
||||
case Win11PinToTaskBarResultStatus::NotCurrentlyAllowed:
|
||||
case Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked:
|
||||
case Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
nsAutoString aShortcutPath) {
|
||||
@@ -120,257 +108,229 @@ Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||
"thread only. It blocks, waiting on things to execute "
|
||||
"asynchronously on the main thread.");
|
||||
|
||||
{
|
||||
RefPtr<Win11LimitedAccessFeaturesInterface> limitedAccessFeatures =
|
||||
CreateWin11LimitedAccessFeaturesInterface();
|
||||
auto result =
|
||||
limitedAccessFeatures->Unlock(Win11LimitedAccessFeatureType::Taskbar);
|
||||
if (result.isErr()) {
|
||||
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};
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
Win11PinToTaskBarResultStatus resultStatus =
|
||||
Win11PinToTaskBarResultStatus::NotSupported;
|
||||
|
||||
// Pinning with the Win 11 APIs sometimes reports that pinning is not
|
||||
// available. There is no documentation on what causes it to not be available
|
||||
// or why. One way to work around that is to try again. We try 3 times if it's
|
||||
// not currently available.
|
||||
const int maxNumberOfRetryAttempts = 3;
|
||||
int delayInMilliseconds = 200;
|
||||
int count = 0;
|
||||
do {
|
||||
EventWrapper event;
|
||||
EventWrapper event;
|
||||
|
||||
// Everything related to the taskbar and pinning must be done on the main /
|
||||
// user interface thread or Windows will cause them to fail.
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"PinCurrentAppToTaskbarWin11",
|
||||
[&event, &hr, &resultStatus, aCheckOnly] {
|
||||
auto CompletedOperations =
|
||||
[&event, &resultStatus](Win11PinToTaskBarResultStatus status) {
|
||||
resultStatus = status;
|
||||
event.Set();
|
||||
};
|
||||
// Everything related to the taskbar and pinning must be done on the main /
|
||||
// user interface thread or Windows will cause them to fail.
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"PinCurrentAppToTaskbarWin11", [&event, &hr, &resultStatus, aCheckOnly] {
|
||||
auto CompletedOperations =
|
||||
[&event, &resultStatus](Win11PinToTaskBarResultStatus status) {
|
||||
resultStatus = status;
|
||||
event.Set();
|
||||
};
|
||||
|
||||
{
|
||||
RefPtr<Win11LimitedAccessFeaturesInterface> limitedAccessFeatures =
|
||||
CreateWin11LimitedAccessFeaturesInterface();
|
||||
auto result = limitedAccessFeatures->Unlock(
|
||||
Win11LimitedAccessFeatureType::Taskbar);
|
||||
if (result.isErr()) {
|
||||
hr = result.unwrapErr();
|
||||
TASKBAR_PINNING_LOG(LogLevel::Debug,
|
||||
"Taskbar unlock: Error. HRESULT = 0x%lx", hr);
|
||||
return CompletedOperations(
|
||||
Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures);
|
||||
}
|
||||
auto result = InitializeTaskbar();
|
||||
if (result.isErr()) {
|
||||
hr = result.unwrapErr();
|
||||
return CompletedOperations(
|
||||
Win11PinToTaskBarResultStatus::NotSupported);
|
||||
}
|
||||
|
||||
if (result.unwrap() == false) {
|
||||
TASKBAR_PINNING_LOG(LogLevel::Debug,
|
||||
"Taskbar unlock: failed. Not supported on "
|
||||
"this version of Windows.");
|
||||
return CompletedOperations(
|
||||
Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = InitializeTaskbar();
|
||||
if (result.isErr()) {
|
||||
hr = result.unwrapErr();
|
||||
return CompletedOperations(
|
||||
Win11PinToTaskBarResultStatus::NotSupported);
|
||||
}
|
||||
|
||||
ComPtr<ITaskbarManager> taskbar = result.unwrap();
|
||||
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);
|
||||
}
|
||||
|
||||
ComPtr<IAsyncOperation<bool>> isPinnedOperation = nullptr;
|
||||
hr = taskbar->IsCurrentAppPinnedAsync(&isPinnedOperation);
|
||||
ComPtr<ITaskbarManager> taskbar = result.unwrap();
|
||||
boolean supported;
|
||||
hr = taskbar->get_IsSupported(&supported);
|
||||
if (FAILED(hr) || !supported) {
|
||||
if (FAILED(hr)) {
|
||||
TASKBAR_PINNING_LOG(
|
||||
LogLevel::Debug,
|
||||
"Taskbar: is current app pinned operation failed. HRESULT = "
|
||||
"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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Copy the taskbar; don't use it as a reference.
|
||||
// With the async calls, it's not guaranteed to still be valid
|
||||
// if sent as a reference.
|
||||
// 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;
|
||||
};
|
||||
|
||||
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);
|
||||
if (FAILED(hr)) {
|
||||
TASKBAR_PINNING_LOG(
|
||||
LogLevel::Debug,
|
||||
"Taskbar: is current app pinned check failed. HRESULT = 0x%lx",
|
||||
hr);
|
||||
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
|
||||
}
|
||||
|
||||
// Copy the taskbar; don't use it as a reference.
|
||||
// With the async calls, it's not guaranteed to still be valid
|
||||
// if sent as a reference.
|
||||
// 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;
|
||||
};
|
||||
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: is pinned operation failed to complete.");
|
||||
"Taskbar: request pin current app operation did not "
|
||||
"complete.");
|
||||
return CompletedOperations(Win11PinToTaskBarResultStatus::Failed);
|
||||
}
|
||||
|
||||
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);
|
||||
unsigned char successfullyPinned = 0;
|
||||
hr = asyncInfo->GetResults(&successfullyPinned);
|
||||
if (FAILED(hr) || !successfullyPinned) {
|
||||
if (FAILED(hr)) {
|
||||
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) {
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
TASKBAR_PINNING_LOG(
|
||||
LogLevel::Debug,
|
||||
"Taskbar: request pin current app operation succeeded");
|
||||
return CompletedOperations(
|
||||
Win11PinToTaskBarResultStatus::Success);
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 "
|
||||
"Taskbar: request pin current app operation succeeded");
|
||||
return CompletedOperations(Win11PinToTaskBarResultStatus::Success);
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// DO NOT SET event HERE. It will be set in the is pin operation
|
||||
// callback. As in, operations are not completed, so don't call
|
||||
// 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;
|
||||
});
|
||||
|
||||
// block until the pinning is completed on the main thread
|
||||
event.Wait();
|
||||
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);
|
||||
}
|
||||
|
||||
count++;
|
||||
if (!IsStatusToRetry(resultStatus) || (count >= maxNumberOfRetryAttempts)) {
|
||||
break;
|
||||
}
|
||||
// DO NOT SET event HERE. It will be set in the is pin operation
|
||||
// callback As in, operations are not completed, so don't call
|
||||
// CompletedOperations
|
||||
}));
|
||||
|
||||
// If retrying, put in a delay. Make it short the first time and slightly
|
||||
// longer the second time. This is not on the main thread so shouldn't
|
||||
// forcefully block the user. If called from Javascript with an await it
|
||||
// will still block, but that's a decision on the Javascript side
|
||||
Sleep(delayInMilliseconds);
|
||||
delayInMilliseconds *= 2;
|
||||
} while (count < maxNumberOfRetryAttempts);
|
||||
// block until the pinning is completed on the main thread
|
||||
event.Wait();
|
||||
|
||||
return {hr, resultStatus, count};
|
||||
return {hr, resultStatus};
|
||||
}
|
||||
|
||||
#else // MINGW32 implementation below
|
||||
|
||||
@@ -14,17 +14,18 @@
|
||||
#include "nsString.h"
|
||||
#include <wrl.h>
|
||||
#include <windows.h> // for HRESULT
|
||||
#include <mozilla/DefineEnum.h>
|
||||
|
||||
MOZ_DEFINE_ENUM_CLASS(Win11PinToTaskBarResultStatus,
|
||||
(Failed, NotCurrentlyAllowed, AlreadyPinned, Success,
|
||||
NotSupported, ErrorLimitedAccessFeatures,
|
||||
LimitedAccessFeaturesLocked));
|
||||
enum class Win11PinToTaskBarResultStatus {
|
||||
Failed,
|
||||
NotCurrentlyAllowed,
|
||||
AlreadyPinned,
|
||||
Success,
|
||||
NotSupported,
|
||||
};
|
||||
|
||||
struct Win11PinToTaskBarResult {
|
||||
HRESULT errorCode;
|
||||
Win11PinToTaskBarResultStatus result;
|
||||
int numAttempts;
|
||||
};
|
||||
|
||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11(
|
||||
|
||||
@@ -1,713 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsWindowsShellServiceInternal.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/FOGFixture.h"
|
||||
#include "mozilla/glean/fog_ffi_generated.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::glean::impl;
|
||||
using namespace mozilla::glean::pinning_windows;
|
||||
|
||||
namespace telemetry_event {
|
||||
|
||||
template <typename event_type>
|
||||
bool IsValidButEmpty(const event_type& event) {
|
||||
auto value = event.TestGetValue();
|
||||
if (!value.isOk()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.unwrap().isSome()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename event_type>
|
||||
bool CountsMatch(const event_type& event, size_t count) {
|
||||
auto value = event.TestGetValue();
|
||||
if (!value.isOk()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto unwrapped = value.unwrap();
|
||||
if (!unwrapped.isSome()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unwrapped.ref().Length() != count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace telemetry_event
|
||||
|
||||
template <typename event_extra_type>
|
||||
static std::map<nsCString, nsCString> CreateKeyValuePairs(
|
||||
const event_extra_type& eventExtras) {
|
||||
auto serializedExtras = eventExtras.ToFfiExtra();
|
||||
auto keys = std::move(std::get<0>(serializedExtras));
|
||||
auto values = std::move(std::get<1>(serializedExtras));
|
||||
|
||||
if (keys.Length() != values.Length()) {
|
||||
MOZ_ASSERT(false);
|
||||
return std::map<nsCString, nsCString>();
|
||||
}
|
||||
|
||||
std::map<nsCString, nsCString> result;
|
||||
for (size_t i = 0; i < keys.Length(); i++) {
|
||||
result[keys[i]] = values[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename extra_type>
|
||||
bool IsEqual(const extra_type& control,
|
||||
mozilla::glean::impl::RecordedEvent& event) {
|
||||
// generate a map from the control data
|
||||
std::map<nsCString, nsCString> controlMap = CreateKeyValuePairs(control);
|
||||
|
||||
if (controlMap.size() != event.mExtra.Length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// now walk through the event data and check
|
||||
for (size_t i = 0; i < event.mExtra.Length(); i++) {
|
||||
const auto& key = std::get<0>(event.mExtra[i]);
|
||||
const auto& value = std::get<1>(event.mExtra[i]);
|
||||
|
||||
auto iterator = controlMap.find(key);
|
||||
if (iterator == controlMap.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iterator->second != value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename extra_type>
|
||||
bool IsEqual(const extra_type& control, const extra_type& generated) {
|
||||
std::map<nsCString, nsCString> controlMap = CreateKeyValuePairs(control);
|
||||
std::map<nsCString, nsCString> generatedMap = CreateKeyValuePairs(generated);
|
||||
|
||||
if (controlMap.size() != generatedMap.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto i : controlMap) {
|
||||
auto found = generatedMap.find(i.first);
|
||||
if (found == generatedMap.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (found->second != i.second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class WindowsPinningShortcutTestFixture : public FOGFixture {};
|
||||
|
||||
MOZ_DEFINE_ENUM_CLASS(PinningShortcutOperation,
|
||||
(Succeed, FailFileNotFound, FailError, FailEmptyOnFind));
|
||||
|
||||
static const char* EnumName(PinningShortcutOperation operation) {
|
||||
switch (operation) {
|
||||
case PinningShortcutOperation::Succeed:
|
||||
return "PinningShortcutOperation::Succeed";
|
||||
|
||||
case PinningShortcutOperation::FailFileNotFound:
|
||||
return "PinningShortcutOperation::FailFileNotFound";
|
||||
|
||||
case PinningShortcutOperation::FailError:
|
||||
return "PinningShortcutOperation::FailError";
|
||||
|
||||
case PinningShortcutOperation::FailEmptyOnFind:
|
||||
return "PinningShortcutOperation::FailEmptyOnFind";
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return "PinningShortcutOperation::UNDEFINED";
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_DEFINE_ENUM_CLASS(PinningFallbackOperation, (Succeed, Fail));
|
||||
|
||||
static const char* EnumName(PinningFallbackOperation operation) {
|
||||
switch (operation) {
|
||||
case PinningFallbackOperation::Succeed:
|
||||
return "PinningFallbackOperation::Succeed";
|
||||
|
||||
case PinningFallbackOperation::Fail:
|
||||
return "PinningFallbackOperation::Fail";
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return "PinningFallbackOperation::UNDEFINED";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* EnumName(Win11PinToTaskBarResultStatus operation) {
|
||||
switch (operation) {
|
||||
case Win11PinToTaskBarResultStatus::Success:
|
||||
return "Win11PinToTaskBarResultStatus::Success";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::Failed:
|
||||
return "Win11PinToTaskBarResultStatus::Failed";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::NotCurrentlyAllowed:
|
||||
return "Win11PinToTaskBarResultStatus::NotCurrentlyAllowed";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::AlreadyPinned:
|
||||
return "Win11PinToTaskBarResultStatus::AlreadyPinned";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::NotSupported:
|
||||
return "Win11PinToTaskBarResultStatus::NotSupported";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures:
|
||||
return "Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures";
|
||||
|
||||
case Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked:
|
||||
return "Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked";
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return "Win11PinToTaskBarResultStatus::UNDEFINED";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock version of PinCurrentAppToTaskbarHelper.
|
||||
*
|
||||
* Takes the values to return from the methods and returns them
|
||||
* to mock results for testing telemetry events are generated
|
||||
* properly by PinCurrentAppToTaskbarImpl.
|
||||
*/
|
||||
class PinCurrentAppToTaskbarHelperMetricsTesting
|
||||
: public PinCurrentAppToTaskbarHelper {
|
||||
public:
|
||||
PinCurrentAppToTaskbarHelperMetricsTesting(
|
||||
PinningShortcutOperation shortcutOperation,
|
||||
Win11PinToTaskBarResultStatus apiOperation,
|
||||
PinningFallbackOperation fallbackOperation);
|
||||
|
||||
void CheckNotMainThread() override {}
|
||||
|
||||
mozilla::Result<bool, nsresult> CreateShortcutForTaskbar(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
nsAutoString& aShortcutPath) override;
|
||||
|
||||
Win11PinToTaskBarResult PinCurrentAppViaAPI(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
nsAutoString aShortcutPath) override;
|
||||
|
||||
nsresult PinCurrentAppFallback(bool aCheckOnly,
|
||||
const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutPath) override;
|
||||
|
||||
private:
|
||||
PinningShortcutOperation mShortcutOperation;
|
||||
Win11PinToTaskBarResultStatus mApiOperation;
|
||||
PinningFallbackOperation mFallbackOperation;
|
||||
};
|
||||
|
||||
inline PinCurrentAppToTaskbarHelperMetricsTesting::
|
||||
PinCurrentAppToTaskbarHelperMetricsTesting(
|
||||
PinningShortcutOperation shortcutOperation,
|
||||
Win11PinToTaskBarResultStatus apiOperation,
|
||||
PinningFallbackOperation fallbackOperation)
|
||||
: mShortcutOperation(shortcutOperation),
|
||||
mApiOperation(apiOperation),
|
||||
mFallbackOperation(fallbackOperation) {}
|
||||
|
||||
inline mozilla::Result<bool, nsresult>
|
||||
PinCurrentAppToTaskbarHelperMetricsTesting::CreateShortcutForTaskbar(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
nsAutoString& aShortcutPath) {
|
||||
using namespace mozilla;
|
||||
|
||||
switch (mShortcutOperation) {
|
||||
case PinningShortcutOperation::Succeed:
|
||||
return true;
|
||||
|
||||
case PinningShortcutOperation::FailFileNotFound:
|
||||
return Err(NS_ERROR_FILE_NOT_FOUND);
|
||||
|
||||
case PinningShortcutOperation::FailError:
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
|
||||
case PinningShortcutOperation::FailEmptyOnFind:
|
||||
return false;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
inline Win11PinToTaskBarResult
|
||||
PinCurrentAppToTaskbarHelperMetricsTesting::PinCurrentAppViaAPI(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
nsAutoString aShortcutPath) {
|
||||
const int numAttempts = 1;
|
||||
return {S_OK, mApiOperation, numAttempts};
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
PinCurrentAppToTaskbarHelperMetricsTesting::PinCurrentAppFallback(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutPath) {
|
||||
switch (mFallbackOperation) {
|
||||
case PinningFallbackOperation::Fail:
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
case PinningFallbackOperation::Succeed:
|
||||
return NS_OK;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
static void TestPinning(bool aCheckOnly,
|
||||
PinningShortcutOperation shortcutOperation,
|
||||
Win11PinToTaskBarResultStatus apiOperation,
|
||||
PinningFallbackOperation fallbackOperation,
|
||||
bool privateBrowsing = false) {
|
||||
UniquePtr<PinCurrentAppToTaskbarHelper> helper(
|
||||
new PinCurrentAppToTaskbarHelperMetricsTesting(
|
||||
shortcutOperation, apiOperation, fallbackOperation));
|
||||
|
||||
auto appUserModelId = u""_ns;
|
||||
auto shortcutName = u""_ns;
|
||||
auto shortcutSubstring = u""_ns;
|
||||
nsIFile* shortcutsLogDir = nullptr;
|
||||
nsIFile* greDir = nullptr;
|
||||
nsIFile* programsDir = nullptr;
|
||||
PinCurrentAppToTaskbarImpl(aCheckOnly, privateBrowsing, appUserModelId,
|
||||
shortcutName, shortcutSubstring, shortcutsLogDir,
|
||||
greDir, programsDir, std::move(helper));
|
||||
}
|
||||
|
||||
struct ShortcutTestCase {
|
||||
PinningShortcutOperation operation;
|
||||
nsresult expectedResult;
|
||||
ShortcutCreatedExtra expectedExtras;
|
||||
|
||||
friend void PrintTo(const ShortcutTestCase& testCase, std::ostream* os) {
|
||||
*os << "(With operation " << EnumName(testCase.operation)
|
||||
<< ", expected result event text == " << int(testCase.expectedResult)
|
||||
<< " and expectedExtras with result text == "
|
||||
<< testCase.expectedExtras.result << ")";
|
||||
}
|
||||
};
|
||||
|
||||
class WindowsPinningShortcuts : public FOGFixtureWithParam<ShortcutTestCase> {};
|
||||
|
||||
TEST_P(
|
||||
WindowsPinningShortcuts,
|
||||
WindowsPinningTestShortcutTelemetryEventCreationCheckOnlyPrivateBrowsingOn) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = true;
|
||||
const bool privateBrowsing = true;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, testCase.operation,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
}
|
||||
|
||||
TEST_P(
|
||||
WindowsPinningShortcuts,
|
||||
WindowsPinningTestShortcutTelemetryEventCreationCheckOnlyPrivateBrowsingOff) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = true;
|
||||
const bool privateBrowsing = false;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, testCase.operation,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningShortcuts,
|
||||
WindowsPinningTestShortcutTelemetryEventCreationPrivateBrowsingOn) {
|
||||
auto testCase = GetParam();
|
||||
const bool doFullPinningFlow = false;
|
||||
const bool privateBrowsing = true;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(doFullPinningFlow, testCase.operation,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
auto extras = telemetry::shortcut::CreateEventExtra(testCase.expectedResult,
|
||||
privateBrowsing);
|
||||
|
||||
// confirm that the event extras creation works as expected
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
size_t one = 1;
|
||||
EXPECT_TRUE(telemetry_event::CountsMatch(shortcut_created, one));
|
||||
|
||||
auto metricsEvents = shortcut_created.TestGetValue().unwrap().ref();
|
||||
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningShortcuts,
|
||||
WindowsPinningTestShortcutTelemetryEventCreationPrivateBrowsingOff) {
|
||||
auto testCase = GetParam();
|
||||
const bool doFullPinningFlow = false;
|
||||
const bool privateBrowsing = false;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(doFullPinningFlow, testCase.operation,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
auto extras = telemetry::shortcut::CreateEventExtra(testCase.expectedResult,
|
||||
privateBrowsing);
|
||||
|
||||
// confirm that the event extras creation works as expected
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
size_t one = 1;
|
||||
EXPECT_TRUE(telemetry_event::CountsMatch(shortcut_created, one));
|
||||
|
||||
auto metricsEvents = shortcut_created.TestGetValue().unwrap().ref();
|
||||
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
static const ShortcutTestCase shortcutTestCases[] = {
|
||||
{.operation = PinningShortcutOperation::FailFileNotFound,
|
||||
.expectedResult = NS_ERROR_FILE_NOT_FOUND,
|
||||
.expectedExtras = {.fileNotFound = Some(true),
|
||||
.privateBrowsing = Some(false),
|
||||
.result = Some(
|
||||
telemetry::shortcut::TELEMETRY_FILE_NOT_FOUND)}},
|
||||
{.operation = PinningShortcutOperation::FailError,
|
||||
.expectedResult = NS_ERROR_FAILURE,
|
||||
.expectedExtras = {.error = Some(true),
|
||||
.privateBrowsing = Some(false),
|
||||
.result = Some(telemetry::shortcut::TELEMETRY_ERROR)}},
|
||||
{.operation = PinningShortcutOperation::Succeed,
|
||||
.expectedResult = NS_OK,
|
||||
.expectedExtras = {.privateBrowsing = Some(false),
|
||||
.result = Some(telemetry::shortcut::TELEMETRY_SUCCESS),
|
||||
.success = Some(true)}},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WindowsPinningShortcutTelemetryTests,
|
||||
WindowsPinningShortcuts,
|
||||
::testing::ValuesIn(shortcutTestCases));
|
||||
|
||||
TEST_F(WindowsPinningShortcutTestFixture,
|
||||
TestShortcutFailOnEmptyFindPrivateBrowsingOn) {
|
||||
const bool privateBrowsing = true;
|
||||
|
||||
// special case FailEmptyOnFind. That should not generate an event at all
|
||||
TestPinning(true, PinningShortcutOperation::FailEmptyOnFind,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
|
||||
TestResetFOG();
|
||||
|
||||
TestPinning(false, PinningShortcutOperation::FailEmptyOnFind,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
}
|
||||
|
||||
TEST_F(WindowsPinningShortcutTestFixture,
|
||||
TestShortcutFailOnEmptyFindPrivateBrowsingOff) {
|
||||
const bool privateBrowsing = false;
|
||||
|
||||
// special case FailEmptyOnFind. That should not generate an event at all
|
||||
TestPinning(true, PinningShortcutOperation::FailEmptyOnFind,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
|
||||
TestResetFOG();
|
||||
|
||||
TestPinning(false, PinningShortcutOperation::FailEmptyOnFind,
|
||||
Win11PinToTaskBarResultStatus::Success,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(shortcut_created));
|
||||
}
|
||||
|
||||
struct PinningAPITestCase {
|
||||
Win11PinToTaskBarResultStatus result;
|
||||
PinnedToTaskbarExtra expectedExtras;
|
||||
|
||||
friend void PrintTo(const PinningAPITestCase& testCase, std::ostream* os) {
|
||||
*os << "(For pinning api operation == " << EnumName(testCase.result)
|
||||
<< ", expectedExtras result text should == "
|
||||
<< testCase.expectedExtras.result << ")";
|
||||
}
|
||||
};
|
||||
|
||||
class WindowsPinningAPIFixture
|
||||
: public FOGFixtureWithParam<PinningAPITestCase> {};
|
||||
|
||||
TEST_P(WindowsPinningAPIFixture,
|
||||
WindowsPinningTestTelemetryEventCreationCheckOnlyPrivateBrowsingOn) {
|
||||
const auto testCase = GetParam();
|
||||
const bool checkOnly = true;
|
||||
const bool privateBrowsing = true;
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
// confirm we don't generate events when checking only
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(pinned_to_taskbar));
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningAPIFixture,
|
||||
WindowsPinningTestTelemetryEventCreationCheckOnlyPrivateBrowsingOff) {
|
||||
const auto testCase = GetParam();
|
||||
const bool checkOnly = true;
|
||||
const bool privateBrowsing = false;
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
// confirm we don't generate events when checking only
|
||||
EXPECT_TRUE(telemetry_event::IsValidButEmpty(pinned_to_taskbar));
|
||||
}
|
||||
|
||||
static bool isFallbackSuccess(Win11PinToTaskBarResultStatus result) {
|
||||
// fallback fails when the api succeeds
|
||||
return (result != Win11PinToTaskBarResultStatus::Success) &&
|
||||
(result != Win11PinToTaskBarResultStatus::AlreadyPinned);
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningAPIFixture,
|
||||
WindowsPinningTestTelemetryEventCreationPrivateBrowsingOn) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = false;
|
||||
const bool privateBrowsing = true;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
const bool fallbackSucceeded = isFallbackSuccess(testCase.result);
|
||||
auto extras = telemetry::pinning::CreateEventExtra(
|
||||
{S_OK, testCase.result, 1}, privateBrowsing, fallbackSucceeded);
|
||||
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
size_t one = 1;
|
||||
|
||||
EXPECT_TRUE(telemetry_event::CountsMatch(pinned_to_taskbar, one));
|
||||
|
||||
auto metricsEvents = pinned_to_taskbar.TestGetValue().unwrap().ref();
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningAPIFixture,
|
||||
WindowsPinningTestTelemetryEventCreationPrivateBrowsingOff) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = false;
|
||||
const bool privateBrowsing = false;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Succeed, privateBrowsing);
|
||||
|
||||
// fallback fails when the api succeeds
|
||||
const bool fallbackSucceeded = isFallbackSuccess(testCase.result);
|
||||
auto extras = telemetry::pinning::CreateEventExtra(
|
||||
{S_OK, testCase.result, 1}, privateBrowsing, fallbackSucceeded);
|
||||
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
size_t one = 1;
|
||||
|
||||
EXPECT_TRUE(telemetry_event::CountsMatch(pinned_to_taskbar, one));
|
||||
|
||||
auto metricsEvents = pinned_to_taskbar.TestGetValue().unwrap().ref();
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
static const PinningAPITestCase apiValidationTestCases[] = {
|
||||
{.result = Win11PinToTaskBarResultStatus::NotSupported,
|
||||
.expectedExtras = {.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.notSupported = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result =
|
||||
Some(telemetry::pinning::TELEMETRY_NOT_SUPPORTED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::Success,
|
||||
.expectedExtras = {.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.success = Some(true)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::AlreadyPinned,
|
||||
.expectedExtras = {.alreadyPinned = Some(true),
|
||||
.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_ALREADY_PINNED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::NotCurrentlyAllowed,
|
||||
.expectedExtras =
|
||||
{.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.notCurrentlyAllowed = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_NOT_CURRENTLY_ALLOWED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::Failed,
|
||||
.expectedExtras = {.error = Some(true),
|
||||
.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_ERROR)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures,
|
||||
.expectedExtras =
|
||||
{.errorLimitedAccessFeatures = Some(true),
|
||||
.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_ERROR_LIMITED_ACCESS_FEATURES)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked,
|
||||
.expectedExtras =
|
||||
{.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.limitedAccessFeaturesLocked = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_LIMITED_ACCESS_FEATURES_LOCKED)}},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WindowsPinningAPITelemetryTests,
|
||||
WindowsPinningAPIFixture,
|
||||
::testing::ValuesIn(apiValidationTestCases));
|
||||
|
||||
class WindowsPinningAPIFallbackFixture
|
||||
: public FOGFixtureWithParam<PinningAPITestCase> {};
|
||||
|
||||
TEST_P(WindowsPinningAPIFallbackFixture,
|
||||
WindowsPinningTestFallbackFailsEventPrivateBrowsingOn) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = false;
|
||||
const bool privateBrowsing = true;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Fail, privateBrowsing);
|
||||
|
||||
const bool fallbackSucceeded = false;
|
||||
auto extras = telemetry::pinning::CreateEventExtra(
|
||||
{S_OK, testCase.result, 1}, privateBrowsing, fallbackSucceeded);
|
||||
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
auto metricsEvents = pinned_to_taskbar.TestGetValue().unwrap().ref();
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
TEST_P(WindowsPinningAPIFallbackFixture,
|
||||
WindowsPinningTestFallbackFailsEventPrivateBrowsingOff) {
|
||||
auto testCase = GetParam();
|
||||
const bool checkOnly = false;
|
||||
const bool privateBrowsing = false;
|
||||
testCase.expectedExtras.privateBrowsing = Some(privateBrowsing);
|
||||
|
||||
TestPinning(checkOnly, PinningShortcutOperation::Succeed, testCase.result,
|
||||
PinningFallbackOperation::Fail, privateBrowsing);
|
||||
|
||||
const bool fallbackSucceeded = false;
|
||||
auto extras = telemetry::pinning::CreateEventExtra(
|
||||
{S_OK, testCase.result, 1}, privateBrowsing, fallbackSucceeded);
|
||||
|
||||
EXPECT_TRUE(IsEqual(testCase.expectedExtras, extras));
|
||||
|
||||
auto metricsEvents = pinned_to_taskbar.TestGetValue().unwrap().ref();
|
||||
auto control = testCase.expectedExtras;
|
||||
EXPECT_TRUE(IsEqual(control, metricsEvents[0]));
|
||||
}
|
||||
|
||||
static const PinningAPITestCase fallbackFailedTestCases[] = {
|
||||
{.result = Win11PinToTaskBarResultStatus::NotSupported,
|
||||
.expectedExtras = {.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.notSupported = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result =
|
||||
Some(telemetry::pinning::TELEMETRY_NOT_SUPPORTED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::Success,
|
||||
.expectedExtras = {.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_SUCCESS),
|
||||
.success = Some(true)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::AlreadyPinned,
|
||||
.expectedExtras = {.alreadyPinned = Some(true),
|
||||
.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_ALREADY_PINNED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::NotCurrentlyAllowed,
|
||||
.expectedExtras =
|
||||
{.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.notCurrentlyAllowed = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_NOT_CURRENTLY_ALLOWED)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::Failed,
|
||||
.expectedExtras = {.error = Some(true),
|
||||
.fallbackPinningSuccess =
|
||||
Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(telemetry::pinning::TELEMETRY_ERROR)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures,
|
||||
.expectedExtras =
|
||||
{.errorLimitedAccessFeatures = Some(true),
|
||||
.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_ERROR_LIMITED_ACCESS_FEATURES)}},
|
||||
{.result = Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked,
|
||||
.expectedExtras =
|
||||
{.fallbackPinningSuccess = Some(telemetry::pinning::TELEMETRY_ERROR),
|
||||
.limitedAccessFeaturesLocked = Some(true),
|
||||
.numberOfAttempts = Some(1),
|
||||
.result = Some(
|
||||
telemetry::pinning::TELEMETRY_LIMITED_ACCESS_FEATURES_LOCKED)}},
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WindowsPinningFallbackTelemetryTests,
|
||||
WindowsPinningAPIFallbackFixture,
|
||||
::testing::ValuesIn(fallbackFailedTestCases));
|
||||
@@ -1,14 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
||||
LOCAL_INCLUDES += ["/browser/components/shell", "/toolkit/components/glean/tests"]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"TaskbarPinningMetricsTests.cpp",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "xul-gtest"
|
||||
@@ -10,8 +10,6 @@ LOCAL_INCLUDES += ["/xpcom/build"]
|
||||
BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
|
||||
XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"]
|
||||
|
||||
TEST_DIRS += ["gtest"]
|
||||
|
||||
JAR_MANIFESTS += ["jar.mn"]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
|
||||
#define UNICODE
|
||||
|
||||
#include "nsWindowsShellServiceInternal.h"
|
||||
#include "nsWindowsShellService.h"
|
||||
|
||||
#include "mozilla/glean/GleanMetrics.h"
|
||||
|
||||
#include "BinaryPath.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgIRequest.h"
|
||||
@@ -1640,28 +1637,26 @@ static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
|
||||
return ManageShortcutTaskbarPins(aCheckOnly, pinType, aShortcutPath);
|
||||
}
|
||||
|
||||
void PinCurrentAppToTaskbarHelper::CheckNotMainThread() {
|
||||
static nsresult PinCurrentAppToTaskbarImpl(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
!NS_IsMainThread(),
|
||||
"PinCurrentAppToTaskbarImpl should be called off main thread only");
|
||||
}
|
||||
|
||||
Result<bool, nsresult> PinCurrentAppToTaskbarHelper::CreateShortcutForTaskbar(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
nsAutoString& aShortcutPath) {
|
||||
nsAutoString shortcutPath;
|
||||
nsresult rv = FindMatchingShortcut(aAppUserModelId, aShortcutSubstring,
|
||||
aPrivateBrowsing, aShortcutPath);
|
||||
aPrivateBrowsing, shortcutPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
aShortcutPath.Truncate();
|
||||
shortcutPath.Truncate();
|
||||
}
|
||||
if (aShortcutPath.IsEmpty()) {
|
||||
if (shortcutPath.IsEmpty()) {
|
||||
if (aCheckOnly) {
|
||||
// Later checks rely on a shortcut already existing.
|
||||
// We don't want to create a shortcut in check only mode
|
||||
// so the best we can do is assume those parts will work.
|
||||
return false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString linkName(aShortcutName);
|
||||
@@ -1671,23 +1666,23 @@ Result<bool, nsresult> PinCurrentAppToTaskbarHelper::CreateShortcutForTaskbar(
|
||||
nsAutoString pbExeStr(PRIVATE_BROWSING_BINARY);
|
||||
nsresult rv = exeFile->Append(pbExeStr);
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
wchar_t exePath[MAXPATHLEN] = {};
|
||||
if (NS_WARN_IF(NS_FAILED(BinaryPath::GetLong(exePath)))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoString exeStr(exePath);
|
||||
nsresult rv = NS_NewLocalFile(exeStr, true, getter_AddRefs(exeFile));
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return Err(NS_ERROR_FILE_NOT_FOUND);
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> shortcutFile(aProgramsDir);
|
||||
shortcutFile->Append(aShortcutName);
|
||||
aShortcutPath.Assign(shortcutFile->NativePath());
|
||||
shortcutPath.Assign(shortcutFile->NativePath());
|
||||
|
||||
nsTArray<nsString> arguments;
|
||||
rv = CreateShortcutImpl(exeFile, arguments, aShortcutName, exeFile,
|
||||
@@ -1697,62 +1692,12 @@ Result<bool, nsresult> PinCurrentAppToTaskbarHelper::CreateShortcutForTaskbar(
|
||||
linkName, shortcutFile->NativePath(),
|
||||
aShortcutsLogDir);
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return Err(NS_ERROR_FILE_NOT_FOUND);
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Win11PinToTaskBarResult PinCurrentAppToTaskbarHelper::PinCurrentAppViaAPI(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
nsAutoString aShortcutPath) {
|
||||
return PinCurrentAppToTaskbarWin11(aCheckOnly, aAppUserModelId,
|
||||
aShortcutPath);
|
||||
}
|
||||
|
||||
nsresult PinCurrentAppToTaskbarHelper::PinCurrentAppFallback(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutPath) {
|
||||
return PinCurrentAppToTaskbarWin10(aCheckOnly, aAppUserModelId,
|
||||
aShortcutPath);
|
||||
}
|
||||
|
||||
nsresult PinCurrentAppToTaskbarImpl(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
UniquePtr<PinCurrentAppToTaskbarHelper> helper) {
|
||||
if (!helper) {
|
||||
helper.reset(new PinCurrentAppToTaskbarHelper);
|
||||
}
|
||||
|
||||
helper->CheckNotMainThread();
|
||||
|
||||
nsAutoString shortcutPath;
|
||||
|
||||
auto shortcutResult = helper->CreateShortcutForTaskbar(
|
||||
aCheckOnly, aPrivateBrowsing, aAppUserModelId, aShortcutName,
|
||||
aShortcutSubstring, aShortcutsLogDir, aGreDir, aProgramsDir,
|
||||
shortcutPath);
|
||||
|
||||
if (shortcutResult.isErr()) {
|
||||
nsresult err = shortcutResult.unwrapErr();
|
||||
|
||||
telemetry::shortcut::Record(aCheckOnly, err, aPrivateBrowsing);
|
||||
|
||||
return err;
|
||||
} else {
|
||||
if (!shortcutResult.unwrap()) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
telemetry::shortcut::Record(aCheckOnly, NS_OK, aPrivateBrowsing);
|
||||
|
||||
auto pinWithWin11TaskbarAPIResults =
|
||||
helper->PinCurrentAppViaAPI(aCheckOnly, aAppUserModelId, shortcutPath);
|
||||
|
||||
PinCurrentAppToTaskbarWin11(aCheckOnly, aAppUserModelId, shortcutPath);
|
||||
switch (pinWithWin11TaskbarAPIResults.result) {
|
||||
case Win11PinToTaskBarResultStatus::NotSupported:
|
||||
// Fall through to the win 10 mechanism
|
||||
@@ -1760,21 +1705,9 @@ nsresult PinCurrentAppToTaskbarImpl(
|
||||
|
||||
case Win11PinToTaskBarResultStatus::Success:
|
||||
case Win11PinToTaskBarResultStatus::AlreadyPinned:
|
||||
telemetry::pinning::Record(aCheckOnly, pinWithWin11TaskbarAPIResults,
|
||||
aPrivateBrowsing, false);
|
||||
return NS_OK;
|
||||
|
||||
case Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures:
|
||||
case Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked:
|
||||
case Win11PinToTaskBarResultStatus::NotCurrentlyAllowed:
|
||||
// return NS_ERROR_FAILURE;
|
||||
|
||||
// Fall through to the old mechanism for now
|
||||
// In future, we should be sending telemetry for when
|
||||
// an error occurs or for when pinning is not allowed
|
||||
// with the Win 11 APIs.
|
||||
break;
|
||||
|
||||
case Win11PinToTaskBarResultStatus::Failed:
|
||||
// return NS_ERROR_FAILURE;
|
||||
|
||||
@@ -1785,13 +1718,7 @@ nsresult PinCurrentAppToTaskbarImpl(
|
||||
break;
|
||||
}
|
||||
|
||||
auto result =
|
||||
helper->PinCurrentAppFallback(aCheckOnly, aAppUserModelId, shortcutPath);
|
||||
|
||||
telemetry::pinning::Record(aCheckOnly, pinWithWin11TaskbarAPIResults,
|
||||
aPrivateBrowsing, NS_SUCCEEDED(result));
|
||||
|
||||
return result;
|
||||
return PinCurrentAppToTaskbarWin10(aCheckOnly, aAppUserModelId, shortcutPath);
|
||||
}
|
||||
|
||||
static nsresult PinCurrentAppToTaskbarAsyncImpl(bool aCheckOnly,
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nswindowsshellserviceinternal_h____
|
||||
#define nswindowsshellserviceinternal_h____
|
||||
|
||||
#include "nsString.h"
|
||||
#include <mozilla/DefineEnum.h>
|
||||
#include "mozilla/Result.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include <windows.h>
|
||||
#include "mozilla/glean/GleanMetrics.h"
|
||||
#include "Windows11TaskbarPinning.h"
|
||||
|
||||
/**
|
||||
* Namespace to wrap recording of telemetry and separate it from everything
|
||||
* else. Should be easy to move into a class if it needs to be stubbed later for
|
||||
* testing purposes.
|
||||
*/
|
||||
namespace telemetry {
|
||||
namespace shortcut {
|
||||
|
||||
static const auto TELEMETRY_SUCCESS = "Success"_ns;
|
||||
static const auto TELEMETRY_FILE_NOT_FOUND = "FileNotFound"_ns;
|
||||
static const auto TELEMETRY_ERROR = "Error"_ns;
|
||||
|
||||
inline mozilla::glean::pinning_windows::ShortcutCreatedExtra CreateEventExtra(
|
||||
nsresult result, bool aPrivateBrowsing) {
|
||||
using namespace mozilla::glean::pinning_windows;
|
||||
using namespace mozilla;
|
||||
|
||||
switch (result) {
|
||||
case NS_OK:
|
||||
return ShortcutCreatedExtra{.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_SUCCESS),
|
||||
.success = Some(true)};
|
||||
|
||||
case NS_ERROR_FILE_NOT_FOUND:
|
||||
return ShortcutCreatedExtra{.fileNotFound = Some(true),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_FILE_NOT_FOUND)};
|
||||
|
||||
default:
|
||||
return ShortcutCreatedExtra{.error = Some(true),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_ERROR)};
|
||||
}
|
||||
}
|
||||
|
||||
inline void Record(bool aCheckOnly, nsresult result, bool aPrivateBrowsing) {
|
||||
using namespace mozilla::glean::pinning_windows;
|
||||
using namespace mozilla;
|
||||
|
||||
if (!aCheckOnly) {
|
||||
shortcut_created.Record(Some(CreateEventExtra(result, aPrivateBrowsing)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace shortcut
|
||||
|
||||
namespace pinning {
|
||||
|
||||
static const auto TELEMETRY_NOT_SUPPORTED = "NotSupported"_ns;
|
||||
static const auto TELEMETRY_SUCCESS = "Success"_ns;
|
||||
static const auto TELEMETRY_ALREADY_PINNED = "AlreadyPinned"_ns;
|
||||
static const auto TELEMETRY_NOT_CURRENTLY_ALLOWED = "NotCurrentlyAllowed"_ns;
|
||||
static const auto TELEMETRY_ERROR = "Error"_ns;
|
||||
static const auto TELEMETRY_ERROR_LIMITED_ACCESS_FEATURES =
|
||||
"ErrorLimitedAccessFeatures"_ns;
|
||||
static const auto TELEMETRY_LIMITED_ACCESS_FEATURES_LOCKED =
|
||||
"LimitedAccessFeaturesLocked"_ns;
|
||||
|
||||
inline mozilla::glean::pinning_windows::PinnedToTaskbarExtra CreateEventExtra(
|
||||
Win11PinToTaskBarResult result, bool aPrivateBrowsing,
|
||||
bool fallbackSucceeded) {
|
||||
using namespace mozilla::glean::pinning_windows;
|
||||
using namespace mozilla;
|
||||
|
||||
const auto fallbackResultString =
|
||||
fallbackSucceeded ? TELEMETRY_SUCCESS : TELEMETRY_ERROR;
|
||||
|
||||
auto resultStatus = result.result;
|
||||
switch (resultStatus) {
|
||||
case Win11PinToTaskBarResultStatus::NotSupported:
|
||||
return {.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.notSupported = Some(true),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_NOT_SUPPORTED)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::Success:
|
||||
return {.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_SUCCESS),
|
||||
.success = Some(true)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::AlreadyPinned:
|
||||
return {.alreadyPinned = Some(true),
|
||||
.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_ALREADY_PINNED)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::NotCurrentlyAllowed:
|
||||
return {.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.notCurrentlyAllowed = Some(true),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_NOT_CURRENTLY_ALLOWED)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::ErrorLimitedAccessFeatures:
|
||||
return {.errorLimitedAccessFeatures = Some(true),
|
||||
.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_ERROR_LIMITED_ACCESS_FEATURES)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::LimitedAccessFeaturesLocked:
|
||||
return {.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.limitedAccessFeaturesLocked = Some(true),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_LIMITED_ACCESS_FEATURES_LOCKED)};
|
||||
|
||||
case Win11PinToTaskBarResultStatus::Failed:
|
||||
default:
|
||||
return {.error = Some(true),
|
||||
.fallbackPinningSuccess = Some(fallbackResultString),
|
||||
.numberOfAttempts = Some(result.numAttempts),
|
||||
.privateBrowsing = Some(aPrivateBrowsing),
|
||||
.result = Some(TELEMETRY_ERROR)};
|
||||
}
|
||||
}
|
||||
|
||||
inline void Record(bool aCheckOnly, Win11PinToTaskBarResult result,
|
||||
bool aPrivateBrowsing, bool fallbackSucceeded) {
|
||||
using namespace mozilla::glean::pinning_windows;
|
||||
using namespace mozilla;
|
||||
|
||||
if (!aCheckOnly) {
|
||||
pinned_to_taskbar.Record(
|
||||
Some(CreateEventExtra(result, aPrivateBrowsing, fallbackSucceeded)));
|
||||
}
|
||||
}
|
||||
} // namespace pinning
|
||||
|
||||
} // namespace telemetry
|
||||
|
||||
/**
|
||||
* Helper class to wrap calling the logic for taskbar pinning. Specifically done
|
||||
* this way so that it can be stubbed out with a mock implementation for testing
|
||||
* metrics are collected properly. The base class includes the default
|
||||
* implementation that should be used outside of testing and is a light wrapper
|
||||
* around static functions.
|
||||
*/
|
||||
class PinCurrentAppToTaskbarHelper {
|
||||
public:
|
||||
virtual ~PinCurrentAppToTaskbarHelper() {}
|
||||
|
||||
virtual void CheckNotMainThread();
|
||||
|
||||
virtual mozilla::Result<bool, nsresult> CreateShortcutForTaskbar(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
nsAutoString& aShortcutPath);
|
||||
|
||||
virtual Win11PinToTaskBarResult PinCurrentAppViaAPI(
|
||||
bool aCheckOnly, const nsAString& aAppUserModelId,
|
||||
nsAutoString aShortcutPath);
|
||||
virtual nsresult PinCurrentAppFallback(bool aCheckOnly,
|
||||
const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutPath);
|
||||
};
|
||||
|
||||
class nsIFile;
|
||||
|
||||
nsresult PinCurrentAppToTaskbarImpl(
|
||||
bool aCheckOnly, bool aPrivateBrowsing, const nsAString& aAppUserModelId,
|
||||
const nsAString& aShortcutName, const nsAString& aShortcutSubstring,
|
||||
nsIFile* aShortcutsLogDir, nsIFile* aGreDir, nsIFile* aProgramsDir,
|
||||
mozilla::UniquePtr<PinCurrentAppToTaskbarHelper> helper =
|
||||
mozilla::UniquePtr<PinCurrentAppToTaskbarHelper>());
|
||||
|
||||
#endif // nswindowsshellserviceinternal_h____
|
||||
@@ -14,24 +14,10 @@ using namespace mozilla::glean::impl;
|
||||
class FOGFixture : public ::testing::Test {
|
||||
protected:
|
||||
FOGFixture() = default;
|
||||
virtual void SetUp() { TestResetFOG(); }
|
||||
|
||||
public:
|
||||
static void TestResetFOG() {
|
||||
virtual void SetUp() {
|
||||
nsCString empty;
|
||||
ASSERT_EQ(NS_OK, fog_test_reset(&empty, &empty));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ParamType>
|
||||
class FOGFixtureWithParam : public ::testing::TestWithParam<ParamType> {
|
||||
protected:
|
||||
FOGFixtureWithParam() = default;
|
||||
|
||||
virtual void SetUp() { TestResetFOG(); }
|
||||
|
||||
// Can be called by derived fixtures
|
||||
void TestResetFOG() { FOGFixture::TestResetFOG(); }
|
||||
};
|
||||
|
||||
#endif // FOGFixture_h_
|
||||
|
||||
Reference in New Issue
Block a user