diff --git a/browser/components/shell/Windows11LimitedAccessFeatures.cpp b/browser/components/shell/Windows11LimitedAccessFeatures.cpp new file mode 100644 index 000000000000..5c766965b9e2 --- /dev/null +++ b/browser/components/shell/Windows11LimitedAccessFeatures.cpp @@ -0,0 +1,237 @@ +/* -*- 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. + * + * Note that we keep our tokens secret. They are stored on our secrets + * cluster and picked up by our continuous build machines + * when they build and are injected below via define. + * + * For the taskbar, MOZ_WINDOWS_TASKBAR_PINNING_API_KEY is registered + * in the moz.build file for this, driven by the build environment config. + * + * The matching value in the build environment config is declared in two + * places: + * 1) in toolkit/moz.configure, which registers that it exists but doesn't + * set it's value + * 2) in win32, win64 and win64-aarch/common-opt files, which tell the + * system where to get the files from, via: + * + * ac_add_options + --with-windows-taskbar-pinning-api-keyfile=${APIKEYDIR}/windows-laf-tokens.data + * + * The file with the data is pulled down by the build infrastructure and + * only by the build infrastructure. To see all of the places where that + * data is used by the CI system, do a searchfox for windows-laf-tokens.data. + + * In order to unlock a feature locally, if you know the product name + * and token, you can store it in a file with the following format. + * + * PRODUCT_NAME TOKEN + * + * And that's it. No white space before, no white space or newlines or comments + after. + * Assuming you stored the above in + browser/branding/nightly/windows-taskbar-pinning-api.key, + * then you can add a line like this to your mozconfig file: + * + * ac_add_options + --with-windows-taskbar-pinning-api-keyfile=@TOPSRCDIR@/browser/branding/nightly/windows-taskbar-pinning-api.key + * + * And then when you recompile and run, the taskbar-pinning apis for + * Windows 11 will then work. + * + */ +static LimitedAccessFeatureInfo limitedAccessFeatureInfo[] = {{ + // Win11LimitedAccessFeatureType::Taskbar + MOZ_WINDOWS_TASKBAR_PINNING_API_FEATURE, + MOZ_WINDOWS_TASKBAR_PINNING_API_KEY, + MOZ_WINDOWS_TASKBAR_PINNING_API_ATTRIBUTION, +}}; + +/** + 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 diff --git a/browser/components/shell/Windows11LimitedAccessFeatures.h b/browser/components/shell/Windows11LimitedAccessFeatures.h new file mode 100644 index 000000000000..625b3f3d35dc --- /dev/null +++ b/browser/components/shell/Windows11LimitedAccessFeatures.h @@ -0,0 +1,52 @@ +/* -*- 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 SHELL_WINDOWS11LIMITEDACCESSFEATURES_H__ +#define SHELL_WINDOWS11LIMITEDACCESSFEATURES_H__ + +#include "nsISupportsImpl.h" +#include "mozilla/Result.h" +#include "mozilla/ResultVariant.h" +#include + +enum class Win11LimitedAccessFeatureType { + Taskbar, +}; + +/** + * Class to manage unlocking limited access features on Windows 11. + * Unless stubbing for testing purposes, create objects of this + * class with CreateWin11LimitedAccessFeaturesInterface. + * + * Windows 11 requires certain features to be unlocked in order to work + * (for instance, the Win11 Taskbar pinning APIs). Call Unlock() + * to unlock them. Generally, results will be cached in atomic variables + * and future calls to Unlock will be as long as it takes + * to fetch an atomic variable. + */ +class Win11LimitedAccessFeaturesInterface { + public: + /** + * Unlocks the limited access features, if possible. + * + * Returns an error code on error, true on successful unlock, + * false on unlock failed (but with no error). + */ + virtual mozilla::Result Unlock( + Win11LimitedAccessFeatureType feature) = 0; + + /** + * Reference counting and cycle collection. + */ + NS_INLINE_DECL_REFCOUNTING(Win11LimitedAccessFeaturesInterface) + + protected: + virtual ~Win11LimitedAccessFeaturesInterface() {} +}; + +RefPtr +CreateWin11LimitedAccessFeaturesInterface(); + +#endif // SHELL_WINDOWS11LIMITEDACCESSFEATURES_H__ diff --git a/browser/components/shell/Windows11TaskbarPinning.cpp b/browser/components/shell/Windows11TaskbarPinning.cpp new file mode 100644 index 000000000000..d6d6833e6a61 --- /dev/null +++ b/browser/components/shell/Windows11TaskbarPinning.cpp @@ -0,0 +1,260 @@ +/* -*- 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/. */ + +#include "Windows11TaskbarPinning.h" +#include "Windows11LimitedAccessFeatures.h" + +#include "nsWindowsHelpers.h" +#include "MainThreadUtils.h" +#include "nsThreadUtils.h" +#include + +#include "mozilla/Result.h" +#include "mozilla/ResultVariant.h" + +#ifndef __MINGW32__ // WinRT headers not yet supported by MinGW + +# include + +# include +# include +# include +# include +# include + +/** + * The Win32 SetEvent and WaitForSingleObject functions take HANDLE parameters + * which are typedefs of void*. When using nsAutoHandle, that means if you + * forget to call .get() first, everything still compiles and then doesn't work + * at runtime. For instance, calling SetEvent(mEvent) below would compile but + * not work at runtime and the waits would block forever. + * To ensure this isn't an issue, we wrap the event in a custom class here + * with the simple methods that we want on an event. + */ +class EventWrapper { + public: + EventWrapper() : mEvent(CreateEventW(nullptr, true, false, nullptr)) {} + + void Set() { SetEvent(mEvent.get()); } + + void Reset() { ResetEvent(mEvent.get()); } + + void Wait() { WaitForSingleObject(mEvent.get(), INFINITE); } + + private: + nsAutoHandle mEvent; +}; + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows; +using namespace ABI::Windows::UI::Shell; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::ApplicationModel; + +static mozilla::Result, HRESULT> InitializeTaskbar() { + ComPtr taskbarStaticsInspectable; + + HRESULT hr = RoGetActivationFactory( + HStringReference(RuntimeClass_Windows_UI_Shell_TaskbarManager).Get(), + IID_ITaskbarManagerStatics, &taskbarStaticsInspectable); + if (FAILED(hr)) { + return mozilla::Err(hr); + } + + ComPtr taskbarStatics; + + hr = taskbarStaticsInspectable.As(&taskbarStatics); + if (FAILED(hr)) { + return mozilla::Err(hr); + } + + ComPtr taskbarManager; + + hr = taskbarStatics->GetDefault(&taskbarManager); + if (FAILED(hr)) { + return mozilla::Err(hr); + } + + return taskbarManager; +} + +Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11( + bool aCheckOnly, const nsAString& aAppUserModelId, + nsAutoString aShortcutPath) { + MOZ_DIAGNOSTIC_ASSERT(!NS_IsMainThread(), + "PinCurrentAppToTaskbarWin11 should be called off main " + "thread only. It blocks, waiting on things to execute " + "asynchronously on the main thread."); + + { + RefPtr limitedAccessFeatures = + CreateWin11LimitedAccessFeaturesInterface(); + auto result = + limitedAccessFeatures->Unlock(Win11LimitedAccessFeatureType::Taskbar); + if (result.isErr()) { + return {result.unwrapErr(), Win11PinToTaskBarResultStatus::NotSupported}; + } + + if (result.unwrap() == false) { + return {S_OK, Win11PinToTaskBarResultStatus::NotSupported}; + } + } + + HRESULT hr; + Win11PinToTaskBarResultStatus resultStatus = + Win11PinToTaskBarResultStatus::NotSupported; + + 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(); + }; + + auto result = InitializeTaskbar(); + if (result.isErr()) { + hr = result.unwrapErr(); + return CompletedOperations( + Win11PinToTaskBarResultStatus::NotSupported); + } + + ComPtr taskbar = result.unwrap(); + boolean supported; + hr = taskbar->get_IsSupported(&supported); + if (FAILED(hr) || !supported) { + return CompletedOperations( + Win11PinToTaskBarResultStatus::NotSupported); + } + + if (aCheckOnly) { + return CompletedOperations(Win11PinToTaskBarResultStatus::Success); + } + + boolean isAllowed = false; + hr = taskbar->get_IsPinningAllowed(&isAllowed); + if (FAILED(hr) || !isAllowed) { + return CompletedOperations( + Win11PinToTaskBarResultStatus::NotCurrentlyAllowed); + } + + ComPtr> isPinnedOperation = nullptr; + hr = taskbar->IsCurrentAppPinnedAsync(&isPinnedOperation); + if (FAILED(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>( + [taskbar, &event, &resultStatus, &hr]( + IAsyncOperation* 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); + } + + unsigned char isCurrentAppPinned = false; + hr = asyncInfo->GetResults(&isCurrentAppPinned); + if (FAILED(hr)) { + return CompletedOperations( + Win11PinToTaskBarResultStatus::Failed); + } + + if (isCurrentAppPinned) { + return CompletedOperations( + Win11PinToTaskBarResultStatus::AlreadyPinned); + } + + ComPtr> requestPinOperation = nullptr; + hr = taskbar->RequestPinCurrentAppAsync(&requestPinOperation); + if (FAILED(hr)) { + return CompletedOperations( + Win11PinToTaskBarResultStatus::Failed); + } + + auto pinAppCallback = + Callback>( + [CompletedOperations, &hr]( + IAsyncOperation* 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; + }); + + HRESULT isPinnedOperationHR = + isPinnedOperation->put_Completed(isPinnedCallback.Get()); + if (FAILED(isPinnedOperationHR)) { + hr = isPinnedOperationHR; + 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 + // CompletedOperations + })); + + // block until the pinning is completed on the main thread + event.Wait(); + + return {hr, resultStatus}; +} + +#else // MINGW32 implementation below + +Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11( + bool aCheckOnly, const nsAString& aAppUserModelId, + nsAutoString aShortcutPath) { + return {S_OK, Win11PinToTaskBarResultStatus::NotSupported}; +} + +#endif // #ifndef __MINGW32__ // WinRT headers not yet supported by MinGW diff --git a/browser/components/shell/Windows11TaskbarPinning.h b/browser/components/shell/Windows11TaskbarPinning.h new file mode 100644 index 000000000000..14d6c4ea7f8f --- /dev/null +++ b/browser/components/shell/Windows11TaskbarPinning.h @@ -0,0 +1,34 @@ +/* -*- 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 to keep the Windows 11 Taskbar Pinning API + * related code as self-contained as possible. + */ + +#ifndef SHELL_WINDOWS11TASKBARPINNING_H__ +#define SHELL_WINDOWS11TASKBARPINNING_H__ + +#include "nsString.h" +#include + +enum class Win11PinToTaskBarResultStatus { + Failed, + NotCurrentlyAllowed, + AlreadyPinned, + Success, + NotSupported, +}; + +struct Win11PinToTaskBarResult { + HRESULT errorCode; + Win11PinToTaskBarResultStatus result; +}; + +Win11PinToTaskBarResult PinCurrentAppToTaskbarWin11( + bool aCheckOnly, const nsAString& aAppUserModelId, + nsAutoString aShortcutPath); + +#endif // SHELL_WINDOWS11TASKBARPINNING_H__ diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build index fe70623907f8..b303bd959767 100644 --- a/browser/components/shell/moz.build +++ b/browser/components/shell/moz.build @@ -50,6 +50,8 @@ elif CONFIG["OS_ARCH"] == "WINNT": ] SOURCES += [ "nsWindowsShellService.cpp", + "Windows11LimitedAccessFeatures.cpp", + "Windows11TaskbarPinning.cpp", "WindowsDefaultBrowser.cpp", "WindowsUserChoice.cpp", ] @@ -82,6 +84,25 @@ for var in ( ): DEFINES[var] = '"%s"' % CONFIG[var] +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": + apiKey = "MOZ_WINDOWS_TASKBAR_PINNING_API_KEY" + DEFINES[apiKey] = 'L"%s"' % ( + CONFIG[apiKey] or "MOZ_WINDOWS_TASKBAR_PINNING_API_KEY_UNDEFINED" + ) + + # Inject these other values here as well, to keep all of the data together + # but also to construct the attribution key on the fly + # at compile time instead of at runtime. + windows_feature = "com.microsoft.windows.taskbar.pin" + publisher_id = "pcsmm0jrprpb2" + + DEFINES["MOZ_WINDOWS_TASKBAR_PINNING_API_FEATURE"] = 'L"%s"' % windows_feature + DEFINES["MOZ_WINDOWS_TASKBAR_PINNING_API_ATTRIBUTION"] = ( + 'L"%s has registered their use of %s with Microsoft and agrees to the terms of use."' + % (publisher_id, windows_feature) + ) + + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] diff --git a/browser/components/shell/nsWindowsShellService.cpp b/browser/components/shell/nsWindowsShellService.cpp index 86c7694bf87e..f7bca95b09ec 100644 --- a/browser/components/shell/nsWindowsShellService.cpp +++ b/browser/components/shell/nsWindowsShellService.cpp @@ -39,6 +39,7 @@ #include "nsIXULAppInfo.h" #include "nsINIParser.h" #include "nsNativeAppSupportWin.h" +#include "Windows11TaskbarPinning.h" #include #include @@ -1626,7 +1627,7 @@ nsWindowsShellService::GetTaskbarTabPins(nsTArray& aShortcutPaths) { static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly, const nsAString& aAppUserModelId, - nsAutoString aShortcutPath) { + const nsAString& aShortcutPath) { // The behavior here is identical if we're only checking or if we try to pin // but the app is already pinned so we update the variable accordingly. if (!aCheckOnly) { @@ -1695,6 +1696,28 @@ static nsresult PinCurrentAppToTaskbarImpl( } } + auto pinWithWin11TaskbarAPIResults = + PinCurrentAppToTaskbarWin11(aCheckOnly, aAppUserModelId, shortcutPath); + switch (pinWithWin11TaskbarAPIResults.result) { + case Win11PinToTaskBarResultStatus::NotSupported: + // Fall through to the win 10 mechanism + break; + + case Win11PinToTaskBarResultStatus::Success: + case Win11PinToTaskBarResultStatus::AlreadyPinned: + return NS_OK; + + case Win11PinToTaskBarResultStatus::NotCurrentlyAllowed: + case Win11PinToTaskBarResultStatus::Failed: + // 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; + } + return PinCurrentAppToTaskbarWin10(aCheckOnly, aAppUserModelId, shortcutPath); } @@ -1720,7 +1743,7 @@ static nsresult PinCurrentAppToTaskbarAsyncImpl(bool aCheckOnly, } nsAutoString aumid; - if (NS_WARN_IF(!mozilla::widget::WinTaskbar::GenerateAppUserModelID( + if (NS_WARN_IF(!mozilla::widget::WinTaskbar::GetAppUserModelID( aumid, aPrivateBrowsing))) { return NS_ERROR_FAILURE; } diff --git a/config/create_rc.py b/config/create_rc.py index d75959d4e02b..b741952f43ba 100644 --- a/config/create_rc.py +++ b/config/create_rc.py @@ -26,6 +26,8 @@ TEMPLATE = """ {include} +Identity LimitedAccessFeature {{ L"{lafidentity}_pcsmm0jrprpb2" }} + ///////////////////////////////////////////////////////////////////////////// // @@ -112,8 +114,8 @@ def split_and_normalize_version(version, len): def has_manifest(module_rc, manifest_id): - for line in module_rc.splitlines(): - line = line.split(None, 2) + for lineFromInput in module_rc.splitlines(): + line = lineFromInput.split(None, 2) if len(line) < 2: continue id, what, *rest = line @@ -167,8 +169,13 @@ def generate_module_rc(binary="", rcinclude=None): else: include = "" + lafidentity = buildconfig.substs.get( + "MOZ_WINDOWS_TASKBAR_PINNING_API_CLIENTID", "LAF_ID_UNDEFINED" + ) + data = TEMPLATE.format( include=include, + lafidentity=lafidentity, fileversion=overrides.get("WIN32_MODULE_FILEVERSION", milestone_winversion), productversion=overrides.get( "WIN32_MODULE_PRODUCTVERSION", milestone_winversion diff --git a/toolkit/moz.configure b/toolkit/moz.configure index 2b034e666c7b..68f0e126f4ce 100644 --- a/toolkit/moz.configure +++ b/toolkit/moz.configure @@ -1051,6 +1051,8 @@ id_and_secret_keyfile("Leanplum SDK") simple_keyfile("Pocket API") +id_and_secret_keyfile("Windows Taskbar Pinning API") + # WebRender Debugger integration # ==============================================================