/* -*- 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 # include # include # include # include 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; mozilla::Result Unlock( Win11LimitedAccessFeatureType feature) override; private: AtomicState& GetState(Win11LimitedAccessFeatureType feature); mozilla::Result 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 CreateWin11LimitedAccessFeaturesInterface() { RefPtr result( new Win11LimitedAccessFeatures()); return result; } mozilla::Result 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 Win11LimitedAccessFeatures::UnlockImplementation( Win11LimitedAccessFeatureType feature) { ComPtr limitedAccessFeatures; ComPtr 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(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 CreateWin11LimitedAccessFeaturesInterface() { RefPtr result; return result; } #endif