gecko-dev/browser/components/shell/Windows11LimitedAccessFeatures.cpp
Michael Hughes e284de36c4 Bug 1879975 - Newer versions of Windows disable pinning to the taskbar using older methods r=mpohle,bhearsum,nrishel,glandium,nalexander
This is adding in the new Windows 11 only version of taskbar pinning. For the new pinning to work, we need to use limited access feature tokens. Those are going to be made private and aren't included with this change.
This change will compile, and will work if built against the correct limited access feature tokens, as specified in developer local machine config files, but for every other build, the new taskbar pinning won't work and will fall back to the old methods.
I will implement the try / release building machines using the secret limited access feature tokens in a follow-up diff.

Differential Revision: https://phabricator.services.mozilla.com/D205004
2024-04-22 23:07:37 +00:00

221 lines
6.6 KiB
C++

/* -*- 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/. */
/**
* This file exists so that LaunchModernSettingsDialogDefaultApps can be called
* without linking to libxul.
*/
#include "Windows11LimitedAccessFeatures.h"
// MINGW32 is not supported for these features
// Fall back function defined in the #else
#ifndef __MINGW32__
# include "nsString.h"
# include "nsWindowsHelpers.h"
# include "mozilla/Atomics.h"
# include <wrl.h>
# include <inspectable.h>
# include <roapi.h>
# include <windows.services.store.h>
# include <windows.foundation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
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;
};
/**
* To unlock features, we need a feature identifier, a token, and an
* attestation string. The token is generated by Microsoft and must
* match the publisher id Microsoft thinks we have.
*
* To get a token, find the right microsoft email address by doing
* a search on the web for the feature you want unlocked and reach
* out to the right people at Microsoft.
*
* The token is generated from Microsoft.
* The jumbled code in the attestation string is a publisher id and
* must match the code in the resources / .rc file for the identity
* looking like this:
*
* Identity LimitedAccessFeature {{ L"MozillaFirefox_pcsmm0jrprpb2" }}
*
* That is injected into our build in create_rc.py and is necessary
* to unlock the taskbar pinning feature / APIs from an unpackaged
* build.
*
*/
LimitedAccessFeatureInfo releaseTabPinningInfo{
L"com.microsoft.windows.taskbar.pin", L"kRFiWpEK5uS6PMJZKmR7MQ==",
L"pcsmm0jrprpb2 has registered their use of "
L"com.microsoft.windows.taskbar.pin with Microsoft and agrees to the terms "
L"of use."};
/*
// these keys were also provided by Microsoft. They require matching changes to
create_rc.py
LimitedAccessFeatureInfo betaTabPinningInfo {
L"com.microsoft.windows.taskbar.pin",
L"RGEhsYgKhmPLKyzkEHnMhQ==",
L"pcsmm0jrprpb2 has registered their use of com.microsoft.windows.taskbar.pin
with Microsoft and agrees to the terms of use."
};
LimitedAccessFeatureInfo nightlyTabPinningInfo {
L"com.microsoft.windows.taskbar.pin",
L"qbVzns/9kT+t15YbIwT4Jw==",
L"pcsmm0jrprpb2 has registered their use of com.microsoft.windows.taskbar.pin
with Microsoft and agrees to the terms of use."
};
*/
static LimitedAccessFeatureInfo limitedAccessFeatureInfo[] = {
{// Win11LimitedAccessFeatureType::Taskbar
releaseTabPinningInfo}};
/**
Implementation of the Win11LimitedAccessFeaturesInterface.
*/
class Win11LimitedAccessFeatures : public Win11LimitedAccessFeaturesInterface {
public:
using AtomicState = mozilla::Atomic<int, mozilla::SequentiallyConsistent>;
mozilla::Result<bool, HRESULT> Unlock(
Win11LimitedAccessFeatureType feature) override;
private:
AtomicState& GetState(Win11LimitedAccessFeatureType feature);
mozilla::Result<bool, HRESULT> UnlockImplementation(
Win11LimitedAccessFeatureType feature);
/**
* Store the state as an atomic so that it can be safely accessed from
* different threads.
*/
static AtomicState mTaskbarState;
static AtomicState mDefaultState;
enum State {
Uninitialized,
Locked,
Unlocked,
};
};
Win11LimitedAccessFeatures::AtomicState
Win11LimitedAccessFeatures::mTaskbarState(
Win11LimitedAccessFeatures::Uninitialized);
Win11LimitedAccessFeatures::AtomicState
Win11LimitedAccessFeatures::mDefaultState(
Win11LimitedAccessFeatures::Uninitialized);
RefPtr<Win11LimitedAccessFeaturesInterface>
CreateWin11LimitedAccessFeaturesInterface() {
RefPtr<Win11LimitedAccessFeaturesInterface> result(
new Win11LimitedAccessFeatures());
return result;
}
mozilla::Result<bool, HRESULT> Win11LimitedAccessFeatures::Unlock(
Win11LimitedAccessFeatureType feature) {
AtomicState& atomicState = GetState(feature);
int state = atomicState;
if (state != Uninitialized) {
return (state == Unlocked);
}
// If multiple threads read the state at the same time, and it's unitialized,
// both threads will unlock the feature. This situation is unlikely, but even
// if it happens, it's not a problem.
auto result = UnlockImplementation(feature);
int newState = Locked;
if (!result.isErr() && result.unwrap()) {
newState = Unlocked;
}
atomicState = newState;
return result;
}
Win11LimitedAccessFeatures::AtomicState& Win11LimitedAccessFeatures::GetState(
Win11LimitedAccessFeatureType feature) {
switch (feature) {
case Win11LimitedAccessFeatureType::Taskbar:
return mTaskbarState;
default:
MOZ_ASSERT(false,
"Unhandled feature type! Add a new atomic state variable, add "
"that entry to the switch statement above, and add the proper "
"entries for the feature and the token.");
return mDefaultState;
}
}
mozilla::Result<bool, HRESULT> Win11LimitedAccessFeatures::UnlockImplementation(
Win11LimitedAccessFeatureType feature) {
ComPtr<ILimitedAccessFeaturesStatics> limitedAccessFeatures;
ComPtr<ILimitedAccessFeatureRequestResult> limitedAccessFeaturesResult;
HRESULT hr = RoGetActivationFactory(
HStringReference(
RuntimeClass_Windows_ApplicationModel_LimitedAccessFeatures)
.Get(),
IID_ILimitedAccessFeaturesStatics, &limitedAccessFeatures);
if (!SUCCEEDED(hr)) {
return mozilla::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);
}
LimitedAccessFeatureStatus status;
hr = limitedAccessFeaturesResult->get_Status(&status);
if (!SUCCEEDED(hr)) {
return mozilla::Err(hr);
}
int state = Unlocked;
if ((status != LimitedAccessFeatureStatus_Available) &&
(status != LimitedAccessFeatureStatus_AvailableWithoutToken)) {
state = Locked;
}
return (state == Unlocked);
}
#else // MINGW32 implementation
RefPtr<Win11LimitedAccessFeaturesInterface>
CreateWin11LimitedAccessFeaturesInterface() {
RefPtr<Win11LimitedAccessFeaturesInterface> result;
return result;
}
#endif