diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln index bd34bfa0e9..0d2c7b00d9 100644 --- a/WindowsAppRuntime.sln +++ b/WindowsAppRuntime.sln @@ -1353,10 +1353,6 @@ Global {A3FBA80D-5B35-471F-9A45-DB4B29E195B9} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} {91D03B95-1B0C-4BEB-8441-30DA7D615538} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} {103C0C23-7BA8-4D44-A63C-83488E2E3A81} = {91D03B95-1B0C-4BEB-8441-30DA7D615538} - {5B2D17FE-C371-417F-860C-3D32397C2404} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} - {424A6D96-37EE-4456-8347-08AB425C8DBE} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} - {56A1D696-FEDA-4333-BF37-772EBECECB10} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} - {D012E4BB-F16B-472D-A26D-D449CEFA988E} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} {1307DD1B-BBE8-4CD0-B1A0-0DB6D61EEAA0} = {91D03B95-1B0C-4BEB-8441-30DA7D615538} {A1B25DCF-6A54-414D-8E24-F4D24EE9299D} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} diff --git a/dev/AppLifecycle/ActivationRegistrationManager.h b/dev/AppLifecycle/ActivationRegistrationManager.h index 374586308e..d7ef5dcde2 100644 --- a/dev/AppLifecycle/ActivationRegistrationManager.h +++ b/dev/AppLifecycle/ActivationRegistrationManager.h @@ -11,7 +11,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation static PCWSTR c_argumentSuffix{ L":" }; static PCWSTR c_msProtocolArgumentString{ L"ms-protocol" }; static PCWSTR c_pushProtocolArgumentString{ L"WindowsAppRuntimePushServer" }; - static PCWSTR c_toastProtocolArgumentString{ L"AppNotificationActivated" }; + static PCWSTR c_appNotificationProtocolArgumentString{ L"AppNotificationActivated" }; static PCWSTR c_runKeyPath{ LR"(Software\Microsoft\Windows\CurrentVersion\Run\)" }; struct ActivationRegistrationManager diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index 4314626ab1..cb149ef6c9 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -68,7 +68,8 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation wil::unique_hlocal_ptr argv{ CommandLineToArgvW(commandLine.c_str(), &argc) }; - PCWSTR activationKinds[] = { c_msProtocolArgumentString, c_pushProtocolArgumentString, c_toastProtocolArgumentString }; + PCWSTR activationKinds[] = { c_msProtocolArgumentString, c_pushProtocolArgumentString, c_appNotificationProtocolArgumentString }; + for (auto activationKind : activationKinds) { auto [ kind, data ] = GetActivationArguments(argv.get(), argc, activationKind); @@ -488,10 +489,10 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation // protocol, except the catch-all LaunchActivatedEventArgs case. if (!contractArgument.empty()) { - if (contractArgument == c_pushProtocolArgumentString || contractArgument == c_toastProtocolArgumentString) + if (contractArgument == c_pushProtocolArgumentString || contractArgument == c_appNotificationProtocolArgumentString) { // Generate a basic encoded launch Uri for Push/Toast activations - PCWSTR contractId = (contractArgument == c_pushProtocolArgumentString) ? c_pushContractId : c_toastContractId; + PCWSTR contractId = (contractArgument == c_pushProtocolArgumentString) ? c_pushContractId : c_appNotificationContractId; std::wstring tempContractData = GenerateEncodedLaunchUri(L"App", contractId); contractArgument = c_msProtocolArgumentString; diff --git a/dev/AppLifecycle/ExtensionContract.h b/dev/AppLifecycle/ExtensionContract.h index 74c42d3b0d..a7c845b654 100644 --- a/dev/AppLifecycle/ExtensionContract.h +++ b/dev/AppLifecycle/ExtensionContract.h @@ -26,7 +26,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { ExtendedActivationKind::Protocol, c_protocolContractId, &ProtocolActivatedEventArgs::Deserialize }, { ExtendedActivationKind::StartupTask, c_startupTaskContractId, &StartupActivatedEventArgs::Deserialize }, { ExtendedActivationKind::Push, c_pushContractId, &winrt::Microsoft::Windows::PushNotifications::Deserialize }, - { ExtendedActivationKind::AppNotification, c_toastContractId, &winrt::Microsoft::Windows::PushNotifications::Deserialize }, + { ExtendedActivationKind::AppNotification, c_appNotificationContractId, &winrt::Microsoft::Windows::PushNotifications::Deserialize }, }; inline bool IsEncodedLaunch(winrt::Windows::Foundation::Uri const& uri) diff --git a/dev/PushNotifications/GetNotificationEventArgs.h b/dev/PushNotifications/GetNotificationEventArgs.h index df8b44c146..ff30ec6fb0 100644 --- a/dev/PushNotifications/GetNotificationEventArgs.h +++ b/dev/PushNotifications/GetNotificationEventArgs.h @@ -7,7 +7,7 @@ #include "externs.h" constexpr PCWSTR c_pushContractId = L"Windows.Push"; -constexpr PCWSTR c_toastContractId = L"Windows.Toast"; +constexpr PCWSTR c_appNotificationContractId = L"Windows.Toast"; namespace winrt::Microsoft::Windows::PushNotifications { diff --git a/dev/PushNotifications/PushBackgroundTaskInstance.h b/dev/PushNotifications/PushBackgroundTaskInstance.h new file mode 100644 index 0000000000..0b4993aea6 --- /dev/null +++ b/dev/PushNotifications/PushBackgroundTaskInstance.h @@ -0,0 +1,35 @@ +#include + +// Mocks IBackgroundTaskInstance to send raw payloads to packaged apps in +// PushNotificationBackgroundTask::Run by com activation from PushNotificationsLongRunningProcess +struct PushBackgroundTaskInstance : winrt::implements +{ + PushBackgroundTaskInstance() {}; + PushBackgroundTaskInstance(std::wstring const& payload): m_payload(payload) {}; + + winrt::guid InstanceId() { return winrt::guid(); }; + UINT32 SuspendedCount() { return 0; }; + UINT32 Progress() { return 0; }; + UINT32 Progress(UINT32 /* progress */) { return 0; }; + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration Task() { return nullptr; }; + winrt::Windows::Foundation::IInspectable TriggerDetails() { return winrt::box_value(m_payload); }; + winrt::event_token Canceled(winrt::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler const& /* handler */) { return winrt::event_token{}; }; + void Canceled(winrt::event_token const& /* token */) noexcept { return; }; + winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral() { return nullptr; }; +private: + std::wstring m_payload; +}; + +struct PushBackgroundTaskInstanceFactory : 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/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 0064416ede..0cf0124ff5 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -12,6 +12,12 @@ #include "PushNotificationReceivedEventArgs.h" #include "externs.h" +#include "PushNotificationUtility.h" + +namespace PushNotificationHelpers +{ + using namespace winrt::Microsoft::Windows::PushNotifications::Helpers; +} namespace winrt { @@ -23,8 +29,20 @@ namespace winrt void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { auto appProperties = winrt::CoreApplication::Properties(); - winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::make(taskInstance); - appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); + // This function can be triggered by either OS background infrastructure + // or by the PushNotificationsLongRunningProcess. + if (PushNotificationHelpers::IsPackagedAppScenario()) + { + winrt::PushNotificationReceivedEventArgs activatedEventArgs{ winrt::make(taskInstance) }; + appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); + } + else + { + // Need to mock a RawNotification object instead of winrt boxing: https://github.com/microsoft/WindowsAppSDK/issues/2075 + winrt::hstring payload{ winrt::unbox_value(taskInstance.TriggerDetails()) }; + winrt::PushNotificationReceivedEventArgs activatedEventArgs{ winrt::make(payload.c_str()) }; + appProperties.Insert(LRP_ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); + } SetEvent(GetWaitHandleForArgs().get()); } diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 658e2db70b..aa8c82b736 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -5,25 +5,16 @@ #include #include "PushNotificationChannel.h" #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" -#include #include #include "PushNotificationReceivedEventArgs.h" #include #include "externs.h" #include "PushNotificationTelemetry.h" -#include #include "PushNotificationUtility.h" -namespace winrt::Windows -{ - using namespace winrt::Windows::Networking::PushNotifications; - using namespace winrt::Windows::Foundation; - using namespace winrt::Windows::Metadata; -} -namespace winrt::Microsoft -{ - using namespace winrt::Microsoft::Windows::PushNotifications; -} +using namespace winrt::Windows::Foundation; +using namespace winrt::Microsoft::Windows::PushNotifications; + namespace PushNotificationHelpers { @@ -32,143 +23,92 @@ namespace PushNotificationHelpers namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationChannel::PushNotificationChannel(winrt::Windows::PushNotificationChannel const& channel): m_channel(channel) + Uri PushNotificationChannel::Uri() { - THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::PushNotifications::Feature_PushNotifications::IsEnabled()); + return winrt::Windows::Foundation::Uri{ m_channelInfo.channelUri }; } - winrt::Windows::Uri PushNotificationChannel::Uri() + DateTime PushNotificationChannel::ExpirationTime() { - if (m_channel) - { - return winrt::Windows::Uri{ m_channel.Uri() }; - } - else - { - return winrt::Windows::Uri{ m_channelInfo.channelUri }; - } - } - - winrt::Windows::DateTime PushNotificationChannel::ExpirationTime() - { - if (m_channel) - { - return m_channel.ExpirationTime(); - } - else - { - return m_channelInfo.channelExpiryTime; - } + return m_channelInfo.channelExpiryTime; } void PushNotificationChannel::Close() { try { - if (m_channel) - { - m_channel.Close(); - } - else - { - THROW_IF_FAILED(PushNotifications_CloseChannel(m_channelInfo.appUserModelId.c_str(), m_channelInfo.channelId.c_str())); - } - + THROW_IF_FAILED(PushNotifications_CloseChannel(m_channelInfo.appId.c_str(), m_channelInfo.channelId.c_str())); PushNotificationTelemetry::ChannelClosedByApi(S_OK); } catch (...) { - auto channelCloseException = hresult_error(to_hresult()); + auto channelCloseException { hresult_error(to_hresult()) }; PushNotificationTelemetry::ChannelClosedByApi(channelCloseException.code()); if (channelCloseException.code() != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) { - throw hresult_error(to_hresult()); + throw channelCloseException; } } } - winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) + winrt::event_token PushNotificationChannel::PushReceived(TypedEventHandler handler) { - if (PushNotificationHelpers::IsPackagedAppScenario()) + bool registeredEvent { false }; { - if (m_channel) - { - return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) - { - if (auto strong = weak_self.get()) - { - auto pushArgs = winrt::make(args); - pushArgs.Handled(true); - handler(*strong, pushArgs); - }; - }); - } - else - { - // The channelUri is directly obtained when we request Channel from UDK using RemoteId - auto lock = m_lock.lock_exclusive(); - - if (!m_foregroundHandlerCount) - { - auto appUserModelId{ winrt::Microsoft::Helpers::GetAppUserModelId() }; - - THROW_IF_FAILED(PushNotifications_RegisterNotificationSinkForFullTrustApplication(appUserModelId.get(), this)); - } + auto lock { m_lock.lock_shared() }; + registeredEvent = bool(m_foregroundHandlers); + } - ++m_foregroundHandlerCount; + if(!registeredEvent) + { + if(PushNotificationHelpers::IsPackagedAppScenario()) + { + auto appUserModelId{ PushNotificationHelpers::GetAppUserModelId() }; - return m_foregroundHandlers.add(handler); + // Register a sink with platform which is initialized in the current process + THROW_IF_FAILED(PushNotifications_RegisterNotificationSinkForFullTrustApplication(appUserModelId.get(), this)); } - } - else - { - auto lock = m_lock.lock_exclusive(); - if (!m_foregroundHandlerCount++) + else { - auto notificationsLongRunningPlatform{ winrt::Microsoft::Helpers::GetNotificationPlatform() }; + auto notificationsLongRunningPlatform{ PushNotificationHelpers::GetNotificationPlatform() }; wil::unique_cotaskmem_string processName; THROW_IF_FAILED(GetCurrentProcessPath(processName)); - THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName.get())); + // Register a sink with platform brokered through PushNotificationsLongRunningProcess + THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName.get())); } - return m_foregroundHandlers.add(handler); } + + auto lock { m_lock.lock_exclusive() }; + return m_foregroundHandlers.add(handler); } void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - if (PushNotificationHelpers::IsPackagedAppScenario()) + bool registeredEvent { false }; { - if (m_channel) - { - m_channel.PushNotificationReceived(token); - } - else - { - auto lock = m_lock.lock_exclusive(); - - if (m_foregroundHandlerCount == 1) - { - auto appUserModelId{ winrt::Microsoft::Helpers::GetAppUserModelId() }; + auto lock { m_lock.lock_exclusive() }; + m_foregroundHandlers.remove(token); + registeredEvent = bool(m_foregroundHandlers); + } - THROW_IF_FAILED(PushNotifications_UnregisterNotificationSinkForFullTrustApplication(appUserModelId.get())); - } + if(!registeredEvent) + { + // Packaged apps with BI available will remove their handlers from the platform. + // Unpackaged apps / Packaged apps treated as unpackaged will unregister from Long Running process. + if (PushNotificationHelpers::IsPackagedAppScenario()) + { + auto appUserModelId{ PushNotificationHelpers::GetAppUserModelId() }; - m_foregroundHandlers.remove(token); - --m_foregroundHandlerCount; + THROW_IF_FAILED(PushNotifications_UnregisterNotificationSinkForFullTrustApplication(appUserModelId.get())); } - } - else - { - auto lock = m_lock.lock_exclusive(); - m_foregroundHandlers.remove(token); - if (!--m_foregroundHandlerCount) + else { - auto notificationsLongRunningPlatform{ winrt::Microsoft::Helpers::GetNotificationPlatform() }; + auto notificationsLongRunningPlatform{ PushNotificationHelpers::GetNotificationPlatform() }; wil::unique_cotaskmem_string processName; THROW_IF_FAILED(GetCurrentProcessPath(processName)); @@ -194,9 +134,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (!foregroundHandled) { - wil::unique_cotaskmem_string processName; - THROW_IF_FAILED(GetCurrentProcessPath(processName)); - THROW_IF_FAILED(winrt::Microsoft::Helpers::ProtocolLaunchHelper(processName.get(), payloadLength, payload)); + if (!AppModel::Identity::IsPackagedProcess()) + { + wil::unique_cotaskmem_string processName; + THROW_IF_FAILED(GetCurrentProcessPath(processName)); + THROW_IF_FAILED(PushNotificationHelpers::ProtocolLaunchHelper(processName.get(), payloadLength, payload)); + } } return S_OK; diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 1a1595acd1..9b79dee737 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -6,6 +6,7 @@ #include #include "winrt/Windows.Networking.PushNotifications.h" #include +#include #include "externs.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation @@ -16,9 +17,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation struct PushNotificationChannel : PushNotificationChannelT { - PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); + PushNotificationChannel(struct ChannelDetails channelInfo) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::PushNotifications::Feature_PushNotifications::IsEnabled()); - PushNotificationChannel(struct ChannelDetails const& channelInfo) : m_channelInfo(channelInfo) {}; + std::swap(m_channelInfo, channelInfo); + }; winrt::Windows::Foundation::Uri Uri(); winrt::Windows::Foundation::DateTime ExpirationTime(); @@ -34,14 +38,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation HRESULT __stdcall OnRawNotificationReceived(unsigned int payloadLength, _In_ byte* payload, _In_ HSTRING /*correlationVector */) noexcept; private: - bool IsPackagedAppScenario(); - bool IsBackgroundTaskBuilderAvailable(); - - const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; - const struct ChannelDetails m_channelInfo{}; + struct ChannelDetails m_channelInfo{}; winrt::event m_foregroundHandlers; - ULONG m_foregroundHandlerCount = 0; wil::srwlock m_lock; }; } diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 0c41eeb3c2..36cf77613d 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -18,7 +18,6 @@ #include #include #include "NotificationsLongRunningProcess_h.h" -#include #include "PushNotificationUtility.h" #include "AppNotificationUtility.h" @@ -28,12 +27,18 @@ using namespace Microsoft::Windows::AppNotifications::Helpers; constexpr std::wstring_view backgroundTaskName = L"PushBackgroundTaskName"sv; static wil::unique_event g_waitHandleForArgs; +static winrt::guid g_comServerClsid{ GUID_NULL }; wil::unique_event& GetWaitHandleForArgs() { return g_waitHandleForArgs; } +winrt::guid& GetComServerClsid() +{ + return g_comServerClsid; +} + namespace winrt { using namespace Windows::ApplicationModel::Background; @@ -90,22 +95,15 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_IF_FAILED(notificationPlatform->RegisterFullTrustApplication(processName.get(), remoteId, &unpackagedAppUserModelId)); } - winrt::hresult CreateChannelWithRemoteIdHelper(const winrt::guid& remoteId, ChannelDetails& channelInfo) noexcept try + winrt::hresult CreateChannelWithRemoteIdHelper(wil::unique_cotaskmem_string const& appId, const winrt::guid& remoteId, ChannelDetails& channelInfo) noexcept try { - wchar_t appUserModelId[APPLICATION_USER_MODEL_ID_MAX_LENGTH] = {}; - UINT32 appUserModelIdSize{ ARRAYSIZE(appUserModelId) }; - - THROW_IF_FAILED(GetCurrentApplicationUserModelId(&appUserModelIdSize, appUserModelId)); - - THROW_HR_IF(E_INVALIDARG, (appUserModelIdSize > APPLICATION_USER_MODEL_ID_MAX_LENGTH) || (appUserModelIdSize == 0)); - HRESULT operationalCode{}; ABI::Windows::Foundation::DateTime channelExpiryTime{}; wil::unique_cotaskmem_string channelId; wil::unique_cotaskmem_string channelUri; THROW_IF_FAILED(PushNotifications_CreateChannelWithRemoteIdentifier( - appUserModelId, + appId.get(), remoteId, &operationalCode, &channelId, @@ -115,7 +113,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_IF_FAILED(operationalCode); winrt::copy_from_abi(channelInfo.channelExpiryTime, &channelExpiryTime); - channelInfo.appUserModelId = winrt::hstring{ appUserModelId }; + channelInfo.appId = winrt::hstring{ appId.get() }; channelInfo.channelId = winrt::hstring{ channelId.get() }; channelInfo.channelUri = winrt::hstring{ channelUri.get() }; @@ -123,12 +121,17 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } CATCH_RETURN() + winrt::Microsoft::Windows::PushNotifications::PushNotificationManager PushNotificationManager::Default() + { + static auto pushNotificationManager{ winrt::make() }; + return pushNotificationManager; + } + winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(const winrt::guid remoteId) { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::PushNotifications::Feature_PushNotifications::IsEnabled()); wil::winrt_module_reference moduleRef{}; - bool usingLegacyImplementation{ false }; try { @@ -156,72 +159,38 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { try { - if (IsActivatorSupported(PushNotificationRegistrationActivators::PushTrigger)) + ChannelDetails channelInfo{}; + if (PushNotificationHelpers::IsPackagedAppScenario()) { - ChannelDetails channelInfo{}; - winrt::hresult hr = CreateChannelWithRemoteIdHelper(remoteId, channelInfo); - - // RemoteId APIs are not applicable for downlevel OS versions. - // So we get error E_NOTIMPL and we fallback to calling into - // public WinRT API CreatePushNotificationChannelForApplicationAsync - // to request a channel. - if (SUCCEEDED(hr)) - { - PushNotificationTelemetry::ChannelRequestedByApi(S_OK, remoteId, usingLegacyImplementation); - - co_return winrt::make( - winrt::make(channelInfo), - S_OK, - PushNotificationChannelStatus::CompletedSuccess); - } - else if (hr == E_NOTIMPL) - { - usingLegacyImplementation = true; - - PushNotificationChannelManager channelManager{}; - winrt::PushNotificationChannel pushChannelReceived{ nullptr }; - - pushChannelReceived = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); - - PushNotificationTelemetry::ChannelRequestedByApi(S_OK, remoteId, usingLegacyImplementation); - - co_return winrt::make( - winrt::make(pushChannelReceived), - S_OK, - PushNotificationChannelStatus::CompletedSuccess); - } - else - { - winrt::check_hresult(hr); - } + auto appUserModelId{ PushNotificationHelpers::GetAppUserModelId() }; + THROW_IF_FAILED(CreateChannelWithRemoteIdHelper(appUserModelId, remoteId, channelInfo)); } else { + // AppId is generated by PushNotificationLongRunningTask singleton wil::unique_cotaskmem_string unpackagedAppUserModelId; RegisterUnpackagedApplicationHelper(remoteId, unpackagedAppUserModelId); - PushNotificationChannelManager channelManager{}; - winrt::PushNotificationChannel pushChannelReceived{ co_await channelManager.CreatePushNotificationChannelForApplicationAsync(unpackagedAppUserModelId.get()) }; + THROW_IF_FAILED(CreateChannelWithRemoteIdHelper(unpackagedAppUserModelId, remoteId, channelInfo)); auto notificationPlatform{ PushNotificationHelpers::GetNotificationPlatform() }; wil::unique_cotaskmem_string processName; THROW_IF_FAILED(GetCurrentProcessPath(processName)); - THROW_IF_FAILED(notificationPlatform->RegisterLongRunningActivator(processName.get())); + THROW_IF_FAILED(notificationPlatform->RegisterLongRunningActivatorWithClsid(processName.get(), GetComServerClsid())); std::wstring toastAppId{ RetrieveNotificationAppId() }; THROW_IF_FAILED(notificationPlatform->AddToastRegistrationMapping(processName.get(), toastAppId.c_str())); - - PushNotificationTelemetry::ChannelRequestedByApi(S_OK, remoteId, usingLegacyImplementation); - - co_return winrt::make( - winrt::make(pushChannelReceived), - S_OK, - PushNotificationChannelStatus::CompletedSuccess); } + + PushNotificationTelemetry::ChannelRequestedByApi(S_OK, remoteId); + co_return winrt::make( + winrt::make(channelInfo), + S_OK, + PushNotificationChannelStatus::CompletedSuccess); } catch (...) { - auto channelRequestException = hresult_error(to_hresult(), take_ownership_from_abi); + auto channelRequestException{ hresult_error(to_hresult(), take_ownership_from_abi) }; if ((backOffTime <= c_maxBackoff) && IsChannelRequestRetryable(channelRequestException.code())) { @@ -233,7 +202,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - PushNotificationTelemetry::ChannelRequestedByApi(channelRequestException.code(), remoteId, usingLegacyImplementation); + PushNotificationTelemetry::ChannelRequestedByApi(channelRequestException.code(), remoteId); co_return winrt::make( nullptr, @@ -247,7 +216,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } catch (...) { - PushNotificationTelemetry::ChannelRequestedByApi(wil::ResultFromCaughtException(), remoteId, usingLegacyImplementation); + PushNotificationTelemetry::ChannelRequestedByApi(wil::ResultFromCaughtException(), remoteId); throw; } } @@ -275,6 +244,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_HR_IF(E_INVALIDARG, s_protocolRegistration); } + // AppId generated by PushNotificationsLongRunningTask singleton wil::unique_cotaskmem_string unpackagedAppUserModelId; RegisterUnpackagedApplicationHelper(GUID_NULL, unpackagedAppUserModelId); // create default registration for app @@ -286,7 +256,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation BackgroundTaskBuilder builder{ nullptr }; - if (WI_IsFlagSet(registrationActivators, PushNotificationRegistrationActivators::PushTrigger)) + if (WI_IsFlagSet(registrationActivators, PushNotificationRegistrationActivators::PushTrigger) && PushNotificationHelpers::IsPackagedAppScenario()) { GUID taskClsid = details.TaskClsid(); THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); @@ -361,12 +331,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); { - auto lock = s_activatorInfoLock.lock_shared(); + auto lock{ s_activatorInfoLock.lock_shared() }; THROW_HR_IF_MSG(E_INVALIDARG, s_comActivatorRegistration, "ComActivator already registered."); } GetWaitHandleForArgs().create(); - + GetComServerClsid() = taskClsid; + THROW_IF_FAILED(::CoRegisterClassObject( taskClsid, winrt::make().get(), @@ -485,17 +456,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation auto isProtocolActivatorSet{ WI_IsFlagSet(activators, PushNotificationRegistrationActivators::ProtocolActivator) }; THROW_HR_IF(E_INVALIDARG, isBackgroundTaskFlagSet && isProtocolActivatorSet); // Invalid flag combination - if (PushNotificationHelpers::IsPackagedAppScenario()) + if (AppModel::Identity::IsPackagedProcess() && isBackgroundTaskFlagSet) { - if (isProtocolActivatorSet) // ProtocolActivator unsupported if COM activation is available - { - return false; - } - return isBackgroundTaskFlagSet; + return true; } - else + else if(!AppModel::Identity::IsPackagedProcess() && isProtocolActivatorSet) { - return isProtocolActivatorSet; + return true; } + return false; } } diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index f2b56cc473..3120f2c487 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -8,15 +8,16 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { - struct PushNotificationManager + struct PushNotificationManager : PushNotificationManagerT { - PushNotificationManager() = delete; + PushNotificationManager() = default; - static void RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); - static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationActivators const& activators); - static void UnregisterAllActivators(); + static winrt::Microsoft::Windows::PushNotifications::PushNotificationManager Default(); + void RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); + void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationActivators const& activators); + void UnregisterAllActivators(); - static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid const remoteId); + winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid const remoteId); static bool IsActivatorSupported(Microsoft::Windows::PushNotifications::PushNotificationRegistrationActivators const& activators); }; diff --git a/dev/PushNotifications/PushNotificationTelemetry.h b/dev/PushNotifications/PushNotificationTelemetry.h index fc62ca3606..31be2a5f07 100644 --- a/dev/PushNotifications/PushNotificationTelemetry.h +++ b/dev/PushNotifications/PushNotificationTelemetry.h @@ -21,8 +21,7 @@ class PushNotificationTelemetry : public wil::TraceLoggingProvider public: DEFINE_EVENT_METHOD(ChannelRequestedByApi)( winrt::hresult hr, - const winrt::guid& remoteId, - bool usingLegacyImplementation) noexcept try + const winrt::guid& remoteId) noexcept try { if (c_maxEventLimit >= UpdateLogEventCount()) { @@ -32,7 +31,6 @@ class PushNotificationTelemetry : public wil::TraceLoggingProvider _GENERIC_PARTB_FIELDS_ENABLED, TraceLoggingHexUInt32(hr, "OperationResult"), TraceLoggingGuid(remoteId, "RemoteId"), - TraceLoggingBool(usingLegacyImplementation, "usingLegacyImplementation"), TraceLoggingBool(IsPackagedApp(), "IsAppPackaged"), TraceLoggingWideString(GetAppName(), "AppName")); } diff --git a/dev/PushNotifications/PushNotificationUtility.h b/dev/PushNotifications/PushNotificationUtility.h index e5b89298fb..4b9fe9099c 100644 --- a/dev/PushNotifications/PushNotificationUtility.h +++ b/dev/PushNotifications/PushNotificationUtility.h @@ -6,6 +6,7 @@ #include "NotificationsLongRunningProcess_h.h" #include #include "../Common/AppModel.Identity.h" +#include "PushBackgroundTaskInstance.h" namespace winrt { @@ -108,6 +109,17 @@ namespace winrt::Microsoft::Windows::PushNotifications::Helpers } CATCH_RETURN() + inline HRESULT PackagedAppLauncherByClsid(winrt::guid const& comServerClsid, unsigned int payloadLength, _In_reads_(payloadLength) byte* payload) noexcept try + { + auto payloadAsWideString{ Utf8BytesToWideString(payloadLength, payload) }; + auto pushBackgroundTaskInstance{ winrt::make_self(payloadAsWideString) }; + + auto localBackgroundTask = winrt::create_instance(comServerClsid, CLSCTX_ALL); + localBackgroundTask.Run(*pushBackgroundTaskInstance); + return S_OK; + } + CATCH_RETURN() + inline wil::com_ptr GetNotificationPlatform() { return wil::CoCreateInstance(CLSCTX_LOCAL_SERVER); diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 7e41a286ab..7fb3a82b2e 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -39,9 +39,10 @@ namespace Microsoft.Windows.PushNotifications // Initialize using a Registration option and optionally defined parameters like manifest defined activatorId // 1) If kind = PushTrigger is specified, only the Push Trigger will be Registered with Background Infra // 2) If kind = ComActivator is specified, the Background Task component will be Registered as an in-process COM server + // 3) If kind = ProtocolActivator is specified, the LRP will CoCreateInstance the application in background scenarios PushNotificationActivationInfo(PushNotificationRegistrationActivators activators, Guid taskClsid); - // Applications that need to use ProtocolActivator will use this constructor + // Unpackaged applications that need to register for activation will use this constructor PushNotificationActivationInfo(PushNotificationRegistrationActivators activators); // The CLSID associated with the Client COM server that Windows App SDK will activate @@ -112,22 +113,25 @@ namespace Microsoft.Windows.PushNotifications }; [feature(Feature_PushNotifications)] - static runtimeclass PushNotificationManager + runtimeclass PushNotificationManager { + // Gets a Default instance of a PushNotificationManager + static PushNotificationManager Default{ get; }; + // Register an activator using an ActivationInfo context and cache the flag for unregister - static void RegisterActivator(PushNotificationActivationInfo details); + void RegisterActivator(PushNotificationActivationInfo details); // Unregister any activator given PushNotificationRegistrationActivators // 1) If kind = PushTrigger is specified, the trigger itself will be removed // 2) If kind = ComActivator is specified, the Project Reunion Background Task component will no longer act as an InProc COM Server // 3) If kind = ProtocolActivator is specified, the application will be unregistered from the long running process that handles activation - static void UnregisterActivator(PushNotificationRegistrationActivators activators); + void UnregisterActivator(PushNotificationRegistrationActivators activators); // Unregister all activators registered for the application - static void UnregisterAllActivators(); + void UnregisterAllActivators(); // Request a Push Channel with an encoded RemoteId from WNS. RemoteId is an AAD identifier GUID - static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); + Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); // Applications will call this to check which flags are supported for RegisterActivator static Boolean IsActivatorSupported(PushNotificationRegistrationActivators activators); diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems index 3e6d5a339d..67f0907d9f 100644 --- a/dev/PushNotifications/PushNotifications.vcxitems +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -27,6 +27,7 @@ + diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl index 9011a91b7b..67cd23a580 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl +++ b/dev/PushNotifications/PushNotificationsLongRunningTask.ProxyStub/NotificationsLongRunningProcess.idl @@ -21,6 +21,8 @@ interface INotificationsLongRunningPlatform : IUnknown { HRESULT RegisterLongRunningActivator([in] LPCWSTR processName); + HRESULT RegisterLongRunningActivatorWithClsid([in] LPCWSTR processName, [in] GUID comServerClsid); + HRESULT UnregisterLongRunningActivator([in] LPCWSTR processName); HRESULT RegisterFullTrustApplication([in] LPCWSTR processName, [in] GUID remoteId, [out] LPWSTR* appId); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.cpp index 373d52db02..3b13b001fb 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.cpp @@ -2,20 +2,28 @@ #include "pch.h" #include "../PushNotificationUtility.h" +#include +using namespace winrt::Windows::ApplicationModel::Background; namespace ToastNotifications { using namespace ABI::Microsoft::Internal::ToastNotifications; } +namespace PushNotificationHelpers +{ + using namespace winrt::Microsoft::Windows::PushNotifications::Helpers; +} HRESULT NotificationListener::RuntimeClassInitialize( std::shared_ptr foregroundSinkManager, std::shared_ptr toastRegistrationManager, std::wstring const& appId, - std::wstring const& processName) noexcept try + std::wstring const& processName, + winrt::guid const& comServerClsid) noexcept try { m_foregroundSinkManager = foregroundSinkManager; m_toastRegistrationManager = toastRegistrationManager; + m_comServerClsid = comServerClsid; m_appId = appId; m_processName = processName; @@ -32,7 +40,14 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationListener::OnRawNotificationReceived if (!m_foregroundSinkManager->InvokeForegroundHandlers(m_appId, payloadArray, payloadLength)) { - THROW_IF_FAILED(winrt::Microsoft::Windows::PushNotifications::Helpers::ProtocolLaunchHelper(m_processName, payloadLength, payload)); + if (m_comServerClsid == winrt::guid()) + { + THROW_IF_FAILED(PushNotificationHelpers::ProtocolLaunchHelper(m_processName, payloadLength, payload)); + } + else + { + THROW_IF_FAILED(PushNotificationHelpers::PackagedAppLauncherByClsid(m_comServerClsid, payloadLength, payload)); + } }; return S_OK; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.h b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.h index 6bccf8193f..a20f676b26 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListener.h @@ -12,7 +12,8 @@ class NotificationListener : public Microsoft::WRL::RuntimeClass<::ABI::Microsof std::shared_ptr foregroundSinkManager, std::shared_ptr toastRegistrationManager, std::wstring const& appId, - std::wstring const& processName) noexcept; + std::wstring const& processName, + winrt::guid const& comServerClsid) noexcept; STDMETHOD(OnRawNotificationReceived)(unsigned int payloadLength, _In_ byte* payload, _In_ HSTRING correlationVector) noexcept; STDMETHOD(OnToastNotificationReceived)(ABI::Microsoft::Internal::ToastNotifications::INotificationProperties* notificationProperties, @@ -23,6 +24,6 @@ class NotificationListener : public Microsoft::WRL::RuntimeClass<::ABI::Microsof std::wstring m_appId; std::wstring m_processName; - + winrt::guid m_comServerClsid; wil::srwlock m_lock; }; diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.cpp index b11fae0753..a28f0ab43a 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.cpp @@ -9,26 +9,25 @@ void NotificationListenerManager::Initialize(std::shared_ptr& appIdList) +// The mapping setup here is appId -> (processName, comServerClsid) +void NotificationListenerManager::SetAppIdMapping(std::map>& appIdList) { for (auto appData : appIdList) { - AddListener(appData.first, appData.second); + AddListener(appData.first /* appId */, appData.second.first /* processName */, appData.second.second /* comServerClsid */); } } -void NotificationListenerManager::AddListener(std::wstring const& appId, std::wstring const& processName) +void NotificationListenerManager::AddListener(std::wstring const& appId, std::wstring const& processName, winrt::guid const& comServerClsid) { THROW_HR_IF(E_INVALIDARG, appId.empty()); - THROW_HR_IF(E_INVALIDARG, processName.empty()); - - + THROW_HR_IF(E_INVALIDARG, processName.empty()); // Make sure we keep the long running sink up-to-date with wpncore. ComPtr newListener; { auto lock{ m_lock.lock_shared() }; - THROW_IF_FAILED(MakeAndInitialize(&newListener, m_foregroundSinkManager, m_toastRegistrationManager, appId, processName)); + THROW_IF_FAILED(MakeAndInitialize(&newListener, m_foregroundSinkManager, m_toastRegistrationManager, appId, processName, comServerClsid)); } THROW_IF_FAILED(PushNotifications_RegisterNotificationSinkForFullTrustApplication(appId.c_str(), newListener.Get())); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.h b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.h index 3a7e906842..a0f43718a6 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/NotificationListenerManager.h @@ -12,9 +12,9 @@ class NotificationListenerManager // This function has to be called after initializing the ForegroundSinkManager during Platform initialization void Initialize(std::shared_ptr foregroundSinkManager, std::shared_ptr toastRegistrationManager); - void SetAppIdMapping(std::map& appIdList); + void SetAppIdMapping(std::map>& appIdList); - void AddListener(std::wstring const& appId, std::wstring const& processName); + void AddListener(std::wstring const& appId, std::wstring const& processName, winrt::guid const& comServerClsid); void RemoveListener(std::wstring appId); bool IsEmpty(); diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config b/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config index fa49afb662..187841df87 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config @@ -6,4 +6,4 @@ - + \ No newline at end of file diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/pch.h b/dev/PushNotifications/PushNotificationsLongRunningTask/pch.h index 06a9eae8b1..6d8be97e55 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/pch.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/pch.h @@ -22,9 +22,10 @@ #include #include - +#include +#include +#include #include - #include // UDK/ProxyStub files diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp index 7c595459ad..794a6488d4 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.cpp @@ -23,6 +23,9 @@ void NotificationsLongRunningPlatformImpl::Initialize() m_rawStorage = Storage::ApplicationData::Current().LocalSettings().CreateContainer( L"Raw", Storage::ApplicationDataCreateDisposition::Always); + m_comServerClsidStorage = Storage::ApplicationData::Current().LocalSettings().CreateContainer( + L"ComServerClsid", Storage::ApplicationDataCreateDisposition::Always); + m_foregroundSinkManager = std::make_shared(); m_toastRegistrationManager = std::make_shared(); @@ -78,20 +81,36 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterL auto lock = m_lock.lock_shared(); THROW_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + RegisterLongRunningActivatorHelper(processName, GUID_NULL); + return S_OK; +} +CATCH_RETURN() + +STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RegisterLongRunningActivatorWithClsid(_In_ PCWSTR processName, GUID comServerClsid) noexcept try +{ + auto lock = m_lock.lock_shared(); + THROW_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); + + RegisterLongRunningActivatorHelper(processName, comServerClsid); + return S_OK; +} +CATCH_RETURN() + +void NotificationsLongRunningPlatformImpl::RegisterLongRunningActivatorHelper(PCWSTR processName, GUID comServerClsid) +{ // NotificationsLongRunningPlatformImpl::RegisterFullTrustApplication should be called before this or we ignore the call const std::wstring appId{ GetAppIdentifier(processName) }; if (appId.empty()) { - return S_OK; + return; } - m_notificationListenerManager.AddListener(appId, processName); + m_comServerClsidStorage.Values().Insert(appId, winrt::box_value(comServerClsid)); + m_notificationListenerManager.AddListener(appId, processName, comServerClsid); m_lifetimeManager.Cancel(); - - return S_OK; + return; } -CATCH_RETURN() STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::UnregisterLongRunningActivator(_In_ PCWSTR processName) noexcept try { @@ -105,8 +124,9 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::Unregiste m_notificationListenerManager.RemoveListener(appId); m_foregroundSinkManager->Remove(appId); - RemoveAppIdentifier(appId); - RemoveToastHelper(processName); + m_rawStorage.Values().Remove(appId); + m_comServerClsidStorage.Values().Remove(appId); + m_toastRegistrationManager->Remove(processName); } if (m_notificationListenerManager.IsEmpty()) @@ -175,16 +195,16 @@ STDMETHODIMP_(HRESULT __stdcall) NotificationsLongRunningPlatformImpl::RemoveToa auto lock{ m_lock.lock_exclusive() }; THROW_HR_IF(WPN_E_PLATFORM_UNAVAILABLE, m_shutdown); - RemoveToastHelper(processName); + m_toastRegistrationManager->Remove(processName); return S_OK; } CATCH_RETURN() // Returns a map of key-value pairs, where key is appId and value is processName. // It should only be called by Initialize(), which already acquired a lock. -std::map NotificationsLongRunningPlatformImpl::GetFullTrustApps() +std::map> NotificationsLongRunningPlatformImpl::GetFullTrustApps() { - std::map mapOfFullTrustApps; + std::map> mapOfFullTrustApps; // Get list of full trust apps with valid channels from wpncore wil::unique_cotaskmem_array_ptr appIds; @@ -192,13 +212,14 @@ std::map NotificationsLongRunningPlatformImpl::GetFu // Get list of apps from Storage auto values{ m_rawStorage.Values() }; - + auto comServerClsidValues{ m_comServerClsidStorage.Values() }; for (size_t i = 0; i < appIds.size(); ++i) { if (values.HasKey(appIds[i])) { winrt::hstring processName{ winrt::unbox_value(values.Lookup(appIds[i])) }; - mapOfFullTrustApps.emplace(reinterpret_cast(appIds[i]), processName.c_str()); + winrt::guid comServerClsid{ winrt::unbox_value(comServerClsidValues.Lookup(appIds[i])) }; + mapOfFullTrustApps.emplace(reinterpret_cast(appIds[i]), std::pair{ processName.c_str(), comServerClsid }); } } @@ -239,14 +260,3 @@ const std::wstring NotificationsLongRunningPlatformImpl::BuildAppIdentifier(std: m_rawStorage.Values().Insert(guidStr.get(), winrt::box_value(processName.c_str())); return guidStr.get(); } - -void NotificationsLongRunningPlatformImpl::RemoveAppIdentifier(std::wstring const& appId) -{ - m_rawStorage.Values().Remove(appId); -} - -void NotificationsLongRunningPlatformImpl::RemoveToastHelper(std::wstring const& processName) -{ - m_toastRegistrationManager->Remove(processName); -} - diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h index c7c3516254..ca7be0a823 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/platform.h @@ -17,6 +17,8 @@ struct __declspec(uuid(PUSHNOTIFICATIONS_IMPL_CLSID_STRING)) NotificationsLongRu STDMETHOD(RegisterLongRunningActivator)(_In_ PCWSTR processName) noexcept; + STDMETHOD(RegisterLongRunningActivatorWithClsid)(_In_ PCWSTR processName, GUID comServerClsid) noexcept; + STDMETHOD(UnregisterLongRunningActivator)(_In_ PCWSTR processName) noexcept; STDMETHOD(RegisterForegroundActivator)(_In_ IWpnForegroundSink* sink, _In_ PCWSTR processName) noexcept; @@ -28,14 +30,13 @@ struct __declspec(uuid(PUSHNOTIFICATIONS_IMPL_CLSID_STRING)) NotificationsLongRu STDMETHOD(RemoveToastRegistrationMapping)(_In_ PCWSTR processName) noexcept; private: - std::map GetFullTrustApps(); + std::map> GetFullTrustApps(); // AppId -> (processName, comServerGuid) + void RegisterLongRunningActivatorHelper(PCWSTR processName, GUID comServerClsid); const std::wstring GetAppIdentifier(std::wstring const& processName); const std::wstring BuildAppIdentifier(std::wstring const& processName); - void RemoveAppIdentifier(std::wstring const& processName); - void RemoveToastHelper(std::wstring const& processName); winrt::Windows::Storage::ApplicationDataContainer m_rawStorage{ nullptr }; - + winrt::Windows::Storage::ApplicationDataContainer m_comServerClsidStorage{ nullptr }; wil::srwlock m_lock; bool m_initialized = false; diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index d0eb2d1b58..427319b5c2 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -4,16 +4,24 @@ #pragma once #include "pch.h" #include +#include "PushNotificationUtility.h" wil::unique_event& GetWaitHandleForArgs(); +winrt::guid& GetComServerClsid(); inline const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; +inline const winrt::hstring LRP_ACTIVATED_EVENT_ARGS_KEY = L"LRPActivatedEventArgs"; + +namespace PushNotificationHelpers +{ + using namespace winrt::Microsoft::Windows::PushNotifications::Helpers; +} struct ChannelDetails { winrt::hstring channelUri; winrt::hstring channelId; - winrt::hstring appUserModelId; + winrt::hstring appId; winrt::Windows::Foundation::DateTime channelExpiryTime; }; @@ -28,5 +36,12 @@ inline winrt::Windows::Foundation::IInspectable GetArgsFromComStore() THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !GetWaitHandleForArgs().wait(receiveArgsTimeoutInMSec)); // If COM static store was uninit, let it throw - return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().Lookup(ACTIVATED_EVENT_ARGS_KEY); + if (PushNotificationHelpers::IsPackagedAppScenario()) + { + return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().Lookup(ACTIVATED_EVENT_ARGS_KEY); + } + else + { + return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().Lookup(LRP_ACTIVATED_EVENT_ARGS_KEY); + } } diff --git a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj index ef37d61e0f..7f87810009 100644 --- a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj +++ b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj @@ -285,4 +285,4 @@ - \ No newline at end of file + diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 976152296f..b2aa63a7cb 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -20,7 +20,7 @@ winrt::Windows::Foundation::IAsyncOperation RequestChan { // To obtain an AAD RemoteIdentifier for your app, // follow the instructions on https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app - auto channelOperation = PushNotificationManager::CreateChannelAsync( + auto channelOperation = PushNotificationManager::Default().CreateChannelAsync( winrt::guid("0160ee84-0c53-4851-9ff2-d7f5a87ed914")); // Setup the inprogress event handler @@ -98,20 +98,20 @@ int main() const UINT32 c_Version_MajorMinor{ 0x00040001 }; const PACKAGE_VERSION minVersion{}; RETURN_IF_FAILED(MddBootstrapInitialize(c_Version_MajorMinor, nullptr, minVersion)); - } + } - if (PushNotificationManager::IsActivatorSupported(PushNotificationRegistrationActivators::ComActivator)) + if (PushNotificationManager::Default().IsActivatorSupported(PushNotificationRegistrationActivators::ComActivator)) { PushNotificationActivationInfo info( PushNotificationRegistrationActivators::PushTrigger | PushNotificationRegistrationActivators::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest - PushNotificationManager::RegisterActivator(info); + PushNotificationManager::Default().RegisterActivator(info); } else { PushNotificationActivationInfo info(PushNotificationRegistrationActivators::ProtocolActivator); - PushNotificationManager::RegisterActivator(info); + PushNotificationManager::Default().RegisterActivator(info); } auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); @@ -148,10 +148,10 @@ int main() std::cin.ignore(); } - if (PushNotificationManager::IsActivatorSupported(PushNotificationRegistrationActivators::ComActivator)) + if (PushNotificationManager::Default().IsActivatorSupported(PushNotificationRegistrationActivators::ComActivator)) { // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. - PushNotificationManager::UnregisterActivator(PushNotificationRegistrationActivators::ComActivator); + PushNotificationManager::Default().UnregisterActivator(PushNotificationRegistrationActivators::ComActivator); } if (!Test::AppModel::IsPackagedProcess()) diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index 65d30def92..99129ec444 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -43,7 +43,7 @@ - + WindowsAppRuntimeTestProtocol diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index a8fabd0728..1eea034c34 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -24,7 +24,7 @@ bool ChannelRequestUsingNullRemoteId() { try { - auto channelOperation = PushNotificationManager::CreateChannelAsync(winrt::guid()).get(); + auto channelOperation = PushNotificationManager::Default().CreateChannelAsync(winrt::guid()).get(); } catch (...) { @@ -54,7 +54,7 @@ HRESULT ChannelRequestHelper(IAsyncOperationWithProgress RequestChannelAsync() { // To obtain an AAD RemoteIdentifier for your app, // follow the instructions on https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app - auto channelOperation = winrt::PushNotificationManager::CreateChannelAsync( + auto channelOperation = winrt::PushNotificationManager::Default().CreateChannelAsync( winrt::guid("0160ee84-0c53-4851-9ff2-d7f5a87ed914")); // Setup the inprogress event handler diff --git a/test/TestApps/ToastNotificationsDemoApp/packages.config b/test/TestApps/ToastNotificationsDemoApp/packages.config index d4883e3890..18b80565dd 100644 --- a/test/TestApps/ToastNotificationsDemoApp/packages.config +++ b/test/TestApps/ToastNotificationsDemoApp/packages.config @@ -3,4 +3,4 @@ - \ No newline at end of file + diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png b/test/TestApps/ToastNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000..735f57adb5 Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/SplashScreen.scale-200.png b/test/TestApps/ToastNotificationsDemoPackage/Images/SplashScreen.scale-200.png new file mode 100644 index 0000000000..023e7f1fed Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/SplashScreen.scale-200.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png b/test/TestApps/ToastNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000..af49fec1a5 Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png b/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000..ce342a2ec8 Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000..f6c02ce97e Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/StoreLogo.png b/test/TestApps/ToastNotificationsDemoPackage/Images/StoreLogo.png new file mode 100644 index 0000000000..7385b56c0e Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/StoreLogo.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png b/test/TestApps/ToastNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000..288995b397 Binary files /dev/null and b/test/TestApps/ToastNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png differ diff --git a/test/TestApps/ToastNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/ToastNotificationsDemoPackage/Package.appxmanifest new file mode 100644 index 0000000000..f36806e306 --- /dev/null +++ b/test/TestApps/ToastNotificationsDemoPackage/Package.appxmanifest @@ -0,0 +1,76 @@ + + + + + + + + Toast Notifications Win32 Demo App + Microsoft Corporation + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WindowsAppRuntimeTestProtocol + + + + + + + + + + + + + + + + + + diff --git a/test/TestApps/ToastNotificationsDemoPackage/ToastNotificationsDemoPackage.wapproj b/test/TestApps/ToastNotificationsDemoPackage/ToastNotificationsDemoPackage.wapproj new file mode 100644 index 0000000000..cd4c7b8c49 --- /dev/null +++ b/test/TestApps/ToastNotificationsDemoPackage/ToastNotificationsDemoPackage.wapproj @@ -0,0 +1,88 @@ + + + + 15.0 + + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ + + + + e695a08e-8735-41cd-ae55-a5b589ba297f + 10.0.19041.0 + 10.0.17763.0 + en-US + True + ..\ToastNotificationsDemoApp\ToastNotificationsDemoApp.vcxproj + true + False + $(SolutionDir)temp\MSTest.pfx + SHA256 + True + True + $(Platform) + 0 + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + Designer + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/TestApps/ToastNotificationsTestApp/main.cpp b/test/TestApps/ToastNotificationsTestApp/main.cpp index 1441fd5f39..90d2cd7cbd 100644 --- a/test/TestApps/ToastNotificationsTestApp/main.cpp +++ b/test/TestApps/ToastNotificationsTestApp/main.cpp @@ -543,6 +543,7 @@ bool VerifyUpdateToastProgressDataUsingEmptyTagAndValidGroup() { return winrt::to_hresult() == E_INVALIDARG; } + return false; } bool VerifyUpdateToastProgressDataUsingEmptyTagAndEmptyGroup() @@ -557,6 +558,7 @@ bool VerifyUpdateToastProgressDataUsingEmptyTagAndEmptyGroup() { return winrt::to_hresult() == E_INVALIDARG; } + return false; } bool VerifyFailedUpdateNotificationDataWithNonExistentTagAndGroup() diff --git a/test/TestApps/ToastNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/ToastNotificationsTestAppPackage/Package.appxmanifest index 82398d33c4..a8887425b4 100644 --- a/test/TestApps/ToastNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/ToastNotificationsTestAppPackage/Package.appxmanifest @@ -50,7 +50,7 @@ - +