diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index e3d8ed743f..c790de4883 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -2,16 +2,19 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" +#include #include "PushNotificationChannel.h" #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" #include #include #include "PushNotificationReceivedEventArgs.h" +#include "externs.h" namespace winrt::Windows { using namespace winrt::Windows::Networking::PushNotifications; using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Metadata; } namespace winrt::Microsoft { @@ -26,10 +29,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { return winrt::Windows::Uri{ m_channel.Uri() }; } + winrt::Windows::DateTime PushNotificationChannel::ExpirationTime() { return m_channel.ExpirationTime(); } + void PushNotificationChannel::Close() { try @@ -48,18 +53,73 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { - return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) + if (IsPackagedAppScenario()) { - auto strong = weak_self.get(); - if (strong) + return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { - handler(*strong, winrt::make(args)); - }; - }); + if (auto strong = weak_self.get()) + { + handler(*strong, winrt::make(args)); + }; + }); + } + else + { + auto lock = m_lock.lock_exclusive(); + if (!m_foregroundHandlerCount++) + { + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + wil::unique_cotaskmem_string processName; + THROW_IF_FAILED(GetCurrentProcessPath(processName)); + + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName.get())); + } + return m_foregroundHandlers.add(handler); + } } void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - m_channel.PushNotificationReceived(token); + if (IsPackagedAppScenario()) + { + m_channel.PushNotificationReceived(token); + } + else + { + auto lock = m_lock.lock_exclusive(); + m_foregroundHandlers.remove(token); + if (!--m_foregroundHandlerCount) + { + wil::com_ptr notificationsLongRunningPlatform{ + wil::CoCreateInstance(CLSCTX_LOCAL_SERVER) }; + + wil::unique_cotaskmem_string processName; + THROW_IF_FAILED(GetCurrentProcessPath(processName)); + + THROW_IF_FAILED(notificationsLongRunningPlatform->UnregisterForegroundActivator(processName.get())); + } + } + } + + HRESULT __stdcall PushNotificationChannel::InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept try + { + auto args = winrt::make(payload, length); + m_foregroundHandlers(*this, args); + *foregroundHandled = args.Handled(); + return S_OK; + } + CATCH_RETURN() + + bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() + { + return winrt::Windows::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); + } + + // Determines if the caller should be treated as packaged app or not. + bool PushNotificationChannel::IsPackagedAppScenario() + { + return AppModel::Identity::IsPackagedProcess() && IsBackgroundTaskBuilderAvailable(); } } diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 8349d8f6b8..d3764fb823 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -3,12 +3,18 @@ #pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.h" +#include namespace winrt::Microsoft::Windows::PushNotifications::implementation { - struct PushNotificationChannel : PushNotificationChannelT + typedef winrt::Windows::Foundation::TypedEventHandler< + winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel, + winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> PushNotificationEventHandler; + + struct PushNotificationChannel : PushNotificationChannelT { PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); + winrt::Windows::Foundation::Uri Uri(); winrt::Windows::Foundation::DateTime ExpirationTime(); void Close(); @@ -16,11 +22,21 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::event_token PushReceived(winrt::Windows::Foundation::TypedEventHandler handler); void PushReceived(winrt::event_token const& token) noexcept; + // IWpnForegroundSink + HRESULT __stdcall InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept; + private: + bool IsPackagedAppScenario(); + bool IsBackgroundTaskBuilderAvailable(); + const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + winrt::event m_foregroundHandlers; + ULONG m_foregroundHandlerCount = 0; + wil::srwlock m_lock; }; } + namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation { struct PushNotificationChannel : PushNotificationChannelT diff --git a/dev/PushNotifications/PushNotificationDummyDeferral.h b/dev/PushNotifications/PushNotificationDummyDeferral.h new file mode 100644 index 0000000000..35a3e826ba --- /dev/null +++ b/dev/PushNotifications/PushNotificationDummyDeferral.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once +#include "pch.h" +#include +#include + +struct PushNotificationDummyDeferral : winrt::implements +{ + PushNotificationDummyDeferral() {} + + void Complete() { }; +}; + +struct PushNotificationDummyDeferralFactory : winrt::implements +{ + HRESULT __stdcall CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final + { + RETURN_HR_IF(CLASS_E_NOAGGREGATION, aggregateInterface != nullptr); + return winrt::make().as(interfaceId, object); + } + + HRESULT __stdcall LockServer(BOOL) noexcept final + { + return S_OK; + } +}; diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 9db256b051..29e3623f2f 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -11,6 +11,7 @@ #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.cpp" #include #include +#include #include "ValueMarshaling.h" namespace winrt @@ -23,49 +24,100 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), m_rawNotification(backgroundTask.TriggerDetails().as().ContentBytes()) {} + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): + m_backgroundTaskInstance(backgroundTask), + m_rawNotificationPayload(BuildPayload(backgroundTask.TriggerDetails().as().ContentBytes())), + m_unpackagedAppScenario(false) {} - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(args.RawNotification().ContentBytes()) {} + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): + m_args(args), + m_rawNotificationPayload(BuildPayload(args.RawNotification().ContentBytes())), + m_unpackagedAppScenario(false) {} + + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(byte* const& payload, ULONG const& length) : + m_rawNotificationPayload(BuildPayload(payload, length)), + m_unpackagedAppScenario(true) {} + + std::vector PushNotificationReceivedEventArgs::BuildPayload(winrt::Windows::Storage::Streams::IBuffer const& buffer) + { + return { buffer.data(), buffer.data() + (buffer.Length() * sizeof(uint8_t)) }; + } + + std::vector PushNotificationReceivedEventArgs::BuildPayload(byte* const& payload, ULONG const& length) + { + return { payload, payload + (length * sizeof(uint8_t)) }; + } winrt::com_array PushNotificationReceivedEventArgs::Payload() { - auto rawNotificationData = m_rawNotification.data(); - return { rawNotificationData, rawNotificationData + (m_rawNotification.Length() * sizeof(uint8_t)) }; + return { m_rawNotificationPayload.data(), m_rawNotificationPayload.data() + (m_rawNotificationPayload.size() * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - - return m_backgroundTaskInstance.GetDeferral(); + if (!m_unpackagedAppScenario) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.GetDeferral(); + } + else + { + auto dummyDeferral = winrt::make(); + return dummyDeferral.as(); + } } winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - - return m_backgroundTaskInstance.Canceled(handler); + if (!m_unpackagedAppScenario) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.Canceled(handler); + } + else + { + return { 0 }; + } } void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + if (!m_unpackagedAppScenario) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); - m_backgroundTaskInstance.Canceled(token); + m_backgroundTaskInstance.Canceled(token); + } } bool PushNotificationReceivedEventArgs::Handled() { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); - - return m_args.Cancel(); + if (!m_unpackagedAppScenario) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + return m_args.Cancel(); + } + else + { + return m_handledUnpackaged; + } } void PushNotificationReceivedEventArgs::Handled(bool value) { - THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); - - m_args.Cancel(value); + if (!m_unpackagedAppScenario) + { + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + m_args.Cancel(value); + } + else + { + m_handledUnpackaged = value; + } } } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index 017b1f2f08..e4ef6761ef 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -1,5 +1,6 @@ #pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.h" +#include namespace winrt::Microsoft::Windows::PushNotifications::implementation { @@ -9,6 +10,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); + PushNotificationReceivedEventArgs(byte* const& payload, ULONG const& length); com_array Payload(); winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); @@ -18,8 +20,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void Handled(bool value); private: - const winrt::Windows::Storage::Streams::IBuffer m_rawNotification{}; + std::vector BuildPayload(winrt::Windows::Storage::Streams::IBuffer const& buffer); + std::vector BuildPayload(byte* const& payload, ULONG const& length); + + std::vector m_rawNotificationPayload; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; + + bool m_unpackagedAppScenario; + bool m_handledUnpackaged = true; }; } diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems index ae0ad30459..6787c2d61b 100644 --- a/dev/PushNotifications/PushNotifications.vcxitems +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -10,7 +10,7 @@ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - + @@ -35,5 +35,6 @@ + \ No newline at end of file diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index 64bc2f82ea..a1320b647c 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -6,12 +6,27 @@ import "ocidl.idl"; #include "../PushNotifications-Constants.h" +[object] +[uuid(25604D55-9B17-426F-9D67-2B11B3A65598)] +[pointer_default(unique)] +interface IWpnForegroundSink : IUnknown +{ + HRESULT InvokeAll([in] ULONG length, [in, size_is(length)] byte* data, [out] BOOL* foregroundHandled); +}; + [object] [uuid(60FC21B2-B396-4D49-94F0-7555869FB93C)] [pointer_default(unique)] interface INotificationsLongRunningPlatform : IUnknown { HRESULT RegisterFullTrustApplication([in] LPCWSTR processName, [in] GUID remoteId, [out] GUID* appId); + + HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCWSTR processName); + + HRESULT UnregisterForegroundActivator([in] LPCWSTR processName); + + HRESULT SendBackgroundNotification([in] LPCWSTR processName, [in] ULONG length, [in, size_is(length)] byte* data); + }; [uuid(PUSHNOTIFICATIONS_LIBID_UUID)] diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp new file mode 100644 index 0000000000..4849a0735d --- /dev/null +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.cpp @@ -0,0 +1,36 @@ +#pragma once + +#include "pch.h" + +#include +#include + +void ForegroundSinkManager::Add(std::wstring const& processName, IWpnForegroundSink* const& sink) +{ + auto lock = m_lock.lock_exclusive(); + m_foregroundMap[processName] = sink; +} + +void ForegroundSinkManager::Remove(std::wstring const& processName) +{ + auto lock = m_lock.lock_exclusive(); + m_foregroundMap.erase(processName); +} + +bool ForegroundSinkManager::InvokeForegroundHandlers(std::wstring const& processName, winrt::com_array const& payload, ULONG const& payloadSize) +{ + auto lock = m_lock.lock_exclusive(); + + auto it = m_foregroundMap.find(processName); + if (it != m_foregroundMap.end()) + { + BOOL foregroundHandled = true; + if (FAILED(it->second->InvokeAll(payloadSize, payload.data(), &foregroundHandled))) + { + Remove(processName); + return false; + } + return foregroundHandled; + } + return false; +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h new file mode 100644 index 0000000000..19e99bc885 --- /dev/null +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/ForegroundSinkManager.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include +#include +#include +#include + +class ForegroundSinkManager +{ +public: + ForegroundSinkManager() = default; + + void Add(std::wstring const& processName, IWpnForegroundSink* const& sink); + + void Remove(std::wstring const& processName); + + bool InvokeForegroundHandlers(std::wstring const& processName, winrt::com_array const& payload, ULONG const& payloadSize); + +private: + // An app can only have one activate foreground sink with Long Running Process. Event handlers in + // the sink are managed by the WindowsAppSDK. + std::unordered_map> m_foregroundMap = {}; + wil::srwlock m_lock; + +}; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj index d4fa8ab079..9f207246b2 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj @@ -128,7 +128,7 @@ Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -148,7 +148,7 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -163,7 +163,7 @@ Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -183,7 +183,7 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -192,13 +192,13 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL Windows DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) @@ -210,7 +210,7 @@ NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true Guard - stdcpp17 + stdcpp20 %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL @@ -218,10 +218,11 @@ true true DebugFull - Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + Microsoft.Internal.FrameworkUdk.dll;%(DelayLoadDLLs) + @@ -229,6 +230,7 @@ + diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters index 7b32be73d3..103525bc94 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/PushNotificationsLongRunningTask.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -44,6 +47,9 @@ Source Files + + Source Files + diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index a16f0f7c42..34147c2e26 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -55,3 +55,25 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterF return E_NOTIMPL; } +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterForegroundActivator(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName) +{ + RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + auto lock = m_lock.lock_exclusive(); + + m_foregroundSinkManager.Add(processName, sink); + return S_OK; +} + +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterForegroundActivator(_In_ PCWSTR processName) +{ + RETURN_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + auto lock = m_lock.lock_exclusive(); + + m_foregroundSinkManager.Remove(processName); + return S_OK; +} + +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::SendBackgroundNotification(_In_ PCWSTR processName, _In_ ULONG payloadSize, _In_ byte* payload) +{ + return S_OK; +} diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index 99b353de1b..129a586e8a 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -3,6 +3,7 @@ #include "../PushNotifications-Constants.h" #include "PlatformLifetimeTimerManager.h" +#include "ForegroundSinkManager.h" struct __declspec(uuid(PUSHNOTIFICATIONS_IMPL_CLSID_STRING)) NotificationsLongRunningPlatformImpl WrlFinal : Microsoft::WRL::RuntimeClass< @@ -20,16 +21,21 @@ Microsoft::WRL::RuntimeClass< STDMETHOD(RegisterFullTrustApplication)(_In_ PCWSTR processName, _In_ GUID remoteId, _Out_ GUID* appId) noexcept; - /* Add your functions to retrieve the platform components */ + STDMETHOD(RegisterForegroundActivator)(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName); + + STDMETHOD(UnregisterForegroundActivator)(_In_ PCWSTR processName); -private: + STDMETHOD(SendBackgroundNotification)(_In_ PCWSTR processName, _In_ ULONG payloadSize, _In_ byte* payload); + + /* Add your functions to retrieve the platform components */ + private: wil::srwlock m_lock; bool m_initialized = false; bool m_shutdown = false; - std::unique_ptr m_shutdownTimerManager; - // Here we will define the Platform components i.e. the map wrappings + std::unique_ptr m_shutdownTimerManager; + ForegroundSinkManager m_foregroundSinkManager; }; diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index 19776f45fb..00edb56363 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -7,3 +7,8 @@ wil::unique_event& GetWaitHandleForArgs(); inline const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; + +inline HRESULT GetCurrentProcessPath(wil::unique_cotaskmem_string& processName) +{ + return wil::GetModuleFileNameExW(GetCurrentProcess(), nullptr, processName); +}; diff --git a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj index dd5c04c42f..161e7bc430 100644 --- a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj +++ b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj @@ -174,7 +174,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)appmodel\identity;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)appmodel\identity;$(SolutionDir)common Use Level4 true @@ -193,7 +193,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -212,7 +212,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -231,7 +231,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -250,7 +250,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -273,7 +273,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -296,7 +296,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true @@ -319,7 +319,7 @@ - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(SolutionDir)common + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\DynamicDependency.DataStore.ProxyStub;$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(SolutionDir)common Use Level4 true diff --git a/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml b/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml index 5794d7b2ff..789ada48b2 100644 --- a/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml +++ b/test/PushNotifications/PushNotificationsLongRunningTask.Msix/appxmanifest.xml @@ -56,6 +56,12 @@ + + + + + + RequestChan auto channelExpiry = result.Channel().ExpirationTime(); // Register Push Event for Foreground - result.Channel().PushReceived([](const auto&, PushNotificationReceivedEventArgs const& args) + winrt::event_token token = result.Channel().PushReceived([](const auto&, PushNotificationReceivedEventArgs const& args) { auto payload = args.Payload();